@@ -21,6 +21,11 @@ namespace JavaScriptEngineSwitcher.ChakraCore.JsRt
2121 /// </summary>
2222 internal sealed class TypeMapper : IDisposable
2323 {
24+ /// <summary>
25+ /// Name of property to store the external object
26+ /// </summary>
27+ private const string ExternalObjectPropertyName = "_JavaScriptEngineSwitcher_externalObject" ;
28+
2429 /// <summary>
2530 /// Storage for lazy-initialized embedded objects
2631 /// </summary>
@@ -200,7 +205,7 @@ public JsValue[] MapToScriptType(object[] args)
200205 public object MapToHostType ( JsValue value )
201206 {
202207 JsValueType valueType = value . ValueType ;
203- object result ;
208+ object result = null ;
204209
205210 switch ( valueType )
206211 {
@@ -219,8 +224,18 @@ public object MapToHostType(JsValue value)
219224 case JsValueType . String :
220225 result = value . ToString ( ) ;
221226 break ;
222- case JsValueType . Object :
223227 case JsValueType . Function :
228+ JsPropertyId externalObjectPropertyId = JsPropertyId . FromString ( ExternalObjectPropertyName ) ;
229+ if ( value . HasProperty ( externalObjectPropertyId ) )
230+ {
231+ JsValue externalObjectValue = value . GetProperty ( externalObjectPropertyId ) ;
232+ result = externalObjectValue . HasExternalData ?
233+ GCHandle . FromIntPtr ( externalObjectValue . ExternalData ) . Target : null ;
234+ }
235+
236+ result = result ?? value . ConvertToObject ( ) ;
237+ break ;
238+ case JsValueType . Object :
224239 case JsValueType . Error :
225240 case JsValueType . Array :
226241 case JsValueType . Symbol :
@@ -311,10 +326,10 @@ private EmbeddedObject CreateEmbeddedFunction(Delegate del)
311326
312327 GCHandle delHandle = GCHandle . Alloc ( del ) ;
313328 IntPtr delPtr = GCHandle . ToIntPtr ( delHandle ) ;
314- JsValue prototypeValue = JsValue . CreateExternalObject ( delPtr , _embeddedObjectFinalizeCallback ) ;
329+ JsValue objValue = JsValue . CreateExternalObject ( delPtr , _embeddedObjectFinalizeCallback ) ;
315330
316331 JsValue functionValue = JsValue . CreateFunction ( nativeFunction ) ;
317- functionValue . Prototype = prototypeValue ;
332+ SetNonEnumerableProperty ( functionValue , ExternalObjectPropertyName , objValue ) ;
318333
319334 var embeddedObject = new EmbeddedObject ( del , functionValue ,
320335 new List < JsNativeFunction > { nativeFunction } ) ;
@@ -415,14 +430,12 @@ private EmbeddedType CreateEmbeddedType(Type type)
415430 return resultValue ;
416431 } ;
417432
418- string embeddedTypeKey = type . AssemblyQualifiedName ;
419- GCHandle embeddedTypeKeyHandle = GCHandle . Alloc ( embeddedTypeKey ) ;
420- IntPtr embeddedTypeKeyPtr = GCHandle . ToIntPtr ( embeddedTypeKeyHandle ) ;
421- JsValue prototypeValue = JsValue . CreateExternalObject ( embeddedTypeKeyPtr ,
422- _embeddedTypeFinalizeCallback ) ;
433+ GCHandle embeddedTypeHandle = GCHandle . Alloc ( type ) ;
434+ IntPtr embeddedTypePtr = GCHandle . ToIntPtr ( embeddedTypeHandle ) ;
435+ JsValue objValue = JsValue . CreateExternalObject ( embeddedTypePtr , _embeddedTypeFinalizeCallback ) ;
423436
424437 JsValue typeValue = JsValue . CreateFunction ( nativeConstructorFunction ) ;
425- typeValue . Prototype = prototypeValue ;
438+ SetNonEnumerableProperty ( typeValue , ExternalObjectPropertyName , objValue ) ;
426439
427440 var embeddedType = new EmbeddedType ( type , typeValue ,
428441 new List < JsNativeFunction > { nativeConstructorFunction } ) ;
@@ -442,8 +455,9 @@ private void EmbeddedTypeFinalizeCallback(IntPtr ptr)
442455 return ;
443456 }
444457
445- GCHandle embeddedTypeKeyHandle = GCHandle . FromIntPtr ( ptr ) ;
446- var embeddedTypeKey = ( string ) embeddedTypeKeyHandle . Target ;
458+ GCHandle embeddedTypeHandle = GCHandle . FromIntPtr ( ptr ) ;
459+ var type = ( Type ) embeddedTypeHandle . Target ;
460+ string embeddedTypeKey = type . AssemblyQualifiedName ;
447461 var lazyEmbeddedTypes = _lazyEmbeddedTypes ;
448462
449463 if ( ! string . IsNullOrEmpty ( embeddedTypeKey ) && lazyEmbeddedTypes != null )
@@ -456,7 +470,7 @@ private void EmbeddedTypeFinalizeCallback(IntPtr ptr)
456470 }
457471 }
458472
459- embeddedTypeKeyHandle . Free ( ) ;
473+ embeddedTypeHandle . Free ( ) ;
460474 }
461475
462476 private void ProjectFields ( EmbeddedItem externalItem )
@@ -772,7 +786,7 @@ private object[] GetHostItemMemberArguments(JsValue[] args)
772786 }
773787
774788 [ MethodImpl ( ( MethodImplOptions ) 256 /* AggressiveInlining */ ) ]
775- private void FreezeObject ( JsValue objValue )
789+ private static void FreezeObject ( JsValue objValue )
776790 {
777791 JsValue freezeMethodValue = JsValue . GlobalObject
778792 . GetProperty ( "Object" )
@@ -781,6 +795,18 @@ private void FreezeObject(JsValue objValue)
781795 freezeMethodValue . CallFunction ( objValue ) ;
782796 }
783797
798+ [ MethodImpl ( ( MethodImplOptions ) 256 /* AggressiveInlining */ ) ]
799+ private static void SetNonEnumerableProperty ( JsValue objValue , string name , JsValue value )
800+ {
801+ JsValue descriptorValue = JsValue . CreateObject ( ) ;
802+ descriptorValue . SetProperty ( "enumerable" , JsValue . False , true ) ;
803+ descriptorValue . SetProperty ( "writable" , JsValue . True , true ) ;
804+
805+ JsPropertyId id = JsPropertyId . FromString ( name ) ;
806+ objValue . DefineProperty ( id , descriptorValue ) ;
807+ objValue . SetProperty ( id , value , true ) ;
808+ }
809+
784810 #region IDisposable implementation
785811
786812 /// <summary>
0 commit comments