summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpdfsdk/src/jsapi/fxjs_v8.cpp171
-rw-r--r--testing/resources/javascript/apply.in75
-rw-r--r--testing/resources/javascript/apply_expected.txt8
3 files changed, 154 insertions, 100 deletions
diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp
index 7b93a2ad26..a626bce345 100644
--- a/fpdfsdk/src/jsapi/fxjs_v8.cpp
+++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp
@@ -24,6 +24,8 @@ static unsigned int g_embedderDataSlot = 1u;
// kPerContextDataStartIndex + kEmbedderPDFium, which is 3.
static const unsigned int kPerContextDataIndex = 3u;
+static v8::Global<v8::ObjectTemplate> g_DefaultGlobalObjectTemplate;
+
class CFXJS_PrivateData {
public:
CFXJS_PrivateData(int nObjDefID) : ObjDefID(nObjDefID), pPrivate(NULL) {}
@@ -52,35 +54,70 @@ class CFXJS_ObjDefinition {
objType(eObjType),
m_pConstructor(pConstructor),
m_pDestructor(pDestructor),
- m_bSetAsGlobalObject(FALSE) {
+ m_bSetAsGlobalObject(FALSE),
+ m_pIsolate(isolate) {
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
- v8::Local<v8::ObjectTemplate> objTemplate =
- v8::ObjectTemplate::New(isolate);
- objTemplate->SetInternalFieldCount(2);
- m_objTemplate.Reset(isolate, objTemplate);
+ v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
+ fun->InstanceTemplate()->SetInternalFieldCount(2);
+ m_FunctionTemplate.Reset(isolate, fun);
+
+ v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
+ m_Signature.Reset(isolate, sig);
// Document as the global object.
if (FXSYS_wcscmp(sObjName, L"Document") == 0) {
m_bSetAsGlobalObject = TRUE;
}
}
- ~CFXJS_ObjDefinition() {
- m_objTemplate.Reset();
- m_StaticObj.Reset();
+
+ int AssignID() {
+ FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_pIsolate);
+ pData->m_ObjectDefnArray.Add(this);
+ return pData->m_ObjectDefnArray.GetSize() - 1;
+ }
+
+ v8::Local<v8::ObjectTemplate> GetInstanceTemplate() {
+ v8::EscapableHandleScope scope(m_pIsolate);
+ v8::Local<v8::FunctionTemplate> function =
+ m_FunctionTemplate.Get(m_pIsolate);
+ return scope.Escape(function->InstanceTemplate());
+ }
+
+ v8::Local<v8::Signature> GetSignature() {
+ v8::EscapableHandleScope scope(m_pIsolate);
+ return scope.Escape(m_Signature.Get(m_pIsolate));
}
const wchar_t* objName;
- FXJSOBJTYPE objType;
- FXJS_CONSTRUCTOR m_pConstructor;
- FXJS_DESTRUCTOR m_pDestructor;
+ const FXJSOBJTYPE objType;
+ const FXJS_CONSTRUCTOR m_pConstructor;
+ const FXJS_DESTRUCTOR m_pDestructor;
FX_BOOL m_bSetAsGlobalObject;
- v8::Global<v8::ObjectTemplate> m_objTemplate;
+ v8::Isolate* m_pIsolate;
+ v8::Global<v8::FunctionTemplate> m_FunctionTemplate;
+ v8::Global<v8::Signature> m_Signature;
v8::Global<v8::Object> m_StaticObj;
};
+static v8::Local<v8::ObjectTemplate> GetGlobalObjectTemplate(
+ v8::Isolate* pIsolate) {
+ int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
+ for (int i = 0; i < maxID; ++i) {
+ CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
+ if (pObjDef->m_bSetAsGlobalObject)
+ return pObjDef->GetInstanceTemplate();
+ }
+
+ if (g_DefaultGlobalObjectTemplate.IsEmpty())
+ g_DefaultGlobalObjectTemplate.Reset(pIsolate,
+ v8::ObjectTemplate::New(pIsolate));
+
+ return g_DefaultGlobalObjectTemplate.Get(pIsolate);
+}
+
void* FXJS_ArrayBufferAllocator::Allocate(size_t length) {
return calloc(1, length);
}
@@ -121,10 +158,9 @@ int FXJS_DefineObj(v8::Isolate* pIsolate,
v8::HandleScope handle_scope(pIsolate);
FXJS_PerIsolateData::SetUp(pIsolate);
- FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
- pData->m_ObjectDefnArray.Add(new CFXJS_ObjDefinition(
- pIsolate, sObjName, eObjType, pConstructor, pDestructor));
- return pData->m_ObjectDefnArray.GetSize() - 1;
+ CFXJS_ObjDefinition* pObjDef = new CFXJS_ObjDefinition(
+ pIsolate, sObjName, eObjType, pConstructor, pDestructor);
+ return pObjDef->AssignID();
}
void FXJS_DefineObjMethod(v8::Isolate* pIsolate,
@@ -133,18 +169,15 @@ void FXJS_DefineObjMethod(v8::Isolate* pIsolate,
v8::FunctionCallback pMethodCall) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
CFX_ByteString bsMethodName = CFX_WideString(sMethodName).UTF8Encode();
CFXJS_ObjDefinition* pObjDef =
CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
- v8::Local<v8::ObjectTemplate> objTemp =
- v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
-
- objTemp->Set(
+ pObjDef->GetInstanceTemplate()->Set(
v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
v8::NewStringType::kNormal).ToLocalChecked(),
- v8::FunctionTemplate::New(pIsolate, pMethodCall), v8::ReadOnly);
- pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
+ v8::FunctionTemplate::New(pIsolate, pMethodCall, v8::Local<v8::Value>(),
+ pObjDef->GetSignature()),
+ v8::ReadOnly);
}
void FXJS_DefineObjProperty(v8::Isolate* pIsolate,
@@ -154,17 +187,13 @@ void FXJS_DefineObjProperty(v8::Isolate* pIsolate,
v8::AccessorSetterCallback pPropPut) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
CFX_ByteString bsPropertyName = CFX_WideString(sPropName).UTF8Encode();
CFXJS_ObjDefinition* pObjDef =
CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
- v8::Local<v8::ObjectTemplate> objTemp =
- v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
- objTemp->SetAccessor(
+ pObjDef->GetInstanceTemplate()->SetAccessor(
v8::String::NewFromUtf8(pIsolate, bsPropertyName.c_str(),
v8::NewStringType::kNormal).ToLocalChecked(),
pPropGet, pPropPut);
- pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
}
void FXJS_DefineObjAllProperties(v8::Isolate* pIsolate,
@@ -175,13 +204,10 @@ void FXJS_DefineObjAllProperties(v8::Isolate* pIsolate,
v8::NamedPropertyDeleterCallback pPropDel) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
CFXJS_ObjDefinition* pObjDef =
CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
- v8::Local<v8::ObjectTemplate> objTemp =
- v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
- objTemp->SetNamedPropertyHandler(pPropGet, pPropPut, pPropQurey, pPropDel);
- pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
+ pObjDef->GetInstanceTemplate()->SetNamedPropertyHandler(pPropGet, pPropPut,
+ pPropQurey, pPropDel);
}
void FXJS_DefineObjConst(v8::Isolate* pIsolate,
@@ -190,29 +216,10 @@ void FXJS_DefineObjConst(v8::Isolate* pIsolate,
v8::Local<v8::Value> pDefault) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
CFX_ByteString bsConstName = CFX_WideString(sConstName).UTF8Encode();
CFXJS_ObjDefinition* pObjDef =
CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
- v8::Local<v8::ObjectTemplate> objTemp =
- v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
- objTemp->Set(pIsolate, bsConstName.c_str(), pDefault);
- pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
-}
-
-static v8::Global<v8::ObjectTemplate>& _getGlobalObjectTemplate(
- v8::Isolate* pIsolate) {
- v8::Isolate::Scope isolate_scope(pIsolate);
- v8::HandleScope handle_scope(pIsolate);
-
- int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
- for (int i = 0; i < maxID; ++i) {
- CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
- if (pObjDef->m_bSetAsGlobalObject)
- return pObjDef->m_objTemplate;
- }
- static v8::Global<v8::ObjectTemplate> gloabalObjectTemplate;
- return gloabalObjectTemplate;
+ pObjDef->GetInstanceTemplate()->Set(pIsolate, bsConstName.c_str(), pDefault);
}
void FXJS_DefineGlobalMethod(v8::Isolate* pIsolate,
@@ -220,24 +227,11 @@ void FXJS_DefineGlobalMethod(v8::Isolate* pIsolate,
v8::FunctionCallback pMethodCall) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
CFX_ByteString bsMethodName = CFX_WideString(sMethodName).UTF8Encode();
- v8::Local<v8::FunctionTemplate> funTempl =
- v8::FunctionTemplate::New(pIsolate, pMethodCall);
- v8::Local<v8::ObjectTemplate> objTemp;
-
- v8::Global<v8::ObjectTemplate>& globalObjTemp =
- _getGlobalObjectTemplate(pIsolate);
- if (globalObjTemp.IsEmpty())
- objTemp = v8::ObjectTemplate::New(pIsolate);
- else
- objTemp = v8::Local<v8::ObjectTemplate>::New(pIsolate, globalObjTemp);
- objTemp->Set(
+ GetGlobalObjectTemplate(pIsolate)->Set(
v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
v8::NewStringType::kNormal).ToLocalChecked(),
- funTempl, v8::ReadOnly);
-
- globalObjTemp.Reset(pIsolate, objTemp);
+ v8::FunctionTemplate::New(pIsolate, pMethodCall), v8::ReadOnly);
}
void FXJS_DefineGlobalConst(v8::Isolate* pIsolate,
@@ -245,24 +239,11 @@ void FXJS_DefineGlobalConst(v8::Isolate* pIsolate,
v8::Local<v8::Value> pDefault) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
- CFX_WideString ws = CFX_WideString(sConstName);
- CFX_ByteString bsConst = ws.UTF8Encode();
-
- v8::Local<v8::ObjectTemplate> objTemp;
-
- v8::Global<v8::ObjectTemplate>& globalObjTemp =
- _getGlobalObjectTemplate(pIsolate);
- if (globalObjTemp.IsEmpty())
- objTemp = v8::ObjectTemplate::New(pIsolate);
- else
- objTemp = v8::Local<v8::ObjectTemplate>::New(pIsolate, globalObjTemp);
- objTemp->Set(
+ CFX_ByteString bsConst = CFX_WideString(sConstName).UTF8Encode();
+ GetGlobalObjectTemplate(pIsolate)->Set(
v8::String::NewFromUtf8(pIsolate, bsConst.c_str(),
v8::NewStringType::kNormal).ToLocalChecked(),
pDefault, v8::ReadOnly);
-
- globalObjTemp.Reset(pIsolate, objTemp);
}
void FXJS_InitializeRuntime(v8::Isolate* pIsolate,
@@ -271,12 +252,8 @@ void FXJS_InitializeRuntime(v8::Isolate* pIsolate,
v8::Global<v8::Context>& v8PersistentContext) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::HandleScope handle_scope(pIsolate);
-
- v8::Global<v8::ObjectTemplate>& globalObjTemp =
- _getGlobalObjectTemplate(pIsolate);
- v8::Local<v8::Context> v8Context = v8::Context::New(
- pIsolate, NULL,
- v8::Local<v8::ObjectTemplate>::New(pIsolate, globalObjTemp));
+ v8::Local<v8::Context> v8Context =
+ v8::Context::New(pIsolate, NULL, GetGlobalObjectTemplate(pIsolate));
v8::Context::Scope context_scope(v8Context);
FXJS_PerIsolateData::SetUp(pIsolate);
@@ -362,10 +339,7 @@ int FXJS_Execute(v8::Isolate* pIsolate,
FXJSErr* pError) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::TryCatch try_catch(pIsolate);
-
- CFX_WideString wsScript(script);
- CFX_ByteString bsScript = wsScript.UTF8Encode();
-
+ CFX_ByteString bsScript = CFX_WideString(script).UTF8Encode();
v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
v8::Local<v8::Script> compiled_script;
if (!v8::Script::Compile(
@@ -395,9 +369,9 @@ v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
if (nObjDefnID == -1) {
v8::Local<v8::ObjectTemplate> objTempl = v8::ObjectTemplate::New(pIsolate);
v8::Local<v8::Object> obj;
- if (objTempl->NewInstance(context).ToLocal(&obj))
- return obj;
- return v8::Local<v8::Object>();
+ if (!objTempl->NewInstance(context).ToLocal(&obj))
+ return v8::Local<v8::Object>();
+ return obj;
}
FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
@@ -409,11 +383,8 @@ v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
CFXJS_ObjDefinition* pObjDef =
CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
-
- v8::Local<v8::ObjectTemplate> objTemp =
- v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
v8::Local<v8::Object> obj;
- if (!objTemp->NewInstance(context).ToLocal(&obj))
+ if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj))
return v8::Local<v8::Object>();
obj->SetAlignedPointerInInternalField(0, new CFXJS_PrivateData(nObjDefnID));
diff --git a/testing/resources/javascript/apply.in b/testing/resources/javascript/apply.in
new file mode 100644
index 0000000000..1342c1af4e
--- /dev/null
+++ b/testing/resources/javascript/apply.in
@@ -0,0 +1,75 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /OpenAction 10 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+>>
+endobj
+% Page number 0.
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <</F1 15 0 R>>
+ >>
+ /Contents [21 0 R]
+ /MediaBox [0 0 612 792]
+>>
+% OpenAction action
+{{object 10 0}} <<
+ /Type /Action
+ /S /JavaScript
+ /JS 11 0 R
+>>
+endobj
+% JS program to exexute
+{{object 11 0}} <<
+>>
+stream
+app.alert('Applying to util itself - should succeed');
+try {
+ app.alert(util.byteToChar.apply(util, [65]));
+}
+catch (e) {
+ app.alert('Caught: ' + e);
+}
+
+app.alert('Applying to array - should throw');
+try {
+ app.alert(util.byteToChar.apply([], [65]));
+}
+catch (e) {
+ app.alert('Caught: ' + e);
+}
+
+app.alert('Applying to number - should throw');
+try {
+ app.alert(util.byteToChar.apply(7, [65]));
+}
+catch (e) {
+ app.alert('Caught: ' + e);
+}
+
+app.alert('Applying to wrong native obj - should throw');
+try {
+ app.alert(util.byteToChar.apply(app, [65]));
+}
+catch (e) {
+ app.alert('Caught: ' + e);
+}
+endstream
+endobj
+{{xref}}
+trailer <<
+ /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/javascript/apply_expected.txt b/testing/resources/javascript/apply_expected.txt
new file mode 100644
index 0000000000..750676f235
--- /dev/null
+++ b/testing/resources/javascript/apply_expected.txt
@@ -0,0 +1,8 @@
+Alert: Applying to util itself - should succeed
+Alert: A
+Alert: Applying to array - should throw
+Alert: Caught: TypeError: Illegal invocation
+Alert: Applying to number - should throw
+Alert: Caught: TypeError: Illegal invocation
+Alert: Applying to wrong native obj - should throw
+Alert: Caught: TypeError: Illegal invocation