Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(685)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md

Issue 1542623004: Add documentation about Isolate, Context, World, Frames etc (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md b/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
new file mode 100644
index 0000000000000000000000000000000000000000..e02e97c4aca8514e8e819092258940db56f2fa28
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
@@ -0,0 +1,259 @@
+# Design of V8 bindings
+
+This document explains key concepts in the V8 binding architecture
+except the lifetime management of DOM wrappers.
+See [V8GCController.md](V8GCController.md) to learn the lifetime management.
+
+[TOC]
+
+## Isolate
+
+An isolate is a concept of a thread in V8.
jochen (gone - plz use gerrit) 2016/01/07 10:18:44 that's not really true, it's just the way Blink us
haraken 2016/01/08 05:22:34 Reworded.
+Isolates and threads are in 1:1 relationship.
+One isolate is associated with the main thread.
+One isolate is associated with one worker thread.
+
+## Context
+
+A context is a concept of a global variable scope in V8.
+Roughly speaking, one window object corresponds to one context.
+For example, `<iframe>` has a window object different from a window object
+of its parent frame. So the context of the `<iframe>` is different from
+the context of the parent frame. Since these contexts create their own
+global variable scopes, global variables and prototype chains of the `<iframe>`
+are isolated from the ones of the parent frame.
+
+Here is an example:
+
+```html
+// main.html
+<html><body>
+<iframe src="iframe.html"></iframe>
+<script>
+var foo = 1234;
+String.prototype.substr =
+ function (position, length) { // Hijacks String.prototype.substr
+ console.log(length);
+ return "hijacked";
+ };
+</script>
+</body></html>
+
+// iframe.html
+<script>
+console.log(foo); // undefined
+var bar = "aaaa".substr(0, 2); // Nothing is logged.
+console.log(bar); // "aa"
+</script>
+```
+
+In summary, each frame has a window object.
+Each window object has a context.
+Each context has its own global variable scope and prototype chains.
+
+## Entered context and current context
+
+A relationship between isolates and contexts is interesting.
+One isolate has to execute JavaScripts in multiple frames,
+each of which has its own context. This means that the context associated
+with the isolate changes over time. In other words, the relationship between
+isolates and contexts is 1:N over the lifetime of the isolate.
+
+Here we have a concept of an entered context and a current context.
+To understand the difference, you need to understand two kinds of
+runtime stacks.
+
+The first stack is a stack of JavaScript functions.
+This stack is managed by V8. When one function calls another function,
+the callee function is pushed onto the stack. When that function returns,
jochen (gone - plz use gerrit) 2016/01/07 10:18:45 that's not true in general (e.g. tail calls don't
haraken 2016/01/08 05:22:34 I don't want to run into that kind of details sinc
+the function is popped from the stack and the control returns to the caller
+function that is now on the top of the stack. Each function has
+an associated context. We call the context of the function
+that is currently running (i.e., the context of the function that is on the top
+of the stack) a current context.
jochen (gone - plz use gerrit) 2016/01/07 10:18:44 unless the debugger is active, then the top contex
haraken 2016/01/08 05:22:34 Added the explanation for a debugger context.
+
+Here is an example:
+
+```html
+// main.html
+<html><body>
+<iframe src="iframe.html"></iframe>
+<script>
+var iframe = document.querySelector("iframe");
+iframe.onload = function () {
+ iframe.contentWindow.func();
+}
+</script>
+</body></html>
+
+// iframe.html
+<script>
+function func() {
+ ...;
+}
+</script>
+```
+
+In the above example, at the point when func() is running,
+the current context is the context of the `<iframe>`.
+
+There is a second stack that operates on a much coarser granularity.
+This stack is managed by V8 binding (not by V8).
+When V8 binding invokes JavaScript, V8 binding enters a context
+and pushes the context onto the stack.
+The JavaScript starts running on the context. When the JavaScript finishes
+and the control returns back to V8 binding, V8 binding pops the context
+from the stack. Given that the control between V8 binding and V8 can be nested
+(i.e., V8 binding invokes JavaScript, which calls into V8 binding,
+which invokes another JavaScript etc), these contexts form a stack.
+The pushing and popping are done by calling v8::Context::Enter() and
+v8::Context::Exit() (or v8::Context::Scope). We call the most recently entered
+context an entered context.
jochen (gone - plz use gerrit) 2016/01/07 10:18:45 any V8 C++ API that takes a context argument enter
haraken 2016/01/08 05:22:34 Added.
+
+In the above example, at the point when func() is running,
+the entered context is the context of the main frame
+(not the context of `<iframe>`).
+
+The entered context is a concept to implement the
+[entry settings object](https://html.spec.whatwg.org/multipage/webappapis.html#entry-settings-object)
+of the HTML spec. The current context is a concept to implement the
+[incumbent settings object](https://html.spec.whatwg.org/multipage/webappapis.html#incumbent-settings-object)
+of the HTML spec.
+
+In summary, the entered context is a context from which the current JavaScript
+execution was started. The current context is a context of
+the JavaScript function that is currently running.
+
+## World
+
+A world is a concept to sandbox DOM wrappers among content scripts of
+Chrome extensions. There are three kinds of worlds: a main world,
+an isolated world and a worker world.
+A main world is a world where a normal JavaScript downloaded from the web
+is executed.
+An isolated world is a world where a content script of a Chrome extension.
+An isolate of the main thread has 1 main world and N isolated worlds.
+An isolate of a worker thread has 1 worker world and 0 isolated world.
jochen (gone - plz use gerrit) 2016/01/07 10:18:44 is that also true for compositor workers?
haraken 2016/01/08 05:22:34 This description is true, but it is not true that
+[This diagram](https://drive.google.com/file/d/0B1obCOyvTnPKQmJEWkVtOEN2TmM/view?usp=sharing)
+will be helpful to understand the relationship.
+
+All worlds in one isolate share underlying C++ DOM objects,
jochen (gone - plz use gerrit) 2016/01/07 10:18:45 for one specific iframe that is
haraken 2016/01/08 05:22:34 What do you mean?
+but each world has its own DOM wrappers. That way the worlds in one isolate
+can operate on the same C++ DOM object without sharing any DOM wrapper
+among the worlds.
+
+Also each world has its own context.
+This means that each world has its own global variable scope and
+prototype chains.
+
+As a result of the sandboxing, the worlds in one isolate cannot share
+any DOM wrappers or contexts but can share underlying C++ DOM objects.
+The fact that no DOM wrappers or contexts are shared means that no JavaScript
+objects are shared among the worlds. That way we guarantee the security model
+that Chrome extensions doesn't share any JavaScript objects while sharing
+the underlying C++ DOM objects. This sandbox allows the Chrome extensions to run
+untrusted JavaScripts on a shared DOM structure.
+
+(Note: An isolated world is a concept of V8 binding,
+whereas an isolate and a context are a concept of V8.
+V8 does not know what isolated worlds are in an isolate.)
+
+In summary, an isolate of the main thread consists of 1 main world
+and N isolated worlds. An isolate of a worker thread consists of
+1 worker world and 0 isolated world. All worlds in one isolate share the
+underlying C++ DOM objects, but each world has its own DOM wrappers.
+Each world has its own context and thus has its own global variable scope
+and prototype chains.
+
+## A relationship between isolates, contexts, worlds and frames
+
+Let's wrap up the relationship between isolates, contexts, worlds and frames.
+
+* As a requirement of the DOM side, one HTML page has N frames.
+Each frame has its own context.
+
+* As a requirement of the JavaScript side, one isolate has M worlds.
+Each world has its own context.
+
+As a result, when we execute the main thread where N frames and M worlds
+are involved, there exists N * M contexts. In other words, one context is
+created for each pair of (frame, world).
+[This diagram](https://drive.google.com/file/d/0B1obCOyvTnPKSERSMmpRVjVKQWc/view?usp=sharing)
+will be helpful to understand the relationship.
+
+The main thread can have only one current context at one time,
+but the main thread can have the N * M contexts over its lifetime.
+For example, when the main thread is operating on a frame X using a JavaScript
+in a world Y, the current context is set to a context for the pair of (X, Y).
+The current context of the main thread changes over its lifetime.
+
+On the other hand, a worker thread has 0 frame and 1 world.
+Thus a worker thread has only 1 context.
+The current context of the worker thread never changes.
+
+## DOM wrappers and worlds
+
+For compatibility reasons (although this is not speced),
jochen (gone - plz use gerrit) 2016/01/07 10:18:45 At least some specs explicitly state this
haraken 2016/01/08 05:22:34 Removed the words in the parentheses.
+we need to make sure that the same DOM wrapper is returned to JavaScript
+as long as the underlying C++ DOM object is alive.
+We should not return different DOM wrappers for the same C++ DOM object.
+
+Here is an example:
+
+```html
+var div = document.createElement("div");
+div.foo = 1234; // expando
+var p = document.createElement("p");
+p.appendChild(div);
+div = null;
+gc();
+console.log(p.firstChild.foo); // This should be 1234, not undefined
+```
+
+To accomplish the semantics that the same DOM wrapper is returned to JavaScript
+as long as the underlying C++ DOM object is alive, we need a mapping
+from the C++ DOM objects to the DOM wrappers.
+In addition, we need to sandbox DOM wrappers in each world.
+To meet the requirements, we make each world hold a DOM wrapper storage
+that stores a mapping from the C++ DOM objects to the DOM wrappers in that world.
+
+As a result, we have multiple DOM wrapper storages in one isolate.
+The mapping of the main world is written in ScriptWrappable.
+If ScriptWrappable::m_wrapper has a non-empty value, it is a DOM wrapper of
+the C++ DOM object of the main world.
+The mapping of other worlds are written in DOMWrapperMap.
+
+## DOM wrappers and contexts
+
+When you create a new DOM wrapper, you need to choose a correct context
+on which the DOM wrapper is created. If you create a new DOM wrapper in a
+wrong context, you will end up with leaking JavaScript objects to other
+contexts, which is very likely to cause security issues.
+
+Here is an example:
+
+```html
+// main.html
+<html><body>
+<iframe src="iframe.html"></iframe>
+<script>
+var iframe = document.querySelector("iframe");
+iframe; // The wrapper of the iframe should be created in the context of the main frame.
+iframe.contentDocument; // The wrapper of the document should be created in the context of the iframe.
+iframe.contentDocument.addEventListener("click",
+ function (event) { // The wrapper of the event should be created in the context of the iframe.
+ event.target;
+ });
+</script>
+</body></html>
+
+// iframe.html
+<script>
+</script>
+```
+
+To make sure that a DOM wrapper is created in a correct context, you need to
+make sure that the current context must be set to the correct context
+whenever you call toV8(). If you're not sure what context to use,
+ask haraken@chromium.org.
+
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698