1// Copyright 2014 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 "xfa/src/foxitlib.h"
8#include "fxv8.h"
9#include "class.h"
10#include "value.h"
11static void FXJSE_DynPropGetterAdapter_MethodCallback(
12    const v8::FunctionCallbackInfo<v8::Value>& info) {
13  v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>();
14  FXJSE_CLASS* lpClass = static_cast<FXJSE_CLASS*>(
15      hCallBackInfo->GetAlignedPointerFromInternalField(0));
16  v8::Local<v8::String> hPropName =
17      hCallBackInfo->GetInternalField(1).As<v8::String>();
18  ASSERT(lpClass && !hPropName.IsEmpty());
19  v8::String::Utf8Value szPropName(hPropName);
20  CFX_ByteStringC szFxPropName = *szPropName;
21  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
22  lpThisValue->ForceSetValue(info.This());
23  CFXJSE_Value* lpRetValue = CFXJSE_Value::Create(info.GetIsolate());
24  CFXJSE_ArgumentsImpl impl = {&info, lpRetValue};
25  lpClass->dynMethodCall(reinterpret_cast<FXJSE_HOBJECT>(lpThisValue),
26                         szFxPropName,
27                         reinterpret_cast<CFXJSE_Arguments&>(impl));
28  if (!lpRetValue->DirectGetValue().IsEmpty()) {
29    info.GetReturnValue().Set(lpRetValue->DirectGetValue());
30  }
31  delete lpRetValue;
32  lpRetValue = nullptr;
33  delete lpThisValue;
34  lpThisValue = nullptr;
35}
36static void FXJSE_DynPropGetterAdapter(const FXJSE_CLASS* lpClass,
37                                       FXJSE_HOBJECT hObject,
38                                       const CFX_ByteStringC& szPropName,
39                                       FXJSE_HVALUE hValue) {
40  ASSERT(lpClass);
41  int32_t nPropType =
42      lpClass->dynPropTypeGetter == nullptr
43          ? FXJSE_ClassPropType_Property
44          : lpClass->dynPropTypeGetter(hObject, szPropName, FALSE);
45  if (nPropType == FXJSE_ClassPropType_Property) {
46    if (lpClass->dynPropGetter) {
47      lpClass->dynPropGetter(hObject, szPropName, hValue);
48    }
49  } else if (nPropType == FXJSE_ClassPropType_Method) {
50    if (lpClass->dynMethodCall && hValue) {
51      CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
52      v8::Isolate* pIsolate = lpValue->GetIsolate();
53      v8::HandleScope hscope(pIsolate);
54      v8::Local<v8::ObjectTemplate> hCallBackInfoTemplate =
55          v8::ObjectTemplate::New();
56      hCallBackInfoTemplate->SetInternalFieldCount(2);
57      v8::Local<v8::Object> hCallBackInfo =
58          hCallBackInfoTemplate->NewInstance();
59      hCallBackInfo->SetAlignedPointerInInternalField(
60          0, const_cast<FXJSE_CLASS*>(lpClass));
61      hCallBackInfo->SetInternalField(
62          1, v8::String::NewFromUtf8(
63                 pIsolate, reinterpret_cast<const char*>(szPropName.GetPtr()),
64                 v8::String::kNormalString, szPropName.GetLength()));
65      lpValue->ForceSetValue(v8::Function::New(
66          lpValue->GetIsolate(), FXJSE_DynPropGetterAdapter_MethodCallback,
67          hCallBackInfo));
68    }
69  }
70}
71static void FXJSE_DynPropSetterAdapter(const FXJSE_CLASS* lpClass,
72                                       FXJSE_HOBJECT hObject,
73                                       const CFX_ByteStringC& szPropName,
74                                       FXJSE_HVALUE hValue) {
75  ASSERT(lpClass);
76  int32_t nPropType =
77      lpClass->dynPropTypeGetter == nullptr
78          ? FXJSE_ClassPropType_Property
79          : lpClass->dynPropTypeGetter(hObject, szPropName, FALSE);
80  if (nPropType != FXJSE_ClassPropType_Method) {
81    if (lpClass->dynPropSetter) {
82      lpClass->dynPropSetter(hObject, szPropName, hValue);
83    }
84  }
85}
86static FX_BOOL FXJSE_DynPropQueryAdapter(const FXJSE_CLASS* lpClass,
87                                         FXJSE_HOBJECT hObject,
88                                         const CFX_ByteStringC& szPropName) {
89  ASSERT(lpClass);
90  int32_t nPropType =
91      lpClass->dynPropTypeGetter == nullptr
92          ? FXJSE_ClassPropType_Property
93          : lpClass->dynPropTypeGetter(hObject, szPropName, TRUE);
94  return nPropType != FXJSE_ClassPropType_None;
95}
96static FX_BOOL FXJSE_DynPropDeleterAdapter(const FXJSE_CLASS* lpClass,
97                                           FXJSE_HOBJECT hObject,
98                                           const CFX_ByteStringC& szPropName) {
99  ASSERT(lpClass);
100  int32_t nPropType =
101      lpClass->dynPropTypeGetter == nullptr
102          ? FXJSE_ClassPropType_Property
103          : lpClass->dynPropTypeGetter(hObject, szPropName, FALSE);
104  if (nPropType != FXJSE_ClassPropType_Method) {
105    if (lpClass->dynPropDeleter) {
106      return lpClass->dynPropDeleter(hObject, szPropName);
107    } else {
108      return nPropType == FXJSE_ClassPropType_Property ? FALSE : TRUE;
109    }
110  }
111  return FALSE;
112}
113static void FXJSE_V8ProxyCallback_getOwnPropertyDescriptor_getter(
114    const v8::FunctionCallbackInfo<v8::Value>& info) {
115  v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>();
116  FXJSE_CLASS* lpClass = static_cast<FXJSE_CLASS*>(
117      hCallBackInfo->GetAlignedPointerFromInternalField(0));
118  v8::Local<v8::String> hPropName =
119      hCallBackInfo->GetInternalField(1).As<v8::String>();
120  ASSERT(lpClass && !hPropName.IsEmpty());
121  v8::String::Utf8Value szPropName(hPropName);
122  CFX_ByteStringC szFxPropName = *szPropName;
123  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
124  CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate());
125  lpThisValue->ForceSetValue(info.This());
126  FXJSE_DynPropGetterAdapter(
127      lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName,
128      reinterpret_cast<FXJSE_HVALUE>(lpNewValue));
129  info.GetReturnValue().Set(lpNewValue->DirectGetValue());
130  delete lpThisValue;
131  lpThisValue = nullptr;
132  delete lpNewValue;
133  lpNewValue = nullptr;
134}
135static void FXJSE_V8ProxyCallback_getOwnPropertyDescriptor_setter(
136    const v8::FunctionCallbackInfo<v8::Value>& info) {
137  v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>();
138  FXJSE_CLASS* lpClass = static_cast<FXJSE_CLASS*>(
139      hCallBackInfo->GetAlignedPointerFromInternalField(0));
140  v8::Local<v8::String> hPropName =
141      hCallBackInfo->GetInternalField(1).As<v8::String>();
142  ASSERT(lpClass && !hPropName.IsEmpty());
143  v8::String::Utf8Value szPropName(hPropName);
144  CFX_ByteStringC szFxPropName = *szPropName;
145  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
146  CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate());
147  lpThisValue->ForceSetValue(info.This());
148  lpNewValue->ForceSetValue(info[0]);
149  FXJSE_DynPropSetterAdapter(
150      lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName,
151      reinterpret_cast<FXJSE_HVALUE>(lpNewValue));
152  delete lpThisValue;
153  lpThisValue = nullptr;
154  delete lpNewValue;
155  lpNewValue = nullptr;
156}
157static void FXJSE_V8ProxyCallback_getOwnPropertyDescriptor(
158    const v8::FunctionCallbackInfo<v8::Value>& info) {
159  const FXJSE_CLASS* lpClass =
160      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
161  if (!lpClass) {
162    return;
163  }
164  v8::Isolate* pIsolate = info.GetIsolate();
165  v8::HandleScope scope(pIsolate);
166  v8::Local<v8::String> hPropName = info[0]->ToString();
167  v8::String::Utf8Value szPropName(hPropName);
168  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
169  v8::Local<v8::ObjectTemplate> hCallBackInfoTemplate =
170      v8::ObjectTemplate::New();
171  hCallBackInfoTemplate->SetInternalFieldCount(2);
172  v8::Local<v8::Object> hCallBackInfo = hCallBackInfoTemplate->NewInstance();
173  hCallBackInfo->SetAlignedPointerInInternalField(
174      0, const_cast<FXJSE_CLASS*>(lpClass));
175  hCallBackInfo->SetInternalField(1, hPropName);
176  v8::Local<v8::Object> hPropDescriptor = v8::Object::New(pIsolate);
177  hPropDescriptor->ForceSet(
178      v8::String::NewFromUtf8(pIsolate, "get"),
179      v8::Function::New(pIsolate,
180                        FXJSE_V8ProxyCallback_getOwnPropertyDescriptor_getter,
181                        hCallBackInfo));
182  hPropDescriptor->ForceSet(
183      v8::String::NewFromUtf8(pIsolate, "set"),
184      v8::Function::New(pIsolate,
185                        FXJSE_V8ProxyCallback_getOwnPropertyDescriptor_setter,
186                        hCallBackInfo));
187  hPropDescriptor->ForceSet(v8::String::NewFromUtf8(pIsolate, "enumerable"),
188                            v8::Boolean::New(pIsolate, false));
189  hPropDescriptor->ForceSet(v8::String::NewFromUtf8(pIsolate, "configurable"),
190                            v8::Boolean::New(pIsolate, true));
191  info.GetReturnValue().Set(hPropDescriptor);
192}
193static void FXJSE_V8ProxyCallback_getPropertyDescriptor(
194    const v8::FunctionCallbackInfo<v8::Value>& info) {
195  v8::Isolate* pIsolate = info.GetIsolate();
196  v8::Local<v8::Object> hChainObj =
197      info.This()->GetPrototype().As<v8::Object>();
198  v8::Local<v8::Script> fnSource = v8::Script::Compile(v8::String::NewFromUtf8(
199      pIsolate,
200      "(function (o, name) { var fn, x, d; fn = "
201      "Object.getOwnPropertyDescriptor; x = o; while(x && !(d = fn(x, "
202      "name))){x = x.__proto__;} return d; })"));
203  v8::Local<v8::Function> fn = fnSource->Run().As<v8::Function>();
204  v8::Local<v8::Value> rgArgs[] = {hChainObj, info[0]};
205  v8::Local<v8::Value> hChainDescriptor = fn->Call(info.This(), 2, rgArgs);
206  if (!hChainDescriptor.IsEmpty() && hChainDescriptor->IsObject()) {
207    info.GetReturnValue().Set(hChainDescriptor);
208  } else {
209    FXJSE_V8ProxyCallback_getOwnPropertyDescriptor(info);
210  }
211}
212static void FXJSE_V8ProxyCallback_getOwnPropertyNames(
213    const v8::FunctionCallbackInfo<v8::Value>& info) {
214  v8::Isolate* pIsolate = info.GetIsolate();
215  v8::HandleScope scope(pIsolate);
216  info.GetReturnValue().Set(v8::Array::New(pIsolate));
217}
218static void FXJSE_V8ProxyCallback_getPropertyNames(
219    const v8::FunctionCallbackInfo<v8::Value>& info) {
220  v8::Local<v8::Object> hChainObj =
221      info.This()->GetPrototype().As<v8::Object>();
222  v8::Local<v8::Value> hChainPropertyNames = hChainObj->GetPropertyNames();
223  info.GetReturnValue().Set(hChainPropertyNames);
224}
225static void FXJSE_V8ProxyCallback_defineProperty(
226    const v8::FunctionCallbackInfo<v8::Value>& info) {
227  const FXJSE_CLASS* lpClass =
228      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
229  if (!lpClass) {
230    return;
231  }
232  v8::Isolate* pIsolate = info.GetIsolate();
233  v8::HandleScope scope(pIsolate);
234  v8::Local<v8::String> hPropName = info[0]->ToString();
235  v8::Local<v8::Object> hPropDescriptor = info[1]->ToObject();
236  v8::String::Utf8Value szPropName(hPropName);
237  if (!hPropDescriptor->Has(v8::String::NewFromUtf8(pIsolate, "value"))) {
238    return;
239  }
240  v8::Local<v8::Value> hPropValue =
241      hPropDescriptor->Get(v8::String::NewFromUtf8(pIsolate, "value"));
242  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
243  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
244  CFXJSE_Value* lpPropValue = CFXJSE_Value::Create(info.GetIsolate());
245  lpThisValue->ForceSetValue(info.This());
246  lpPropValue->ForceSetValue(hPropValue);
247  FXJSE_DynPropSetterAdapter(
248      lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName,
249      reinterpret_cast<FXJSE_HVALUE>(lpPropValue));
250  delete lpThisValue;
251  lpThisValue = nullptr;
252  delete lpPropValue;
253  lpPropValue = nullptr;
254}
255static void FXJSE_V8ProxyCallback_delete(
256    const v8::FunctionCallbackInfo<v8::Value>& info) {
257  info.GetReturnValue().Set(true);
258  const FXJSE_CLASS* lpClass =
259      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
260  if (!lpClass) {
261    return;
262  }
263  v8::Isolate* pIsolate = info.GetIsolate();
264  v8::HandleScope scope(pIsolate);
265  v8::Local<v8::String> hPropName = info[0]->ToString();
266  v8::String::Utf8Value szPropName(hPropName);
267  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
268  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
269  lpThisValue->ForceSetValue(info.This());
270  info.GetReturnValue().Set(
271      FXJSE_DynPropDeleterAdapter(
272          lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName)
273          ? true
274          : false);
275  delete lpThisValue;
276  lpThisValue = nullptr;
277}
278static void FXJSE_V8ProxyCallback_fix(
279    const v8::FunctionCallbackInfo<v8::Value>& info) {
280  info.GetReturnValue().SetUndefined();
281}
282static void FXJSE_V8_GenericNamedPropertyQueryCallback(
283    v8::Local<v8::Name> property,
284    const v8::PropertyCallbackInfo<v8::Integer>& info) {
285  v8::Local<v8::Object> thisObject = info.This();
286  const FXJSE_CLASS* lpClass =
287      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
288  v8::Isolate* pIsolate = info.GetIsolate();
289  v8::HandleScope scope(pIsolate);
290  v8::String::Utf8Value szPropName(property);
291  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
292  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
293  lpThisValue->ForceSetValue(thisObject);
294  if (FXJSE_DynPropQueryAdapter(lpClass,
295                                reinterpret_cast<FXJSE_HOBJECT>(lpThisValue),
296                                szFxPropName)) {
297    info.GetReturnValue().Set(v8::DontDelete);
298  } else {
299    const int32_t iV8Absent = 64;
300    info.GetReturnValue().Set(iV8Absent);
301  }
302  delete lpThisValue;
303  lpThisValue = nullptr;
304}
305static void FXJSE_V8_GenericNamedPropertyDeleterCallback(
306    v8::Local<v8::Name> property,
307    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
308  v8::Local<v8::Object> thisObject = info.This();
309  const FXJSE_CLASS* lpClass =
310      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
311  v8::Isolate* pIsolate = info.GetIsolate();
312  v8::HandleScope scope(pIsolate);
313  v8::String::Utf8Value szPropName(property);
314  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
315  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
316  lpThisValue->ForceSetValue(thisObject);
317  info.GetReturnValue().Set(
318      FXJSE_DynPropDeleterAdapter(
319          lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName)
320          ? true
321          : false);
322  delete lpThisValue;
323  lpThisValue = nullptr;
324}
325static void FXJSE_V8_GenericNamedPropertyGetterCallback(
326    v8::Local<v8::Name> property,
327    const v8::PropertyCallbackInfo<v8::Value>& info) {
328  v8::Local<v8::Object> thisObject = info.This();
329  const FXJSE_CLASS* lpClass =
330      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
331  v8::String::Utf8Value szPropName(property);
332  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
333  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
334  lpThisValue->ForceSetValue(thisObject);
335  CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate());
336  FXJSE_DynPropGetterAdapter(
337      lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName,
338      reinterpret_cast<FXJSE_HVALUE>(lpNewValue));
339  info.GetReturnValue().Set(lpNewValue->DirectGetValue());
340  delete lpThisValue;
341  lpThisValue = nullptr;
342}
343static void FXJSE_V8_GenericNamedPropertySetterCallback(
344    v8::Local<v8::Name> property,
345    v8::Local<v8::Value> value,
346    const v8::PropertyCallbackInfo<v8::Value>& info) {
347  v8::Local<v8::Object> thisObject = info.This();
348  const FXJSE_CLASS* lpClass =
349      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
350  v8::String::Utf8Value szPropName(property);
351  CFX_ByteStringC szFxPropName(*szPropName, szPropName.length());
352  CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate());
353  lpThisValue->ForceSetValue(thisObject);
354  CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate());
355  lpNewValue->ForceSetValue(value);
356  FXJSE_DynPropSetterAdapter(
357      lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName,
358      reinterpret_cast<FXJSE_HVALUE>(lpNewValue));
359  info.GetReturnValue().Set(value);
360  delete lpThisValue;
361  lpThisValue = nullptr;
362}
363static void FXJSE_V8_GenericNamedPropertyEnumeratorCallback(
364    const v8::PropertyCallbackInfo<v8::Array>& info) {
365  const FXJSE_CLASS* lpClass =
366      static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value());
367  v8::Isolate* pIsolate = info.GetIsolate();
368  v8::Local<v8::Array> newArray = v8::Array::New(pIsolate, lpClass->propNum);
369  for (int i = 0; i < lpClass->propNum; i++) {
370    newArray->Set(
371        i, v8::String::NewFromUtf8(pIsolate, lpClass->properties[i].name));
372  }
373  info.GetReturnValue().Set(newArray);
374}
375
376void CFXJSE_Class::SetUpDynPropHandler(CFXJSE_Context* pContext,
377                                       CFXJSE_Value* pValue,
378                                       const FXJSE_CLASS* lpClassDefinition) {
379  v8::Isolate* pIsolate = pValue->GetIsolate();
380  CFXJSE_ScopeUtil_IsolateHandleRootOrNormalContext scope(pIsolate, pContext);
381  v8::Local<v8::Context> hContext = v8::Local<v8::Context>::New(
382      pIsolate, pContext ? pContext->m_hContext
383                         : CFXJSE_RuntimeData::Get(pIsolate)->m_hRootContext);
384  v8::Local<v8::Object> hObject =
385      v8::Local<v8::Value>::New(pIsolate, pValue->m_hValue).As<v8::Object>();
386  v8::Local<v8::Object> hHarmonyProxyObj =
387      hContext->Global()
388          ->Get(v8::String::NewFromUtf8(pIsolate, "Proxy"))
389          .As<v8::Object>();
390  v8::Local<v8::Function> hHarmonyProxyCreateFn =
391      hHarmonyProxyObj->Get(v8::String::NewFromUtf8(pIsolate, "create"))
392          .As<v8::Function>();
393  v8::Local<v8::Value> hOldPrototype = hObject->GetPrototype();
394  v8::Local<v8::Object> hTrapper = v8::Object::New(pIsolate);
395  hTrapper->ForceSet(
396      v8::String::NewFromUtf8(pIsolate, "getOwnPropertyDescriptor"),
397      v8::Function::New(
398          pIsolate, FXJSE_V8ProxyCallback_getOwnPropertyDescriptor,
399          v8::External::New(pIsolate,
400                            const_cast<FXJSE_CLASS*>(lpClassDefinition))));
401  hTrapper->ForceSet(
402      v8::String::NewFromUtf8(pIsolate, "getPropertyDescriptor"),
403      v8::Function::New(pIsolate, FXJSE_V8ProxyCallback_getPropertyDescriptor,
404                        v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(
405                                                        lpClassDefinition))));
406  hTrapper->ForceSet(
407      v8::String::NewFromUtf8(pIsolate, "getOwnPropertyNames"),
408      v8::Function::New(pIsolate, FXJSE_V8ProxyCallback_getOwnPropertyNames,
409                        v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(
410                                                        lpClassDefinition))));
411  hTrapper->ForceSet(
412      v8::String::NewFromUtf8(pIsolate, "getPropertyNames"),
413      v8::Function::New(pIsolate, FXJSE_V8ProxyCallback_getPropertyNames,
414                        v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(
415                                                        lpClassDefinition))));
416  hTrapper->ForceSet(
417      v8::String::NewFromUtf8(pIsolate, "delete"),
418      v8::Function::New(pIsolate, FXJSE_V8ProxyCallback_delete,
419                        v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(
420                                                        lpClassDefinition))));
421  hTrapper->ForceSet(
422      v8::String::NewFromUtf8(pIsolate, "defineProperty"),
423      v8::Function::New(pIsolate, FXJSE_V8ProxyCallback_defineProperty,
424                        v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(
425                                                        lpClassDefinition))));
426  hTrapper->ForceSet(
427      v8::String::NewFromUtf8(pIsolate, "fix"),
428      v8::Function::New(pIsolate, FXJSE_V8ProxyCallback_fix,
429                        v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(
430                                                        lpClassDefinition))));
431  v8::Local<v8::Value> rgArgs[] = {hTrapper, hOldPrototype};
432  v8::Local<v8::Value> hNewPrototype =
433      hHarmonyProxyCreateFn->Call(hHarmonyProxyObj, 2, rgArgs);
434  hObject->SetPrototype(hNewPrototype);
435}
436void CFXJSE_Class::SetUpNamedPropHandler(
437    v8::Isolate* pIsolate,
438    v8::Local<v8::ObjectTemplate>& hObjectTemplate,
439    const FXJSE_CLASS* lpClassDefinition) {
440  v8::NamedPropertyHandlerConfiguration configuration(
441      lpClassDefinition->dynPropGetter
442          ? FXJSE_V8_GenericNamedPropertyGetterCallback
443          : 0,
444      lpClassDefinition->dynPropSetter
445          ? FXJSE_V8_GenericNamedPropertySetterCallback
446          : 0,
447      lpClassDefinition->dynPropTypeGetter
448          ? FXJSE_V8_GenericNamedPropertyQueryCallback
449          : 0,
450      lpClassDefinition->dynPropDeleter
451          ? FXJSE_V8_GenericNamedPropertyDeleterCallback
452          : 0,
453      FXJSE_V8_GenericNamedPropertyEnumeratorCallback,
454      v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(lpClassDefinition)),
455      v8::PropertyHandlerFlags::kNonMasking);
456  hObjectTemplate->SetHandler(configuration);
457}
458