[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75
aa at chromium.org
aa at chromium.org
Thu Oct 29 20:41:28 UTC 2009
The following commit has been merged in the webkit-1.1 branch:
commit 0ad18647cb60c3a09d6dbdeed0a25e6f57c0f5d0
Author: aa at chromium.org <aa at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Oct 8 00:07:11 2009 +0000
Update isolated worlds under v8 to support world reuse.
https://bugs.webkit.org/show_bug.cgi?id=30145
Patch by Aaron Boodman <aa at chromium.org> on 2009-10-07
Reviewed by Adam Barth.
WebCore:
* bindings/v8/ScriptController.cpp:
Replace evaluateInNewIsolatedWorld() withe evaluateInIsolatedWorld(id).
(WebCore::ScriptController::evaluateInIsolatedWorld):
* bindings/v8/ScriptController.h: Ditto.
* bindings/v8/V8Proxy.cpp: Ditto.
(WebCore::V8Proxy::~V8Proxy): Dittio.
(WebCore::V8Proxy::evaluateInIsolatedWorld): Ditto.
* bindings/v8/V8Proxy.h: Ditto.
* bindings/v8/V8IsolatedWorld.cpp:
Add support for controlling lifetime of a world, rather than relying on GC.
(WebCore::V8IsolatedWorld::contextWeakReferenceCallback): Ditto.
(WebCore::V8IsolatedWorld::V8IsolatedWorld): Ditto.
(WebCore::V8IsolatedWorld::destroy): Ditto.
* bindings/v8/V8IsolatedWorld.h: Ditto.
LayoutTests:
* http/tests/security/isolatedWorld/iframe.html: Added.
* http/tests/security/isolatedWorld/world-reuse-expected.txt: Added.
* http/tests/security/isolatedWorld/world-reuse.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49278 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 8662401..a799d67 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2009-10-07 Aaron Boodman <aa at chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Update isolated worlds under v8 to support world reuse.
+ https://bugs.webkit.org/show_bug.cgi?id=30145
+
+ * http/tests/security/isolatedWorld/iframe.html: Added.
+ * http/tests/security/isolatedWorld/world-reuse-expected.txt: Added.
+ * http/tests/security/isolatedWorld/world-reuse.html: Added.
+
2009-10-07 Brady Eidson <beidson at apple.com>
Reviewed by Darin Adler.
diff --git a/LayoutTests/http/tests/security/isolatedWorld/iframe.html b/LayoutTests/http/tests/security/isolatedWorld/iframe.html
new file mode 100644
index 0000000..4fb1977
--- /dev/null
+++ b/LayoutTests/http/tests/security/isolatedWorld/iframe.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="output"></div>
+<script>
+window.focus();
+
+// This should not pick up the 'bar' defined in the isolated world from the parent
+// document, or the 'hotdog' defined in previous runs of this frame.
+layoutTestController.evaluateScriptInIsolatedWorld(1,
+ "document.getElementById('output').appendChild(document.createTextNode(window.bar + ',' + window.hotdog));");
+
+// Next time we run, we also shouldn't see this 'hotdog'.
+layoutTestController.evaluateScriptInIsolatedWorld(1, "var hotdog = 'hotdog';");
+
+parent.iframeComplete(document.getElementById("output").textContent);
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/isolatedWorld/world-reuse-expected.txt b/LayoutTests/http/tests/security/isolatedWorld/world-reuse-expected.txt
new file mode 100644
index 0000000..8567d57
--- /dev/null
+++ b/LayoutTests/http/tests/security/isolatedWorld/world-reuse-expected.txt
@@ -0,0 +1,7 @@
+
+Expecting undefined: undefined
+Expecting bar: bar
+Expecting undefined: undefined
+Expecting undefined,undefined: undefined,undefined
+Expecting undefined,undefined: undefined,undefined
+
diff --git a/LayoutTests/http/tests/security/isolatedWorld/world-reuse.html b/LayoutTests/http/tests/security/isolatedWorld/world-reuse.html
new file mode 100644
index 0000000..d1c8723
--- /dev/null
+++ b/LayoutTests/http/tests/security/isolatedWorld/world-reuse.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+
+ // World id 0 is never saved, so this should print 'undefined'.
+ layoutTestController.evaluateScriptInIsolatedWorld(0, "var foo = 'foo';");
+ layoutTestController.evaluateScriptInIsolatedWorld(0,
+ "document.body.appendChild(document.createTextNode('Expecting undefined: ' + window.foo));" +
+ "document.body.appendChild(document.createElement('br'));");
+
+ // Since these two run in the same world, this should print 'bar'.
+ layoutTestController.evaluateScriptInIsolatedWorld(1, "var bar = 'bar';");
+ layoutTestController.evaluateScriptInIsolatedWorld(1,
+ "document.body.appendChild(document.createTextNode('Expecting bar: ' + window.bar));" +
+ "document.body.appendChild(document.createElement('br'));");
+
+ // Since these two are in different worlds, this should print 'undefined'.
+ layoutTestController.evaluateScriptInIsolatedWorld(2, "var baz = 'baz';");
+ layoutTestController.evaluateScriptInIsolatedWorld(3,
+ "document.body.appendChild(document.createTextNode('Expecting undefined: ' + window.baz));" +
+ "document.body.appendChild(document.createElement('br'));");
+
+ // Worlds should not be shared across documents, so another frame that uses the same
+ // world id should not see our variables.
+ var iframe = document.createElement("iframe");
+ document.body.insertBefore(iframe, document.body.firstChild);
+ document.body.insertBefore(document.createElement("br"), iframe.nextSibling);
+ var iframeComplete = function(result) {
+ document.body.appendChild(document.createTextNode('Expecting undefined,undefined: ' + result));
+ document.body.appendChild(document.createElement('br'));
+ reloadFrame();
+ }
+ iframe.src = "iframe.html";
+
+ // Also, navigating a single frame should not result in sharing variables.
+ function reloadFrame() {
+ iframeComplete = function(result) {
+ document.body.appendChild(document.createTextNode('Expecting undefined,undefined: ' + result));
+ document.body.appendChild(document.createElement('br'));
+ layoutTestController.notifyDone();
+ }
+ iframe.contentWindow.location.reload(true);
+ }
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/platform/gtk/Skipped b/LayoutTests/platform/gtk/Skipped
index 561f36b..9e93b42 100644
--- a/LayoutTests/platform/gtk/Skipped
+++ b/LayoutTests/platform/gtk/Skipped
@@ -5389,6 +5389,7 @@ http/tests/security/isolatedWorld/number-prototype.html
http/tests/security/isolatedWorld/object-prototype.html
http/tests/security/isolatedWorld/string-prototype.html
http/tests/security/isolatedWorld/window-properties.html
+http/tests/security/isolatedWorld/world-reuse.html
# Missing DRT ability return a null request for willSendRequest redirect calls
http/tests/misc/will-send-request-returns-null-on-redirect.html
diff --git a/LayoutTests/platform/mac/Skipped b/LayoutTests/platform/mac/Skipped
index b89ae7d..1ed01d4 100644
--- a/LayoutTests/platform/mac/Skipped
+++ b/LayoutTests/platform/mac/Skipped
@@ -89,6 +89,7 @@ http/tests/security/isolatedWorld/number-prototype.html
http/tests/security/isolatedWorld/object-prototype.html
http/tests/security/isolatedWorld/string-prototype.html
http/tests/security/isolatedWorld/window-properties.html
+http/tests/security/isolatedWorld/world-reuse.html
# New test with questionable results
# See https://bugs.webkit.org/show_bug.cgi?id=28079 for explanation.
diff --git a/LayoutTests/platform/qt/Skipped b/LayoutTests/platform/qt/Skipped
index cf4e608..fb858c5 100644
--- a/LayoutTests/platform/qt/Skipped
+++ b/LayoutTests/platform/qt/Skipped
@@ -80,6 +80,7 @@ http/tests/security/isolatedWorld/number-prototype.html
http/tests/security/isolatedWorld/object-prototype.html
http/tests/security/isolatedWorld/string-prototype.html
http/tests/security/isolatedWorld/window-properties.html
+http/tests/security/isolatedWorld/world-reuse.html
# Missing DRT ability return a null request for willSendRequest redirect calls
http/tests/misc/will-send-request-returns-null-on-redirect.html
diff --git a/LayoutTests/platform/win/Skipped b/LayoutTests/platform/win/Skipped
index 0674d3e..031cb22 100644
--- a/LayoutTests/platform/win/Skipped
+++ b/LayoutTests/platform/win/Skipped
@@ -618,6 +618,7 @@ http/tests/security/isolatedWorld/number-prototype.html
http/tests/security/isolatedWorld/object-prototype.html
http/tests/security/isolatedWorld/string-prototype.html
http/tests/security/isolatedWorld/window-properties.html
+http/tests/security/isolatedWorld/world-reuse.html
# New test with questionable results
# See https://bugs.webkit.org/show_bug.cgi?id=28079 for explanation.
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 9caeaeb..2b45b03 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,25 @@
+2009-10-07 Aaron Boodman <aa at chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Update isolated worlds under v8 to support world reuse.
+ https://bugs.webkit.org/show_bug.cgi?id=30145
+
+ * bindings/v8/ScriptController.cpp:
+ Replace evaluateInNewIsolatedWorld() withe evaluateInIsolatedWorld(id).
+ (WebCore::ScriptController::evaluateInIsolatedWorld):
+ * bindings/v8/ScriptController.h: Ditto.
+ * bindings/v8/V8Proxy.cpp: Ditto.
+ (WebCore::V8Proxy::~V8Proxy): Dittio.
+ (WebCore::V8Proxy::evaluateInIsolatedWorld): Ditto.
+ * bindings/v8/V8Proxy.h: Ditto.
+ * bindings/v8/V8IsolatedWorld.cpp:
+ Add support for controlling lifetime of a world, rather than relying on GC.
+ (WebCore::V8IsolatedWorld::contextWeakReferenceCallback): Ditto.
+ (WebCore::V8IsolatedWorld::V8IsolatedWorld): Ditto.
+ (WebCore::V8IsolatedWorld::destroy): Ditto.
+ * bindings/v8/V8IsolatedWorld.h: Ditto.
+
2009-10-07 Jeremy Orlow <jorlow at chromium.org>
Build fix for http://trac.webkit.org/changeset/49272 on Windows
diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp
index 2ff6115..efefed0 100644
--- a/WebCore/bindings/v8/ScriptController.cpp
+++ b/WebCore/bindings/v8/ScriptController.cpp
@@ -181,13 +181,12 @@ bool ScriptController::processingUserGesture() const
void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources)
{
- // FIXME: Get rid of extensionGroup here.
- m_proxy->evaluateInNewWorld(sources, 1);
+ m_proxy->evaluateInIsolatedWorld(worldID, sources, 0);
}
-void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup)
+void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup)
{
- m_proxy->evaluateInNewWorld(sources, extensionGroup);
+ m_proxy->evaluateInIsolatedWorld(worldID, sources, extensionGroup);
}
void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup)
diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h
index dc55efa..9658b05 100644
--- a/WebCore/bindings/v8/ScriptController.h
+++ b/WebCore/bindings/v8/ScriptController.h
@@ -65,13 +65,18 @@ namespace WebCore {
ScriptValue evaluate(const ScriptSourceCode&);
void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&);
-
- // Executes JavaScript in a new world associated with the web frame. The
- // script gets its own global scope, its own prototypes for intrinsic
- // JavaScript objects (String, Array, and so-on), and its own wrappers for
- // all DOM nodes and DOM constructors.
- // FIXME: Move to using evaluateInIsolatedWorld instead.
- void evaluateInNewWorld(const Vector<ScriptSourceCode>&, int extensionGroup);
+
+ // Executes JavaScript in an isolated world. The script gets its own global scope,
+ // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on),
+ // and its own wrappers for all DOM nodes and DOM constructors.
+ //
+ // If an isolated world with the specified ID already exists, it is reused.
+ // Otherwise, a new world is created.
+ //
+ // If the worldID is 0, a new world is always created.
+ //
+ // FIXME: Get rid of extensionGroup here.
+ void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup);
// Executes JavaScript in a new context associated with the web frame. The
// script gets its own global scope and its own prototypes for intrinsic
diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedWorld.cpp
index 0842305..d4e4f52 100644
--- a/WebCore/bindings/v8/V8IsolatedWorld.cpp
+++ b/WebCore/bindings/v8/V8IsolatedWorld.cpp
@@ -45,32 +45,27 @@ namespace WebCore {
int V8IsolatedWorld::isolatedWorldCount = 0;
-static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world)
+void V8IsolatedWorld::contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world)
{
// Our context is going away. Time to clean up the world.
V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world);
delete world;
}
-void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup)
+V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup)
{
+ ++isolatedWorldCount;
+
v8::HandleScope scope;
- v8::Persistent<v8::Context> context = proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup);
+ m_context = SharedPersistent<v8::Context>::create(proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup));
// Run code in the new context.
- v8::Context::Scope context_scope(context);
+ v8::Context::Scope context_scope(m_context->get());
- // The lifetime of this object is controlled by the V8 GC.
- // We need to create the world before touching DOM wrappers.
- V8IsolatedWorld* world = new V8IsolatedWorld(context);
+ m_context->get()->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this));
- V8Proxy::installHiddenObjectPrototype(context);
- proxy->installDOMWindow(context, proxy->frame()->domWindow());
-
- proxy->frame()->loader()->client()->didCreateIsolatedScriptContext();
-
- for (size_t i = 0; i < sources.size(); ++i)
- proxy->evaluate(sources[i], 0);
+ V8Proxy::installHiddenObjectPrototype(m_context->get());
+ proxy->installDOMWindow(m_context->get(), proxy->frame()->domWindow());
// Using the default security token means that the canAccess is always
// called, which is slow.
@@ -78,20 +73,14 @@ void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy*
// created contexts so that they can all be updated when the
// document domain
// changes.
- // FIXME: Move this statement above proxy->evaluate? It seems like we
- // should set up the token before running the script.
- context->UseDefaultSecurityToken();
+ m_context->get()->UseDefaultSecurityToken();
- context.Dispose();
- // WARNING! This might well delete |world|.
+ proxy->frame()->loader()->client()->didCreateIsolatedScriptContext();
}
-V8IsolatedWorld::V8IsolatedWorld(v8::Handle<v8::Context> context)
- : m_context(SharedPersistent<v8::Context>::create(v8::Persistent<v8::Context>::New(context)))
+void V8IsolatedWorld::destroy()
{
- ++isolatedWorldCount;
m_context->get().MakeWeak(this, &contextWeakReferenceCallback);
- context->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this));
}
V8IsolatedWorld::~V8IsolatedWorld()
diff --git a/WebCore/bindings/v8/V8IsolatedWorld.h b/WebCore/bindings/v8/V8IsolatedWorld.h
index bac2900..15d8711 100644
--- a/WebCore/bindings/v8/V8IsolatedWorld.h
+++ b/WebCore/bindings/v8/V8IsolatedWorld.h
@@ -58,11 +58,14 @@ namespace WebCore {
//
class V8IsolatedWorld {
public:
- ~V8IsolatedWorld();
+ // Creates an isolated world. To destroy it, call destroy().
+ // This will delete the isolated world when the context it owns is GC'd.
+ V8IsolatedWorld(V8Proxy* proxy, int extensionGroup);
- // Evaluate JavaScript in a new isolated world. The script has access
- // to the DOM of the document associated with |proxy|.
- static void evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup);
+ // Call this to destroy the isolated world. It will be deleted sometime
+ // after this call, once all script references to the world's context
+ // have been dropped.
+ void destroy();
// Returns the isolated world associated with
// v8::Context::GetEntered(). Because worlds are isolated, the entire
@@ -90,12 +93,13 @@ namespace WebCore {
DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); }
private:
+ ~V8IsolatedWorld();
+
static V8IsolatedWorld* getEnteredImpl();
- // The lifetime of an isolated world is managed by the V8 garbage
- // collector. In particular, the object created by this constructor is
- // freed when |context| is garbage collected.
- explicit V8IsolatedWorld(v8::Handle<v8::Context> context);
+ // Called by the garbage collector when our JavaScript context is about
+ // to be destroyed.
+ static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world);
// The v8::Context for the isolated world. This object is keep on the
// heap as long as |m_context| has not been garbage collected.
diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp
index 5664ebd..21ec7cc 100644
--- a/WebCore/bindings/v8/V8Proxy.cpp
+++ b/WebCore/bindings/v8/V8Proxy.cpp
@@ -274,10 +274,32 @@ bool V8Proxy::handleOutOfMemory()
return true;
}
-void V8Proxy::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup)
+void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup)
{
initContextIfNeeded();
- V8IsolatedWorld::evaluate(sources, this, extensionGroup);
+
+ v8::HandleScope handleScope;
+ V8IsolatedWorld* world = 0;
+
+ if (worldID > 0) {
+ IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID);
+ if (iter != m_isolatedWorlds.end()) {
+ world = iter->second;
+ } else {
+ world = new V8IsolatedWorld(this, extensionGroup);
+ m_isolatedWorlds.set(worldID, world);
+ }
+ } else {
+ world = new V8IsolatedWorld(this, extensionGroup);
+ }
+
+ v8::Local<v8::Context> context = v8::Local<v8::Context>::New(world->context());
+ v8::Context::Scope context_scope(context);
+ for (size_t i = 0; i < sources.size(); ++i)
+ evaluate(sources[i], 0);
+
+ if (worldID == 0)
+ world->destroy();
}
void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup)
@@ -708,9 +730,20 @@ void V8Proxy::disconnectEventListeners()
m_listenerGuard->disconnectListeners();
m_listenerGuard = V8ListenerGuard::create();
}
+
+void V8Proxy::resetIsolatedWorlds()
+{
+ for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin();
+ iter != m_isolatedWorlds.end(); ++iter) {
+ iter->second->destroy();
+ }
+ m_isolatedWorlds.clear();
+}
void V8Proxy::clearForClose()
{
+ resetIsolatedWorlds();
+
if (!context().IsEmpty()) {
v8::HandleScope handleScope;
@@ -722,6 +755,8 @@ void V8Proxy::clearForClose()
void V8Proxy::clearForNavigation()
{
disconnectEventListeners();
+ resetIsolatedWorlds();
+
if (!context().IsEmpty()) {
v8::HandleScope handle;
clearDocumentWrapper();
diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h
index 04c113e..f21366d 100644
--- a/WebCore/bindings/v8/V8Proxy.h
+++ b/WebCore/bindings/v8/V8Proxy.h
@@ -58,6 +58,7 @@ namespace WebCore {
class ScriptExecutionContext;
class String;
class V8EventListener;
+ class V8IsolatedWorld;
// FIXME: use standard logging facilities in WebCore.
void logInfo(Frame*, const String& message, const String& url);
@@ -166,7 +167,7 @@ namespace WebCore {
// global scope, its own prototypes for intrinsic JavaScript objects (String,
// Array, and so-on), and its own wrappers for all DOM nodes and DOM
// constructors.
- void evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup);
+ void evaluateInIsolatedWorld(int worldId, const Vector<ScriptSourceCode>& sources, int extensionGroup);
// Evaluate JavaScript in a new context. The script gets its own global scope
// and its own prototypes for intrinsic JavaScript objects (String, Array,
@@ -348,6 +349,8 @@ namespace WebCore {
void releaseStorageMutex();
void disconnectEventListeners();
+
+ void resetIsolatedWorlds();
static bool canAccessPrivate(DOMWindow*);
@@ -414,6 +417,16 @@ namespace WebCore {
// All of the extensions registered with the context.
static V8Extensions m_extensions;
+
+ // The isolated worlds we are tracking for this frame. We hold them alive
+ // here so that they can be used again by future calls to
+ // evaluateInIsolatedWorld().
+ //
+ // Note: although the pointer is raw, the instance is kept alive by a strong
+ // reference to the v8 context it contains, which is not made weak until we
+ // call world->destroy().
+ typedef HashMap<int, V8IsolatedWorld*> IsolatedWorldMap;
+ IsolatedWorldMap m_isolatedWorlds;
};
template <int tag, typename T>
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list