diff --git a/src/README.md b/src/README.md
index 2333a90fa04b10..15317f06ae0ca3 100644
--- a/src/README.md
+++ b/src/README.md
@@ -96,6 +96,7 @@ Typical ways of accessing the current `Isolate` in the Node.js code are:
using `args.GetIsolate()`.
* Given a [`Context`][], using `context->GetIsolate()`.
* Given a [`Environment`][], using `env->isolate()`.
+* Given a [`Realm`][], using `realm->isolate()`.
### V8 JavaScript values
@@ -264,19 +265,25 @@ heap. Node.js exposes this ability through the [`vm` module][].
V8 refers to each of these global objects and their associated builtins as a
`Context`.
-Currently, in Node.js there is one main `Context` associated with an
-[`Environment`][] instance, and most Node.js features will only work inside
-that context. (The only exception at the time of writing are
-[`MessagePort`][] objects.) This restriction is not inherent to the design of
-Node.js, and a sufficiently committed person could restructure Node.js to
-provide built-in modules inside of `vm.Context`s.
+Currently, in Node.js there is one main `Context` associated with the
+principal [`Realm`][] of an [`Environment`][] instance, and a number of
+subsidiary `Context`s that are created with `vm.Context` or associated with
+[`ShadowRealm`][].
+
+Most Node.js features will only work inside a context associated with a
+`Realm`. The only exception at the time of writing are [`MessagePort`][]
+objects. This restriction is not inherent to the design of Node.js, and a
+sufficiently committed person could restructure Node.js to provide built-in
+modules inside of `vm.Context`s.
Often, the `Context` is passed around for [exception handling][].
Typical ways of accessing the current `Context` in the Node.js code are:
* Given an [`Isolate`][], using `isolate->GetCurrentContext()`.
* Given an [`Environment`][], using `env->context()` to get the `Environment`'s
- main context.
+ principal [`Realm`][]'s context.
+* Given a [`Realm`][], using `realm->context()` to get the `Realm`'s
+ context.
@@ -303,15 +310,11 @@ Currently, every `Environment` class is associated with:
* One [event loop][]
* One [`Isolate`][]
-* One main [`Context`][]
+* One principal [`Realm`][]
The `Environment` class contains a large number of different fields for
-different Node.js modules, for example a libuv timer for `setTimeout()` or
-the memory for a `Float64Array` that the `fs` module uses for storing data
-returned from a `fs.stat()` call.
-
-It also provides [cleanup hooks][] and maintains a list of [`BaseObject`][]
-instances.
+different built-in modules that can be shared across different `Realm`
+instances, for example, the inspector agent, async hooks info.
Typical ways of accessing the current `Environment` in the Node.js code are:
@@ -325,6 +328,45 @@ Typical ways of accessing the current `Environment` in the Node.js code are:
* Given an [`Isolate`][], using `Environment::GetCurrent(isolate)`. This looks
up the current [`Context`][] and then uses that.
+
+
+### `Realm`
+
+The `Realm` class is a container for a set of JavaScript objects and functions
+that are associated with a particular [ECMAScript realm][].
+
+Each ECMAScript realm comes with a global object and a set of intrinsic
+objects. An ECMAScript realm has a `[[HostDefined]]` field, which represents
+the Node.js [`Realm`][] object.
+
+Every `Realm` instance is created for a particular [`Context`][]. A `Realm`
+can be a principal realm or a synthetic realm. A principal realm is created
+for each `Environment`'s main [`Context`][]. A synthetic realm is created
+for the [`Context`][] of each [`ShadowRealm`][] constructed from the JS API. No
+`Realm` is created for the [`Context`][] of a `vm.Context`.
+
+Native bindings and built-in modules can be evaluated in either a principal
+realm or a synthetic realm.
+
+The `Realm` class contains a large number of different fields for
+different built-in modules, for example the memory for a `Uint32Array` that
+the `url` module uses for storing data returned from a
+`urlBinding.update()` call.
+
+It also provides [cleanup hooks][] and maintains a list of [`BaseObject`][]
+instances.
+
+Typical ways of accessing the current `Realm` in the Node.js code are:
+
+* Given a `FunctionCallbackInfo` for a [binding function][],
+ using `Realm::GetCurrent(args)`.
+* Given a [`BaseObject`][], using `realm()` or `self->realm()`.
+* Given a [`Context`][], using `Realm::GetCurrent(context)`.
+ This requires that `context` has been associated with the `Realm`
+ instance, e.g. is the principal `Realm` for the `Environment`.
+* Given an [`Isolate`][], using `Realm::GetCurrent(isolate)`. This looks
+ up the current [`Context`][] and then uses its `Realm`.
+
### `IsolateData`
@@ -509,7 +551,7 @@ implement them. Otherwise, add the id and the class name to the
// In the HTTP parser source code file:
class BindingData : public BaseObject {
public:
- BindingData(Environment* env, Local