@@ -52,14 +52,38 @@ JavascriptExternal::JavascriptExternal(System::Object^ iObject)
52
52
{
53
53
mObjectHandle = System::Runtime::InteropServices::GCHandle::Alloc (iObject);
54
54
mOptions = SetParameterOptions::None;
55
- mMethods = gcnew System::Collections::Generic::Dictionary<System::String ^, WrappedMethod>();
56
55
}
57
56
58
57
// //////////////////////////////////////////////////////////////////////////////////////////////////
59
58
60
59
JavascriptExternal::~JavascriptExternal ()
61
60
{
62
- mObjectHandle .Free ();
61
+ mObjectHandle .Free ();
62
+ if (!mPersistent .IsEmpty ()) {
63
+ mPersistent .ClearWeak <void >();
64
+ mPersistent .Reset ();
65
+ }
66
+
67
+ }
68
+
69
+ // //////////////////////////////////////////////////////////////////////////////////////////////////
70
+
71
+ void GCCallback (const WeakCallbackInfo<JavascriptExternal>& data)
72
+ {
73
+ auto context = JavascriptContext::GetCurrent ();
74
+ auto external = data.GetParameter ();
75
+ auto object = external->GetObject ();
76
+ if (context->mExternals ->ContainsKey (object))
77
+ context->mExternals ->Remove (object);
78
+ delete external;
79
+ }
80
+
81
+ void
82
+ JavascriptExternal::Wrap (Isolate* isolate, Local<Object> object)
83
+ {
84
+ object->SetInternalField (0 , External::New (isolate, this ));
85
+ mPersistent .Reset (isolate, object);
86
+ mPersistent .SetWeak (this , &GCCallback, WeakCallbackType::kParameter );
63
87
}
64
88
65
89
// //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -75,40 +99,28 @@ JavascriptExternal::GetObject()
75
99
Local<Function>
76
100
JavascriptExternal::GetMethod (wstring iName)
77
101
{
78
- v8::Isolate *isolate = JavascriptContext::GetCurrentIsolate ();
79
- System::Collections::Generic::Dictionary<System::String ^, WrappedMethod> ^methods = mMethods ;
80
- System::String^ memberName = gcnew System::String (iName.c_str ());
81
- WrappedMethod method;
82
- if (methods->TryGetValue (memberName, method))
83
- return Local<Function>::New (isolate, *(method.Pointer ));
84
- else
85
- {
86
- System::Object^ self = mObjectHandle .Target ;
87
- System::Type^ type = self->GetType ();
88
- System::String^ memberName = gcnew System::String (iName.c_str ());
89
- cli::array<System::Object^>^ objectInfo = gcnew cli::array<System::Object^>(2 );
90
- objectInfo->SetValue (self,0 );
91
- objectInfo->SetValue (memberName,1 );
92
-
93
- // Verification if it a method
94
- cli::array<MemberInfo^>^ members = type->GetMember (memberName);
95
- if (members->Length > 0 && members[0 ]->MemberType == MemberTypes::Method)
96
- {
97
- JavascriptContext^ context = JavascriptContext::GetCurrent ();
98
- Local<External> external = External::New (isolate, context->WrapObject (objectInfo));
99
- Local<FunctionTemplate> functionTemplate = FunctionTemplate::New (isolate, JavascriptInterop::Invoker, external);
100
- Local<Function> function = functionTemplate->GetFunction (isolate->GetCurrentContext ()).ToLocalChecked ();
102
+ auto context = JavascriptContext::GetCurrent ();
103
+ auto isolate = JavascriptContext::GetCurrentIsolate ();
101
104
102
- Persistent<Function> *function_ptr = new Persistent<Function>(isolate, function );
103
- WrappedMethod wrapped (function_ptr );
104
- methods[memberName] = wrapped ;
105
+ auto type = mObjectHandle . Target -> GetType ( );
106
+ auto memberName = gcnew System::String (iName. c_str () );
107
+ auto uniqueMethodName = type-> AssemblyQualifiedName + L" . " + memberName ;
105
108
106
- return function;
107
- }
108
- }
109
+ if (context->mMethods ->ContainsKey (uniqueMethodName))
110
+ return Local<Function>::New (isolate, *context->mMethods [uniqueMethodName].Pointer );
111
+
112
+ // Verification if it a method
113
+ auto members = type->GetMember (memberName);
114
+ if (members->Length > 0 && members[0 ]->MemberType == MemberTypes::Method)
115
+ {
116
+ auto functionTemplate = FunctionTemplate::New (isolate, JavascriptInterop::Invoker, JavascriptInterop::ConvertToV8 (memberName));
117
+ auto function = functionTemplate->GetFunction (isolate->GetCurrentContext ()).ToLocalChecked ();
118
+ context->mMethods [uniqueMethodName] = WrappedMethod (new Persistent<Function>(isolate, function));
119
+ return function;
120
+ }
109
121
110
122
// Wasn't an method
111
- return Local<Function>();
123
+ return Local<Function>();
112
124
}
113
125
114
126
// //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -333,37 +345,49 @@ JavascriptExternal::SetProperty(uint32_t iIndex, Local<Value> iValue)
333
345
334
346
Local<Function> JavascriptExternal::GetIterator ()
335
347
{
348
+ auto context = JavascriptContext::GetCurrent ();
349
+ auto type = mObjectHandle .Target ->GetType ();
350
+ auto uniqueMethodName = type->AssemblyQualifiedName + L" .$$Iterator" ;
351
+
336
352
auto isolate = JavascriptContext::GetCurrentIsolate ();
337
- if (mIterator != nullptr )
338
- return Local<Function>::New (isolate, *mIterator );
353
+ if (context-> mMethods -> ContainsKey (uniqueMethodName) )
354
+ return Local<Function>::New (isolate, *context-> mMethods [uniqueMethodName]. Pointer );
339
355
340
- auto self = mObjectHandle .Target ;
341
- auto context = JavascriptContext::GetCurrent ();
342
- auto external = External::New (isolate, context->WrapObject (self));
343
- auto functionTemplate = FunctionTemplate::New (isolate, JavascriptExternal::IteratorCallback, external);
356
+ auto functionTemplate = FunctionTemplate::New (isolate, JavascriptExternal::IteratorCallback);
344
357
auto function = functionTemplate->GetFunction (isolate->GetCurrentContext ()).ToLocalChecked ();
345
- mIterator = std::make_unique< Persistent<Function>> (isolate, function);
358
+ context-> mMethods [uniqueMethodName] = WrappedMethod ( new Persistent<Function>(isolate, function) );
346
359
return function;
347
360
}
348
361
349
362
void JavascriptExternal::IteratorCallback (const v8::FunctionCallbackInfo<Value>& iArgs)
350
363
{
351
364
auto isolate = iArgs.GetIsolate ();
352
- auto enumerable = (System::Collections::IEnumerable^) JavascriptInterop::UnwrapObject (Local<External>::Cast (iArgs.Data ()));
353
- auto enumerator = enumerable->GetEnumerator ();
354
- auto context = JavascriptContext::GetCurrent ();
355
- auto external = External::New (isolate, context->WrapObject (enumerator));
356
365
357
366
auto iterator = ObjectTemplate::New (isolate);
358
- auto functionTemplate = FunctionTemplate::New (isolate, JavascriptExternal::IteratorNextCallback, external);
367
+ iterator->SetInternalFieldCount (1 );
368
+ auto functionTemplate = FunctionTemplate::New (isolate, JavascriptExternal::IteratorNextCallback);
359
369
iterator->Set (String::NewFromUtf8 (isolate, " next" ).ToLocalChecked (), functionTemplate);
360
- iArgs.GetReturnValue ().Set (iterator->NewInstance (isolate->GetCurrentContext ()).ToLocalChecked ());
370
+ auto iteratorInstance = iterator->NewInstance (isolate->GetCurrentContext ()).ToLocalChecked ();
371
+
372
+ auto internalField = Local<External>::Cast (iArgs.Holder ()->GetInternalField (0 ));
373
+ auto external = (JavascriptExternal*)internalField->Value ();
374
+ auto enumerable = (System::Collections::IEnumerable^)external->GetObject ();
375
+ auto enumerator = enumerable->GetEnumerator ();
376
+
377
+ auto context = JavascriptContext::GetCurrent ();
378
+ auto enumeratorExternal = context->WrapObject (enumerator);
379
+ enumeratorExternal->Wrap (isolate, iteratorInstance);
380
+
381
+ iArgs.GetReturnValue ().Set (iteratorInstance);
361
382
}
362
383
363
384
void JavascriptExternal::IteratorNextCallback (const v8::FunctionCallbackInfo<Value>& iArgs)
364
385
{
365
386
auto isolate = iArgs.GetIsolate ();
366
- auto enumerator = (System::Collections::IEnumerator^) JavascriptInterop::UnwrapObject (Local<External>::Cast (iArgs.Data ()));
387
+
388
+ auto internalField = Local<External>::Cast (iArgs.Holder ()->GetInternalField (0 ));
389
+ auto external = (JavascriptExternal*)internalField->Value ();
390
+ auto enumerator = (System::Collections::IEnumerator^) external->GetObject ();
367
391
auto done = !enumerator->MoveNext ();
368
392
369
393
auto resultTemplate = ObjectTemplate::New (isolate);
@@ -378,4 +402,4 @@ void JavascriptExternal::IteratorNextCallback(const v8::FunctionCallbackInfo<Val
378
402
379
403
} } // namespace Noesis::Javascript
380
404
381
- // //////////////////////////////////////////////////////////////////////////////////////////////////
405
+ // //////////////////////////////////////////////////////////////////////////////////////////////////
0 commit comments