OLD | NEW |
| (Empty) |
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 "fxjse/include/cfxjse_value.h" | |
8 | |
9 #include <math.h> | |
10 | |
11 #include "fxjse/context.h" | |
12 #include "fxjse/include/cfxjse_class.h" | |
13 | |
14 namespace { | |
15 | |
16 double FXJSE_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 | |
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 | |
67 CFXJSE_Value::CFXJSE_Value(v8::Isolate* pIsolate) : m_pIsolate(pIsolate) {} | |
68 | |
69 CFXJSE_Value::~CFXJSE_Value() {} | |
70 | |
71 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 | |
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 | |
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 | |
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 | |
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 | |
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, FXJSE_ftod(fFloat)); | |
128 m_hValue.Reset(m_pIsolate, pValue); | |
129 } | |
130 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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) | |
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 } | |
OLD | NEW |