1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fxjs/cfxjse_class.h"
8
9 #include <memory>
10
11 #include "fxjs/cfxjse_context.h"
12 #include "fxjs/cfxjse_value.h"
13
14 namespace {
15
V8FunctionCallback_Wrapper(const v8::FunctionCallbackInfo<v8::Value> & info)16 void V8FunctionCallback_Wrapper(
17 const v8::FunctionCallbackInfo<v8::Value>& info) {
18 const FXJSE_FUNCTION_DESCRIPTOR* lpFunctionInfo =
19 static_cast<FXJSE_FUNCTION_DESCRIPTOR*>(
20 info.Data().As<v8::External>()->Value());
21 if (!lpFunctionInfo)
22 return;
23
24 CFX_ByteStringC szFunctionName(lpFunctionInfo->name);
25 std::unique_ptr<CFXJSE_Value> lpThisValue(
26 new CFXJSE_Value(info.GetIsolate()));
27 lpThisValue->ForceSetValue(info.This());
28 std::unique_ptr<CFXJSE_Value> lpRetValue(new CFXJSE_Value(info.GetIsolate()));
29 CFXJSE_Arguments impl(&info, lpRetValue.get());
30 lpFunctionInfo->callbackProc(lpThisValue.get(), szFunctionName, impl);
31 if (!lpRetValue->DirectGetValue().IsEmpty())
32 info.GetReturnValue().Set(lpRetValue->DirectGetValue());
33 }
34
V8ClassGlobalConstructorCallback_Wrapper(const v8::FunctionCallbackInfo<v8::Value> & info)35 void V8ClassGlobalConstructorCallback_Wrapper(
36 const v8::FunctionCallbackInfo<v8::Value>& info) {
37 const FXJSE_CLASS_DESCRIPTOR* lpClassDefinition =
38 static_cast<FXJSE_CLASS_DESCRIPTOR*>(
39 info.Data().As<v8::External>()->Value());
40 if (!lpClassDefinition)
41 return;
42
43 CFX_ByteStringC szFunctionName(lpClassDefinition->name);
44 std::unique_ptr<CFXJSE_Value> lpThisValue(
45 new CFXJSE_Value(info.GetIsolate()));
46 lpThisValue->ForceSetValue(info.This());
47 std::unique_ptr<CFXJSE_Value> lpRetValue(new CFXJSE_Value(info.GetIsolate()));
48 CFXJSE_Arguments impl(&info, lpRetValue.get());
49 lpClassDefinition->constructor(lpThisValue.get(), szFunctionName, impl);
50 if (!lpRetValue->DirectGetValue().IsEmpty())
51 info.GetReturnValue().Set(lpRetValue->DirectGetValue());
52 }
53
V8GetterCallback_Wrapper(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)54 void V8GetterCallback_Wrapper(v8::Local<v8::String> property,
55 const v8::PropertyCallbackInfo<v8::Value>& info) {
56 const FXJSE_PROPERTY_DESCRIPTOR* lpPropertyInfo =
57 static_cast<FXJSE_PROPERTY_DESCRIPTOR*>(
58 info.Data().As<v8::External>()->Value());
59 if (!lpPropertyInfo)
60 return;
61
62 CFX_ByteStringC szPropertyName(lpPropertyInfo->name);
63 std::unique_ptr<CFXJSE_Value> lpThisValue(
64 new CFXJSE_Value(info.GetIsolate()));
65 std::unique_ptr<CFXJSE_Value> lpPropValue(
66 new CFXJSE_Value(info.GetIsolate()));
67 lpThisValue->ForceSetValue(info.This());
68 lpPropertyInfo->getProc(lpThisValue.get(), szPropertyName, lpPropValue.get());
69 info.GetReturnValue().Set(lpPropValue->DirectGetValue());
70 }
71
V8SetterCallback_Wrapper(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)72 void V8SetterCallback_Wrapper(v8::Local<v8::String> property,
73 v8::Local<v8::Value> value,
74 const v8::PropertyCallbackInfo<void>& info) {
75 const FXJSE_PROPERTY_DESCRIPTOR* lpPropertyInfo =
76 static_cast<FXJSE_PROPERTY_DESCRIPTOR*>(
77 info.Data().As<v8::External>()->Value());
78 if (!lpPropertyInfo)
79 return;
80
81 CFX_ByteStringC szPropertyName(lpPropertyInfo->name);
82 std::unique_ptr<CFXJSE_Value> lpThisValue(
83 new CFXJSE_Value(info.GetIsolate()));
84 std::unique_ptr<CFXJSE_Value> lpPropValue(
85 new CFXJSE_Value(info.GetIsolate()));
86 lpThisValue->ForceSetValue(info.This());
87 lpPropValue->ForceSetValue(value);
88 lpPropertyInfo->setProc(lpThisValue.get(), szPropertyName, lpPropValue.get());
89 }
90
V8ConstructorCallback_Wrapper(const v8::FunctionCallbackInfo<v8::Value> & info)91 void V8ConstructorCallback_Wrapper(
92 const v8::FunctionCallbackInfo<v8::Value>& info) {
93 if (!info.IsConstructCall())
94 return;
95
96 const FXJSE_CLASS_DESCRIPTOR* lpClassDefinition =
97 static_cast<FXJSE_CLASS_DESCRIPTOR*>(
98 info.Data().As<v8::External>()->Value());
99 if (!lpClassDefinition)
100 return;
101
102 ASSERT(info.This()->InternalFieldCount());
103 info.This()->SetAlignedPointerInInternalField(0, nullptr);
104 }
105
Context_GlobalObjToString(const v8::FunctionCallbackInfo<v8::Value> & info)106 void Context_GlobalObjToString(
107 const v8::FunctionCallbackInfo<v8::Value>& info) {
108 const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
109 info.Data().As<v8::External>()->Value());
110 if (!lpClass)
111 return;
112
113 if (info.This() == info.Holder() && lpClass->name) {
114 CFX_ByteString szStringVal;
115 szStringVal.Format("[object %s]", lpClass->name);
116 info.GetReturnValue().Set(v8::String::NewFromUtf8(
117 info.GetIsolate(), szStringVal.c_str(), v8::String::kNormalString,
118 szStringVal.GetLength()));
119 return;
120 }
121 v8::Local<v8::String> local_str =
122 info.This()
123 ->ObjectProtoToString(info.GetIsolate()->GetCurrentContext())
124 .FromMaybe(v8::Local<v8::String>());
125 info.GetReturnValue().Set(local_str);
126 }
127
DynPropGetterAdapter_MethodCallback(const v8::FunctionCallbackInfo<v8::Value> & info)128 void DynPropGetterAdapter_MethodCallback(
129 const v8::FunctionCallbackInfo<v8::Value>& info) {
130 v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>();
131 FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
132 hCallBackInfo->GetAlignedPointerFromInternalField(0));
133 v8::Local<v8::String> hPropName =
134 hCallBackInfo->GetInternalField(1).As<v8::String>();
135 ASSERT(lpClass && !hPropName.IsEmpty());
136 v8::String::Utf8Value szPropName(hPropName);
137 CFX_ByteStringC szFxPropName = *szPropName;
138 std::unique_ptr<CFXJSE_Value> lpThisValue(
139 new CFXJSE_Value(info.GetIsolate()));
140 lpThisValue->ForceSetValue(info.This());
141 std::unique_ptr<CFXJSE_Value> lpRetValue(new CFXJSE_Value(info.GetIsolate()));
142 CFXJSE_Arguments impl(&info, lpRetValue.get());
143 lpClass->dynMethodCall(lpThisValue.get(), szFxPropName, impl);
144 if (!lpRetValue->DirectGetValue().IsEmpty())
145 info.GetReturnValue().Set(lpRetValue->DirectGetValue());
146 }
147
DynPropGetterAdapter(const FXJSE_CLASS_DESCRIPTOR * lpClass,CFXJSE_Value * pObject,const CFX_ByteStringC & szPropName,CFXJSE_Value * pValue)148 void DynPropGetterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass,
149 CFXJSE_Value* pObject,
150 const CFX_ByteStringC& szPropName,
151 CFXJSE_Value* pValue) {
152 ASSERT(lpClass);
153 int32_t nPropType =
154 lpClass->dynPropTypeGetter == nullptr
155 ? FXJSE_ClassPropType_Property
156 : lpClass->dynPropTypeGetter(pObject, szPropName, false);
157 if (nPropType == FXJSE_ClassPropType_Property) {
158 if (lpClass->dynPropGetter)
159 lpClass->dynPropGetter(pObject, szPropName, pValue);
160 } else if (nPropType == FXJSE_ClassPropType_Method) {
161 if (lpClass->dynMethodCall && pValue) {
162 v8::Isolate* pIsolate = pValue->GetIsolate();
163 v8::HandleScope hscope(pIsolate);
164 v8::Local<v8::ObjectTemplate> hCallBackInfoTemplate =
165 v8::ObjectTemplate::New(pIsolate);
166 hCallBackInfoTemplate->SetInternalFieldCount(2);
167 v8::Local<v8::Object> hCallBackInfo =
168 hCallBackInfoTemplate->NewInstance();
169 hCallBackInfo->SetAlignedPointerInInternalField(
170 0, const_cast<FXJSE_CLASS_DESCRIPTOR*>(lpClass));
171 hCallBackInfo->SetInternalField(
172 1, v8::String::NewFromUtf8(
173 pIsolate, reinterpret_cast<const char*>(szPropName.raw_str()),
174 v8::String::kNormalString, szPropName.GetLength()));
175 pValue->ForceSetValue(
176 v8::Function::New(pValue->GetIsolate()->GetCurrentContext(),
177 DynPropGetterAdapter_MethodCallback, hCallBackInfo,
178 0, v8::ConstructorBehavior::kThrow)
179 .ToLocalChecked());
180 }
181 }
182 }
183
DynPropSetterAdapter(const FXJSE_CLASS_DESCRIPTOR * lpClass,CFXJSE_Value * pObject,const CFX_ByteStringC & szPropName,CFXJSE_Value * pValue)184 void DynPropSetterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass,
185 CFXJSE_Value* pObject,
186 const CFX_ByteStringC& szPropName,
187 CFXJSE_Value* pValue) {
188 ASSERT(lpClass);
189 int32_t nPropType =
190 lpClass->dynPropTypeGetter == nullptr
191 ? FXJSE_ClassPropType_Property
192 : lpClass->dynPropTypeGetter(pObject, szPropName, false);
193 if (nPropType != FXJSE_ClassPropType_Method) {
194 if (lpClass->dynPropSetter)
195 lpClass->dynPropSetter(pObject, szPropName, pValue);
196 }
197 }
198
DynPropQueryAdapter(const FXJSE_CLASS_DESCRIPTOR * lpClass,CFXJSE_Value * pObject,const CFX_ByteStringC & szPropName)199 bool DynPropQueryAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass,
200 CFXJSE_Value* pObject,
201 const CFX_ByteStringC& szPropName) {
202 ASSERT(lpClass);
203 int32_t nPropType =
204 lpClass->dynPropTypeGetter == nullptr
205 ? FXJSE_ClassPropType_Property
206 : lpClass->dynPropTypeGetter(pObject, szPropName, true);
207 return nPropType != FXJSE_ClassPropType_None;
208 }
209
DynPropDeleterAdapter(const FXJSE_CLASS_DESCRIPTOR * lpClass,CFXJSE_Value * pObject,const CFX_ByteStringC & szPropName)210 bool DynPropDeleterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass,
211 CFXJSE_Value* pObject,
212 const CFX_ByteStringC& szPropName) {
213 ASSERT(lpClass);
214 int32_t nPropType =
215 lpClass->dynPropTypeGetter == nullptr
216 ? FXJSE_ClassPropType_Property
217 : lpClass->dynPropTypeGetter(pObject, szPropName, false);
218 if (nPropType != FXJSE_ClassPropType_Method) {
219 if (lpClass->dynPropDeleter)
220 return lpClass->dynPropDeleter(pObject, szPropName);
221 return nPropType != FXJSE_ClassPropType_Property;
222 }
223 return false;
224 }
225
NamedPropertyQueryCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Integer> & info)226 void NamedPropertyQueryCallback(
227 v8::Local<v8::Name> property,
228 const v8::PropertyCallbackInfo<v8::Integer>& info) {
229 v8::Local<v8::Object> thisObject = info.This();
230 const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
231 info.Data().As<v8::External>()->Value());
232 v8::Isolate* pIsolate = info.GetIsolate();
233 v8::HandleScope scope(pIsolate);
234 v8::String::Utf8Value szPropName(property);
235 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
236 std::unique_ptr<CFXJSE_Value> lpThisValue(
237 new CFXJSE_Value(info.GetIsolate()));
238 lpThisValue->ForceSetValue(thisObject);
239 if (DynPropQueryAdapter(lpClass, lpThisValue.get(), szFxPropName)) {
240 info.GetReturnValue().Set(v8::DontDelete);
241 return;
242 }
243 const int32_t iV8Absent = 64;
244 info.GetReturnValue().Set(iV8Absent);
245 }
246
NamedPropertyDeleterCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Boolean> & info)247 void NamedPropertyDeleterCallback(
248 v8::Local<v8::Name> property,
249 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
250 v8::Local<v8::Object> thisObject = info.This();
251 const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
252 info.Data().As<v8::External>()->Value());
253 v8::Isolate* pIsolate = info.GetIsolate();
254 v8::HandleScope scope(pIsolate);
255 v8::String::Utf8Value szPropName(property);
256 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
257 std::unique_ptr<CFXJSE_Value> lpThisValue(
258 new CFXJSE_Value(info.GetIsolate()));
259 lpThisValue->ForceSetValue(thisObject);
260 info.GetReturnValue().Set(
261 !!DynPropDeleterAdapter(lpClass, lpThisValue.get(), szFxPropName));
262 }
263
NamedPropertyGetterCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info)264 void NamedPropertyGetterCallback(
265 v8::Local<v8::Name> property,
266 const v8::PropertyCallbackInfo<v8::Value>& info) {
267 v8::Local<v8::Object> thisObject = info.This();
268 const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
269 info.Data().As<v8::External>()->Value());
270 v8::String::Utf8Value szPropName(property);
271 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
272 std::unique_ptr<CFXJSE_Value> lpThisValue(
273 new CFXJSE_Value(info.GetIsolate()));
274 lpThisValue->ForceSetValue(thisObject);
275 std::unique_ptr<CFXJSE_Value> lpNewValue(new CFXJSE_Value(info.GetIsolate()));
276 DynPropGetterAdapter(lpClass, lpThisValue.get(), szFxPropName,
277 lpNewValue.get());
278 info.GetReturnValue().Set(lpNewValue->DirectGetValue());
279 }
280
NamedPropertySetterCallback(v8::Local<v8::Name> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value> & info)281 void NamedPropertySetterCallback(
282 v8::Local<v8::Name> property,
283 v8::Local<v8::Value> value,
284 const v8::PropertyCallbackInfo<v8::Value>& info) {
285 v8::Local<v8::Object> thisObject = info.This();
286 const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
287 info.Data().As<v8::External>()->Value());
288 v8::String::Utf8Value szPropName(property);
289 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
290 std::unique_ptr<CFXJSE_Value> lpThisValue(
291 new CFXJSE_Value(info.GetIsolate()));
292 lpThisValue->ForceSetValue(thisObject);
293
294 std::unique_ptr<CFXJSE_Value> lpNewValue(new CFXJSE_Value(info.GetIsolate()));
295 lpNewValue->ForceSetValue(value);
296 DynPropSetterAdapter(lpClass, lpThisValue.get(), szFxPropName,
297 lpNewValue.get());
298 info.GetReturnValue().Set(value);
299 }
300
NamedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array> & info)301 void NamedPropertyEnumeratorCallback(
302 const v8::PropertyCallbackInfo<v8::Array>& info) {
303 const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast<FXJSE_CLASS_DESCRIPTOR*>(
304 info.Data().As<v8::External>()->Value());
305 v8::Isolate* pIsolate = info.GetIsolate();
306 v8::Local<v8::Array> newArray = v8::Array::New(pIsolate, lpClass->propNum);
307 for (int i = 0; i < lpClass->propNum; i++) {
308 newArray->Set(
309 i, v8::String::NewFromUtf8(pIsolate, lpClass->properties[i].name));
310 }
311 info.GetReturnValue().Set(newArray);
312 }
313
314 } // namespace
315
316 // static
Create(CFXJSE_Context * lpContext,const FXJSE_CLASS_DESCRIPTOR * lpClassDefinition,bool bIsJSGlobal)317 CFXJSE_Class* CFXJSE_Class::Create(
318 CFXJSE_Context* lpContext,
319 const FXJSE_CLASS_DESCRIPTOR* lpClassDefinition,
320 bool bIsJSGlobal) {
321 if (!lpContext || !lpClassDefinition)
322 return nullptr;
323
324 CFXJSE_Class* pClass =
325 GetClassFromContext(lpContext, lpClassDefinition->name);
326 if (pClass)
327 return pClass;
328
329 v8::Isolate* pIsolate = lpContext->m_pIsolate;
330 pClass = new CFXJSE_Class(lpContext);
331 pClass->m_szClassName = lpClassDefinition->name;
332 pClass->m_lpClassDefinition = lpClassDefinition;
333 CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate);
334 v8::Local<v8::FunctionTemplate> hFunctionTemplate = v8::FunctionTemplate::New(
335 pIsolate, bIsJSGlobal ? 0 : V8ConstructorCallback_Wrapper,
336 v8::External::New(
337 pIsolate, const_cast<FXJSE_CLASS_DESCRIPTOR*>(lpClassDefinition)));
338 hFunctionTemplate->SetClassName(
339 v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name));
340 hFunctionTemplate->InstanceTemplate()->SetInternalFieldCount(1);
341 v8::Local<v8::ObjectTemplate> hObjectTemplate =
342 hFunctionTemplate->InstanceTemplate();
343 SetUpNamedPropHandler(pIsolate, hObjectTemplate, lpClassDefinition);
344
345 if (lpClassDefinition->propNum) {
346 for (int32_t i = 0; i < lpClassDefinition->propNum; i++) {
347 hObjectTemplate->SetNativeDataProperty(
348 v8::String::NewFromUtf8(pIsolate,
349 lpClassDefinition->properties[i].name),
350 lpClassDefinition->properties[i].getProc ? V8GetterCallback_Wrapper
351 : nullptr,
352 lpClassDefinition->properties[i].setProc ? V8SetterCallback_Wrapper
353 : nullptr,
354 v8::External::New(pIsolate, const_cast<FXJSE_PROPERTY_DESCRIPTOR*>(
355 lpClassDefinition->properties + i)),
356 static_cast<v8::PropertyAttribute>(v8::DontDelete));
357 }
358 }
359 if (lpClassDefinition->methNum) {
360 for (int32_t i = 0; i < lpClassDefinition->methNum; i++) {
361 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(
362 pIsolate, V8FunctionCallback_Wrapper,
363 v8::External::New(pIsolate, const_cast<FXJSE_FUNCTION_DESCRIPTOR*>(
364 lpClassDefinition->methods + i)));
365 fun->RemovePrototype();
366 hObjectTemplate->Set(
367 v8::String::NewFromUtf8(pIsolate, lpClassDefinition->methods[i].name),
368 fun,
369 static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
370 }
371 }
372 if (lpClassDefinition->constructor) {
373 if (bIsJSGlobal) {
374 hObjectTemplate->Set(
375 v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name),
376 v8::FunctionTemplate::New(
377 pIsolate, V8ClassGlobalConstructorCallback_Wrapper,
378 v8::External::New(pIsolate, const_cast<FXJSE_CLASS_DESCRIPTOR*>(
379 lpClassDefinition))),
380 static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
381 } else {
382 v8::Local<v8::Context> hLocalContext =
383 v8::Local<v8::Context>::New(pIsolate, lpContext->m_hContext);
384 FXJSE_GetGlobalObjectFromContext(hLocalContext)
385 ->Set(v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name),
386 v8::Function::New(
387 pIsolate, V8ClassGlobalConstructorCallback_Wrapper,
388 v8::External::New(pIsolate,
389 const_cast<FXJSE_CLASS_DESCRIPTOR*>(
390 lpClassDefinition))));
391 }
392 }
393 if (bIsJSGlobal) {
394 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(
395 pIsolate, Context_GlobalObjToString,
396 v8::External::New(
397 pIsolate, const_cast<FXJSE_CLASS_DESCRIPTOR*>(lpClassDefinition)));
398 fun->RemovePrototype();
399 hObjectTemplate->Set(v8::String::NewFromUtf8(pIsolate, "toString"), fun);
400 }
401 pClass->m_hTemplate.Reset(lpContext->m_pIsolate, hFunctionTemplate);
402 lpContext->m_rgClasses.push_back(std::unique_ptr<CFXJSE_Class>(pClass));
403 return pClass;
404 }
405
406 // static
GetClassFromContext(CFXJSE_Context * pContext,const CFX_ByteStringC & szName)407 CFXJSE_Class* CFXJSE_Class::GetClassFromContext(CFXJSE_Context* pContext,
408 const CFX_ByteStringC& szName) {
409 for (const auto& pClass : pContext->m_rgClasses) {
410 if (pClass->m_szClassName == szName)
411 return pClass.get();
412 }
413 return nullptr;
414 }
415
416 // static
SetUpNamedPropHandler(v8::Isolate * pIsolate,v8::Local<v8::ObjectTemplate> & hObjectTemplate,const FXJSE_CLASS_DESCRIPTOR * lpClassDefinition)417 void CFXJSE_Class::SetUpNamedPropHandler(
418 v8::Isolate* pIsolate,
419 v8::Local<v8::ObjectTemplate>& hObjectTemplate,
420 const FXJSE_CLASS_DESCRIPTOR* lpClassDefinition) {
421 v8::NamedPropertyHandlerConfiguration configuration(
422 lpClassDefinition->dynPropGetter ? NamedPropertyGetterCallback : 0,
423 lpClassDefinition->dynPropSetter ? NamedPropertySetterCallback : 0,
424 lpClassDefinition->dynPropTypeGetter ? NamedPropertyQueryCallback : 0,
425 lpClassDefinition->dynPropDeleter ? NamedPropertyDeleterCallback : 0,
426 NamedPropertyEnumeratorCallback,
427 v8::External::New(pIsolate,
428 const_cast<FXJSE_CLASS_DESCRIPTOR*>(lpClassDefinition)),
429 v8::PropertyHandlerFlags::kNonMasking);
430 hObjectTemplate->SetHandler(configuration);
431 }
432
CFXJSE_Class(CFXJSE_Context * lpContext)433 CFXJSE_Class::CFXJSE_Class(CFXJSE_Context* lpContext)
434 : m_lpClassDefinition(nullptr), m_pContext(lpContext) {}
435
~CFXJSE_Class()436 CFXJSE_Class::~CFXJSE_Class() {}
437