OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "xfa/fxfa/parser/xfa_script_imp.h" | 7 #include "xfa/fxfa/parser/xfa_script_imp.h" |
8 | 8 |
9 #include "core/fxcrt/include/fx_ext.h" | 9 #include "core/fxcrt/include/fx_ext.h" |
10 #include "xfa/fxfa/app/xfa_ffnotify.h" | 10 #include "xfa/fxfa/app/xfa_ffnotify.h" |
11 #include "xfa/fxfa/parser/xfa_doclayout.h" | 11 #include "xfa/fxfa/parser/xfa_doclayout.h" |
12 #include "xfa/fxfa/parser/xfa_document.h" | 12 #include "xfa/fxfa/parser/xfa_document.h" |
13 #include "xfa/fxfa/parser/xfa_localemgr.h" | 13 #include "xfa/fxfa/parser/xfa_localemgr.h" |
14 #include "xfa/fxfa/parser/xfa_object.h" | 14 #include "xfa/fxfa/parser/xfa_object.h" |
15 #include "xfa/fxfa/parser/xfa_parser.h" | 15 #include "xfa/fxfa/parser/xfa_parser.h" |
16 #include "xfa/fxfa/parser/xfa_script.h" | 16 #include "xfa/fxfa/parser/xfa_script.h" |
17 #include "xfa/fxfa/parser/xfa_script_nodehelper.h" | 17 #include "xfa/fxfa/parser/xfa_script_nodehelper.h" |
18 #include "xfa/fxfa/parser/xfa_script_resolveprocessor.h" | 18 #include "xfa/fxfa/parser/xfa_script_resolveprocessor.h" |
19 #include "xfa/fxfa/parser/xfa_utils.h" | 19 #include "xfa/fxfa/parser/xfa_utils.h" |
20 #include "xfa/fxjse/cfxjse_arguments.h" | 20 #include "xfa/fxjse/cfxjse_arguments.h" |
| 21 #include "xfa/fxjse/class.h" |
21 #include "xfa/fxjse/value.h" | 22 #include "xfa/fxjse/value.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { | 26 const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { |
26 "Root", // name | 27 "Root", // name |
27 nullptr, // constructor | 28 nullptr, // constructor |
28 nullptr, // properties | 29 nullptr, // properties |
29 nullptr, // methods | 30 nullptr, // methods |
30 0, // property count | 31 0, // property count |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 while (ps) { | 98 while (ps) { |
98 CXFA_Object* pXFAObj; | 99 CXFA_Object* pXFAObj; |
99 CFXJSE_Value* pValue; | 100 CFXJSE_Value* pValue; |
100 m_mapXFAToValue.GetNextAssoc(ps, pXFAObj, pValue); | 101 m_mapXFAToValue.GetNextAssoc(ps, pXFAObj, pValue); |
101 delete pValue; | 102 delete pValue; |
102 } | 103 } |
103 m_mapXFAToValue.RemoveAll(); | 104 m_mapXFAToValue.RemoveAll(); |
104 ReleaseVariablesMap(); | 105 ReleaseVariablesMap(); |
105 | 106 |
106 delete m_hFM2JSContext; | 107 delete m_hFM2JSContext; |
| 108 delete m_pJsContext; |
107 | 109 |
108 if (m_pJsContext) { | |
109 FXJSE_Context_Release(m_pJsContext); | |
110 m_pJsContext = NULL; | |
111 } | |
112 delete m_pResolveProcessor; | 110 delete m_pResolveProcessor; |
113 m_upObjectArray.RemoveAll(); | 111 m_upObjectArray.RemoveAll(); |
114 for (int32_t i = 0; i < m_CacheListArray.GetSize(); i++) | 112 for (int32_t i = 0; i < m_CacheListArray.GetSize(); i++) |
115 delete m_CacheListArray[i]; | 113 delete m_CacheListArray[i]; |
116 } | 114 } |
117 void CXFA_ScriptContext::Initialize(v8::Isolate* pIsolate) { | 115 void CXFA_ScriptContext::Initialize(v8::Isolate* pIsolate) { |
118 m_pIsolate = pIsolate; | 116 m_pIsolate = pIsolate; |
119 DefineJsContext(); | 117 DefineJsContext(); |
120 DefineJsClass(); | 118 DefineJsClass(); |
121 m_pResolveProcessor = new CXFA_ResolveProcessor; | 119 m_pResolveProcessor = new CXFA_ResolveProcessor; |
(...skipping 20 matching lines...) Expand all Loading... |
142 } | 140 } |
143 btScript = | 141 btScript = |
144 FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength()); | 142 FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength()); |
145 } else { | 143 } else { |
146 btScript = FX_UTF8Encode(wsScript.c_str(), wsScript.GetLength()); | 144 btScript = FX_UTF8Encode(wsScript.c_str(), wsScript.GetLength()); |
147 } | 145 } |
148 CXFA_Object* pOriginalObject = m_pThisObject; | 146 CXFA_Object* pOriginalObject = m_pThisObject; |
149 m_pThisObject = pThisObject; | 147 m_pThisObject = pThisObject; |
150 CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : NULL; | 148 CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : NULL; |
151 FX_BOOL bRet = | 149 FX_BOOL bRet = |
152 FXJSE_ExecuteScript(m_pJsContext, btScript.c_str(), hRetValue, pValue); | 150 m_pJsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue); |
153 m_pThisObject = pOriginalObject; | 151 m_pThisObject = pOriginalObject; |
154 m_eScriptType = eSaveType; | 152 m_eScriptType = eSaveType; |
155 return bRet; | 153 return bRet; |
156 } | 154 } |
157 void CXFA_ScriptContext::GlobalPropertySetter(CFXJSE_Value* pObject, | 155 void CXFA_ScriptContext::GlobalPropertySetter(CFXJSE_Value* pObject, |
158 const CFX_ByteStringC& szPropName, | 156 const CFX_ByteStringC& szPropName, |
159 CFXJSE_Value* pValue) { | 157 CFXJSE_Value* pValue) { |
160 CXFA_Object* lpOrginalNode = ToObject(pObject, nullptr); | 158 CXFA_Object* lpOrginalNode = ToObject(pObject, nullptr); |
161 CXFA_Document* pDoc = lpOrginalNode->GetDocument(); | 159 CXFA_Document* pDoc = lpOrginalNode->GetDocument(); |
162 CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); | 160 CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); |
163 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode); | 161 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode); |
164 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); | 162 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); |
165 uint32_t dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | | 163 uint32_t dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | |
166 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | | 164 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | |
167 XFA_RESOLVENODE_Attributes; | 165 XFA_RESOLVENODE_Attributes; |
168 CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); | 166 CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); |
169 if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) { | 167 if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) { |
170 pRefNode = ToNode(lpCurNode); | 168 pRefNode = ToNode(lpCurNode); |
171 } | 169 } |
172 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, | 170 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, |
173 dwFlag, TRUE)) { | 171 dwFlag, TRUE)) { |
174 return; | 172 return; |
175 } | 173 } |
176 if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) { | 174 if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) { |
177 if (FXJSE_Value_IsUndefined(pValue)) { | 175 if (pValue && pValue->IsUndefined()) { |
178 pObject->SetObjectOwnProperty(szPropName, pValue); | 176 pObject->SetObjectOwnProperty(szPropName, pValue); |
179 return; | 177 return; |
180 } | 178 } |
181 } | 179 } |
182 CXFA_FFNotify* pNotify = pDoc->GetNotify(); | 180 CXFA_FFNotify* pNotify = pDoc->GetNotify(); |
183 if (!pNotify) { | 181 if (!pNotify) { |
184 return; | 182 return; |
185 } | 183 } |
186 pNotify->GetDocProvider()->SetGlobalProperty(pNotify->GetHDOC(), szPropName, | 184 pNotify->GetDocProvider()->SetGlobalProperty(pNotify->GetHDOC(), szPropName, |
187 pValue); | 185 pValue); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 | 413 |
416 (pObject->*(lpMethodInfo->lpfnCallback))(&args); | 414 (pObject->*(lpMethodInfo->lpfnCallback))(&args); |
417 } | 415 } |
418 FX_BOOL CXFA_ScriptContext::IsStrictScopeInJavaScript() { | 416 FX_BOOL CXFA_ScriptContext::IsStrictScopeInJavaScript() { |
419 return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); | 417 return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); |
420 } | 418 } |
421 XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() { | 419 XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() { |
422 return m_eScriptType; | 420 return m_eScriptType; |
423 } | 421 } |
424 void CXFA_ScriptContext::DefineJsContext() { | 422 void CXFA_ScriptContext::DefineJsContext() { |
425 m_pJsContext = FXJSE_Context_Create(m_pIsolate, &GlobalClassDescriptor, | 423 m_pJsContext = CFXJSE_Context::Create(m_pIsolate, &GlobalClassDescriptor, |
426 m_pDocument->GetRoot()); | 424 m_pDocument->GetRoot()); |
427 RemoveBuiltInObjs(m_pJsContext); | 425 RemoveBuiltInObjs(m_pJsContext); |
428 FXJSE_Context_EnableCompatibleMode(m_pJsContext); | 426 m_pJsContext->EnableCompatibleMode(); |
429 } | 427 } |
430 CFXJSE_Context* CXFA_ScriptContext::CreateVariablesContext( | 428 CFXJSE_Context* CXFA_ScriptContext::CreateVariablesContext( |
431 CXFA_Node* pScriptNode, | 429 CXFA_Node* pScriptNode, |
432 CXFA_Node* pSubform) { | 430 CXFA_Node* pSubform) { |
433 if (!pScriptNode || !pSubform) | 431 if (!pScriptNode || !pSubform) |
434 return nullptr; | 432 return nullptr; |
435 | 433 |
436 CFXJSE_Context* pVariablesContext = | 434 CFXJSE_Context* pVariablesContext = |
437 FXJSE_Context_Create(m_pIsolate, &VariablesClassDescriptor, | 435 CFXJSE_Context::Create(m_pIsolate, &VariablesClassDescriptor, |
438 new CXFA_ThisProxy(pSubform, pScriptNode)); | 436 new CXFA_ThisProxy(pSubform, pScriptNode)); |
439 RemoveBuiltInObjs(pVariablesContext); | 437 RemoveBuiltInObjs(pVariablesContext); |
440 FXJSE_Context_EnableCompatibleMode(pVariablesContext); | 438 pVariablesContext->EnableCompatibleMode(); |
441 m_mapVariableToContext.SetAt(pScriptNode, pVariablesContext); | 439 m_mapVariableToContext.SetAt(pScriptNode, pVariablesContext); |
442 return pVariablesContext; | 440 return pVariablesContext; |
443 } | 441 } |
444 CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject, | 442 CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject, |
445 FX_BOOL bScriptNode) { | 443 FX_BOOL bScriptNode) { |
446 if (pObject->GetObjectType() != XFA_OBJECTTYPE_VariablesThis) | 444 if (pObject->GetObjectType() != XFA_OBJECTTYPE_VariablesThis) |
447 return pObject; | 445 return pObject; |
448 | 446 |
449 CXFA_ThisProxy* pProxy = static_cast<CXFA_ThisProxy*>(pObject); | 447 CXFA_ThisProxy* pProxy = static_cast<CXFA_ThisProxy*>(pObject); |
450 return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); | 448 return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); |
(...skipping 23 matching lines...) Expand all Loading... |
474 | 472 |
475 CFX_ByteString btScript = | 473 CFX_ByteString btScript = |
476 FX_UTF8Encode(wsScript.c_str(), wsScript.GetLength()); | 474 FX_UTF8Encode(wsScript.c_str(), wsScript.GetLength()); |
477 std::unique_ptr<CFXJSE_Value> hRetValue(new CFXJSE_Value(m_pIsolate)); | 475 std::unique_ptr<CFXJSE_Value> hRetValue(new CFXJSE_Value(m_pIsolate)); |
478 CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent); | 476 CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent); |
479 CFXJSE_Context* pVariablesContext = | 477 CFXJSE_Context* pVariablesContext = |
480 CreateVariablesContext(pScriptNode, pThisObject); | 478 CreateVariablesContext(pScriptNode, pThisObject); |
481 CXFA_Object* pOriginalObject = m_pThisObject; | 479 CXFA_Object* pOriginalObject = m_pThisObject; |
482 m_pThisObject = pThisObject; | 480 m_pThisObject = pThisObject; |
483 FX_BOOL bRet = | 481 FX_BOOL bRet = |
484 FXJSE_ExecuteScript(pVariablesContext, btScript.c_str(), hRetValue.get()); | 482 pVariablesContext->ExecuteScript(btScript.c_str(), hRetValue.get()); |
485 m_pThisObject = pOriginalObject; | 483 m_pThisObject = pOriginalObject; |
486 return bRet; | 484 return bRet; |
487 } | 485 } |
488 | 486 |
489 FX_BOOL CXFA_ScriptContext::QueryVariableValue( | 487 FX_BOOL CXFA_ScriptContext::QueryVariableValue( |
490 CXFA_Node* pScriptNode, | 488 CXFA_Node* pScriptNode, |
491 const CFX_ByteStringC& szPropName, | 489 const CFX_ByteStringC& szPropName, |
492 CFXJSE_Value* pValue, | 490 CFXJSE_Value* pValue, |
493 FX_BOOL bGetter) { | 491 FX_BOOL bGetter) { |
494 if (!pScriptNode || pScriptNode->GetClassID() != XFA_ELEMENT_Script) | 492 if (!pScriptNode || pScriptNode->GetClassID() != XFA_ELEMENT_Script) |
495 return FALSE; | 493 return FALSE; |
496 | 494 |
497 CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); | 495 CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); |
498 if (!variablesNode || variablesNode->GetClassID() != XFA_ELEMENT_Variables) | 496 if (!variablesNode || variablesNode->GetClassID() != XFA_ELEMENT_Variables) |
499 return FALSE; | 497 return FALSE; |
500 | 498 |
501 void* lpVariables = m_mapVariableToContext.GetValueAt(pScriptNode); | 499 void* lpVariables = m_mapVariableToContext.GetValueAt(pScriptNode); |
502 if (!lpVariables) | 500 if (!lpVariables) |
503 return FALSE; | 501 return FALSE; |
504 | 502 |
505 FX_BOOL bRes = FALSE; | 503 FX_BOOL bRes = FALSE; |
506 CFXJSE_Context* pVariableContext = static_cast<CFXJSE_Context*>(lpVariables); | 504 CFXJSE_Context* pVariableContext = static_cast<CFXJSE_Context*>(lpVariables); |
507 std::unique_ptr<CFXJSE_Value> pObject( | 505 std::unique_ptr<CFXJSE_Value> pObject( |
508 FXJSE_Context_GetGlobalObject(pVariableContext)); | 506 new CFXJSE_Value(pVariableContext->GetRuntime())); |
| 507 pVariableContext->GetGlobalObject(pObject.get()); |
| 508 |
509 std::unique_ptr<CFXJSE_Value> hVariableValue(new CFXJSE_Value(m_pIsolate)); | 509 std::unique_ptr<CFXJSE_Value> hVariableValue(new CFXJSE_Value(m_pIsolate)); |
510 if (!bGetter) { | 510 if (!bGetter) { |
511 pObject->SetObjectOwnProperty(szPropName, pValue); | 511 pObject->SetObjectOwnProperty(szPropName, pValue); |
512 bRes = TRUE; | 512 bRes = TRUE; |
513 } else if (pObject->HasObjectOwnProperty(szPropName, FALSE)) { | 513 } else if (pObject->HasObjectOwnProperty(szPropName, FALSE)) { |
514 pObject->GetObjectProperty(szPropName, hVariableValue.get()); | 514 pObject->GetObjectProperty(szPropName, hVariableValue.get()); |
515 if (FXJSE_Value_IsFunction(hVariableValue.get())) | 515 if (hVariableValue->IsFunction()) |
516 pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); | 516 pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); |
517 else if (bGetter) | 517 else if (bGetter) |
518 pValue->Assign(hVariableValue.get()); | 518 pValue->Assign(hVariableValue.get()); |
519 else | 519 else |
520 hVariableValue.get()->Assign(pValue); | 520 hVariableValue.get()->Assign(pValue); |
521 bRes = TRUE; | 521 bRes = TRUE; |
522 } | 522 } |
523 return bRes; | 523 return bRes; |
524 } | 524 } |
525 | 525 |
526 void CXFA_ScriptContext::ReleaseVariablesMap() { | 526 void CXFA_ScriptContext::ReleaseVariablesMap() { |
527 FX_POSITION ps = m_mapVariableToContext.GetStartPosition(); | 527 FX_POSITION ps = m_mapVariableToContext.GetStartPosition(); |
528 while (ps) { | 528 while (ps) { |
529 CXFA_Object* pScriptNode; | 529 CXFA_Object* pScriptNode; |
530 CFXJSE_Context* pVariableContext = nullptr; | 530 CFXJSE_Context* pVariableContext = nullptr; |
531 m_mapVariableToContext.GetNextAssoc(ps, pScriptNode, pVariableContext); | 531 m_mapVariableToContext.GetNextAssoc(ps, pScriptNode, pVariableContext); |
532 std::unique_ptr<CFXJSE_Value> pObject( | 532 std::unique_ptr<CFXJSE_Value> pObject( |
533 FXJSE_Context_GetGlobalObject(pVariableContext)); | 533 new CFXJSE_Value(pVariableContext->GetRuntime())); |
| 534 pVariableContext->GetGlobalObject(pObject.get()); |
| 535 |
534 delete ToThisProxy(pObject.get(), nullptr); | 536 delete ToThisProxy(pObject.get(), nullptr); |
535 FXJSE_Context_Release(pVariableContext); | 537 delete pVariableContext; |
536 } | 538 } |
537 m_mapVariableToContext.RemoveAll(); | 539 m_mapVariableToContext.RemoveAll(); |
538 } | 540 } |
539 | 541 |
540 void CXFA_ScriptContext::DefineJsClass() { | 542 void CXFA_ScriptContext::DefineJsClass() { |
541 m_pJsClass = FXJSE_DefineClass(m_pJsContext, &NormalClassDescriptor); | 543 m_pJsClass = CFXJSE_Class::Create(m_pJsContext, &NormalClassDescriptor); |
542 } | 544 } |
543 | 545 |
544 void CXFA_ScriptContext::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { | 546 void CXFA_ScriptContext::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { |
545 static const CFX_ByteStringC OBJ_NAME[2] = {"Number", "Date"}; | 547 static const CFX_ByteStringC OBJ_NAME[2] = {"Number", "Date"}; |
546 std::unique_ptr<CFXJSE_Value> pObject( | 548 std::unique_ptr<CFXJSE_Value> pObject( |
547 FXJSE_Context_GetGlobalObject(pContext)); | 549 new CFXJSE_Value(pContext->GetRuntime())); |
| 550 pContext->GetGlobalObject(pObject.get()); |
| 551 |
548 std::unique_ptr<CFXJSE_Value> hProp(new CFXJSE_Value(m_pIsolate)); | 552 std::unique_ptr<CFXJSE_Value> hProp(new CFXJSE_Value(m_pIsolate)); |
549 for (int i = 0; i < 2; ++i) { | 553 for (int i = 0; i < 2; ++i) { |
550 if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) | 554 if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) |
551 pObject.get()->DeleteObjectProperty(OBJ_NAME[i]); | 555 pObject.get()->DeleteObjectProperty(OBJ_NAME[i]); |
552 } | 556 } |
553 } | 557 } |
554 CFXJSE_Class* CXFA_ScriptContext::GetJseNormalClass() { | 558 CFXJSE_Class* CXFA_ScriptContext::GetJseNormalClass() { |
555 return m_pJsClass; | 559 return m_pJsClass; |
556 } | 560 } |
557 int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode, | 561 int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode, |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 } | 765 } |
762 } | 766 } |
763 void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) { | 767 void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) { |
764 if (!m_pScriptNodeArray) { | 768 if (!m_pScriptNodeArray) { |
765 return; | 769 return; |
766 } | 770 } |
767 if (m_pScriptNodeArray->Find(pNode) == -1) { | 771 if (m_pScriptNodeArray->Find(pNode) == -1) { |
768 m_pScriptNodeArray->Add(pNode); | 772 m_pScriptNodeArray->Add(pNode); |
769 } | 773 } |
770 } | 774 } |
OLD | NEW |