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 "fxjs/include/cfxjse_value.h"
8 
9 #include <math.h>
10 
11 #include "fxjs/include/cfxjse_class.h"
12 #include "fxjs/include/cfxjse_context.h"
13 
14 namespace {
15 
ftod(FX_FLOAT fNumber)16 double ftod(FX_FLOAT fNumber) {
17   static_assert(sizeof(FX_FLOAT) == 4, "FX_FLOAT of incorrect size");
18 
19   uint32_t nFloatBits = (uint32_t&)fNumber;
20   uint8_t nExponent = (uint8_t)(nFloatBits >> 23);
21   if (nExponent == 0 || nExponent == 255)
22     return fNumber;
23 
24   int8_t nErrExp = nExponent - 150;
25   if (nErrExp >= 0)
26     return fNumber;
27 
28   double dwError = pow(2.0, nErrExp), dwErrorHalf = dwError / 2;
29   double dNumber = fNumber, dNumberAbs = fabs(fNumber);
30   double dNumberAbsMin = dNumberAbs - dwErrorHalf,
31          dNumberAbsMax = dNumberAbs + dwErrorHalf;
32   int32_t iErrPos = 0;
33   if (floor(dNumberAbsMin) == floor(dNumberAbsMax)) {
34     dNumberAbsMin = fmod(dNumberAbsMin, 1.0);
35     dNumberAbsMax = fmod(dNumberAbsMax, 1.0);
36     int32_t iErrPosMin = 1, iErrPosMax = 38;
37     do {
38       int32_t iMid = (iErrPosMin + iErrPosMax) / 2;
39       double dPow = pow(10.0, iMid);
40       if (floor(dNumberAbsMin * dPow) == floor(dNumberAbsMax * dPow)) {
41         iErrPosMin = iMid + 1;
42       } else {
43         iErrPosMax = iMid;
44       }
45     } while (iErrPosMin < iErrPosMax);
46     iErrPos = iErrPosMax;
47   }
48   double dPow = pow(10.0, iErrPos);
49   return fNumber < 0 ? ceil(dNumber * dPow - 0.5) / dPow
50                      : floor(dNumber * dPow + 0.5) / dPow;
51 }
52 
53 }  // namespace
54 
FXJSE_ThrowMessage(const CFX_ByteStringC & utf8Message)55 void FXJSE_ThrowMessage(const CFX_ByteStringC& utf8Message) {
56   v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
57   ASSERT(pIsolate);
58 
59   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate);
60   v8::Local<v8::String> hMessage = v8::String::NewFromUtf8(
61       pIsolate, utf8Message.c_str(), v8::String::kNormalString,
62       utf8Message.GetLength());
63   v8::Local<v8::Value> hError = v8::Exception::Error(hMessage);
64   pIsolate->ThrowException(hError);
65 }
66 
CFXJSE_Value(v8::Isolate * pIsolate)67 CFXJSE_Value::CFXJSE_Value(v8::Isolate* pIsolate) : m_pIsolate(pIsolate) {}
68 
~CFXJSE_Value()69 CFXJSE_Value::~CFXJSE_Value() {}
70 
ToHostObject(CFXJSE_Class * lpClass) const71 CFXJSE_HostObject* CFXJSE_Value::ToHostObject(CFXJSE_Class* lpClass) const {
72   ASSERT(!m_hValue.IsEmpty());
73 
74   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
75   v8::Local<v8::Value> pValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
76   ASSERT(!pValue.IsEmpty());
77 
78   if (!pValue->IsObject())
79     return nullptr;
80 
81   return FXJSE_RetrieveObjectBinding(pValue.As<v8::Object>(), lpClass);
82 }
83 
SetObject(CFXJSE_HostObject * lpObject,CFXJSE_Class * pClass)84 void CFXJSE_Value::SetObject(CFXJSE_HostObject* lpObject,
85                              CFXJSE_Class* pClass) {
86   if (!pClass) {
87     ASSERT(!lpObject);
88     SetJSObject();
89     return;
90   }
91   SetHostObject(lpObject, pClass);
92 }
93 
SetHostObject(CFXJSE_HostObject * lpObject,CFXJSE_Class * lpClass)94 void CFXJSE_Value::SetHostObject(CFXJSE_HostObject* lpObject,
95                                  CFXJSE_Class* lpClass) {
96   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
97   ASSERT(lpClass);
98   v8::Local<v8::FunctionTemplate> hClass =
99       v8::Local<v8::FunctionTemplate>::New(m_pIsolate, lpClass->m_hTemplate);
100   v8::Local<v8::Object> hObject = hClass->InstanceTemplate()->NewInstance();
101   FXJSE_UpdateObjectBinding(hObject, lpObject);
102   m_hValue.Reset(m_pIsolate, hObject);
103 }
104 
SetArray(uint32_t uValueCount,CFXJSE_Value ** rgValues)105 void CFXJSE_Value::SetArray(uint32_t uValueCount, CFXJSE_Value** rgValues) {
106   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
107   v8::Local<v8::Array> hArrayObject = v8::Array::New(m_pIsolate, uValueCount);
108   if (rgValues) {
109     for (uint32_t i = 0; i < uValueCount; i++) {
110       if (rgValues[i]) {
111         hArrayObject->Set(i, v8::Local<v8::Value>::New(
112                                  m_pIsolate, rgValues[i]->DirectGetValue()));
113       }
114     }
115   }
116   m_hValue.Reset(m_pIsolate, hArrayObject);
117 }
118 
SetDate(double dDouble)119 void CFXJSE_Value::SetDate(double dDouble) {
120   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
121   v8::Local<v8::Value> hDate = v8::Date::New(m_pIsolate, dDouble);
122   m_hValue.Reset(m_pIsolate, hDate);
123 }
124 
SetFloat(FX_FLOAT fFloat)125 void CFXJSE_Value::SetFloat(FX_FLOAT fFloat) {
126   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
127   v8::Local<v8::Value> pValue = v8::Number::New(m_pIsolate, ftod(fFloat));
128   m_hValue.Reset(m_pIsolate, pValue);
129 }
130 
SetObjectProperty(const CFX_ByteStringC & szPropName,CFXJSE_Value * lpPropValue)131 FX_BOOL CFXJSE_Value::SetObjectProperty(const CFX_ByteStringC& szPropName,
132                                         CFXJSE_Value* lpPropValue) {
133   ASSERT(lpPropValue);
134   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
135   v8::Local<v8::Value> hObject =
136       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
137   if (!hObject->IsObject())
138     return FALSE;
139 
140   v8::Local<v8::Value> hPropValue =
141       v8::Local<v8::Value>::New(m_pIsolate, lpPropValue->DirectGetValue());
142   return (FX_BOOL)hObject.As<v8::Object>()->Set(
143       v8::String::NewFromUtf8(m_pIsolate, szPropName.c_str(),
144                               v8::String::kNormalString,
145                               szPropName.GetLength()),
146       hPropValue);
147 }
148 
GetObjectProperty(const CFX_ByteStringC & szPropName,CFXJSE_Value * lpPropValue)149 FX_BOOL CFXJSE_Value::GetObjectProperty(const CFX_ByteStringC& szPropName,
150                                         CFXJSE_Value* lpPropValue) {
151   ASSERT(lpPropValue);
152   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
153   v8::Local<v8::Value> hObject =
154       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
155   if (!hObject->IsObject())
156     return FALSE;
157 
158   v8::Local<v8::Value> hPropValue =
159       hObject.As<v8::Object>()->Get(v8::String::NewFromUtf8(
160           m_pIsolate, szPropName.c_str(), v8::String::kNormalString,
161           szPropName.GetLength()));
162   lpPropValue->ForceSetValue(hPropValue);
163   return TRUE;
164 }
165 
SetObjectProperty(uint32_t uPropIdx,CFXJSE_Value * lpPropValue)166 FX_BOOL CFXJSE_Value::SetObjectProperty(uint32_t uPropIdx,
167                                         CFXJSE_Value* lpPropValue) {
168   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
169   v8::Local<v8::Value> hObject =
170       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
171   if (!hObject->IsObject())
172     return FALSE;
173 
174   v8::Local<v8::Value> hPropValue =
175       v8::Local<v8::Value>::New(m_pIsolate, lpPropValue->DirectGetValue());
176   return (FX_BOOL)hObject.As<v8::Object>()->Set(uPropIdx, hPropValue);
177 }
178 
GetObjectPropertyByIdx(uint32_t uPropIdx,CFXJSE_Value * lpPropValue)179 FX_BOOL CFXJSE_Value::GetObjectPropertyByIdx(uint32_t uPropIdx,
180                                              CFXJSE_Value* lpPropValue) {
181   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
182   v8::Local<v8::Value> hObject =
183       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
184   if (!hObject->IsObject())
185     return FALSE;
186 
187   v8::Local<v8::Value> hPropValue = hObject.As<v8::Object>()->Get(uPropIdx);
188   lpPropValue->ForceSetValue(hPropValue);
189   return TRUE;
190 }
191 
DeleteObjectProperty(const CFX_ByteStringC & szPropName)192 FX_BOOL CFXJSE_Value::DeleteObjectProperty(const CFX_ByteStringC& szPropName) {
193   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
194   v8::Local<v8::Value> hObject =
195       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
196   if (!hObject->IsObject())
197     return FALSE;
198 
199   hObject.As<v8::Object>()->Delete(v8::String::NewFromUtf8(
200       m_pIsolate, szPropName.c_str(), v8::String::kNormalString,
201       szPropName.GetLength()));
202   return TRUE;
203 }
204 
HasObjectOwnProperty(const CFX_ByteStringC & szPropName,FX_BOOL bUseTypeGetter)205 FX_BOOL CFXJSE_Value::HasObjectOwnProperty(const CFX_ByteStringC& szPropName,
206                                            FX_BOOL bUseTypeGetter) {
207   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
208   v8::Local<v8::Value> hObject =
209       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
210   if (!hObject->IsObject())
211     return FALSE;
212 
213   v8::Local<v8::String> hKey = v8::String::NewFromUtf8(
214       m_pIsolate, szPropName.c_str(), v8::String::kNormalString,
215       szPropName.GetLength());
216   return hObject.As<v8::Object>()->HasRealNamedProperty(hKey) ||
217          (bUseTypeGetter &&
218           hObject.As<v8::Object>()
219               ->HasOwnProperty(m_pIsolate->GetCurrentContext(), hKey)
220               .FromMaybe(false));
221 }
222 
SetObjectOwnProperty(const CFX_ByteStringC & szPropName,CFXJSE_Value * lpPropValue)223 FX_BOOL CFXJSE_Value::SetObjectOwnProperty(const CFX_ByteStringC& szPropName,
224                                            CFXJSE_Value* lpPropValue) {
225   ASSERT(lpPropValue);
226   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
227   v8::Local<v8::Value> hObject =
228       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
229   if (!hObject->IsObject())
230     return FALSE;
231 
232   v8::Local<v8::Value> pValue =
233       v8::Local<v8::Value>::New(m_pIsolate, lpPropValue->m_hValue);
234   return hObject.As<v8::Object>()
235       ->DefineOwnProperty(
236           m_pIsolate->GetCurrentContext(),
237           v8::String::NewFromUtf8(m_pIsolate, szPropName.c_str(),
238                                   v8::String::kNormalString,
239                                   szPropName.GetLength()),
240           pValue)
241       .FromMaybe(false);
242 }
243 
SetFunctionBind(CFXJSE_Value * lpOldFunction,CFXJSE_Value * lpNewThis)244 FX_BOOL CFXJSE_Value::SetFunctionBind(CFXJSE_Value* lpOldFunction,
245                                       CFXJSE_Value* lpNewThis) {
246   ASSERT(lpOldFunction && lpNewThis);
247 
248   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
249   v8::Local<v8::Value> rgArgs[2];
250   v8::Local<v8::Value> hOldFunction =
251       v8::Local<v8::Value>::New(m_pIsolate, lpOldFunction->DirectGetValue());
252   if (hOldFunction.IsEmpty() || !hOldFunction->IsFunction())
253     return FALSE;
254 
255   rgArgs[0] = hOldFunction;
256   v8::Local<v8::Value> hNewThis =
257       v8::Local<v8::Value>::New(m_pIsolate, lpNewThis->DirectGetValue());
258   if (hNewThis.IsEmpty())
259     return FALSE;
260 
261   rgArgs[1] = hNewThis;
262   v8::Local<v8::String> hBinderFuncSource =
263       v8::String::NewFromUtf8(m_pIsolate,
264                               "(function (oldfunction, newthis) { return "
265                               "oldfunction.bind(newthis); })");
266   v8::Local<v8::Function> hBinderFunc =
267       v8::Script::Compile(hBinderFuncSource)->Run().As<v8::Function>();
268   v8::Local<v8::Value> hBoundFunction =
269       hBinderFunc->Call(m_pIsolate->GetCurrentContext()->Global(), 2, rgArgs);
270   if (hBoundFunction.IsEmpty() || !hBoundFunction->IsFunction())
271     return FALSE;
272 
273   m_hValue.Reset(m_pIsolate, hBoundFunction);
274   return TRUE;
275 }
276 
277 #define FXJSE_INVALID_PTR ((void*)(intptr_t)-1)
Call(CFXJSE_Value * lpReceiver,CFXJSE_Value * lpRetValue,uint32_t nArgCount,CFXJSE_Value ** lpArgs)278 FX_BOOL CFXJSE_Value::Call(CFXJSE_Value* lpReceiver,
279                            CFXJSE_Value* lpRetValue,
280                            uint32_t nArgCount,
281                            CFXJSE_Value** lpArgs) {
282   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
283   v8::Local<v8::Value> hFunctionValue =
284       v8::Local<v8::Value>::New(m_pIsolate, DirectGetValue());
285   v8::Local<v8::Object> hFunctionObject =
286       !hFunctionValue.IsEmpty() && hFunctionValue->IsObject()
287           ? hFunctionValue.As<v8::Object>()
288           : v8::Local<v8::Object>();
289 
290   v8::TryCatch trycatch(m_pIsolate);
291   if (hFunctionObject.IsEmpty() || !hFunctionObject->IsCallable()) {
292     if (lpRetValue)
293       lpRetValue->ForceSetValue(FXJSE_CreateReturnValue(m_pIsolate, trycatch));
294     return FALSE;
295   }
296 
297   v8::Local<v8::Value> hReturnValue;
298   v8::Local<v8::Value>* lpLocalArgs = NULL;
299   if (nArgCount) {
300     lpLocalArgs = FX_Alloc(v8::Local<v8::Value>, nArgCount);
301     for (uint32_t i = 0; i < nArgCount; i++) {
302       new (lpLocalArgs + i) v8::Local<v8::Value>;
303       CFXJSE_Value* lpArg = lpArgs[i];
304       if (lpArg) {
305         lpLocalArgs[i] =
306             v8::Local<v8::Value>::New(m_pIsolate, lpArg->DirectGetValue());
307       }
308       if (lpLocalArgs[i].IsEmpty()) {
309         lpLocalArgs[i] = v8::Undefined(m_pIsolate);
310       }
311     }
312   }
313 
314   FX_BOOL bRetValue = TRUE;
315   if (lpReceiver == FXJSE_INVALID_PTR) {
316     v8::MaybeLocal<v8::Value> maybe_retvalue =
317         hFunctionObject->CallAsConstructor(m_pIsolate->GetCurrentContext(),
318                                            nArgCount, lpLocalArgs);
319     hReturnValue = maybe_retvalue.FromMaybe(v8::Local<v8::Value>());
320   } else {
321     v8::Local<v8::Value> hReceiver;
322     if (lpReceiver) {
323       hReceiver =
324           v8::Local<v8::Value>::New(m_pIsolate, lpReceiver->DirectGetValue());
325     }
326     if (hReceiver.IsEmpty() || !hReceiver->IsObject())
327       hReceiver = v8::Object::New(m_pIsolate);
328 
329     v8::MaybeLocal<v8::Value> maybe_retvalue = hFunctionObject->CallAsFunction(
330         m_pIsolate->GetCurrentContext(), hReceiver, nArgCount, lpLocalArgs);
331     hReturnValue = maybe_retvalue.FromMaybe(v8::Local<v8::Value>());
332   }
333 
334   if (trycatch.HasCaught()) {
335     hReturnValue = FXJSE_CreateReturnValue(m_pIsolate, trycatch);
336     bRetValue = FALSE;
337   }
338 
339   if (lpRetValue)
340     lpRetValue->ForceSetValue(hReturnValue);
341 
342   if (lpLocalArgs) {
343     for (uint32_t i = 0; i < nArgCount; i++)
344       lpLocalArgs[i].~Local();
345     FX_Free(lpLocalArgs);
346   }
347   return bRetValue;
348 }
349 
IsUndefined() const350 FX_BOOL CFXJSE_Value::IsUndefined() const {
351   if (m_hValue.IsEmpty())
352     return FALSE;
353 
354   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
355   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
356   return hValue->IsUndefined();
357 }
358 
IsNull() const359 FX_BOOL CFXJSE_Value::IsNull() const {
360   if (m_hValue.IsEmpty())
361     return FALSE;
362 
363   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
364   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
365   return hValue->IsNull();
366 }
367 
IsBoolean() const368 FX_BOOL CFXJSE_Value::IsBoolean() const {
369   if (m_hValue.IsEmpty())
370     return FALSE;
371 
372   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
373   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
374   return hValue->IsBoolean();
375 }
376 
IsString() const377 FX_BOOL CFXJSE_Value::IsString() const {
378   if (m_hValue.IsEmpty())
379     return FALSE;
380 
381   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
382   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
383   return hValue->IsString();
384 }
385 
IsNumber() const386 FX_BOOL CFXJSE_Value::IsNumber() const {
387   if (m_hValue.IsEmpty())
388     return FALSE;
389 
390   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
391   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
392   return hValue->IsNumber();
393 }
394 
IsInteger() const395 FX_BOOL CFXJSE_Value::IsInteger() const {
396   if (m_hValue.IsEmpty())
397     return FALSE;
398 
399   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
400   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
401   return hValue->IsInt32();
402 }
403 
IsObject() const404 FX_BOOL CFXJSE_Value::IsObject() const {
405   if (m_hValue.IsEmpty())
406     return FALSE;
407 
408   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
409   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
410   return hValue->IsObject();
411 }
412 
IsArray() const413 FX_BOOL CFXJSE_Value::IsArray() const {
414   if (m_hValue.IsEmpty())
415     return FALSE;
416 
417   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
418   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
419   return hValue->IsArray();
420 }
421 
IsFunction() const422 FX_BOOL CFXJSE_Value::IsFunction() const {
423   if (m_hValue.IsEmpty())
424     return FALSE;
425 
426   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
427   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
428   return hValue->IsFunction();
429 }
430 
IsDate() const431 FX_BOOL CFXJSE_Value::IsDate() const {
432   if (m_hValue.IsEmpty())
433     return FALSE;
434 
435   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
436   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
437   return hValue->IsDate();
438 }
439 
ToBoolean() const440 FX_BOOL CFXJSE_Value::ToBoolean() const {
441   ASSERT(!m_hValue.IsEmpty());
442   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
443   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
444   return static_cast<FX_BOOL>(hValue->BooleanValue());
445 }
446 
ToFloat() const447 FX_FLOAT CFXJSE_Value::ToFloat() const {
448   ASSERT(!m_hValue.IsEmpty());
449   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
450   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
451   return static_cast<FX_FLOAT>(hValue->NumberValue());
452 }
453 
ToDouble() const454 double CFXJSE_Value::ToDouble() const {
455   ASSERT(!m_hValue.IsEmpty());
456   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
457   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
458   return static_cast<double>(hValue->NumberValue());
459 }
460 
ToInteger() const461 int32_t CFXJSE_Value::ToInteger() const {
462   ASSERT(!m_hValue.IsEmpty());
463   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
464   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
465   return static_cast<int32_t>(hValue->NumberValue());
466 }
467 
ToString() const468 CFX_ByteString CFXJSE_Value::ToString() const {
469   ASSERT(!m_hValue.IsEmpty());
470   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
471   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
472   v8::Local<v8::String> hString = hValue->ToString();
473   v8::String::Utf8Value hStringVal(hString);
474   return CFX_ByteString(*hStringVal);
475 }
476 
SetUndefined()477 void CFXJSE_Value::SetUndefined() {
478   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
479   v8::Local<v8::Value> hValue = v8::Undefined(m_pIsolate);
480   m_hValue.Reset(m_pIsolate, hValue);
481 }
482 
SetNull()483 void CFXJSE_Value::SetNull() {
484   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
485   v8::Local<v8::Value> hValue = v8::Null(m_pIsolate);
486   m_hValue.Reset(m_pIsolate, hValue);
487 }
488 
SetBoolean(FX_BOOL bBoolean)489 void CFXJSE_Value::SetBoolean(FX_BOOL bBoolean) {
490   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
491   v8::Local<v8::Value> hValue = v8::Boolean::New(m_pIsolate, bBoolean != FALSE);
492   m_hValue.Reset(m_pIsolate, hValue);
493 }
494 
SetInteger(int32_t nInteger)495 void CFXJSE_Value::SetInteger(int32_t nInteger) {
496   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
497   v8::Local<v8::Value> hValue = v8::Integer::New(m_pIsolate, nInteger);
498   m_hValue.Reset(m_pIsolate, hValue);
499 }
500 
SetDouble(double dDouble)501 void CFXJSE_Value::SetDouble(double dDouble) {
502   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
503   v8::Local<v8::Value> hValue = v8::Number::New(m_pIsolate, dDouble);
504   m_hValue.Reset(m_pIsolate, hValue);
505 }
506 
SetString(const CFX_ByteStringC & szString)507 void CFXJSE_Value::SetString(const CFX_ByteStringC& szString) {
508   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
509   v8::Local<v8::Value> hValue = v8::String::NewFromUtf8(
510       m_pIsolate, reinterpret_cast<const char*>(szString.raw_str()),
511       v8::String::kNormalString, szString.GetLength());
512   m_hValue.Reset(m_pIsolate, hValue);
513 }
514 
SetJSObject()515 void CFXJSE_Value::SetJSObject() {
516   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
517   v8::Local<v8::Value> hValue = v8::Object::New(m_pIsolate);
518   m_hValue.Reset(m_pIsolate, hValue);
519 }
520