Skip to content

Commit d9140a0

Browse files
committed
In JavaScriptEngineSwitcher.ChakraCore was improved a fix for error #82 “Program crash after function call with too much parameters”
1 parent 195e024 commit d9140a0

File tree

5 files changed

+170
-42
lines changed

5 files changed

+170
-42
lines changed

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/TypeMapper.cs

Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,6 @@ public JsValue MapToScriptType(object value)
192192
}
193193
}
194194

195-
/// <summary>
196-
/// Makes a mapping of array items from the host type to a script type
197-
/// </summary>
198-
/// <param name="args">The source array</param>
199-
/// <returns>The mapped array</returns>
200-
public JsValue[] MapToScriptType(object[] args)
201-
{
202-
return args.Select(MapToScriptType).ToArray();
203-
}
204-
205195
/// <summary>
206196
/// Makes a mapping of value from the script type to a host type
207197
/// </summary>
@@ -257,16 +247,6 @@ public object MapToHostType(JsValue value)
257247
return result;
258248
}
259249

260-
/// <summary>
261-
/// Makes a mapping of array items from the script type to a host type
262-
/// </summary>
263-
/// <param name="args">The source array</param>
264-
/// <returns>The mapped array</returns>
265-
public object[] MapToHostType(JsValue[] args)
266-
{
267-
return args.Select(MapToHostType).ToArray();
268-
}
269-
270250
private EmbeddedObject CreateEmbeddedObjectOrFunction(object obj)
271251
{
272252
var del = obj as Delegate;
@@ -298,13 +278,13 @@ private EmbeddedObject CreateEmbeddedFunction(Delegate del)
298278
{
299279
JsNativeFunction nativeFunction = (callee, isConstructCall, args, argCount, callbackData) =>
300280
{
301-
object[] processedArgs = GetHostItemMemberArguments(args);
302281
#if NET40
303282
MethodInfo method = del.Method;
304283
#else
305284
MethodInfo method = del.GetMethodInfo();
306285
#endif
307286
ParameterInfo[] parameters = method.GetParameters();
287+
object[] processedArgs = GetHostItemMemberArguments(args, parameters.Length);
308288

309289
ReflectionHelpers.FixArgumentTypes(ref processedArgs, parameters);
310290

@@ -316,6 +296,7 @@ private EmbeddedObject CreateEmbeddedFunction(Delegate del)
316296
}
317297
catch (Exception e)
318298
{
299+
JsValue undefinedValue = JsValue.Undefined;
319300
Exception exception = UnwrapException(e);
320301
var wrapperException = exception as WrapperException;
321302
JsValue errorValue = wrapperException != null ?
@@ -326,7 +307,7 @@ private EmbeddedObject CreateEmbeddedFunction(Delegate del)
326307
;
327308
JsContext.SetException(errorValue);
328309

329-
return JsValue.Undefined;
310+
return undefinedValue;
330311
}
331312

332313
JsValue resultValue = MapToScriptType(result);
@@ -397,10 +378,12 @@ private EmbeddedType CreateEmbeddedType(Type type)
397378
return resultValue;
398379
}
399380

381+
JsValue undefinedValue = JsValue.Undefined;
382+
400383
if (constructors.Length == 0)
401384
{
402385
CreateAndSetError(string.Format(Strings.Runtime_HostTypeConstructorNotFound, typeName));
403-
return JsValue.Undefined;
386+
return undefinedValue;
404387
}
405388

406389
var bestFitConstructor = (ConstructorInfo)ReflectionHelpers.GetBestFitMethod(
@@ -409,7 +392,7 @@ private EmbeddedType CreateEmbeddedType(Type type)
409392
{
410393
CreateAndSetReferenceError(string.Format(
411394
Strings.Runtime_SuitableConstructorOfHostTypeNotFound, typeName));
412-
return JsValue.Undefined;
395+
return undefinedValue;
413396
}
414397

415398
ReflectionHelpers.FixArgumentTypes(ref processedArgs, bestFitConstructor.GetParameters());
@@ -430,7 +413,7 @@ private EmbeddedType CreateEmbeddedType(Type type)
430413
;
431414
JsContext.SetException(errorValue);
432415

433-
return JsValue.Undefined;
416+
return undefinedValue;
434417
}
435418

436419
resultValue = MapToScriptType(result);
@@ -502,11 +485,13 @@ private void ProjectFields(EmbeddedItem externalItem)
502485

503486
JsNativeFunction nativeGetFunction = (callee, isConstructCall, args, argCount, callbackData) =>
504487
{
488+
JsValue undefinedValue = JsValue.Undefined;
489+
505490
if (instance && obj == null)
506491
{
507492
CreateAndSetTypeError(string.Format(
508493
Strings.Runtime_InvalidThisContextForHostObjectField, fieldName));
509-
return JsValue.Undefined;
494+
return undefinedValue;
510495
}
511496

512497
object result;
@@ -538,7 +523,7 @@ private void ProjectFields(EmbeddedItem externalItem)
538523
}
539524
JsContext.SetException(errorValue);
540525

541-
return JsValue.Undefined;
526+
return undefinedValue;
542527
}
543528

544529
JsValue resultValue = MapToScriptType(result);
@@ -552,11 +537,13 @@ private void ProjectFields(EmbeddedItem externalItem)
552537

553538
JsNativeFunction nativeSetFunction = (callee, isConstructCall, args, argCount, callbackData) =>
554539
{
540+
JsValue undefinedValue = JsValue.Undefined;
541+
555542
if (instance && obj == null)
556543
{
557544
CreateAndSetTypeError(string.Format(
558545
Strings.Runtime_InvalidThisContextForHostObjectField, fieldName));
559-
return JsValue.Undefined;
546+
return undefinedValue;
560547
}
561548

562549
object value = MapToHostType(args[1]);
@@ -589,10 +576,10 @@ private void ProjectFields(EmbeddedItem externalItem)
589576
}
590577
JsContext.SetException(errorValue);
591578

592-
return JsValue.Undefined;
579+
return undefinedValue;
593580
}
594581

595-
return JsValue.Undefined;
582+
return undefinedValue;
596583
};
597584
nativeFunctions.Add(nativeSetFunction);
598585

@@ -626,11 +613,13 @@ private void ProjectProperties(EmbeddedItem externalItem)
626613
{
627614
JsNativeFunction nativeGetFunction = (callee, isConstructCall, args, argCount, callbackData) =>
628615
{
616+
JsValue undefinedValue = JsValue.Undefined;
617+
629618
if (instance && obj == null)
630619
{
631620
CreateAndSetTypeError(string.Format(
632621
Strings.Runtime_InvalidThisContextForHostObjectProperty, propertyName));
633-
return JsValue.Undefined;
622+
return undefinedValue;
634623
}
635624

636625
object result;
@@ -662,7 +651,7 @@ private void ProjectProperties(EmbeddedItem externalItem)
662651
}
663652
JsContext.SetException(errorValue);
664653

665-
return JsValue.Undefined;
654+
return undefinedValue;
666655
}
667656

668657
JsValue resultValue = MapToScriptType(result);
@@ -679,11 +668,13 @@ private void ProjectProperties(EmbeddedItem externalItem)
679668
{
680669
JsNativeFunction nativeSetFunction = (callee, isConstructCall, args, argCount, callbackData) =>
681670
{
671+
JsValue undefinedValue = JsValue.Undefined;
672+
682673
if (instance && obj == null)
683674
{
684675
CreateAndSetTypeError(string.Format(
685676
Strings.Runtime_InvalidThisContextForHostObjectProperty, propertyName));
686-
return JsValue.Undefined;
677+
return undefinedValue;
687678
}
688679

689680
object value = MapToHostType(args[1]);
@@ -716,10 +707,10 @@ private void ProjectProperties(EmbeddedItem externalItem)
716707
}
717708
JsContext.SetException(errorValue);
718709

719-
return JsValue.Undefined;
710+
return undefinedValue;
720711
}
721712

722-
return JsValue.Undefined;
713+
return undefinedValue;
723714
};
724715
nativeFunctions.Add(nativeSetFunction);
725716

@@ -752,11 +743,13 @@ private void ProjectMethods(EmbeddedItem externalItem)
752743

753744
JsNativeFunction nativeFunction = (callee, isConstructCall, args, argCount, callbackData) =>
754745
{
746+
JsValue undefinedValue = JsValue.Undefined;
747+
755748
if (instance && obj == null)
756749
{
757750
CreateAndSetTypeError(string.Format(
758751
Strings.Runtime_InvalidThisContextForHostObjectMethod, methodName));
759-
return JsValue.Undefined;
752+
return undefinedValue;
760753
}
761754

762755
object[] processedArgs = GetHostItemMemberArguments(args);
@@ -767,7 +760,7 @@ private void ProjectMethods(EmbeddedItem externalItem)
767760
{
768761
CreateAndSetReferenceError(string.Format(
769762
Strings.Runtime_SuitableMethodOfHostObjectNotFound, methodName));
770-
return JsValue.Undefined;
763+
return undefinedValue;
771764
}
772765

773766
ReflectionHelpers.FixArgumentTypes(ref processedArgs, bestFitMethod.GetParameters());
@@ -801,7 +794,7 @@ private void ProjectMethods(EmbeddedItem externalItem)
801794
}
802795
JsContext.SetException(errorValue);
803796

804-
return JsValue.Undefined;
797+
return undefinedValue;
805798
}
806799

807800
JsValue resultValue = MapToScriptType(result);
@@ -815,11 +808,35 @@ private void ProjectMethods(EmbeddedItem externalItem)
815808
}
816809
}
817810

818-
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
819-
private object[] GetHostItemMemberArguments(JsValue[] args)
811+
private object[] GetHostItemMemberArguments(JsValue[] args, int maxArgCount = -1)
820812
{
821-
object[] processedArgs = args.Length > 1 ?
822-
MapToHostType(args.Skip(1).ToArray()) : new object[0];
813+
if (args == null)
814+
{
815+
throw new ArgumentNullException(nameof(args));
816+
}
817+
818+
int argCount = args.Length;
819+
const int skippedArgCount = 1;
820+
int processedArgCount = argCount >= skippedArgCount ? argCount - skippedArgCount : 0;
821+
if (maxArgCount >= 0 && processedArgCount > maxArgCount)
822+
{
823+
processedArgCount = maxArgCount;
824+
}
825+
object[] processedArgs;
826+
827+
if (processedArgCount > 0)
828+
{
829+
processedArgs = args
830+
.Skip(skippedArgCount)
831+
.Take(processedArgCount)
832+
.Select(MapToHostType)
833+
.ToArray()
834+
;
835+
}
836+
else
837+
{
838+
processedArgs = new object[0];
839+
}
823840

824841
return processedArgs;
825842
}

test/JavaScriptEngineSwitcher.Tests/InteropTestsBase.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,56 @@ public virtual void EmbeddedInstanceOfDelegateHasFunctionPrototype()
611611
Assert.True(output);
612612
}
613613

614+
[Fact]
615+
public virtual void CallingOfEmbeddedDelegateWithMissingParameter()
616+
{
617+
// Arrange
618+
var sumFunc = new Func<int, int, int>((a, b) => a + b);
619+
620+
const string input = "sum(678)";
621+
JsRuntimeException exception = null;
622+
623+
// Act
624+
using (var jsEngine = CreateJsEngine())
625+
{
626+
jsEngine.EmbedHostObject("sum", sumFunc);
627+
628+
try
629+
{
630+
int result = jsEngine.Evaluate<int>(input);
631+
}
632+
catch (JsRuntimeException e)
633+
{
634+
exception = e;
635+
}
636+
}
637+
638+
// Assert
639+
Assert.NotNull(exception);
640+
}
641+
642+
[Fact]
643+
public virtual void CallingOfEmbeddedDelegateWithExtraParameter()
644+
{
645+
// Arrange
646+
var sumFunc = new Func<int, int, int>((a, b) => a + b);
647+
648+
const string input = "sum(678, 711, 611)";
649+
const int targetOutput = 1389;
650+
651+
// Act
652+
int output;
653+
654+
using (var jsEngine = CreateJsEngine())
655+
{
656+
jsEngine.EmbedHostObject("sum", sumFunc);
657+
output = jsEngine.Evaluate<int>(input);
658+
}
659+
660+
// Assert
661+
Assert.Equal(targetOutput, output);
662+
}
663+
614664
#endregion
615665

616666
#region Recursive calls

test/JavaScriptEngineSwitcher.Tests/Jint/InteropTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,32 @@ public override void EmbeddingOfInstanceOfCustomReferenceTypeWithFieldsIsCorrect
6161

6262
#endregion
6363

64+
#region Delegates
65+
66+
[Fact]
67+
public override void CallingOfEmbeddedDelegateWithMissingParameter()
68+
{
69+
// Arrange
70+
var sumFunc = new Func<int, int, int>((a, b) => a + b);
71+
72+
const string input = "sum(678)";
73+
const int targetOutput = 678;
74+
75+
// Act
76+
int output;
77+
78+
using (var jsEngine = CreateJsEngine())
79+
{
80+
jsEngine.EmbedHostObject("sum", sumFunc);
81+
output = jsEngine.Evaluate<int>(input);
82+
}
83+
84+
// Assert
85+
Assert.Equal(targetOutput, output);
86+
}
87+
88+
#endregion
89+
6490
#region Recursive calls
6591

6692
#region Mapping of errors

0 commit comments

Comments
 (0)