Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxjse / src / context.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../foxitlib.h"\r
8 #include "fxv8.h"\r
9 #include "context.h"\r
10 #include "class.h"\r
11 #include "value.h"\r
12 #include "scope_inline.h"\r
13 #include "util_inline.h"\r
14 FXJSE_HCONTEXT  FXJSE_Context_Create(FXJSE_HRUNTIME hRuntime, const FXJSE_CLASS* lpGlobalClass , FX_LPVOID lpGlobalObject )\r
15 {\r
16     CFXJSE_Context* pContext = CFXJSE_Context::Create(reinterpret_cast<v8::Isolate*>(hRuntime), lpGlobalClass, lpGlobalObject);\r
17     return reinterpret_cast<FXJSE_HCONTEXT>(pContext);\r
18 }\r
19 void FXJSE_Context_Release(FXJSE_HCONTEXT hContext)\r
20 {\r
21     CFXJSE_Context* pContext = reinterpret_cast<CFXJSE_Context*>(hContext);\r
22     if(pContext) {\r
23         delete pContext;\r
24     }\r
25 }\r
26 FXJSE_HVALUE FXJSE_Context_GetGlobalObject(FXJSE_HCONTEXT hContext)\r
27 {\r
28     CFXJSE_Context* pContext = reinterpret_cast<CFXJSE_Context*>(hContext);\r
29     if(!pContext) {\r
30         return NULL;\r
31     }\r
32     CFXJSE_Value* lpValue = CFXJSE_Value::Create(pContext->GetRuntime());\r
33     ASSERT(lpValue);\r
34     pContext->GetGlobalObject(lpValue);\r
35     return reinterpret_cast<FXJSE_HVALUE>(lpValue);\r
36 }\r
37 FXJSE_HRUNTIME  FXJSE_Context_GetRuntime(FXJSE_HCONTEXT hContext)\r
38 {\r
39     CFXJSE_Context* pContext = reinterpret_cast<CFXJSE_Context*>(hContext);\r
40     return pContext ? reinterpret_cast<FXJSE_HRUNTIME>(pContext->GetRuntime()) : NULL;\r
41 }\r
42 static FX_LPCSTR szCompatibleModeScripts[] = {\r
43     "(function (global, list) { 'use strict'; var objname; for (objname in list) { var globalobj = global[objname];\n\\r
44                         if (globalobj) { list[objname].forEach( function (name) { if (!globalobj[name]) { Object.defineProperty(globalobj, name, {writable: true, enumerable: false, value: \n\\r
45                         (function (obj) {\n\\r
46         if (arguments.length === 0) {\n\\r
47                 throw new TypeError('missing argument 0 when calling function ' + objname + '.' + name);\n\\r
48         }\n\\r
49         return globalobj.prototype[name].apply(obj, Array.prototype.slice.call(arguments, 1));\n\\r
50 })});}});}}}(this, {String: ['substr', 'toUpperCase']}));",\r
51 };\r
52 void FXJSE_Context_EnableCompatibleMode(FXJSE_HCONTEXT hContext, FX_DWORD dwCompatibleFlags)\r
53 {\r
54     for (uint32_t i = 0; i < (uint32_t)FXJSE_COMPATIBLEMODEFLAGCOUNT; i++) {\r
55         if (dwCompatibleFlags & (1 << i)) {\r
56             FXJSE_ExecuteScript(hContext, szCompatibleModeScripts[i], NULL, NULL);\r
57         }\r
58     }\r
59 }\r
60 FX_BOOL FXJSE_ExecuteScript(FXJSE_HCONTEXT hContext, FX_LPCSTR szScript, FXJSE_HVALUE hRetValue, FXJSE_HVALUE hNewThisObject )\r
61 {\r
62     CFXJSE_Context* pContext = reinterpret_cast<CFXJSE_Context*>(hContext);\r
63     ASSERT(pContext);\r
64     return pContext->ExecuteScript(szScript, reinterpret_cast<CFXJSE_Value*>(hRetValue), reinterpret_cast<CFXJSE_Value*>(hNewThisObject));\r
65 }\r
66 v8::Local<v8::Object> FXJSE_CreateReturnValue(v8::Isolate* pIsolate, v8::TryCatch& trycatch)\r
67 {\r
68     v8::Local<v8::Object> hReturnValue = v8::Object::New(pIsolate);\r
69     if (trycatch.HasCaught()) {\r
70         v8::Local<v8::Value> hException = trycatch.Exception();\r
71         v8::Local<v8::Message> hMessage = trycatch.Message();\r
72         if (hException->IsObject()) {\r
73             v8::Local<v8::Value> hValue;\r
74             hValue = hException.As<v8::Object>()->Get(v8::String::NewFromUtf8(pIsolate, "name"));\r
75             if(hValue->IsString() || hValue->IsStringObject()) {\r
76                 hReturnValue->Set(0, hValue);\r
77             } else {\r
78                 hReturnValue->Set(0, v8::String::NewFromUtf8(pIsolate, "Error"));\r
79             }\r
80             hValue = hException.As<v8::Object>()->Get(v8::String::NewFromUtf8(pIsolate, "message"));\r
81             if(hValue->IsString() || hValue->IsStringObject()) {\r
82                 hReturnValue->Set(1, hValue);\r
83             } else {\r
84                 hReturnValue->Set(1, hMessage->Get());\r
85             }\r
86         } else {\r
87             hReturnValue->Set(0, v8::String::NewFromUtf8(pIsolate, "Error"));\r
88             hReturnValue->Set(1, hMessage->Get());\r
89         }\r
90         hReturnValue->Set(2, hException);\r
91         hReturnValue->Set(3, v8::Integer::New(pIsolate, hMessage->GetLineNumber()));\r
92         hReturnValue->Set(4, hMessage->GetSourceLine());\r
93         hReturnValue->Set(5, v8::Integer::New(pIsolate, hMessage->GetStartColumn()));\r
94         hReturnValue->Set(6, v8::Integer::New(pIsolate, hMessage->GetEndColumn()));\r
95     }\r
96     return hReturnValue;\r
97 }\r
98 FX_BOOL FXJSE_ReturnValue_GetMessage(FXJSE_HVALUE hRetValue, CFX_ByteString& utf8Name, CFX_ByteString& utf8Message)\r
99 {\r
100     CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hRetValue);\r
101     if(!lpValue) {\r
102         return FALSE;\r
103     }\r
104     v8::Isolate* pIsolate = lpValue->GetIsolate();\r
105     CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate);\r
106     v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(pIsolate, lpValue->DirectGetValue());\r
107     if(!hValue->IsObject()) {\r
108         return FALSE;\r
109     }\r
110     v8::String::Utf8Value hStringVal0(hValue.As<v8::Object>()->Get(0)->ToString());\r
111     utf8Name = *hStringVal0;\r
112     v8::String::Utf8Value hStringVal1(hValue.As<v8::Object>()->Get(1)->ToString());\r
113     utf8Message = *hStringVal1;\r
114     return TRUE;\r
115 }\r
116 FX_BOOL FXJSE_ReturnValue_GetLineInfo(FXJSE_HVALUE hRetValue, int32_t& nLine, int32_t& nCol)\r
117 {\r
118     CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hRetValue);\r
119     if(!lpValue) {\r
120         return FALSE;\r
121     }\r
122     v8::Isolate* pIsolate = lpValue->GetIsolate();\r
123     CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate);\r
124     v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(pIsolate, lpValue->DirectGetValue());\r
125     if(!hValue->IsObject()) {\r
126         return FALSE;\r
127     }\r
128     nLine = hValue.As<v8::Object>()->Get(3)->ToInt32()->Value();\r
129     nCol = hValue.As<v8::Object>()->Get(5)->ToInt32()->Value();\r
130     return TRUE;\r
131 }\r
132 CFXJSE_Context* CFXJSE_Context::Create(v8::Isolate* pIsolate, const FXJSE_CLASS* lpGlobalClass , FX_LPVOID lpGlobalObject )\r
133 {\r
134     CFXJSE_ScopeUtil_IsolateHandle scope(pIsolate);\r
135     CFXJSE_Context* pContext = FX_NEW CFXJSE_Context(pIsolate);\r
136     CFXJSE_Class* lpGlobalClassObj = NULL;\r
137     v8::Local<v8::ObjectTemplate> hObjectTemplate;\r
138     if(lpGlobalClass) {\r
139         lpGlobalClassObj = CFXJSE_Class::Create(pContext, lpGlobalClass, TRUE);\r
140         ASSERT(lpGlobalClassObj);\r
141         v8::Local<v8::FunctionTemplate> hFunctionTemplate = v8::Local<v8::FunctionTemplate>::New(pIsolate, lpGlobalClassObj->m_hTemplate);\r
142         hObjectTemplate = hFunctionTemplate->InstanceTemplate();\r
143     } else {\r
144         hObjectTemplate = v8::ObjectTemplate::New();\r
145         hObjectTemplate->SetInternalFieldCount(1);\r
146     }\r
147     v8::Local<v8::Context> hNewContext = v8::Context::New(pIsolate, NULL, hObjectTemplate);\r
148     v8::Local<v8::Context> hRootContext = v8::Local<v8::Context>::New(pIsolate, CFXJSE_RuntimeData::Get(pIsolate)->m_hRootContext);\r
149     hNewContext->SetSecurityToken(hRootContext->GetSecurityToken());\r
150     v8::Local<v8::Object> hGlobalObject = FXJSE_GetGlobalObjectFromContext(hNewContext);\r
151     FXJSE_UpdateObjectBinding(hGlobalObject, lpGlobalObject);\r
152     pContext->m_hContext.Reset(pIsolate, hNewContext);\r
153     if (lpGlobalClass) {\r
154         if(lpGlobalClass->dynMethodCall || lpGlobalClass->dynPropGetter || lpGlobalClass->dynPropSetter || lpGlobalClass->dynPropTypeGetter) {\r
155             CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(pIsolate);\r
156             lpThisValue->ForceSetValue(hGlobalObject);\r
157             CFXJSE_Class::SetUpDynPropHandler(pContext, lpThisValue, lpGlobalClass);\r
158             delete lpThisValue;\r
159             lpThisValue = NULL;\r
160         }\r
161     }\r
162     return pContext;\r
163 }\r
164 CFXJSE_Context::~CFXJSE_Context()\r
165 {\r
166     for(int32_t i = 0, count = m_rgClasses.GetSize(); i < count; i++) {\r
167         CFXJSE_Class* pClass = m_rgClasses[i];\r
168         if(pClass) {\r
169             delete pClass;\r
170         }\r
171     }\r
172     m_rgClasses.RemoveAll();\r
173 }\r
174 void CFXJSE_Context::GetGlobalObject(CFXJSE_Value* pValue)\r
175 {\r
176     ASSERT(pValue);\r
177     CFXJSE_ScopeUtil_IsolateHandleContext scope(this);\r
178     v8::Local<v8::Context> hContext = v8::Local<v8::Context>::New(m_pIsolate, m_hContext);\r
179     v8::Local<v8::Object> hGlobalObject = hContext->Global();\r
180     pValue->ForceSetValue(hGlobalObject);\r
181 }\r
182 FX_BOOL CFXJSE_Context::ExecuteScript(FX_LPCSTR szScript, CFXJSE_Value* lpRetValue, CFXJSE_Value* lpNewThisObject )\r
183 {\r
184     CFXJSE_ScopeUtil_IsolateHandleContext scope(this);\r
185     v8::TryCatch                        trycatch;\r
186     v8::Local<v8::String>       hScriptString = v8::String::NewFromUtf8(m_pIsolate, szScript);\r
187     if(lpNewThisObject == NULL) {\r
188         v8::Local<v8::Script> hScript = v8::Script::Compile(hScriptString);\r
189         if(!trycatch.HasCaught()) {\r
190             v8::Local<v8::Value> hValue = hScript->Run();\r
191             if(!trycatch.HasCaught()) {\r
192                 if(lpRetValue) {\r
193                     lpRetValue->m_hValue.Reset(m_pIsolate, hValue);\r
194                 }\r
195                 return TRUE;\r
196             }\r
197         }\r
198         if(lpRetValue) {\r
199             lpRetValue->m_hValue.Reset(m_pIsolate, FXJSE_CreateReturnValue(m_pIsolate, trycatch));\r
200         }\r
201         return FALSE;\r
202     } else {\r
203         v8::Local<v8::Value>    hNewThis = v8::Local<v8::Value>::New(m_pIsolate, lpNewThisObject->m_hValue);\r
204         ASSERT(!hNewThis.IsEmpty());\r
205         v8::Local<v8::Script>   hWrapper = v8::Script::Compile(v8::String::NewFromUtf8(m_pIsolate, "(function () { return eval(arguments[0]); })"));\r
206         v8::Local<v8::Value>    hWrapperValue = hWrapper->Run();\r
207         ASSERT(hWrapperValue->IsFunction());\r
208         v8::Local<v8::Function> hWrapperFn    = hWrapperValue.As<v8::Function>();\r
209         if(!trycatch.HasCaught()) {\r
210             v8::Local<v8::Value> rgArgs[] = {hScriptString};\r
211             v8::Local<v8::Value> hValue = hWrapperFn->Call(hNewThis.As<v8::Object>(), 1, rgArgs);\r
212             if(!trycatch.HasCaught()) {\r
213                 if(lpRetValue) {\r
214                     lpRetValue->m_hValue.Reset(m_pIsolate, hValue);\r
215                 }\r
216                 return TRUE;\r
217             }\r
218         }\r
219         if(lpRetValue) {\r
220             lpRetValue->m_hValue.Reset(m_pIsolate, FXJSE_CreateReturnValue(m_pIsolate, trycatch));\r
221         }\r
222         return FALSE;\r
223     }\r
224 }\r