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