11using System ;
22using System . Linq ;
33using System . Reflection ;
4+ using System . Runtime . CompilerServices ;
45using System . Text . RegularExpressions ;
56
67using YantraJS . Core ;
1213using OriginalContext = YantraJS . Core . JSContext ;
1314using OriginalException = YantraJS . Core . JSException ;
1415using OriginalFunction = YantraJS . Core . JSFunction ;
16+ using OriginalTypeConverter = YantraJS . Utils . TypeConverter ;
1517using OriginalUndefined = YantraJS . Core . JSUndefined ;
1618using OriginalValue = YantraJS . Core . JSValue ;
1719
2022using JavaScriptEngineSwitcher . Core . Helpers ;
2123using JavaScriptEngineSwitcher . Core . Utilities ;
2224
25+ using CoreStrings = JavaScriptEngineSwitcher . Core . Resources . Strings ;
2326using WrapperCompilationException = JavaScriptEngineSwitcher . Core . JsCompilationException ;
2427using WrapperException = JavaScriptEngineSwitcher . Core . JsException ;
2528using 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