Skip to content

Commit a0328d2

Browse files
committed
In JavaScriptEngineSwitcher.Yantra improved a conversion of results to a host types
1 parent 14d4eac commit a0328d2

File tree

2 files changed

+160
-74
lines changed

2 files changed

+160
-74
lines changed

src/JavaScriptEngineSwitcher.Jurassic/JurassicJsEngine.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,9 @@ private static T MapToHostType<T>(OriginalEngine engine, object value)
168168
return TypeConverter.ConvertToType<T>(null);
169169
}
170170

171-
if (typeof(T) == typeof(Undefined))
171+
Type targetType = typeof(T);
172+
173+
if (targetType == typeof(Undefined))
172174
{
173175
if (value is OriginalUndefined)
174176
{
@@ -177,7 +179,7 @@ private static T MapToHostType<T>(OriginalEngine engine, object value)
177179
else
178180
{
179181
throw new InvalidOperationException(
180-
string.Format(CoreStrings.Common_CannotConvertObjectToType, value.GetType(), typeof(T))
182+
string.Format(CoreStrings.Common_CannotConvertObjectToType, value.GetType(), targetType)
181183
);
182184
}
183185
}
@@ -194,7 +196,7 @@ private static T MapToHostType<T>(OriginalEngine engine, object value)
194196
}
195197
catch (ArgumentException e)
196198
{
197-
if (typeof(T) == typeof(string) && value != null)
199+
if (targetType == typeof(string) && value != null)
198200
{
199201
return (T)(object)value.ToString();
200202
}

src/JavaScriptEngineSwitcher.Yantra/YantraJsEngine.cs

Lines changed: 155 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq;
33
using System.Reflection;
4+
using System.Runtime.CompilerServices;
45
using System.Text.RegularExpressions;
56

67
using YantraJS.Core;
@@ -12,6 +13,7 @@
1213
using OriginalContext = YantraJS.Core.JSContext;
1314
using OriginalException = YantraJS.Core.JSException;
1415
using OriginalFunction = YantraJS.Core.JSFunction;
16+
using OriginalTypeConverter = YantraJS.Utils.TypeConverter;
1517
using OriginalUndefined = YantraJS.Core.JSUndefined;
1618
using OriginalValue = YantraJS.Core.JSValue;
1719

@@ -20,6 +22,7 @@
2022
using JavaScriptEngineSwitcher.Core.Helpers;
2123
using JavaScriptEngineSwitcher.Core.Utilities;
2224

25+
using CoreStrings = JavaScriptEngineSwitcher.Core.Resources.Strings;
2326
using WrapperCompilationException = JavaScriptEngineSwitcher.Core.JsCompilationException;
2427
using WrapperException = JavaScriptEngineSwitcher.Core.JsException;
2528
using WrapperRuntimeException = JavaScriptEngineSwitcher.Core.JsRuntimeException;
@@ -94,7 +97,7 @@ private static OriginalValue MapToScriptType(object value)
9497
return OriginalUndefined.Value;
9598
}
9699

97-
return value.Marshal();
100+
return OriginalTypeConverter.FromBasic(value);
98101
}
99102

100103
/// <summary>
@@ -134,7 +137,7 @@ private static object MapToHostType(OriginalValue value)
134137
}
135138
else if (value.IsString)
136139
{
137-
result = value.AsStringOrDefault();
140+
result = value.ToString();
138141
}
139142
else
140143
{
@@ -145,13 +148,51 @@ private static object MapToHostType(OriginalValue value)
145148
}
146149

147150
/// <summary>
148-
/// Makes a mapping of array itemp from the script type to a host type
151+
/// Makes a mapping of value from the script type to a host type
149152
/// </summary>
150-
/// <param name="args">The source array</param>
151-
/// <returns>The mapped array</returns>
152-
private static object[] MapToHostType(OriginalValue[] args)
153+
/// <typeparam name="T">The type to convert the value to</typeparam>
154+
/// <param name="value">The source value</param>
155+
/// <returns>The mapped value</returns>
156+
private static T MapToHostType<T>(OriginalValue value)
153157
{
154-
return args.Select(MapToHostType).ToArray();
158+
if (value.IsNull)
159+
{
160+
return TypeConverter.ConvertToType<T>(null);
161+
}
162+
163+
Type targetType = typeof(T);
164+
165+
if (targetType == typeof(Undefined))
166+
{
167+
if (value.IsUndefined)
168+
{
169+
return (T)(object)Undefined.Value;
170+
}
171+
else
172+
{
173+
throw new InvalidOperationException(
174+
string.Format(CoreStrings.Common_CannotConvertObjectToType, value.GetType(), targetType)
175+
);
176+
}
177+
}
178+
179+
T result;
180+
181+
if (!value.ConvertTo<T>(out result))
182+
{
183+
if (targetType == typeof(string))
184+
{
185+
result = (T)(object)value.ToString();
186+
}
187+
else
188+
{
189+
throw new InvalidOperationException(
190+
string.Format(CoreStrings.Common_CannotConvertObjectToType, value.GetType(), targetType)
191+
);
192+
}
193+
}
194+
195+
return result;
155196
}
156197

157198
private static OriginalFunction CreateEmbeddedFunction(Delegate del)
@@ -306,33 +347,56 @@ private WrapperException WrapJsException(OriginalException originalException)
306347

307348
#endregion
308349

309-
#region JsEngineBase overrides
310-
311-
protected override IPrecompiledScript InnerPrecompile(string code)
350+
/// <summary>
351+
/// Evaluates an expression without converting its result to a host type
352+
/// </summary>
353+
/// <param name="expression">JS expression</param>
354+
/// <param name="documentName">Document name</param>
355+
/// <returns>Result of the expression not converted to a host type</returns>
356+
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
357+
private OriginalValue InnerEvaluateWithoutResultConversion(string expression, string documentName)
312358
{
313-
throw new NotSupportedException();
314-
}
359+
OriginalValue resultValue;
360+
string uniqueDocumentName = _documentNameManager.GetUniqueName(documentName);
315361

316-
protected override IPrecompiledScript InnerPrecompile(string code, string documentName)
317-
{
318-
throw new NotSupportedException();
319-
}
362+
try
363+
{
364+
lock (_executionSynchronizer)
365+
{
366+
resultValue = _jsContext.Eval(expression, uniqueDocumentName);
367+
}
368+
}
369+
catch (OriginalException e)
370+
{
371+
throw WrapJsException(e);
372+
}
373+
catch (Exception e) when ((e is TargetInvocationException || e is WrapperException)
374+
&& e.InnerException != null)
375+
{
376+
OriginalException originalException = OriginalException.From(e.InnerException);
377+
throw originalException;
378+
}
320379

321-
protected override object InnerEvaluate(string expression)
322-
{
323-
return InnerEvaluate(expression, null);
380+
return resultValue;
324381
}
325382

326-
protected override object InnerEvaluate(string expression, string documentName)
383+
/// <summary>
384+
/// Calls a function without converting its result to a host type
385+
/// </summary>
386+
/// <param name="functionName">Function name</param>
387+
/// <param name="args">Function arguments</param>
388+
/// <returns>Result of the function execution not converted to a host type</returns>
389+
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
390+
private OriginalValue InnerCallFunctionWithoutResultConversion(string functionName, params object[] args)
327391
{
328392
OriginalValue resultValue;
329-
string uniqueDocumentName = _documentNameManager.GetUniqueName(documentName);
393+
OriginalValue[] processedArgs = MapToScriptType(args);
330394

331395
try
332396
{
333397
lock (_executionSynchronizer)
334398
{
335-
resultValue = _jsContext.Eval(expression, uniqueDocumentName);
399+
resultValue = _jsContext.InvokeMethod(functionName, new OriginalArguments(_jsContext, processedArgs));
336400
}
337401
}
338402
catch (OriginalException e)
@@ -346,6 +410,54 @@ protected override object InnerEvaluate(string expression, string documentName)
346410
throw originalException;
347411
}
348412

413+
return resultValue;
414+
}
415+
416+
/// <summary>
417+
/// Gets a value of variable without converting it to a host type
418+
/// </summary>
419+
/// <param name="variableName">Variable name</param>
420+
/// <returns>Value of variable not converted to a host type</returns>
421+
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
422+
private OriginalValue InnerGetVariableValueWithoutResultConversion(string variableName)
423+
{
424+
OriginalValue variableValue;
425+
426+
try
427+
{
428+
lock (_executionSynchronizer)
429+
{
430+
variableValue = _jsContext[variableName];
431+
}
432+
}
433+
catch (OriginalException e)
434+
{
435+
throw WrapJsException(e);
436+
}
437+
438+
return variableValue;
439+
}
440+
441+
#region JsEngineBase overrides
442+
443+
protected override IPrecompiledScript InnerPrecompile(string code)
444+
{
445+
throw new NotSupportedException();
446+
}
447+
448+
protected override IPrecompiledScript InnerPrecompile(string code, string documentName)
449+
{
450+
throw new NotSupportedException();
451+
}
452+
453+
protected override object InnerEvaluate(string expression)
454+
{
455+
return InnerEvaluate(expression, null);
456+
}
457+
458+
protected override object InnerEvaluate(string expression, string documentName)
459+
{
460+
OriginalValue resultValue = InnerEvaluateWithoutResultConversion(expression, documentName);
349461
object result = MapToHostType(resultValue);
350462

351463
return result;
@@ -358,9 +470,10 @@ protected override T InnerEvaluate<T>(string expression)
358470

359471
protected override T InnerEvaluate<T>(string expression, string documentName)
360472
{
361-
object result = InnerEvaluate(expression, documentName);
473+
OriginalValue resultValue = InnerEvaluateWithoutResultConversion(expression, documentName);
474+
T result = MapToHostType<T>(resultValue);
362475

363-
return TypeConverter.ConvertToType<T>(result);
476+
return result;
364477
}
365478

366479
protected override void InnerExecute(string code)
@@ -398,86 +511,57 @@ protected override void InnerExecute(IPrecompiledScript precompiledScript)
398511

399512
protected override object InnerCallFunction(string functionName, params object[] args)
400513
{
401-
OriginalValue resultValue;
402-
OriginalValue[] processedArgs = MapToScriptType(args);
403-
404-
try
405-
{
406-
lock (_executionSynchronizer)
407-
{
408-
resultValue = _jsContext.InvokeMethod(functionName, new OriginalArguments(_jsContext, processedArgs));
409-
}
410-
}
411-
catch (OriginalException e)
412-
{
413-
throw WrapJsException(e);
414-
}
415-
catch (Exception e) when ((e is TargetInvocationException || e is WrapperException)
416-
&& e.InnerException != null)
417-
{
418-
OriginalException originalException = OriginalException.From(e.InnerException);
419-
throw originalException;
420-
}
421-
514+
OriginalValue resultValue = InnerCallFunctionWithoutResultConversion(functionName, args);
422515
object result = MapToHostType(resultValue);
423516

424517
return result;
425518
}
426519

427520
protected override T InnerCallFunction<T>(string functionName, params object[] args)
428521
{
429-
object result = InnerCallFunction(functionName, args);
522+
OriginalValue resultValue = InnerCallFunctionWithoutResultConversion(functionName, args);
523+
T result = MapToHostType<T>(resultValue);
430524

431-
return TypeConverter.ConvertToType<T>(result);
525+
return result;
432526
}
433527

434528
protected override bool InnerHasVariable(string variableName)
435529
{
436530
bool result;
437531

438-
lock (_executionSynchronizer)
532+
try
439533
{
440-
try
441-
{
442-
OriginalValue variableValue = _jsContext[variableName];
534+
OriginalValue variableValue;
443535

444-
result = !variableValue.IsUndefined;
445-
}
446-
catch (OriginalException)
536+
lock (_executionSynchronizer)
447537
{
448-
result = false;
538+
variableValue = _jsContext[variableName];
449539
}
540+
541+
result = !variableValue.IsUndefined;
542+
}
543+
catch (OriginalException)
544+
{
545+
result = false;
450546
}
451547

452548
return result;
453549
}
454550

455551
protected override object InnerGetVariableValue(string variableName)
456552
{
457-
OriginalValue variableValue;
458-
459-
try
460-
{
461-
lock (_executionSynchronizer)
462-
{
463-
variableValue = _jsContext[variableName];
464-
}
465-
}
466-
catch (OriginalException e)
467-
{
468-
throw WrapJsException(e);
469-
}
470-
553+
OriginalValue variableValue = InnerGetVariableValueWithoutResultConversion(variableName);
471554
object result = MapToHostType(variableValue);
472555

473556
return result;
474557
}
475558

476559
protected override T InnerGetVariableValue<T>(string variableName)
477560
{
478-
object result = InnerGetVariableValue(variableName);
561+
OriginalValue variableValue = InnerGetVariableValueWithoutResultConversion(variableName);
562+
T result = MapToHostType<T>(variableValue);
479563

480-
return TypeConverter.ConvertToType<T>(result);
564+
return result;
481565
}
482566

483567
protected override void InnerSetVariableValue(string variableName, object value)

0 commit comments

Comments
 (0)