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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/IJavaScript.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_Object.h"
11 #include "../../include/javascript/JS_Value.h"
12 #include "../../include/javascript/JS_GlobalData.h"
13 #include "../../include/javascript/global.h"
14 #include "../../include/javascript/JS_EventHandler.h"
15 #include "../../include/javascript/JS_Context.h"
16 #include "../../include/fpdfxfa/fpdfxfa_app.h"
18 /* ---------------------------- global ---------------------------- */
20 BEGIN_JS_STATIC_CONST(CJS_Global)
23 BEGIN_JS_STATIC_PROP(CJS_Global)
26 BEGIN_JS_STATIC_METHOD(CJS_Global)
27 JS_STATIC_METHOD_ENTRY(setPersistent, 2)
28 END_JS_STATIC_METHOD()
30 IMPLEMENT_SPECIAL_JS_CLASS(CJS_Global, global_alternate, global);
32 FX_BOOL CJS_Global::InitInstance(IFXJS_Context* cc)
34 CJS_Context* pContext = (CJS_Context*)cc;
35 ASSERT(pContext != NULL);
37 global_alternate* pGlobal = (global_alternate*)GetEmbedObject();
38 ASSERT(pGlobal != NULL);
40 pGlobal->Initial(pContext->GetReaderApp());
45 global_alternate::global_alternate(CJS_Object* pJSObject)
46 : CJS_EmbedObj(pJSObject),
51 global_alternate::~global_alternate(void)
53 ASSERT(m_pApp != NULL);
55 // CommitGlobalPersisitentVariables();
56 DestroyGlobalPersisitentVariables();
58 CJS_RuntimeFactory* pFactory = FPDFXFA_GetApp()->GetRuntimeFactory();
61 pFactory->ReleaseGlobalData();
64 void global_alternate::Initial(CPDFDoc_Environment* pApp)
68 CJS_RuntimeFactory* pFactory = FPDFXFA_GetApp()->GetRuntimeFactory();
70 m_pGlobalData = pFactory->NewGlobalData(pApp);
71 UpdateGlobalPersistentVariables();
74 FX_BOOL global_alternate::QueryProperty(FX_LPCWSTR propname)
76 return CFX_WideString(propname) != L"setPersistent";
79 FX_BOOL global_alternate::DelProperty(IFXJS_Context* cc, FX_LPCWSTR propname, JS_ErrorString& sError)
81 js_global_data* pData = NULL;
82 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
84 if (m_mapGlobal.Lookup(sPropName, (FX_LPVOID&)pData))
86 pData->bDeleted = TRUE;
93 FX_BOOL global_alternate::DoProperty(IFXJS_Context* cc, FX_LPCWSTR propname, CJS_PropValue& vp, JS_ErrorString& sError)
97 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
104 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_NUMBER, dData, false, "", v8::Handle<v8::Object>(), FALSE);
110 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_BOOLEAN, 0, (bool)vp, "", v8::Handle<v8::Object>(), FALSE);
114 CFX_ByteString sData;
116 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_STRING, 0, false, sData, v8::Handle<v8::Object>(), FALSE);
120 JSObject pData = (JSObject)vp;
121 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "", pData, FALSE);
124 // if (vp.IsArrayObject())
127 // vp.ConvertToArray(array);
128 // return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "",
129 // (Dobject*)(Darray*)array, FALSE);
137 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_NULL, 0, false, "", v8::Handle<v8::Object>(), FALSE);
141 DelProperty(cc, propname, sError);
150 js_global_data* pData = NULL;
151 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
153 if (m_mapGlobal.Lookup(sPropName, (FX_LPVOID&)pData))
157 if (!pData->bDeleted)
159 switch (pData->nType)
161 case JS_GLOBALDATA_TYPE_NUMBER:
164 case JS_GLOBALDATA_TYPE_BOOLEAN:
167 case JS_GLOBALDATA_TYPE_STRING:
170 case JS_GLOBALDATA_TYPE_OBJECT:
172 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(vp.GetIsolate(),pData->pData);
176 case JS_GLOBALDATA_TYPE_NULL:
205 FX_BOOL global_alternate::setPersistent(OBJ_METHOD_PARAMS)
207 if (params.size() != 2)
209 //sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
213 CFX_ByteString sName = params[0];
215 js_global_data* pData = NULL;
216 if (m_mapGlobal.Lookup(sName, (FX_LPVOID&)pData))
218 if (pData && !pData->bDeleted)
220 pData->bPersistent = (bool)params[1];
225 //sError = JSGetStringFromID(IDS_JSPARAM_INCORRECT);
229 void global_alternate::UpdateGlobalPersistentVariables()
231 ASSERT(m_pGlobalData != NULL);
233 for (int i=0,sz=m_pGlobalData->GetSize(); i<sz; i++)
235 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
236 ASSERT(pData != NULL);
238 switch (pData->data.nType)
240 case JS_GLOBALDATA_TYPE_NUMBER:
241 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_NUMBER, pData->data.dData, false, "", v8::Handle<v8::Object>(), pData->bPersistent == 1);
242 JS_PutObjectNumber(NULL,(JSFXObject)(*m_pJSObject),
243 pData->data.sKey.UTF8Decode(), pData->data.dData);
245 case JS_GLOBALDATA_TYPE_BOOLEAN:
246 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_BOOLEAN, 0, (bool)(pData->data.bData == 1), "", v8::Handle<v8::Object>(), pData->bPersistent == 1);
247 JS_PutObjectBoolean(NULL,(JSFXObject)(*m_pJSObject),
248 pData->data.sKey.UTF8Decode(), (bool)(pData->data.bData == 1));
250 case JS_GLOBALDATA_TYPE_STRING:
251 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_STRING, 0, false, pData->data.sData, v8::Handle<v8::Object>(), pData->bPersistent == 1);
252 JS_PutObjectString(NULL,(JSFXObject)(*m_pJSObject),
253 pData->data.sKey.UTF8Decode(),
254 pData->data.sData.UTF8Decode());
256 case JS_GLOBALDATA_TYPE_OBJECT:
258 IJS_Runtime* pRuntime = JS_GetRuntime((JSFXObject)(*m_pJSObject));
259 v8::Handle<v8::Object> pObj = JS_NewFxDynamicObj(pRuntime, NULL, -1);
261 PutObjectProperty(pObj, &pData->data);
263 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "",
264 (JSObject)pObj, pData->bPersistent == 1);
265 JS_PutObjectObject(NULL,(JSFXObject)(*m_pJSObject),
266 pData->data.sKey.UTF8Decode(), (JSObject)pObj);
269 case JS_GLOBALDATA_TYPE_NULL:
270 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_NULL, 0, false, "", v8::Handle<v8::Object>(), pData->bPersistent == 1);
271 JS_PutObjectNull(NULL,(JSFXObject)(*m_pJSObject),
272 pData->data.sKey.UTF8Decode());
278 void global_alternate::CommitGlobalPersisitentVariables()
280 ASSERT(m_pGlobalData != NULL);
282 FX_POSITION pos = m_mapGlobal.GetStartPosition();
286 js_global_data* pData = NULL;
287 m_mapGlobal.GetNextAssoc(pos, name, (FX_LPVOID&)pData);
293 m_pGlobalData->DeleteGlobalVariable(name);
297 switch (pData->nType)
299 case JS_GLOBALDATA_TYPE_NUMBER:
300 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
301 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
303 case JS_GLOBALDATA_TYPE_BOOLEAN:
304 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
305 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
307 case JS_GLOBALDATA_TYPE_STRING:
308 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
309 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
311 case JS_GLOBALDATA_TYPE_OBJECT:
314 CJS_GlobalVariableArray array;
315 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(GetJSObject()->GetIsolate(),pData->pData);
316 ObjectToArray(obj, array);
317 m_pGlobalData->SetGlobalVariableObject(name, array);
318 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
321 case JS_GLOBALDATA_TYPE_NULL:
322 m_pGlobalData->SetGlobalVariableNull(name);
323 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
331 void global_alternate::ObjectToArray(v8::Handle<v8::Object> pObj, CJS_GlobalVariableArray& array)
333 v8::Handle<v8::Array> pKeyList = JS_GetObjectElementNames(pObj);
334 int nObjElements = pKeyList->Length();
336 v8::Local<v8::Context> context = pObj->CreationContext();
337 v8::Isolate* isolate = context->GetIsolate();
339 for (int i=0; i<nObjElements; i++)
342 CFX_WideString ws = JS_ToString(JS_GetArrayElemnet(pKeyList, i));
343 CFX_ByteString sKey = ws.UTF8Encode();
345 v8::Handle<v8::Value> v = JS_GetObjectElement(isolate, pObj, (const wchar_t*)(FX_LPCWSTR)ws);
346 FXJSVALUETYPE vt = GET_VALUE_TYPE(v);
351 CJS_KeyValue* pObjElement = new CJS_KeyValue;
352 pObjElement->nType = JS_GLOBALDATA_TYPE_NUMBER;
353 pObjElement->sKey = sKey;
354 pObjElement->dData = JS_ToNumber(v);
355 array.Add(pObjElement);
360 CJS_KeyValue* pObjElement = new CJS_KeyValue;
361 pObjElement->nType = JS_GLOBALDATA_TYPE_BOOLEAN;
362 pObjElement->sKey = sKey;
363 pObjElement->dData = JS_ToBoolean(v);
364 array.Add(pObjElement);
369 CFX_ByteString sValue = CJS_Value(isolate, v, VT_string);
370 CJS_KeyValue* pObjElement = new CJS_KeyValue;
371 pObjElement->nType = JS_GLOBALDATA_TYPE_STRING;
372 pObjElement->sKey = sKey;
373 pObjElement->sData = sValue;
374 array.Add(pObjElement);
379 CJS_KeyValue* pObjElement = new CJS_KeyValue;
380 pObjElement->nType = JS_GLOBALDATA_TYPE_OBJECT;
381 pObjElement->sKey = sKey;
382 ObjectToArray(JS_ToObject(v), pObjElement->objData);
383 array.Add(pObjElement);
388 CJS_KeyValue* pObjElement = new CJS_KeyValue;
389 pObjElement->nType = JS_GLOBALDATA_TYPE_NULL;
390 pObjElement->sKey = sKey;
391 array.Add(pObjElement);
400 void global_alternate::PutObjectProperty(v8::Handle<v8::Object> pObj, CJS_KeyValue* pData)
402 ASSERT(pData != NULL);
404 for (int i=0,sz=pData->objData.Count(); i<sz; i++)
406 CJS_KeyValue* pObjData = pData->objData.GetAt(i);
407 ASSERT(pObjData != NULL);
409 switch (pObjData->nType)
411 case JS_GLOBALDATA_TYPE_NUMBER:
412 JS_PutObjectNumber(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode(), pObjData->dData);
414 case JS_GLOBALDATA_TYPE_BOOLEAN:
415 JS_PutObjectBoolean(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode(), (bool)(pObjData->bData == 1));
417 case JS_GLOBALDATA_TYPE_STRING:
418 JS_PutObjectString(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode(), pObjData->sData.UTF8Decode());
420 case JS_GLOBALDATA_TYPE_OBJECT:
422 IJS_Runtime* pRuntime = JS_GetRuntime((JSFXObject)(*m_pJSObject));
423 v8::Handle<v8::Object> pNewObj = JS_NewFxDynamicObj(pRuntime, NULL, -1);
424 PutObjectProperty(pNewObj, pObjData);
425 JS_PutObjectObject(NULL, (JSObject)pObj, pObjData->sKey.UTF8Decode(), (JSObject)pNewObj);
428 case JS_GLOBALDATA_TYPE_NULL:
429 JS_PutObjectNull(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode());
435 void global_alternate::DestroyGlobalPersisitentVariables()
437 FX_POSITION pos = m_mapGlobal.GetStartPosition();
441 js_global_data* pData = NULL;
442 m_mapGlobal.GetNextAssoc(pos, name, (FX_LPVOID&)pData);
446 m_mapGlobal.RemoveAll();
450 FX_BOOL global_alternate::SetGlobalVariables(FX_LPCSTR propname, int nType,
451 double dData, bool bData, const CFX_ByteString& sData, JSObject pData, bool bDefaultPersistent)
453 if (propname == NULL) return FALSE;
455 js_global_data* pTemp = NULL;
456 m_mapGlobal.Lookup(propname, (FX_LPVOID&)pTemp);
460 if (pTemp->bDeleted || pTemp->nType != nType)
465 pTemp->nType = nType;
468 pTemp->bDeleted = FALSE;
472 case JS_GLOBALDATA_TYPE_NUMBER:
474 pTemp->dData = dData;
477 case JS_GLOBALDATA_TYPE_BOOLEAN:
479 pTemp->bData = bData;
482 case JS_GLOBALDATA_TYPE_STRING:
484 pTemp->sData = sData;
487 case JS_GLOBALDATA_TYPE_OBJECT:
489 pTemp->pData.Reset(JS_GetRuntime(pData), pData);
492 case JS_GLOBALDATA_TYPE_NULL:
501 js_global_data* pNewData = NULL;
505 case JS_GLOBALDATA_TYPE_NUMBER:
507 pNewData = new js_global_data;
508 pNewData->nType = JS_GLOBALDATA_TYPE_NUMBER;
509 pNewData->dData = dData;
510 pNewData->bPersistent = bDefaultPersistent;
513 case JS_GLOBALDATA_TYPE_BOOLEAN:
515 pNewData = new js_global_data;
516 pNewData->nType = JS_GLOBALDATA_TYPE_BOOLEAN;
517 pNewData->bData = bData;
518 pNewData->bPersistent = bDefaultPersistent;
521 case JS_GLOBALDATA_TYPE_STRING:
523 pNewData = new js_global_data;
524 pNewData->nType = JS_GLOBALDATA_TYPE_STRING;
525 pNewData->sData = sData;
526 pNewData->bPersistent = bDefaultPersistent;
529 case JS_GLOBALDATA_TYPE_OBJECT:
531 pNewData = new js_global_data;
532 pNewData->nType = JS_GLOBALDATA_TYPE_OBJECT;
533 pNewData->pData.Reset(JS_GetRuntime(pData), pData);
534 pNewData->bPersistent = bDefaultPersistent;
537 case JS_GLOBALDATA_TYPE_NULL:
539 pNewData = new js_global_data;
540 pNewData->nType = JS_GLOBALDATA_TYPE_NULL;
541 pNewData->bPersistent = bDefaultPersistent;
548 m_mapGlobal.SetAt(propname, (FX_LPVOID)pNewData);