| 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 "xfa/fxfa/parser/xfa_script_imp.h" | |
| 8 | |
| 9 #include "core/fxcrt/include/fx_ext.h" | |
| 10 #include "fxjs/include/cfxjse_arguments.h" | |
| 11 #include "fxjs/include/cfxjse_class.h" | |
| 12 #include "fxjs/include/cfxjse_value.h" | |
| 13 #include "xfa/fxfa/app/xfa_ffnotify.h" | |
| 14 #include "xfa/fxfa/include/cxfa_eventparam.h" | |
| 15 #include "xfa/fxfa/parser/xfa_doclayout.h" | |
| 16 #include "xfa/fxfa/parser/xfa_document.h" | |
| 17 #include "xfa/fxfa/parser/xfa_localemgr.h" | |
| 18 #include "xfa/fxfa/parser/xfa_object.h" | |
| 19 #include "xfa/fxfa/parser/xfa_script.h" | |
| 20 #include "xfa/fxfa/parser/xfa_script_nodehelper.h" | |
| 21 #include "xfa/fxfa/parser/xfa_script_resolveprocessor.h" | |
| 22 #include "xfa/fxfa/parser/xfa_utils.h" | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { | |
| 27 "Root", // name | |
| 28 nullptr, // constructor | |
| 29 nullptr, // properties | |
| 30 nullptr, // methods | |
| 31 0, // property count | |
| 32 0, // method count | |
| 33 CXFA_ScriptContext::GlobalPropTypeGetter, | |
| 34 CXFA_ScriptContext::GlobalPropertyGetter, | |
| 35 CXFA_ScriptContext::GlobalPropertySetter, | |
| 36 nullptr, // property deleter | |
| 37 CXFA_ScriptContext::NormalMethodCall, | |
| 38 }; | |
| 39 | |
| 40 const FXJSE_CLASS_DESCRIPTOR NormalClassDescriptor = { | |
| 41 "XFAObject", // name | |
| 42 nullptr, // constructor | |
| 43 nullptr, // properties | |
| 44 nullptr, // methods | |
| 45 0, // property count | |
| 46 0, // method count | |
| 47 CXFA_ScriptContext::NormalPropTypeGetter, | |
| 48 CXFA_ScriptContext::NormalPropertyGetter, | |
| 49 CXFA_ScriptContext::NormalPropertySetter, | |
| 50 nullptr, // property deleter | |
| 51 CXFA_ScriptContext::NormalMethodCall, | |
| 52 }; | |
| 53 | |
| 54 const FXJSE_CLASS_DESCRIPTOR VariablesClassDescriptor = { | |
| 55 "XFAScriptObject", // name | |
| 56 nullptr, // constructor | |
| 57 nullptr, // properties | |
| 58 nullptr, // methods | |
| 59 0, // property count | |
| 60 0, // method count | |
| 61 CXFA_ScriptContext::NormalPropTypeGetter, | |
| 62 CXFA_ScriptContext::GlobalPropertyGetter, | |
| 63 CXFA_ScriptContext::GlobalPropertySetter, | |
| 64 nullptr, // property deleter | |
| 65 CXFA_ScriptContext::NormalMethodCall, | |
| 66 }; | |
| 67 | |
| 68 const char kFormCalcRuntime[] = "foxit_xfa_formcalc_runtime"; | |
| 69 | |
| 70 CXFA_ThisProxy* ToThisProxy(CFXJSE_Value* pValue, CFXJSE_Class* pClass) { | |
| 71 return static_cast<CXFA_ThisProxy*>(pValue->ToHostObject(pClass)); | |
| 72 } | |
| 73 | |
| 74 } // namespace | |
| 75 | |
| 76 // static. | |
| 77 CXFA_Object* CXFA_ScriptContext::ToObject(CFXJSE_Value* pValue, | |
| 78 CFXJSE_Class* pClass) { | |
| 79 return static_cast<CXFA_Object*>(pValue->ToHostObject(pClass)); | |
| 80 } | |
| 81 | |
| 82 CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument) | |
| 83 : m_pDocument(pDocument), | |
| 84 m_pIsolate(nullptr), | |
| 85 m_pJsClass(nullptr), | |
| 86 m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown), | |
| 87 m_pScriptNodeArray(nullptr), | |
| 88 m_pThisObject(nullptr), | |
| 89 m_dwBuiltInInFlags(0), | |
| 90 m_eRunAtType(XFA_ATTRIBUTEENUM_Client) {} | |
| 91 | |
| 92 CXFA_ScriptContext::~CXFA_ScriptContext() { | |
| 93 FX_POSITION ps = m_mapVariableToContext.GetStartPosition(); | |
| 94 while (ps) { | |
| 95 CXFA_Object* pScriptNode; | |
| 96 CFXJSE_Context* pVariableContext = nullptr; | |
| 97 m_mapVariableToContext.GetNextAssoc(ps, pScriptNode, pVariableContext); | |
| 98 | |
| 99 delete ToThisProxy(pVariableContext->GetGlobalObject().get(), nullptr); | |
| 100 delete pVariableContext; | |
| 101 } | |
| 102 m_mapVariableToContext.RemoveAll(); | |
| 103 | |
| 104 m_upObjectArray.RemoveAll(); | |
| 105 } | |
| 106 void CXFA_ScriptContext::Initialize(v8::Isolate* pIsolate) { | |
| 107 m_pIsolate = pIsolate; | |
| 108 DefineJsContext(); | |
| 109 DefineJsClass(); | |
| 110 m_ResolveProcessor.reset(new CXFA_ResolveProcessor); | |
| 111 } | |
| 112 FX_BOOL CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType, | |
| 113 const CFX_WideStringC& wsScript, | |
| 114 CFXJSE_Value* hRetValue, | |
| 115 CXFA_Object* pThisObject) { | |
| 116 CFX_ByteString btScript; | |
| 117 XFA_SCRIPTLANGTYPE eSaveType = m_eScriptType; | |
| 118 m_eScriptType = eScriptType; | |
| 119 if (eScriptType == XFA_SCRIPTLANGTYPE_Formcalc) { | |
| 120 if (!m_FM2JSContext) { | |
| 121 m_FM2JSContext.reset( | |
| 122 new CXFA_FM2JSContext(m_pIsolate, m_JsContext.get(), m_pDocument)); | |
| 123 } | |
| 124 CFX_WideTextBuf wsJavaScript; | |
| 125 CFX_WideString wsErrorInfo; | |
| 126 int32_t iFlags = | |
| 127 CXFA_FM2JSContext::Translate(wsScript, wsJavaScript, wsErrorInfo); | |
| 128 if (iFlags) { | |
| 129 hRetValue->SetUndefined(); | |
| 130 return FALSE; | |
| 131 } | |
| 132 btScript = | |
| 133 FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength()); | |
| 134 } else { | |
| 135 btScript = FX_UTF8Encode(wsScript.c_str(), wsScript.GetLength()); | |
| 136 } | |
| 137 CXFA_Object* pOriginalObject = m_pThisObject; | |
| 138 m_pThisObject = pThisObject; | |
| 139 CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : nullptr; | |
| 140 FX_BOOL bRet = | |
| 141 m_JsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue); | |
| 142 m_pThisObject = pOriginalObject; | |
| 143 m_eScriptType = eSaveType; | |
| 144 return bRet; | |
| 145 } | |
| 146 void CXFA_ScriptContext::GlobalPropertySetter(CFXJSE_Value* pObject, | |
| 147 const CFX_ByteStringC& szPropName, | |
| 148 CFXJSE_Value* pValue) { | |
| 149 CXFA_Object* lpOrginalNode = ToObject(pObject, nullptr); | |
| 150 CXFA_Document* pDoc = lpOrginalNode->GetDocument(); | |
| 151 CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); | |
| 152 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode); | |
| 153 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | |
| 154 uint32_t dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | | |
| 155 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | | |
| 156 XFA_RESOLVENODE_Attributes; | |
| 157 CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); | |
| 158 if (lpOrginalNode->IsVariablesThis()) | |
| 159 pRefNode = ToNode(lpCurNode); | |
| 160 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, | |
| 161 dwFlag, TRUE)) { | |
| 162 return; | |
| 163 } | |
| 164 if (lpOrginalNode->IsVariablesThis()) { | |
| 165 if (pValue && pValue->IsUndefined()) { | |
| 166 pObject->SetObjectOwnProperty(szPropName, pValue); | |
| 167 return; | |
| 168 } | |
| 169 } | |
| 170 CXFA_FFNotify* pNotify = pDoc->GetNotify(); | |
| 171 if (!pNotify) { | |
| 172 return; | |
| 173 } | |
| 174 pNotify->GetDocProvider()->SetGlobalProperty(pNotify->GetHDOC(), szPropName, | |
| 175 pValue); | |
| 176 } | |
| 177 FX_BOOL CXFA_ScriptContext::QueryNodeByFlag(CXFA_Node* refNode, | |
| 178 const CFX_WideStringC& propname, | |
| 179 CFXJSE_Value* pValue, | |
| 180 uint32_t dwFlag, | |
| 181 FX_BOOL bSetting) { | |
| 182 if (!refNode) | |
| 183 return false; | |
| 184 XFA_RESOLVENODE_RS resolveRs; | |
| 185 if (ResolveObjects(refNode, propname, resolveRs, dwFlag) <= 0) | |
| 186 return false; | |
| 187 if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { | |
| 188 pValue->Assign(GetJSValueFromMap(resolveRs.nodes[0])); | |
| 189 return true; | |
| 190 } | |
| 191 if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) { | |
| 192 const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = resolveRs.pScriptAttribute; | |
| 193 if (lpAttributeInfo) { | |
| 194 (resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))( | |
| 195 pValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); | |
| 196 } | |
| 197 } | |
| 198 return true; | |
| 199 } | |
| 200 void CXFA_ScriptContext::GlobalPropertyGetter(CFXJSE_Value* pObject, | |
| 201 const CFX_ByteStringC& szPropName, | |
| 202 CFXJSE_Value* pValue) { | |
| 203 CXFA_Object* pOriginalObject = ToObject(pObject, nullptr); | |
| 204 CXFA_Document* pDoc = pOriginalObject->GetDocument(); | |
| 205 CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); | |
| 206 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(pOriginalObject); | |
| 207 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | |
| 208 if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) { | |
| 209 if (szPropName == kFormCalcRuntime) { | |
| 210 lpScriptContext->m_FM2JSContext->GlobalPropertyGetter(pValue); | |
| 211 return; | |
| 212 } | |
| 213 XFA_HashCode uHashCode = static_cast<XFA_HashCode>( | |
| 214 FX_HashCode_GetW(wsPropName.AsStringC(), false)); | |
| 215 if (uHashCode != XFA_HASHCODE_Layout) { | |
| 216 CXFA_Object* pObj = | |
| 217 lpScriptContext->GetDocument()->GetXFAObject(uHashCode); | |
| 218 if (pObj) { | |
| 219 pValue->Assign(lpScriptContext->GetJSValueFromMap(pObj)); | |
| 220 return; | |
| 221 } | |
| 222 } | |
| 223 } | |
| 224 uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | | |
| 225 XFA_RESOLVENODE_Attributes; | |
| 226 CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); | |
| 227 if (pOriginalObject->IsVariablesThis()) { | |
| 228 pRefNode = ToNode(lpCurNode); | |
| 229 } | |
| 230 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, | |
| 231 dwFlag, FALSE)) { | |
| 232 return; | |
| 233 } | |
| 234 dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; | |
| 235 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, | |
| 236 dwFlag, FALSE)) { | |
| 237 return; | |
| 238 } | |
| 239 CXFA_Object* pScriptObject = | |
| 240 lpScriptContext->GetVariablesThis(pOriginalObject, TRUE); | |
| 241 if (pScriptObject && | |
| 242 lpScriptContext->QueryVariableValue(pScriptObject->AsNode(), szPropName, | |
| 243 pValue, TRUE)) { | |
| 244 return; | |
| 245 } | |
| 246 CXFA_FFNotify* pNotify = pDoc->GetNotify(); | |
| 247 if (!pNotify) { | |
| 248 return; | |
| 249 } | |
| 250 pNotify->GetDocProvider()->GetGlobalProperty(pNotify->GetHDOC(), szPropName, | |
| 251 pValue); | |
| 252 } | |
| 253 void CXFA_ScriptContext::NormalPropertyGetter(CFXJSE_Value* pOriginalValue, | |
| 254 const CFX_ByteStringC& szPropName, | |
| 255 CFXJSE_Value* pReturnValue) { | |
| 256 CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); | |
| 257 if (!pOriginalObject) { | |
| 258 pReturnValue->SetUndefined(); | |
| 259 return; | |
| 260 } | |
| 261 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | |
| 262 CXFA_ScriptContext* lpScriptContext = | |
| 263 pOriginalObject->GetDocument()->GetScriptContext(); | |
| 264 CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); | |
| 265 if (wsPropName == FX_WSTRC(L"xfa")) { | |
| 266 CFXJSE_Value* pValue = lpScriptContext->GetJSValueFromMap( | |
| 267 lpScriptContext->GetDocument()->GetRoot()); | |
| 268 pReturnValue->Assign(pValue); | |
| 269 return; | |
| 270 } | |
| 271 uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | | |
| 272 XFA_RESOLVENODE_Attributes; | |
| 273 FX_BOOL bRet = lpScriptContext->QueryNodeByFlag( | |
| 274 ToNode(pObject), wsPropName.AsStringC(), pReturnValue, dwFlag, FALSE); | |
| 275 if (bRet) { | |
| 276 return; | |
| 277 } | |
| 278 if (pObject == lpScriptContext->GetThisObject() || | |
| 279 (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Javascript && | |
| 280 !lpScriptContext->IsStrictScopeInJavaScript())) { | |
| 281 dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; | |
| 282 bRet = lpScriptContext->QueryNodeByFlag( | |
| 283 ToNode(pObject), wsPropName.AsStringC(), pReturnValue, dwFlag, FALSE); | |
| 284 } | |
| 285 if (bRet) { | |
| 286 return; | |
| 287 } | |
| 288 CXFA_Object* pScriptObject = | |
| 289 lpScriptContext->GetVariablesThis(pOriginalObject, TRUE); | |
| 290 if (pScriptObject) { | |
| 291 bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject), | |
| 292 szPropName, pReturnValue, TRUE); | |
| 293 } | |
| 294 if (!bRet) { | |
| 295 pReturnValue->SetUndefined(); | |
| 296 } | |
| 297 } | |
| 298 void CXFA_ScriptContext::NormalPropertySetter(CFXJSE_Value* pOriginalValue, | |
| 299 const CFX_ByteStringC& szPropName, | |
| 300 CFXJSE_Value* pReturnValue) { | |
| 301 CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); | |
| 302 if (!pOriginalObject) | |
| 303 return; | |
| 304 | |
| 305 CXFA_ScriptContext* lpScriptContext = | |
| 306 pOriginalObject->GetDocument()->GetScriptContext(); | |
| 307 CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); | |
| 308 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | |
| 309 const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = XFA_GetScriptAttributeByName( | |
| 310 pObject->GetElementType(), wsPropName.AsStringC()); | |
| 311 if (lpAttributeInfo) { | |
| 312 (pObject->*(lpAttributeInfo->lpfnCallback))( | |
| 313 pReturnValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); | |
| 314 } else { | |
| 315 if (pObject->IsNode()) { | |
| 316 if (wsPropName.GetAt(0) == '#') { | |
| 317 wsPropName = wsPropName.Right(wsPropName.GetLength() - 1); | |
| 318 } | |
| 319 CXFA_Node* pNode = ToNode(pObject); | |
| 320 CXFA_Node* pPropOrChild = nullptr; | |
| 321 XFA_Element eType = XFA_GetElementTypeForName(wsPropName.AsStringC()); | |
| 322 if (eType != XFA_Element::Unknown) | |
| 323 pPropOrChild = pNode->GetProperty(0, eType); | |
| 324 else | |
| 325 pPropOrChild = pNode->GetFirstChildByName(wsPropName.AsStringC()); | |
| 326 | |
| 327 if (pPropOrChild) { | |
| 328 CFX_WideString wsDefaultName(L"{default}"); | |
| 329 const XFA_SCRIPTATTRIBUTEINFO* lpAttrInfo = | |
| 330 XFA_GetScriptAttributeByName(pPropOrChild->GetElementType(), | |
| 331 wsDefaultName.AsStringC()); | |
| 332 if (lpAttrInfo) { | |
| 333 (pPropOrChild->*(lpAttrInfo->lpfnCallback))( | |
| 334 pReturnValue, TRUE, (XFA_ATTRIBUTE)lpAttrInfo->eAttribute); | |
| 335 return; | |
| 336 } | |
| 337 } | |
| 338 } | |
| 339 CXFA_Object* pScriptObject = | |
| 340 lpScriptContext->GetVariablesThis(pOriginalObject, TRUE); | |
| 341 if (pScriptObject) { | |
| 342 lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName, | |
| 343 pReturnValue, FALSE); | |
| 344 } | |
| 345 } | |
| 346 } | |
| 347 int32_t CXFA_ScriptContext::NormalPropTypeGetter( | |
| 348 CFXJSE_Value* pOriginalValue, | |
| 349 const CFX_ByteStringC& szPropName, | |
| 350 FX_BOOL bQueryIn) { | |
| 351 CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); | |
| 352 if (!pObject) | |
| 353 return FXJSE_ClassPropType_None; | |
| 354 | |
| 355 CXFA_ScriptContext* lpScriptContext = | |
| 356 pObject->GetDocument()->GetScriptContext(); | |
| 357 pObject = lpScriptContext->GetVariablesThis(pObject); | |
| 358 XFA_Element eType = pObject->GetElementType(); | |
| 359 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | |
| 360 if (XFA_GetMethodByName(eType, wsPropName.AsStringC())) { | |
| 361 return FXJSE_ClassPropType_Method; | |
| 362 } | |
| 363 if (bQueryIn && | |
| 364 !XFA_GetScriptAttributeByName(eType, wsPropName.AsStringC())) { | |
| 365 return FXJSE_ClassPropType_None; | |
| 366 } | |
| 367 return FXJSE_ClassPropType_Property; | |
| 368 } | |
| 369 int32_t CXFA_ScriptContext::GlobalPropTypeGetter( | |
| 370 CFXJSE_Value* pOriginalValue, | |
| 371 const CFX_ByteStringC& szPropName, | |
| 372 FX_BOOL bQueryIn) { | |
| 373 CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); | |
| 374 if (!pObject) | |
| 375 return FXJSE_ClassPropType_None; | |
| 376 | |
| 377 CXFA_ScriptContext* lpScriptContext = | |
| 378 pObject->GetDocument()->GetScriptContext(); | |
| 379 pObject = lpScriptContext->GetVariablesThis(pObject); | |
| 380 XFA_Element eType = pObject->GetElementType(); | |
| 381 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | |
| 382 if (XFA_GetMethodByName(eType, wsPropName.AsStringC())) { | |
| 383 return FXJSE_ClassPropType_Method; | |
| 384 } | |
| 385 return FXJSE_ClassPropType_Property; | |
| 386 } | |
| 387 void CXFA_ScriptContext::NormalMethodCall(CFXJSE_Value* pThis, | |
| 388 const CFX_ByteStringC& szFuncName, | |
| 389 CFXJSE_Arguments& args) { | |
| 390 CXFA_Object* pObject = ToObject(pThis, nullptr); | |
| 391 if (!pObject) | |
| 392 return; | |
| 393 | |
| 394 CXFA_ScriptContext* lpScriptContext = | |
| 395 pObject->GetDocument()->GetScriptContext(); | |
| 396 pObject = lpScriptContext->GetVariablesThis(pObject); | |
| 397 CFX_WideString wsFunName = CFX_WideString::FromUTF8(szFuncName); | |
| 398 const XFA_METHODINFO* lpMethodInfo = | |
| 399 XFA_GetMethodByName(pObject->GetElementType(), wsFunName.AsStringC()); | |
| 400 if (!lpMethodInfo) | |
| 401 return; | |
| 402 | |
| 403 (pObject->*(lpMethodInfo->lpfnCallback))(&args); | |
| 404 } | |
| 405 FX_BOOL CXFA_ScriptContext::IsStrictScopeInJavaScript() { | |
| 406 return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); | |
| 407 } | |
| 408 XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() { | |
| 409 return m_eScriptType; | |
| 410 } | |
| 411 void CXFA_ScriptContext::DefineJsContext() { | |
| 412 m_JsContext.reset(CFXJSE_Context::Create(m_pIsolate, &GlobalClassDescriptor, | |
| 413 m_pDocument->GetRoot())); | |
| 414 RemoveBuiltInObjs(m_JsContext.get()); | |
| 415 m_JsContext->EnableCompatibleMode(); | |
| 416 } | |
| 417 CFXJSE_Context* CXFA_ScriptContext::CreateVariablesContext( | |
| 418 CXFA_Node* pScriptNode, | |
| 419 CXFA_Node* pSubform) { | |
| 420 if (!pScriptNode || !pSubform) | |
| 421 return nullptr; | |
| 422 | |
| 423 CFXJSE_Context* pVariablesContext = | |
| 424 CFXJSE_Context::Create(m_pIsolate, &VariablesClassDescriptor, | |
| 425 new CXFA_ThisProxy(pSubform, pScriptNode)); | |
| 426 RemoveBuiltInObjs(pVariablesContext); | |
| 427 pVariablesContext->EnableCompatibleMode(); | |
| 428 m_mapVariableToContext.SetAt(pScriptNode, pVariablesContext); | |
| 429 return pVariablesContext; | |
| 430 } | |
| 431 CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject, | |
| 432 FX_BOOL bScriptNode) { | |
| 433 if (!pObject->IsVariablesThis()) | |
| 434 return pObject; | |
| 435 | |
| 436 CXFA_ThisProxy* pProxy = static_cast<CXFA_ThisProxy*>(pObject); | |
| 437 return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); | |
| 438 } | |
| 439 | |
| 440 FX_BOOL CXFA_ScriptContext::RunVariablesScript(CXFA_Node* pScriptNode) { | |
| 441 if (!pScriptNode) | |
| 442 return FALSE; | |
| 443 | |
| 444 if (pScriptNode->GetElementType() != XFA_Element::Script) | |
| 445 return TRUE; | |
| 446 | |
| 447 CXFA_Node* pParent = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); | |
| 448 if (!pParent || pParent->GetElementType() != XFA_Element::Variables) | |
| 449 return FALSE; | |
| 450 | |
| 451 if (m_mapVariableToContext.GetValueAt(pScriptNode)) | |
| 452 return TRUE; | |
| 453 | |
| 454 CXFA_Node* pTextNode = pScriptNode->GetNodeItem(XFA_NODEITEM_FirstChild); | |
| 455 if (!pTextNode) | |
| 456 return FALSE; | |
| 457 | |
| 458 CFX_WideStringC wsScript; | |
| 459 if (!pTextNode->TryCData(XFA_ATTRIBUTE_Value, wsScript)) | |
| 460 return FALSE; | |
| 461 | |
| 462 CFX_ByteString btScript = | |
| 463 FX_UTF8Encode(wsScript.c_str(), wsScript.GetLength()); | |
| 464 std::unique_ptr<CFXJSE_Value> hRetValue(new CFXJSE_Value(m_pIsolate)); | |
| 465 CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent); | |
| 466 CFXJSE_Context* pVariablesContext = | |
| 467 CreateVariablesContext(pScriptNode, pThisObject); | |
| 468 CXFA_Object* pOriginalObject = m_pThisObject; | |
| 469 m_pThisObject = pThisObject; | |
| 470 FX_BOOL bRet = | |
| 471 pVariablesContext->ExecuteScript(btScript.c_str(), hRetValue.get()); | |
| 472 m_pThisObject = pOriginalObject; | |
| 473 return bRet; | |
| 474 } | |
| 475 | |
| 476 FX_BOOL CXFA_ScriptContext::QueryVariableValue( | |
| 477 CXFA_Node* pScriptNode, | |
| 478 const CFX_ByteStringC& szPropName, | |
| 479 CFXJSE_Value* pValue, | |
| 480 FX_BOOL bGetter) { | |
| 481 if (!pScriptNode || pScriptNode->GetElementType() != XFA_Element::Script) | |
| 482 return FALSE; | |
| 483 | |
| 484 CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); | |
| 485 if (!variablesNode || | |
| 486 variablesNode->GetElementType() != XFA_Element::Variables) | |
| 487 return FALSE; | |
| 488 | |
| 489 void* lpVariables = m_mapVariableToContext.GetValueAt(pScriptNode); | |
| 490 if (!lpVariables) | |
| 491 return FALSE; | |
| 492 | |
| 493 FX_BOOL bRes = FALSE; | |
| 494 CFXJSE_Context* pVariableContext = static_cast<CFXJSE_Context*>(lpVariables); | |
| 495 std::unique_ptr<CFXJSE_Value> pObject = pVariableContext->GetGlobalObject(); | |
| 496 std::unique_ptr<CFXJSE_Value> hVariableValue(new CFXJSE_Value(m_pIsolate)); | |
| 497 if (!bGetter) { | |
| 498 pObject->SetObjectOwnProperty(szPropName, pValue); | |
| 499 bRes = TRUE; | |
| 500 } else if (pObject->HasObjectOwnProperty(szPropName, FALSE)) { | |
| 501 pObject->GetObjectProperty(szPropName, hVariableValue.get()); | |
| 502 if (hVariableValue->IsFunction()) | |
| 503 pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); | |
| 504 else if (bGetter) | |
| 505 pValue->Assign(hVariableValue.get()); | |
| 506 else | |
| 507 hVariableValue.get()->Assign(pValue); | |
| 508 bRes = TRUE; | |
| 509 } | |
| 510 return bRes; | |
| 511 } | |
| 512 | |
| 513 void CXFA_ScriptContext::DefineJsClass() { | |
| 514 m_pJsClass = CFXJSE_Class::Create(m_JsContext.get(), &NormalClassDescriptor); | |
| 515 } | |
| 516 | |
| 517 void CXFA_ScriptContext::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { | |
| 518 static const CFX_ByteStringC OBJ_NAME[2] = {"Number", "Date"}; | |
| 519 std::unique_ptr<CFXJSE_Value> pObject = pContext->GetGlobalObject(); | |
| 520 std::unique_ptr<CFXJSE_Value> hProp(new CFXJSE_Value(m_pIsolate)); | |
| 521 for (int i = 0; i < 2; ++i) { | |
| 522 if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) | |
| 523 pObject->DeleteObjectProperty(OBJ_NAME[i]); | |
| 524 } | |
| 525 } | |
| 526 CFXJSE_Class* CXFA_ScriptContext::GetJseNormalClass() { | |
| 527 return m_pJsClass; | |
| 528 } | |
| 529 int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode, | |
| 530 const CFX_WideStringC& wsExpression, | |
| 531 XFA_RESOLVENODE_RS& resolveNodeRS, | |
| 532 uint32_t dwStyles, | |
| 533 CXFA_Node* bindNode) { | |
| 534 if (wsExpression.IsEmpty()) { | |
| 535 return 0; | |
| 536 } | |
| 537 if (m_eScriptType != XFA_SCRIPTLANGTYPE_Formcalc || | |
| 538 (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { | |
| 539 m_upObjectArray.RemoveAll(); | |
| 540 } | |
| 541 if (refNode && refNode->IsNode() && | |
| 542 (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { | |
| 543 m_upObjectArray.Add(refNode->AsNode()); | |
| 544 } | |
| 545 FX_BOOL bNextCreate = FALSE; | |
| 546 if (dwStyles & XFA_RESOLVENODE_CreateNode) { | |
| 547 m_ResolveProcessor->GetNodeHelper()->SetCreateNodeType(bindNode); | |
| 548 } | |
| 549 m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = nullptr; | |
| 550 m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1; | |
| 551 CXFA_ResolveNodesData rndFind; | |
| 552 int32_t nStart = 0; | |
| 553 int32_t nLevel = 0; | |
| 554 int32_t nRet = -1; | |
| 555 rndFind.m_pSC = this; | |
| 556 CXFA_ObjArray findNodes; | |
| 557 findNodes.Add(refNode ? refNode : m_pDocument->GetRoot()); | |
| 558 int32_t nNodes = 0; | |
| 559 while (TRUE) { | |
| 560 nNodes = findNodes.GetSize(); | |
| 561 int32_t i = 0; | |
| 562 rndFind.m_dwStyles = dwStyles; | |
| 563 m_ResolveProcessor->SetCurStart(nStart); | |
| 564 nStart = m_ResolveProcessor->GetFilter(wsExpression, nStart, rndFind); | |
| 565 if (nStart < 1) { | |
| 566 if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) { | |
| 567 CXFA_Node* pDataNode = nullptr; | |
| 568 nStart = m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart; | |
| 569 if (nStart != -1) { | |
| 570 pDataNode = m_pDocument->GetNotBindNode(findNodes); | |
| 571 if (pDataNode) { | |
| 572 findNodes.RemoveAll(); | |
| 573 findNodes.Add(pDataNode); | |
| 574 break; | |
| 575 } | |
| 576 } else { | |
| 577 pDataNode = findNodes[0]->AsNode(); | |
| 578 findNodes.RemoveAll(); | |
| 579 findNodes.Add(pDataNode); | |
| 580 break; | |
| 581 } | |
| 582 dwStyles |= XFA_RESOLVENODE_Bind; | |
| 583 findNodes.RemoveAll(); | |
| 584 findNodes.Add(m_ResolveProcessor->GetNodeHelper()->m_pAllStartParent); | |
| 585 continue; | |
| 586 } else { | |
| 587 break; | |
| 588 } | |
| 589 } | |
| 590 if (bNextCreate) { | |
| 591 FX_BOOL bCreate = | |
| 592 m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( | |
| 593 rndFind.m_wsName, rndFind.m_wsCondition, | |
| 594 nStart == wsExpression.GetLength(), this); | |
| 595 if (bCreate) { | |
| 596 continue; | |
| 597 } else { | |
| 598 break; | |
| 599 } | |
| 600 } | |
| 601 CXFA_ObjArray retNodes; | |
| 602 while (i < nNodes) { | |
| 603 FX_BOOL bDataBind = FALSE; | |
| 604 if (((dwStyles & XFA_RESOLVENODE_Bind) || | |
| 605 (dwStyles & XFA_RESOLVENODE_CreateNode)) && | |
| 606 nNodes > 1) { | |
| 607 CXFA_ResolveNodesData rndBind; | |
| 608 m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind); | |
| 609 m_ResolveProcessor->SetIndexDataBind(rndBind.m_wsCondition, i, nNodes); | |
| 610 bDataBind = TRUE; | |
| 611 } | |
| 612 rndFind.m_CurNode = findNodes[i++]; | |
| 613 rndFind.m_nLevel = nLevel; | |
| 614 rndFind.m_dwFlag = XFA_RESOVENODE_RSTYPE_Nodes; | |
| 615 nRet = m_ResolveProcessor->Resolve(rndFind); | |
| 616 if (nRet < 1) { | |
| 617 continue; | |
| 618 } | |
| 619 if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute && | |
| 620 rndFind.m_pScriptAttribute && nStart < wsExpression.GetLength()) { | |
| 621 std::unique_ptr<CFXJSE_Value> pValue(new CFXJSE_Value(m_pIsolate)); | |
| 622 (rndFind.m_Nodes[0]->*(rndFind.m_pScriptAttribute->lpfnCallback))( | |
| 623 pValue.get(), FALSE, | |
| 624 (XFA_ATTRIBUTE)rndFind.m_pScriptAttribute->eAttribute); | |
| 625 rndFind.m_Nodes.SetAt(0, ToObject(pValue.get(), nullptr)); | |
| 626 } | |
| 627 int32_t iSize = m_upObjectArray.GetSize(); | |
| 628 if (iSize) { | |
| 629 m_upObjectArray.RemoveAt(iSize - 1); | |
| 630 } | |
| 631 retNodes.Append(rndFind.m_Nodes); | |
| 632 rndFind.m_Nodes.RemoveAll(); | |
| 633 if (bDataBind) { | |
| 634 break; | |
| 635 } | |
| 636 } | |
| 637 findNodes.RemoveAll(); | |
| 638 nNodes = retNodes.GetSize(); | |
| 639 if (nNodes < 1) { | |
| 640 if (dwStyles & XFA_RESOLVENODE_CreateNode) { | |
| 641 bNextCreate = TRUE; | |
| 642 if (!m_ResolveProcessor->GetNodeHelper()->m_pCreateParent) { | |
| 643 m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = | |
| 644 ToNode(rndFind.m_CurNode); | |
| 645 m_ResolveProcessor->GetNodeHelper()->m_iCreateCount = 1; | |
| 646 } | |
| 647 FX_BOOL bCreate = | |
| 648 m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( | |
| 649 rndFind.m_wsName, rndFind.m_wsCondition, | |
| 650 nStart == wsExpression.GetLength(), this); | |
| 651 if (bCreate) { | |
| 652 continue; | |
| 653 } else { | |
| 654 break; | |
| 655 } | |
| 656 } else { | |
| 657 break; | |
| 658 } | |
| 659 } | |
| 660 findNodes.Copy(retNodes); | |
| 661 rndFind.m_Nodes.RemoveAll(); | |
| 662 if (nLevel == 0) { | |
| 663 dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); | |
| 664 } | |
| 665 nLevel++; | |
| 666 } | |
| 667 if (!bNextCreate) { | |
| 668 resolveNodeRS.dwFlags = rndFind.m_dwFlag; | |
| 669 if (nNodes > 0) { | |
| 670 resolveNodeRS.nodes.Append(findNodes); | |
| 671 } | |
| 672 if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute) { | |
| 673 resolveNodeRS.pScriptAttribute = rndFind.m_pScriptAttribute; | |
| 674 return 1; | |
| 675 } | |
| 676 } | |
| 677 if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind | | |
| 678 XFA_RESOLVENODE_BindNew)) { | |
| 679 m_ResolveProcessor->SetResultCreateNode(resolveNodeRS, | |
| 680 rndFind.m_wsCondition); | |
| 681 if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) { | |
| 682 resolveNodeRS.dwFlags = XFA_RESOVENODE_RSTYPE_ExistNodes; | |
| 683 } | |
| 684 return resolveNodeRS.nodes.GetSize(); | |
| 685 } | |
| 686 return nNodes; | |
| 687 } | |
| 688 | |
| 689 void CXFA_ScriptContext::AddToCacheList(std::unique_ptr<CXFA_NodeList> pList) { | |
| 690 m_CacheList.push_back(std::move(pList)); | |
| 691 } | |
| 692 | |
| 693 CFXJSE_Value* CXFA_ScriptContext::GetJSValueFromMap(CXFA_Object* pObject) { | |
| 694 if (!pObject) | |
| 695 return nullptr; | |
| 696 if (pObject->IsNode()) | |
| 697 RunVariablesScript(pObject->AsNode()); | |
| 698 | |
| 699 auto iter = m_mapObjectToValue.find(pObject); | |
| 700 if (iter != m_mapObjectToValue.end()) | |
| 701 return iter->second.get(); | |
| 702 | |
| 703 std::unique_ptr<CFXJSE_Value> jsValue(new CFXJSE_Value(m_pIsolate)); | |
| 704 jsValue->SetObject(pObject, m_pJsClass); | |
| 705 CFXJSE_Value* pValue = jsValue.get(); | |
| 706 m_mapObjectToValue.insert(std::make_pair(pObject, std::move(jsValue))); | |
| 707 return pValue; | |
| 708 } | |
| 709 int32_t CXFA_ScriptContext::GetIndexByName(CXFA_Node* refNode) { | |
| 710 CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); | |
| 711 return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, | |
| 712 lpNodeHelper->NodeIsProperty(refNode), FALSE); | |
| 713 } | |
| 714 int32_t CXFA_ScriptContext::GetIndexByClassName(CXFA_Node* refNode) { | |
| 715 CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); | |
| 716 return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, | |
| 717 lpNodeHelper->NodeIsProperty(refNode), TRUE); | |
| 718 } | |
| 719 void CXFA_ScriptContext::GetSomExpression(CXFA_Node* refNode, | |
| 720 CFX_WideString& wsExpression) { | |
| 721 CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); | |
| 722 lpNodeHelper->GetNameExpression(refNode, wsExpression, TRUE, | |
| 723 XFA_LOGIC_Transparent); | |
| 724 } | |
| 725 void CXFA_ScriptContext::SetNodesOfRunScript(CXFA_NodeArray* pArray) { | |
| 726 m_pScriptNodeArray = pArray; | |
| 727 } | |
| 728 void CXFA_ScriptContext::AddNodesOfRunScript(const CXFA_NodeArray& nodes) { | |
| 729 if (!m_pScriptNodeArray) | |
| 730 return; | |
| 731 if (nodes.GetSize() > 0) | |
| 732 m_pScriptNodeArray->Copy(nodes); | |
| 733 } | |
| 734 void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) { | |
| 735 if (!m_pScriptNodeArray) | |
| 736 return; | |
| 737 if (m_pScriptNodeArray->Find(pNode) == -1) | |
| 738 m_pScriptNodeArray->Add(pNode); | |
| 739 } | |
| OLD | NEW |