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 "xfa/src/fxfa/src/common/xfa_utils.h"
9 #include "xfa/src/fxfa/src/common/xfa_object.h"
10 #include "xfa/src/fxfa/src/common/xfa_document.h"
11 #include "xfa/src/fxfa/src/common/xfa_parser.h"
12 #include "xfa/src/fxfa/src/common/xfa_script.h"
13 #include "xfa/src/fxfa/src/common/xfa_docdata.h"
14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h"
15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h"
16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
17 #include "xfa_script_imp.h"
18 #include "xfa_script_resolveprocessor.h"
19 #include "xfa_script_nodehelper.h"
CXFA_ScriptContext(CXFA_Document * pDocument)20 CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument)
21 : m_pDocument(pDocument),
22 m_hJsContext(nullptr),
23 m_hJsRuntime(nullptr),
24 m_hJsClass(nullptr),
25 m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown),
26 m_pEventParam(nullptr),
27 m_pScriptNodeArray(nullptr),
28 m_pResolveProcessor(nullptr),
29 m_hFM2JSContext(nullptr),
30 m_pThisObject(nullptr),
31 m_dwBuiltInInFlags(0),
32 m_eRunAtType(XFA_ATTRIBUTEENUM_Client) {
33 FX_memset(&m_JsGlobalClass, 0, sizeof(FXJSE_CLASS));
34 FX_memset(&m_JsNormalClass, 0, sizeof(FXJSE_CLASS));
35 }
~CXFA_ScriptContext()36 CXFA_ScriptContext::~CXFA_ScriptContext() {
37 FX_POSITION ps = m_mapXFAToHValue.GetStartPosition();
38 while (ps) {
39 CXFA_Object* pXFAObj;
40 FXJSE_HVALUE pValue;
41 m_mapXFAToHValue.GetNextAssoc(ps, pXFAObj, pValue);
42 FXJSE_Value_Release(pValue);
43 }
44 m_mapXFAToHValue.RemoveAll();
45 ReleaseVariablesMap();
46 if (m_hFM2JSContext) {
47 XFA_FM2JS_ContextRelease(m_hFM2JSContext);
48 m_hFM2JSContext = NULL;
49 }
50 if (m_hJsContext) {
51 FXJSE_Context_Release(m_hJsContext);
52 m_hJsContext = NULL;
53 }
54 if (m_pResolveProcessor) {
55 delete m_pResolveProcessor;
56 m_pResolveProcessor = NULL;
57 }
58 m_upObjectArray.RemoveAll();
59 for (int32_t i = 0; i < m_CacheListArray.GetSize(); i++) {
60 delete ((CXFA_NodeList*)m_CacheListArray[i]);
61 }
62 m_CacheListArray.RemoveAll();
63 if (m_dwBuiltInInFlags & XFA_JSBUILTIN_HasCount) {
64 FX_POSITION ps = m_JSBuiltInObjects.GetStartPosition();
65 while (ps) {
66 CFX_ByteString bsKey;
67 void* pValue = NULL;
68 m_JSBuiltInObjects.GetNextAssoc(ps, bsKey, pValue);
69 if (pValue) {
70 FXJSE_Value_Release((FXJSE_HVALUE)pValue);
71 }
72 }
73 m_JSBuiltInObjects.RemoveAll();
74 }
75 }
Initialize(FXJSE_HRUNTIME hRuntime)76 void CXFA_ScriptContext::Initialize(FXJSE_HRUNTIME hRuntime) {
77 m_hJsRuntime = hRuntime;
78 DefineJsContext();
79 DefineJsClass();
80 m_pResolveProcessor = new CXFA_ResolveProcessor;
81 }
Release()82 void CXFA_ScriptContext::Release() {
83 delete this;
84 }
RunScript(XFA_SCRIPTLANGTYPE eScriptType,const CFX_WideStringC & wsScript,FXJSE_HVALUE hRetValue,CXFA_Object * pThisObject)85 FX_BOOL CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType,
86 const CFX_WideStringC& wsScript,
87 FXJSE_HVALUE hRetValue,
88 CXFA_Object* pThisObject) {
89 CFX_ByteString btScript;
90 XFA_SCRIPTLANGTYPE eSaveType = m_eScriptType;
91 m_eScriptType = eScriptType;
92 if (eScriptType == XFA_SCRIPTLANGTYPE_Formcalc) {
93 if (!m_hFM2JSContext) {
94 m_hFM2JSContext = XFA_FM2JS_ContextCreate();
95 XFA_FM2JS_ContextInitialize(m_hFM2JSContext, m_hJsRuntime, m_hJsContext,
96 m_pDocument);
97 }
98 CFX_WideTextBuf wsJavaScript;
99 CFX_WideString wsErrorInfo;
100 int32_t iFlags = XFA_FM2JS_Translate(wsScript, wsJavaScript, wsErrorInfo);
101 if (iFlags) {
102 FXJSE_Value_SetUndefined(hRetValue);
103 return FALSE;
104 }
105 btScript =
106 FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength());
107 } else {
108 if ((m_dwBuiltInInFlags & XFA_JSBUILTIN_Initialized) == 0) {
109 m_dwBuiltInInFlags = XFA_JSBUILTIN_Initialized;
110 FX_POSITION ps = m_JSBuiltInObjects.GetStartPosition();
111 if (ps) {
112 FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(m_hJsContext);
113 while (ps) {
114 CFX_ByteString bsKey;
115 void* pValue;
116 m_JSBuiltInObjects.GetNextAssoc(ps, bsKey, pValue);
117 FXJSE_HVALUE hProp = FXJSE_Value_Create(m_hJsRuntime);
118 if (FXJSE_Value_GetObjectProp(hObject, bsKey, hProp)) {
119 m_JSBuiltInObjects.SetAt(bsKey, hProp);
120 FXJSE_Value_DeleteObjectProp(hObject, bsKey);
121 m_dwBuiltInInFlags |= XFA_JSBUILTIN_HasCount;
122 } else {
123 m_JSBuiltInObjects.RemoveKey(bsKey);
124 FXJSE_Value_Release(hProp);
125 }
126 }
127 FXJSE_Value_Release(hObject);
128 }
129 }
130 btScript = FX_UTF8Encode(wsScript.GetPtr(), wsScript.GetLength());
131 }
132 CXFA_Object* pOriginalObject = m_pThisObject;
133 m_pThisObject = pThisObject;
134 FXJSE_HVALUE pValue = pThisObject ? GetJSValueFromMap(pThisObject) : NULL;
135 FX_BOOL bRet = FXJSE_ExecuteScript(m_hJsContext, btScript, hRetValue, pValue);
136 m_pThisObject = pOriginalObject;
137 m_eScriptType = eSaveType;
138 return bRet;
139 }
GlobalPropertySetter(FXJSE_HOBJECT hObject,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hValue)140 void CXFA_ScriptContext::GlobalPropertySetter(FXJSE_HOBJECT hObject,
141 const CFX_ByteStringC& szPropName,
142 FXJSE_HVALUE hValue) {
143 CXFA_Object* lpOrginalNode =
144 (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
145 CXFA_Document* pDoc = lpOrginalNode->GetDocument();
146 CXFA_ScriptContext* lpScriptContext =
147 (CXFA_ScriptContext*)pDoc->GetScriptContext();
148 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode);
149 CFX_WideString wsPropName = CFX_WideString::FromUTF8(
150 (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
151 FX_DWORD dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings |
152 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
153 XFA_RESOLVENODE_Attributes;
154 CXFA_Node* pRefNode = (CXFA_Node*)lpScriptContext->GetThisObject();
155 if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
156 pRefNode = (CXFA_Node*)lpCurNode;
157 }
158 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
159 TRUE)) {
160 return;
161 }
162 if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
163 if (FXJSE_Value_IsUndefined(hValue)) {
164 FXJSE_Value_SetObjectOwnProp(hObject, szPropName, hValue);
165 return;
166 }
167 }
168 IXFA_Notify* pNotify = pDoc->GetNotify();
169 if (!pNotify) {
170 return;
171 }
172 pNotify->GetDocProvider()->SetGlobalProperty(pNotify->GetHDOC(), szPropName,
173 hValue);
174 }
QueryNodeByFlag(CXFA_Node * refNode,const CFX_WideStringC & propname,FXJSE_HVALUE hValue,FX_DWORD dwFlag,FX_BOOL bSetting)175 FX_BOOL CXFA_ScriptContext::QueryNodeByFlag(CXFA_Node* refNode,
176 const CFX_WideStringC& propname,
177 FXJSE_HVALUE hValue,
178 FX_DWORD dwFlag,
179 FX_BOOL bSetting) {
180 XFA_RESOLVENODE_RS resolveRs;
181 int32_t iRet = ResolveObjects(refNode, propname, resolveRs, dwFlag);
182 FX_BOOL bResult = FALSE;
183 if (iRet > 0) {
184 bResult = TRUE;
185 if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
186 FXJSE_HVALUE pValue = GetJSValueFromMap(resolveRs.nodes[0]);
187 FXJSE_Value_Set(hValue, pValue);
188 } else if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) {
189 XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo = resolveRs.pScriptAttribute;
190 if (lpAttributeInfo) {
191 (resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))(
192 hValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
193 }
194 }
195 }
196 return bResult;
197 }
GlobalPropertyGetter(FXJSE_HOBJECT hObject,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hValue)198 void CXFA_ScriptContext::GlobalPropertyGetter(FXJSE_HOBJECT hObject,
199 const CFX_ByteStringC& szPropName,
200 FXJSE_HVALUE hValue) {
201 CXFA_Object* pOrginalObject =
202 (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
203 CXFA_Document* pDoc = pOrginalObject->GetDocument();
204 CXFA_ScriptContext* lpScriptContext =
205 (CXFA_ScriptContext*)pDoc->GetScriptContext();
206 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(pOrginalObject);
207 CFX_WideString wsPropName = CFX_WideString::FromUTF8(
208 (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
209 if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) {
210 if (szPropName == FOXIT_XFA_FM2JS_FORMCALC_RUNTIME) {
211 XFA_FM2JS_GlobalPropertyGetter(lpScriptContext->m_hFM2JSContext, hValue);
212 return;
213 }
214 uint32_t uHashCode =
215 FX_HashCode_String_GetW(wsPropName, wsPropName.GetLength());
216 if (uHashCode != XFA_HASHCODE_Layout) {
217 CXFA_Object* pObject =
218 lpScriptContext->GetDocument()->GetXFANode(uHashCode);
219 if (pObject) {
220 FXJSE_Value_Set(hValue, lpScriptContext->GetJSValueFromMap(pObject));
221 return;
222 }
223 }
224 }
225 FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
226 XFA_RESOLVENODE_Attributes;
227 CXFA_Node* pRefNode = (CXFA_Node*)lpScriptContext->GetThisObject();
228 if (pOrginalObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
229 pRefNode = (CXFA_Node*)lpCurNode;
230 }
231 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
232 FALSE)) {
233 return;
234 }
235 dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings;
236 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
237 FALSE)) {
238 return;
239 }
240 CXFA_Object* pScriptObject =
241 lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
242 if (pScriptObject &&
243 lpScriptContext->QueryVariableHValue((CXFA_Node*)pScriptObject,
244 szPropName, hValue, TRUE)) {
245 return;
246 }
247 if (lpScriptContext->QueryBuiltinHValue(szPropName, hValue)) {
248 return;
249 }
250 IXFA_Notify* pNotify = pDoc->GetNotify();
251 if (!pNotify) {
252 return;
253 }
254 pNotify->GetDocProvider()->GetGlobalProperty(pNotify->GetHDOC(), szPropName,
255 hValue);
256 }
NormalPropertyGetter(FXJSE_HOBJECT hObject,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hValue)257 void CXFA_ScriptContext::NormalPropertyGetter(FXJSE_HOBJECT hObject,
258 const CFX_ByteStringC& szPropName,
259 FXJSE_HVALUE hValue) {
260 CXFA_Object* pOrginalObject =
261 (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
262 if (pOrginalObject == NULL) {
263 FXJSE_Value_SetUndefined(hValue);
264 return;
265 }
266 CFX_WideString wsPropName = CFX_WideString::FromUTF8(
267 (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
268 CXFA_ScriptContext* lpScriptContext =
269 (CXFA_ScriptContext*)pOrginalObject->GetDocument()->GetScriptContext();
270 CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOrginalObject);
271 if (wsPropName == FX_WSTRC(L"xfa")) {
272 FXJSE_HVALUE pValue = lpScriptContext->GetJSValueFromMap(
273 lpScriptContext->GetDocument()->GetRoot());
274 FXJSE_Value_Set(hValue, pValue);
275 return;
276 }
277 FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
278 XFA_RESOLVENODE_Attributes;
279 FX_BOOL bRet = lpScriptContext->QueryNodeByFlag(
280 (CXFA_Node*)pObject, wsPropName, hValue, dwFlag, FALSE);
281 if (bRet) {
282 return;
283 }
284 if (pObject == lpScriptContext->GetThisObject() ||
285 (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Javascript &&
286 !lpScriptContext->IsStrictScopeInJavaScript())) {
287 dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings;
288 bRet = lpScriptContext->QueryNodeByFlag((CXFA_Node*)pObject, wsPropName,
289 hValue, dwFlag, FALSE);
290 }
291 if (bRet) {
292 return;
293 }
294 CXFA_Object* pScriptObject =
295 lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
296 if (pScriptObject) {
297 bRet = lpScriptContext->QueryVariableHValue((CXFA_Node*)pScriptObject,
298 szPropName, hValue, TRUE);
299 }
300 if (!bRet) {
301 FXJSE_Value_SetUndefined(hValue);
302 }
303 }
NormalPropertySetter(FXJSE_HOBJECT hObject,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hValue)304 void CXFA_ScriptContext::NormalPropertySetter(FXJSE_HOBJECT hObject,
305 const CFX_ByteStringC& szPropName,
306 FXJSE_HVALUE hValue) {
307 CXFA_Object* pOrginalObject =
308 (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
309 if (pOrginalObject == NULL) {
310 return;
311 }
312 CXFA_ScriptContext* lpScriptContext =
313 (CXFA_ScriptContext*)pOrginalObject->GetDocument()->GetScriptContext();
314 CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOrginalObject);
315 CFX_WideString wsPropName = CFX_WideString::FromUTF8(
316 (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
317 XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo =
318 XFA_GetScriptAttributeByName(pObject->GetClassID(), wsPropName);
319 if (lpAttributeInfo) {
320 (pObject->*(lpAttributeInfo->lpfnCallback))(
321 hValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
322 } else {
323 if (pObject->IsNode()) {
324 if (wsPropName.GetAt(0) == '#') {
325 wsPropName = wsPropName.Right(wsPropName.GetLength() - 1);
326 }
327 CXFA_Node* pNode = (CXFA_Node*)pObject;
328 CXFA_Node* pPropOrChild = NULL;
329 XFA_LPCELEMENTINFO lpElementInfo = XFA_GetElementByName(wsPropName);
330 if (lpElementInfo) {
331 pPropOrChild = pNode->GetProperty(0, lpElementInfo->eName);
332 } else {
333 pPropOrChild = pNode->GetFirstChildByName(wsPropName);
334 }
335 if (pPropOrChild) {
336 CFX_WideString wsDefaultName = FX_WSTRC(L"{default}");
337 XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo =
338 XFA_GetScriptAttributeByName(pPropOrChild->GetClassID(),
339 wsDefaultName);
340 if (lpAttributeInfo) {
341 (pPropOrChild->*(lpAttributeInfo->lpfnCallback))(
342 hValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
343 return;
344 }
345 }
346 }
347 CXFA_Object* pScriptObject =
348 lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
349 if (pScriptObject) {
350 lpScriptContext->QueryVariableHValue((CXFA_Node*)pScriptObject,
351 szPropName, hValue, FALSE);
352 }
353 }
354 }
NormalPropTypeGetter(FXJSE_HOBJECT hObject,const CFX_ByteStringC & szPropName,FX_BOOL bQueryIn)355 int32_t CXFA_ScriptContext::NormalPropTypeGetter(
356 FXJSE_HOBJECT hObject,
357 const CFX_ByteStringC& szPropName,
358 FX_BOOL bQueryIn) {
359 CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
360 if (pObject == NULL) {
361 return FXJSE_ClassPropType_None;
362 }
363 CXFA_ScriptContext* lpScriptContext =
364 (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
365 pObject = lpScriptContext->GetVariablesThis(pObject);
366 XFA_ELEMENT objElement = pObject->GetClassID();
367 CFX_WideString wsPropName = CFX_WideString::FromUTF8(
368 (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
369 if (XFA_GetMethodByName(objElement, wsPropName)) {
370 return FXJSE_ClassPropType_Method;
371 }
372 if (bQueryIn && !XFA_GetScriptAttributeByName(objElement, wsPropName)) {
373 return FXJSE_ClassPropType_None;
374 }
375 return FXJSE_ClassPropType_Property;
376 }
GlobalPropTypeGetter(FXJSE_HOBJECT hObject,const CFX_ByteStringC & szPropName,FX_BOOL bQueryIn)377 int32_t CXFA_ScriptContext::GlobalPropTypeGetter(
378 FXJSE_HOBJECT hObject,
379 const CFX_ByteStringC& szPropName,
380 FX_BOOL bQueryIn) {
381 CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
382 if (pObject == NULL) {
383 return FXJSE_ClassPropType_None;
384 }
385 CXFA_ScriptContext* lpScriptContext =
386 (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
387 pObject = lpScriptContext->GetVariablesThis(pObject);
388 XFA_ELEMENT objElement = pObject->GetClassID();
389 CFX_WideString wsPropName = CFX_WideString::FromUTF8(
390 (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
391 if (XFA_GetMethodByName(objElement, wsPropName)) {
392 return FXJSE_ClassPropType_Method;
393 }
394 return FXJSE_ClassPropType_Property;
395 }
NormalMethodCall(FXJSE_HOBJECT hThis,const CFX_ByteStringC & szFuncName,CFXJSE_Arguments & args)396 void CXFA_ScriptContext::NormalMethodCall(FXJSE_HOBJECT hThis,
397 const CFX_ByteStringC& szFuncName,
398 CFXJSE_Arguments& args) {
399 CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hThis, NULL);
400 if (pObject == NULL) {
401 return;
402 }
403 CXFA_ScriptContext* lpScriptContext =
404 (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
405 pObject = lpScriptContext->GetVariablesThis(pObject);
406 CFX_WideString wsFunName = CFX_WideString::FromUTF8(
407 (const FX_CHAR*)szFuncName.GetPtr(), szFuncName.GetLength());
408 XFA_LPCMETHODINFO lpMethodInfo =
409 XFA_GetMethodByName(pObject->GetClassID(), wsFunName);
410 if (NULL == lpMethodInfo) {
411 return;
412 }
413 (pObject->*(lpMethodInfo->lpfnCallback))(&args);
414 }
IsStrictScopeInJavaScript()415 FX_BOOL CXFA_ScriptContext::IsStrictScopeInJavaScript() {
416 return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping);
417 }
GetType()418 XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() {
419 return m_eScriptType;
420 }
DefineJsContext()421 void CXFA_ScriptContext::DefineJsContext() {
422 m_JsGlobalClass.constructor = NULL;
423 m_JsGlobalClass.name = "Root";
424 m_JsGlobalClass.propNum = 0;
425 m_JsGlobalClass.properties = NULL;
426 m_JsGlobalClass.methNum = 0;
427 m_JsGlobalClass.methods = NULL;
428 m_JsGlobalClass.dynPropGetter = CXFA_ScriptContext::GlobalPropertyGetter;
429 m_JsGlobalClass.dynPropSetter = CXFA_ScriptContext::GlobalPropertySetter;
430 m_JsGlobalClass.dynPropTypeGetter = CXFA_ScriptContext::GlobalPropTypeGetter;
431 m_JsGlobalClass.dynPropDeleter = NULL;
432 m_JsGlobalClass.dynMethodCall = CXFA_ScriptContext::NormalMethodCall;
433 m_hJsContext = FXJSE_Context_Create(m_hJsRuntime, &m_JsGlobalClass,
434 m_pDocument->GetRoot());
435 FXJSE_Context_EnableCompatibleMode(
436 m_hJsContext, FXJSE_COMPATIBLEMODEFLAG_CONSTRUCTOREXTRAMETHODS);
437 }
CreateVariablesContext(CXFA_Node * pScriptNode,CXFA_Node * pSubform)438 FXJSE_HCONTEXT CXFA_ScriptContext::CreateVariablesContext(
439 CXFA_Node* pScriptNode,
440 CXFA_Node* pSubform) {
441 if (pScriptNode == NULL || pSubform == NULL) {
442 return NULL;
443 }
444 if (m_mapVariableToHValue.GetCount() == 0) {
445 m_JsGlobalVariablesClass.constructor = NULL;
446 m_JsGlobalVariablesClass.name = "XFAScriptObject";
447 m_JsGlobalVariablesClass.propNum = 0;
448 m_JsGlobalVariablesClass.properties = NULL;
449 m_JsGlobalVariablesClass.methNum = 0;
450 m_JsGlobalVariablesClass.methods = NULL;
451 m_JsGlobalVariablesClass.dynPropGetter =
452 CXFA_ScriptContext::GlobalPropertyGetter;
453 m_JsGlobalVariablesClass.dynPropSetter =
454 CXFA_ScriptContext::GlobalPropertySetter;
455 m_JsGlobalVariablesClass.dynPropTypeGetter =
456 CXFA_ScriptContext::NormalPropTypeGetter;
457 m_JsGlobalVariablesClass.dynPropDeleter = NULL;
458 m_JsGlobalVariablesClass.dynMethodCall =
459 CXFA_ScriptContext::NormalMethodCall;
460 }
461 CXFA_ThisProxy* lpVariableNode = new CXFA_ThisProxy(pSubform, pScriptNode);
462 FXJSE_HCONTEXT hVariablesContext = FXJSE_Context_Create(
463 m_hJsRuntime, &m_JsGlobalVariablesClass, (CXFA_Object*)lpVariableNode);
464 FXJSE_Context_EnableCompatibleMode(
465 hVariablesContext, FXJSE_COMPATIBLEMODEFLAG_CONSTRUCTOREXTRAMETHODS);
466 m_mapVariableToHValue.SetAt(pScriptNode, hVariablesContext);
467 return hVariablesContext;
468 }
GetVariablesThis(CXFA_Object * pObject,FX_BOOL bScriptNode)469 CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject,
470 FX_BOOL bScriptNode) {
471 if (pObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
472 return bScriptNode ? ((CXFA_ThisProxy*)pObject)->GetScriptNode()
473 : ((CXFA_ThisProxy*)pObject)->GetThisNode();
474 }
475 return pObject;
476 }
RunVariablesScript(CXFA_Node * pScriptNode)477 FX_BOOL CXFA_ScriptContext::RunVariablesScript(CXFA_Node* pScriptNode) {
478 if (pScriptNode == NULL) {
479 return FALSE;
480 }
481 if (pScriptNode->GetClassID() == XFA_ELEMENT_Script) {
482 CXFA_Node* pParent = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent);
483 if (!pParent || pParent->GetClassID() != XFA_ELEMENT_Variables) {
484 return FALSE;
485 }
486 if (m_mapVariableToHValue.GetValueAt(pScriptNode)) {
487 return TRUE;
488 }
489 CXFA_Node* pTextNode = pScriptNode->GetNodeItem(XFA_NODEITEM_FirstChild);
490 if (!pTextNode) {
491 return FALSE;
492 }
493 CFX_WideStringC wsScript;
494 if (!pTextNode->TryCData(XFA_ATTRIBUTE_Value, wsScript)) {
495 return FALSE;
496 }
497 CFX_ByteString btScript =
498 FX_UTF8Encode(wsScript.GetPtr(), wsScript.GetLength());
499 FXJSE_HVALUE hRetValue = FXJSE_Value_Create(m_hJsRuntime);
500 CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent);
501 FXJSE_HCONTEXT hVariablesContext =
502 CreateVariablesContext(pScriptNode, pThisObject);
503 CXFA_Object* pOriginalObject = m_pThisObject;
504 m_pThisObject = pThisObject;
505 FX_BOOL bRet = FXJSE_ExecuteScript(hVariablesContext, btScript, hRetValue);
506 m_pThisObject = pOriginalObject;
507 FXJSE_Value_Release(hRetValue);
508 return bRet;
509 }
510 return TRUE;
511 }
QueryVariableHValue(CXFA_Node * pScriptNode,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hValue,FX_BOOL bGetter)512 FX_BOOL CXFA_ScriptContext::QueryVariableHValue(
513 CXFA_Node* pScriptNode,
514 const CFX_ByteStringC& szPropName,
515 FXJSE_HVALUE hValue,
516 FX_BOOL bGetter) {
517 if (pScriptNode->GetClassID() != XFA_ELEMENT_Script) {
518 return FALSE;
519 }
520 CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent);
521 if (!variablesNode || variablesNode->GetClassID() != XFA_ELEMENT_Variables) {
522 return FALSE;
523 }
524 FX_BOOL bRes = FALSE;
525 void* lpVariables = m_mapVariableToHValue.GetValueAt(pScriptNode);
526 if (lpVariables) {
527 FXJSE_HCONTEXT hVariableContext = (FXJSE_HCONTEXT)lpVariables;
528 FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(hVariableContext);
529 FXJSE_HVALUE hVariableValue = FXJSE_Value_Create(m_hJsRuntime);
530 if (!bGetter) {
531 FXJSE_Value_SetObjectOwnProp(hObject, szPropName, hValue);
532 bRes = TRUE;
533 } else if (FXJSE_Value_ObjectHasOwnProp(hObject, szPropName, FALSE)) {
534 FXJSE_Value_GetObjectProp(hObject, szPropName, hVariableValue);
535 if (FXJSE_Value_IsFunction(hVariableValue)) {
536 FXJSE_Value_SetFunctionBind(hValue, hVariableValue, hObject);
537 } else if (bGetter) {
538 FXJSE_Value_Set(hValue, hVariableValue);
539 } else {
540 FXJSE_Value_Set(hVariableValue, hValue);
541 }
542 bRes = TRUE;
543 }
544 FXJSE_Value_Release(hVariableValue);
545 FXJSE_Value_Release(hObject);
546 }
547 return bRes;
548 }
QueryBuiltinHValue(const CFX_ByteStringC & szPropName,FXJSE_HVALUE hValue)549 FX_BOOL CXFA_ScriptContext::QueryBuiltinHValue(
550 const CFX_ByteStringC& szPropName,
551 FXJSE_HVALUE hValue) {
552 void* pBuiltin = NULL;
553 if ((m_dwBuiltInInFlags & XFA_JSBUILTIN_HasCount) &&
554 m_JSBuiltInObjects.Lookup(szPropName, pBuiltin)) {
555 FXJSE_Value_Set(hValue, (FXJSE_HVALUE)pBuiltin);
556 return TRUE;
557 }
558 return FALSE;
559 }
ReleaseVariablesMap()560 void CXFA_ScriptContext::ReleaseVariablesMap() {
561 FX_POSITION ps = m_mapVariableToHValue.GetStartPosition();
562 while (ps) {
563 CXFA_Object* pScriptNode;
564 FXJSE_HCONTEXT hVariableContext;
565 m_mapVariableToHValue.GetNextAssoc(ps, pScriptNode, hVariableContext);
566 FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(hVariableContext);
567 CXFA_Object* lpCurNode = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
568 if (lpCurNode) {
569 delete (CXFA_ThisProxy*)lpCurNode;
570 lpCurNode = NULL;
571 }
572 FXJSE_Value_Release(hObject);
573 FXJSE_Context_Release(hVariableContext);
574 hVariableContext = NULL;
575 }
576 m_mapVariableToHValue.RemoveAll();
577 }
DefineJsClass()578 void CXFA_ScriptContext::DefineJsClass() {
579 m_JsNormalClass.constructor = NULL;
580 m_JsNormalClass.name = "XFAObject";
581 m_JsNormalClass.propNum = 0;
582 m_JsNormalClass.properties = NULL;
583 m_JsNormalClass.methNum = 0;
584 m_JsNormalClass.methods = NULL;
585 m_JsNormalClass.dynPropGetter = CXFA_ScriptContext::NormalPropertyGetter;
586 m_JsNormalClass.dynPropSetter = CXFA_ScriptContext::NormalPropertySetter;
587 m_JsNormalClass.dynPropTypeGetter = CXFA_ScriptContext::NormalPropTypeGetter;
588 m_JsNormalClass.dynPropDeleter = NULL;
589 m_JsNormalClass.dynMethodCall = CXFA_ScriptContext::NormalMethodCall;
590 m_hJsClass = FXJSE_DefineClass(m_hJsContext, &m_JsNormalClass);
591 }
GetJseNormalClass()592 FXJSE_HCLASS CXFA_ScriptContext::GetJseNormalClass() {
593 return m_hJsClass;
594 }
AddJSBuiltinObject(XFA_LPCJSBUILTININFO pBuitinObject)595 void CXFA_ScriptContext::AddJSBuiltinObject(
596 XFA_LPCJSBUILTININFO pBuitinObject) {
597 if (m_dwBuiltInInFlags & XFA_JSBUILTIN_Initialized) {
598 return;
599 }
600 m_JSBuiltInObjects.SetAt(pBuitinObject->pName, (void*)pBuitinObject);
601 }
ResolveObjects(CXFA_Object * refNode,const CFX_WideStringC & wsExpression,XFA_RESOLVENODE_RS & resolveNodeRS,FX_DWORD dwStyles,CXFA_Node * bindNode)602 int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode,
603 const CFX_WideStringC& wsExpression,
604 XFA_RESOLVENODE_RS& resolveNodeRS,
605 FX_DWORD dwStyles,
606 CXFA_Node* bindNode) {
607 if (wsExpression.IsEmpty()) {
608 return 0;
609 }
610 if (m_eScriptType != XFA_SCRIPTLANGTYPE_Formcalc ||
611 (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) {
612 m_upObjectArray.RemoveAll();
613 }
614 if (refNode &&
615 (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings)) &&
616 refNode->IsNode()) {
617 m_upObjectArray.Add((CXFA_Node*)refNode);
618 }
619 FX_BOOL bNextCreate = FALSE;
620 if (dwStyles & XFA_RESOLVENODE_CreateNode) {
621 m_pResolveProcessor->GetNodeHelper()->XFA_SetCreateNodeType(bindNode);
622 }
623 m_pResolveProcessor->GetNodeHelper()->m_pCreateParent = NULL;
624 m_pResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1;
625 CXFA_ResolveNodesData rndFind;
626 int32_t nStart = 0;
627 int32_t nLevel = 0;
628 int32_t nRet = -1;
629 rndFind.m_pSC = this;
630 CXFA_ObjArray findNodes;
631 if (refNode != NULL) {
632 findNodes.Add(refNode);
633 } else {
634 findNodes.Add(m_pDocument->GetRoot());
635 }
636 int32_t nNodes = 0;
637 while (TRUE) {
638 nNodes = findNodes.GetSize();
639 int32_t i = 0;
640 rndFind.m_dwStyles = dwStyles;
641 m_pResolveProcessor->m_iCurStart = nStart;
642 nStart = m_pResolveProcessor->XFA_ResolveNodes_GetFilter(wsExpression,
643 nStart, rndFind);
644 if (nStart < 1) {
645 if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) {
646 CXFA_Node* pDataNode = NULL;
647 nStart = m_pResolveProcessor->GetNodeHelper()->m_iCurAllStart;
648 if (nStart != -1) {
649 pDataNode = m_pDocument->GetNotBindNode(findNodes);
650 if (pDataNode) {
651 findNodes.RemoveAll();
652 findNodes.Add(pDataNode);
653 break;
654 }
655 } else {
656 pDataNode = (CXFA_Node*)findNodes[0];
657 findNodes.RemoveAll();
658 findNodes.Add(pDataNode);
659 break;
660 }
661 dwStyles |= XFA_RESOLVENODE_Bind;
662 findNodes.RemoveAll();
663 findNodes.Add(m_pResolveProcessor->GetNodeHelper()->m_pAllStartParent);
664 continue;
665 } else {
666 break;
667 }
668 }
669 if (bNextCreate) {
670 FX_BOOL bCreate =
671 m_pResolveProcessor->GetNodeHelper()->XFA_ResolveNodes_CreateNode(
672 rndFind.m_wsName, rndFind.m_wsCondition,
673 nStart == wsExpression.GetLength(), this);
674 if (bCreate) {
675 continue;
676 } else {
677 break;
678 }
679 }
680 CXFA_ObjArray retNodes;
681 while (i < nNodes) {
682 FX_BOOL bDataBind = FALSE;
683 if (((dwStyles & XFA_RESOLVENODE_Bind) ||
684 (dwStyles & XFA_RESOLVENODE_CreateNode)) &&
685 nNodes > 1) {
686 CXFA_ResolveNodesData rndBind;
687 m_pResolveProcessor->XFA_ResolveNodes_GetFilter(wsExpression, nStart,
688 rndBind);
689 m_pResolveProcessor->XFA_ResolveNode_SetIndexDataBind(
690 rndBind.m_wsCondition, i, nNodes);
691 bDataBind = TRUE;
692 }
693 rndFind.m_CurNode = findNodes[i++];
694 rndFind.m_nLevel = nLevel;
695 rndFind.m_dwFlag = XFA_RESOVENODE_RSTYPE_Nodes;
696 nRet = m_pResolveProcessor->XFA_ResolveNodes(rndFind);
697 if (nRet < 1) {
698 continue;
699 }
700 if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute &&
701 rndFind.m_pScriptAttribute && nStart < wsExpression.GetLength()) {
702 FXJSE_HVALUE hValue = FXJSE_Value_Create(m_hJsRuntime);
703 (rndFind.m_Nodes[0]->*(rndFind.m_pScriptAttribute->lpfnCallback))(
704 hValue, FALSE,
705 (XFA_ATTRIBUTE)rndFind.m_pScriptAttribute->eAttribute);
706 rndFind.m_Nodes.SetAt(0,
707 (CXFA_Object*)FXJSE_Value_ToObject(hValue, NULL));
708 FXJSE_Value_Release(hValue);
709 }
710 int32_t iSize = m_upObjectArray.GetSize();
711 if (iSize) {
712 m_upObjectArray.RemoveAt(iSize - 1);
713 }
714 retNodes.Append(rndFind.m_Nodes);
715 rndFind.m_Nodes.RemoveAll();
716 if (bDataBind) {
717 break;
718 }
719 }
720 findNodes.RemoveAll();
721 nNodes = retNodes.GetSize();
722 if (nNodes < 1) {
723 if (dwStyles & XFA_RESOLVENODE_CreateNode) {
724 bNextCreate = TRUE;
725 if (m_pResolveProcessor->GetNodeHelper()->m_pCreateParent == NULL) {
726 m_pResolveProcessor->GetNodeHelper()->m_pCreateParent =
727 (CXFA_Node*)rndFind.m_CurNode;
728 m_pResolveProcessor->GetNodeHelper()->m_iCreateCount = 1;
729 }
730 FX_BOOL bCreate =
731 m_pResolveProcessor->GetNodeHelper()->XFA_ResolveNodes_CreateNode(
732 rndFind.m_wsName, rndFind.m_wsCondition,
733 nStart == wsExpression.GetLength(), this);
734 if (bCreate) {
735 continue;
736 } else {
737 break;
738 }
739 } else {
740 break;
741 }
742 }
743 findNodes.Copy(retNodes);
744 rndFind.m_Nodes.RemoveAll();
745 if (nLevel == 0) {
746 dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
747 }
748 nLevel++;
749 }
750 if (!bNextCreate) {
751 resolveNodeRS.dwFlags = rndFind.m_dwFlag;
752 if (nNodes > 0) {
753 resolveNodeRS.nodes.Append(findNodes);
754 }
755 if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute) {
756 resolveNodeRS.pScriptAttribute = rndFind.m_pScriptAttribute;
757 return 1;
758 }
759 }
760 if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind |
761 XFA_RESOLVENODE_BindNew)) {
762 m_pResolveProcessor->XFA_ResolveNode_SetResultCreateNode(
763 resolveNodeRS, rndFind.m_wsCondition);
764 if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) {
765 resolveNodeRS.dwFlags = XFA_RESOVENODE_RSTYPE_ExistNodes;
766 }
767 return resolveNodeRS.nodes.GetSize();
768 }
769 return nNodes;
770 }
GetJSValueFromMap(CXFA_Object * pObject)771 FXJSE_HVALUE CXFA_ScriptContext::GetJSValueFromMap(CXFA_Object* pObject) {
772 if (!pObject) {
773 return NULL;
774 }
775 if (pObject->IsNode()) {
776 RunVariablesScript((CXFA_Node*)pObject);
777 }
778 void* pValue = m_mapXFAToHValue.GetValueAt(pObject);
779 if (pValue == NULL) {
780 FXJSE_HVALUE jsHvalue = FXJSE_Value_Create(m_hJsRuntime);
781 FXJSE_Value_SetObject(jsHvalue, pObject, m_hJsClass);
782 m_mapXFAToHValue.SetAt(pObject, jsHvalue);
783 pValue = jsHvalue;
784 }
785 return (FXJSE_HVALUE)pValue;
786 }
GetIndexByName(CXFA_Node * refNode)787 int32_t CXFA_ScriptContext::GetIndexByName(CXFA_Node* refNode) {
788 CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
789 return lpNodeHelper->XFA_GetIndex(refNode, XFA_LOGIC_Transparent,
790 lpNodeHelper->XFA_NodeIsProperty(refNode),
791 FALSE);
792 }
GetIndexByClassName(CXFA_Node * refNode)793 int32_t CXFA_ScriptContext::GetIndexByClassName(CXFA_Node* refNode) {
794 CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
795 return lpNodeHelper->XFA_GetIndex(refNode, XFA_LOGIC_Transparent,
796 lpNodeHelper->XFA_NodeIsProperty(refNode),
797 TRUE);
798 }
GetSomExpression(CXFA_Node * refNode,CFX_WideString & wsExpression)799 void CXFA_ScriptContext::GetSomExpression(CXFA_Node* refNode,
800 CFX_WideString& wsExpression) {
801 CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
802 lpNodeHelper->XFA_GetNameExpression(refNode, wsExpression, TRUE,
803 XFA_LOGIC_Transparent);
804 }
SetNodesOfRunScript(CXFA_NodeArray * pArray)805 void CXFA_ScriptContext::SetNodesOfRunScript(CXFA_NodeArray* pArray) {
806 m_pScriptNodeArray = pArray;
807 }
AddNodesOfRunScript(const CXFA_NodeArray & nodes)808 void CXFA_ScriptContext::AddNodesOfRunScript(const CXFA_NodeArray& nodes) {
809 if (!m_pScriptNodeArray) {
810 return;
811 }
812 if (nodes.GetSize() > 0) {
813 m_pScriptNodeArray->Copy(nodes);
814 }
815 }
AddNodesOfRunScript(CXFA_Node * pNode)816 void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) {
817 if (!m_pScriptNodeArray) {
818 return;
819 }
820 if (m_pScriptNodeArray->Find(pNode) == -1) {
821 m_pScriptNodeArray->Add(pNode);
822 }
823 }
XFA_ScriptContext_Create(CXFA_Document * pDocument)824 IXFA_ScriptContext* XFA_ScriptContext_Create(CXFA_Document* pDocument) {
825 return new CXFA_ScriptContext(pDocument);
826 }
827 static const XFA_JSBUILTININFO gs_JSBUILTINData[] = {
828 {0x8108b9a9, "Number"},
829 {0xe07e3fbe, "Date"},
830 };
831 const int32_t g_iJSBuiltinCount =
832 sizeof(XFA_JSBUILTININFO) / sizeof(XFA_JSBUILTININFO);
XFA_GetJSBuiltinByHash(uint32_t uHashCode)833 XFA_LPCJSBUILTININFO XFA_GetJSBuiltinByHash(uint32_t uHashCode) {
834 int32_t iStart = 0, iEnd = g_iJSBuiltinCount - 1, iMid;
835 do {
836 iMid = (iStart + iEnd) / 2;
837 XFA_LPCJSBUILTININFO pInfo = gs_JSBUILTINData + iMid;
838 if (uHashCode == pInfo->uUnicodeHash) {
839 return pInfo;
840 } else if (uHashCode < pInfo->uUnicodeHash) {
841 iEnd = iMid - 1;
842 } else {
843 iStart = iMid + 1;
844 }
845 } while (iStart <= iEnd);
846 return NULL;
847 }
848