summaryrefslogtreecommitdiffstats
path: root/webkit/port
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-13 23:26:13 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-13 23:26:13 +0000
commitbad146c5b3b1a7d0368320fecdbd5b50dbe97501 (patch)
tree8d5aad70f51fcfba24ccebd3359b7d33209370d7 /webkit/port
parentccef48cca72fbc8905a643759092ee0d913aca9c (diff)
downloadchromium_src-bad146c5b3b1a7d0368320fecdbd5b50dbe97501.zip
chromium_src-bad146c5b3b1a7d0368320fecdbd5b50dbe97501.tar.gz
chromium_src-bad146c5b3b1a7d0368320fecdbd5b50dbe97501.tar.bz2
Commit 40144. I had to move to to a separate CL to use gcl's
"try multiple commits" feature. Review URL: http://codereview.chromium.org/46062 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11683 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/port')
-rw-r--r--webkit/port/bindings/v8/NPV8Object.cpp2
-rw-r--r--webkit/port/bindings/v8/ScriptController.cpp15
-rw-r--r--webkit/port/bindings/v8/ScriptController.h7
-rw-r--r--webkit/port/bindings/v8/v8_proxy.cpp135
-rw-r--r--webkit/port/bindings/v8/v8_proxy.h16
5 files changed, 127 insertions, 48 deletions
diff --git a/webkit/port/bindings/v8/NPV8Object.cpp b/webkit/port/bindings/v8/NPV8Object.cpp
index 829fd074..411439f 100644
--- a/webkit/port/bindings/v8/NPV8Object.cpp
+++ b/webkit/port/bindings/v8/NPV8Object.cpp
@@ -272,7 +272,7 @@ bool NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npobj, NPString*
// Convert UTF-8 stream to WebCore::String.
WebCore::String script = WebCore::String::fromUTF8(npscript->UTF8Characters, npscript->UTF8Length);
- v8::Local<v8::Value> v8result = proxy->Evaluate(filename, 0, script, 0);
+ v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(filename)), 0);
// If we had an error, return false.
if (v8result.IsEmpty())
diff --git a/webkit/port/bindings/v8/ScriptController.cpp b/webkit/port/bindings/v8/ScriptController.cpp
index 9dff0b8..84ad8b4 100644
--- a/webkit/port/bindings/v8/ScriptController.cpp
+++ b/webkit/port/bindings/v8/ScriptController.cpp
@@ -207,6 +207,10 @@ bool ScriptController::processingUserGesture() const
return false;
}
+void ScriptController::evaluateInNewContext(
+ const Vector<ScriptSourceCode>& sources) {
+ m_proxy->evaluateInNewContext(sources);
+}
// Evaluate a script file in the environment of this proxy.
ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
@@ -217,14 +221,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
return ScriptValue();
v8::Context::Scope scope(context);
-
- // HTMLTokenizer used to use base zero line numbers for scripts, now it
- // uses base 1. This confuses v8, which uses line offsets from the
- // first line.
- v8::Local<v8::Value> obj = m_proxy->Evaluate(sourceCode.url(),
- sourceCode.startLine() - 1,
- sourceCode.source(),
- NULL);
+ v8::Local<v8::Value> obj = m_proxy->evaluate(sourceCode, NULL);
if (obj.IsEmpty() || obj->IsUndefined())
return ScriptValue();
@@ -289,7 +286,7 @@ void ScriptController::collectGarbage()
v8::Context::Scope scope(context);
- m_proxy->Evaluate("", 0, "if (window.gc) void(gc());", NULL);
+ m_proxy->evaluate(ScriptSourceCode("if (window.gc) void(gc());"), NULL);
}
NPRuntimeFunctions* ScriptController::functions()
diff --git a/webkit/port/bindings/v8/ScriptController.h b/webkit/port/bindings/v8/ScriptController.h
index 1d580fe..e1e9e25 100644
--- a/webkit/port/bindings/v8/ScriptController.h
+++ b/webkit/port/bindings/v8/ScriptController.h
@@ -42,6 +42,7 @@
#include "bindings/npruntime.h"
#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
#include "v8.h"
#include "v8_proxy.h"
@@ -151,6 +152,12 @@ public:
// as a string.
ScriptValue evaluate(const ScriptSourceCode&);
+ // Executes JavaScript in a new context associated with the web frame. The
+ // script gets its own global scope and its own prototypes for intrinsic
+ // JavaScript objects (String, Array, and so-on). It shares the wrappers for
+ // all DOM nodes and DOM constructors.
+ void evaluateInNewContext(const Vector<ScriptSourceCode>& sources);
+
// JSC has a WindowShell object, but for V8, the ScriptController
// is the WindowShell.
bool haveWindowShell() const { return true; }
diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp
index 3ad7143..2725b99 100644
--- a/webkit/port/bindings/v8/v8_proxy.cpp
+++ b/webkit/port/bindings/v8/v8_proxy.cpp
@@ -42,6 +42,7 @@
#include "v8_custom.h"
#include "v8_collection.h"
#include "v8_nodefilter.h"
+#include "V8DOMWindow.h"
#include "ChromiumBridge.h"
@@ -1356,20 +1357,60 @@ bool V8Proxy::HandleOutOfMemory()
return true;
}
-v8::Local<v8::Value> V8Proxy::Evaluate(const String& fileName, int baseLine,
- const String& str, Node* n)
+void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources)
+{
+ InitContextIfNeeded();
+
+ v8::HandleScope handleScope;
+
+ // Set up the DOM window as the prototype of the new global object.
+ v8::Handle<v8::Context> windowContext = m_context;
+ v8::Handle<v8::Object> windowGlobal = windowContext->Global();
+ v8::Handle<v8::Value> windowWrapper =
+ V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal);
+
+ ASSERT(V8Proxy::DOMWrapperToNative<DOMWindow>(windowWrapper) ==
+ m_frame->domWindow());
+
+ v8::Persistent<v8::Context> context =
+ createNewContext(v8::Handle<v8::Object>());
+ v8::Context::Scope context_scope(context);
+ v8::Handle<v8::Object> global = context->Global();
+
+ v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__");
+ global->Set(implicitProtoString, windowWrapper);
+
+ // Give the code running in the new context a way to get access to the
+ // original context.
+ global->Set(v8::String::New("contentWindow"), windowGlobal);
+
+ // Run code in the new context.
+ for (size_t i = 0; i < sources.size(); ++i)
+ evaluate(sources[i], 0);
+
+ // Using the default security token means that the canAccess is always
+ // called, which is slow.
+ // TODO(aa): Use tokens where possible. This will mean keeping track of all
+ // created contexts so that they can all be updated when the document domain
+ // changes.
+ context->UseDefaultSecurityToken();
+ context.Dispose();
+}
+
+v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* n)
{
ASSERT(v8::Context::InContext());
// Compile the script.
- v8::Local<v8::String> code = v8ExternalString(str);
+ v8::Local<v8::String> code = v8ExternalString(source.source());
ChromiumBridge::traceEventBegin("v8.compile", n, "");
- v8::Handle<v8::Script> script = CompileScript(code, fileName, baseLine);
+
+ // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
+ // 1, whereas v8 starts at 0.
+ v8::Handle<v8::Script> script = CompileScript(code, source.url(),
+ source.startLine() - 1);
ChromiumBridge::traceEventEnd("v8.compile", n, "");
- // Set inlineCode to true for <a href="javascript:doSomething()">
- // and false for <script>doSomething</script>. For some reason, fileName
- // gives us this information.
ChromiumBridge::traceEventBegin("v8.run", n, "");
v8::Local<v8::Value> result;
{
@@ -1378,7 +1419,11 @@ v8::Local<v8::Value> V8Proxy::Evaluate(const String& fileName, int baseLine,
// evaluate from C++ when returning from here
v8::TryCatch try_catch;
try_catch.SetVerbose(true);
- result = RunScript(script, fileName.isNull());
+
+ // Set inlineCode to true for <a href="javascript:doSomething()">
+ // and false for <script>doSomething</script>. We make a rough guess at
+ // this based on whether the script source has a URL.
+ result = RunScript(script, source.url().string().isNull());
}
ChromiumBridge::traceEventEnd("v8.run", n, "");
return result;
@@ -2255,6 +2300,39 @@ bool V8Proxy::CheckNodeSecurity(Node* node)
return CanAccessFrame(target, true);
}
+v8::Persistent<v8::Context> V8Proxy::createNewContext(
+ v8::Handle<v8::Object> global)
+{
+ v8::Persistent<v8::Context> result;
+
+ // Create a new environment using an empty template for the shadow
+ // object. Reuse the global object if one has been created earlier.
+ v8::Persistent<v8::ObjectTemplate> globalTemplate =
+ V8DOMWindow::GetShadowObjectTemplate();
+ if (globalTemplate.IsEmpty())
+ return result;
+
+ // Install a security handler with V8.
+ globalTemplate->SetAccessCheckCallbacks(
+ V8Custom::v8DOMWindowNamedSecurityCheck,
+ V8Custom::v8DOMWindowIndexedSecurityCheck,
+ v8::Integer::New(V8ClassIndex::DOMWINDOW));
+
+ // Dynamically tell v8 about our extensions now.
+ const char** extensionNames = new const char*[m_extensions.size()];
+ int index = 0;
+ V8ExtensionList::iterator it = m_extensions.begin();
+ while (it != m_extensions.end()) {
+ extensionNames[index++] = (*it)->name();
+ ++it;
+ }
+ v8::ExtensionConfiguration extensions(m_extensions.size(), extensionNames);
+ result = v8::Context::New(&extensions, globalTemplate, global);
+ delete [] extensionNames;
+ extensionNames = 0;
+
+ return result;
+}
// Create a new environment and setup the global object.
//
@@ -2316,32 +2394,7 @@ void V8Proxy::InitContextIfNeeded()
v8_initialized = true;
}
- // Create a new environment using an empty template for the shadow
- // object. Reuse the global object if one has been created earlier.
- v8::Persistent<v8::ObjectTemplate> global_template =
- V8DOMWindow::GetShadowObjectTemplate();
- if (global_template.IsEmpty())
- return;
-
- // Install a security handler with V8.
- global_template->SetAccessCheckCallbacks(
- V8Custom::v8DOMWindowNamedSecurityCheck,
- V8Custom::v8DOMWindowIndexedSecurityCheck,
- v8::Integer::New(V8ClassIndex::DOMWINDOW));
-
- // Dynamically tell v8 about our extensions now.
- const char** extension_names = new const char*[m_extensions.size()];
- int index = 0;
- V8ExtensionList::iterator it = m_extensions.begin();
- while (it != m_extensions.end()) {
- extension_names[index++] = (*it)->name();
- ++it;
- }
- v8::ExtensionConfiguration extensions(m_extensions.size(), extension_names);
- m_context = v8::Context::New(&extensions, global_template, m_global);
- delete [] extension_names;
- extension_names = 0;
-
+ m_context = createNewContext(m_global);
if (m_context.IsEmpty())
return;
@@ -3409,6 +3462,20 @@ v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window)
if (!frame)
return v8::Handle<v8::Object>();
+ // Special case: Because of evaluateInNewContext() one DOMWindow can have
+ // multipe contexts and multiple global objects associated with it. When
+ // code running in one of those contexts accesses the window object, we
+ // want to return the global object associated with that context, not
+ // necessarily the first global object associated with that DOMWindow.
+ v8::Handle<v8::Context> current_context = v8::Context::GetCurrent();
+ v8::Handle<v8::Object> current_global = current_context->Global();
+ v8::Handle<v8::Object> windowWrapper =
+ LookupDOMWrapper(V8ClassIndex::DOMWINDOW, current_global);
+ if (!windowWrapper.IsEmpty())
+ if (DOMWrapperToNative<DOMWindow>(windowWrapper) == window)
+ return current_global;
+
+ // Otherwise, return the global object associated with this frame.
v8::Handle<v8::Context> context = GetContext(frame);
if (context.IsEmpty())
return v8::Handle<v8::Object>();
diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h
index 69747b5..cb0e433 100644
--- a/webkit/port/bindings/v8/v8_proxy.h
+++ b/webkit/port/bindings/v8/v8_proxy.h
@@ -13,10 +13,12 @@
#include "ChromiumBridge.h"
#include "Node.h"
#include "NodeFilter.h"
-#include "SecurityOrigin.h" // for WebCore::SecurityOrigin
#include "PlatformString.h" // for WebCore::String
-#include <wtf/PassRefPtr.h> // so generated bindings don't have to
+#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode
+#include "SecurityOrigin.h" // for WebCore::SecurityOrigin
#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h> // so generated bindings don't have to
+#include <wtf/Vector.h>
#include <iterator>
#include <list>
@@ -230,11 +232,16 @@ class V8Proxy {
void setEventHandlerLineno(int lineno) { m_handlerLineno = lineno; }
void finishedWithEvent(Event* event) { }
+ // Evaluate JavaScript in a new context. The script gets its own global scope
+ // and its own prototypes for intrinsic JavaScript objects (String, Array,
+ // and so-on). It shares the wrappers for all DOM nodes and DOM constructors.
+ void evaluateInNewContext(const Vector<ScriptSourceCode>& sources);
+
// Evaluate a script file in the current execution environment.
// The caller must hold an execution context.
// If cannot evalute the script, it returns an error.
- v8::Local<v8::Value> Evaluate(const String& filename, int baseLine,
- const String& code, Node* node);
+ v8::Local<v8::Value> evaluate(const ScriptSourceCode& source,
+ Node* node);
// Run an already compiled script.
v8::Local<v8::Value> RunScript(v8::Handle<v8::Script> script,
@@ -445,6 +452,7 @@ class V8Proxy {
static void RegisterExtension(v8::Extension* extension);
private:
+ v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global);
void InitContextIfNeeded();
void DisconnectEventListeners();
void SetSecurityToken();