Skip to content

Specify execution context#905

Open
Rob--W wants to merge 1 commit into
mainfrom
spec-execution-context
Open

Specify execution context#905
Rob--W wants to merge 1 commit into
mainfrom
spec-execution-context

Conversation

@Rob--W

@Rob--W Rob--W commented Nov 13, 2025

Copy link
Copy Markdown
Member

While discussing #873 (comment) at TPAC, I mentioned the ambiguity of "extension context", and suggested "privileged execution context" to disambiguate it. But this term may not be well-known, so I'm adding a definition for it.


Preview | Diff

@oliverdunk oliverdunk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Rob! I left some initial thoughts. Some of the vague language (e.g "a limited number of extension APIs may be available") seems out of a place for a specification, but I'm happy to address that in future PRs.

Comment thread specification/index.bs Outdated

# The `browser` global

The `browser` global is the primary namespace hosting extension APIs, available to [=extension context=]s.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we figure out how to properly cross-reference the browser namespace spec here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried finding an indexed version of our spec, but cannot find it.
But I see that it ought to be possible to cross-reference it with custom biblio entries, even inline in the spec: https://speced.github.io/bikeshed/#biblio-custom
When I tried to add [[webextensions-browser-global]] at first, it rendered as a link with literally that text. I wanted it to render as something friendlier, and it appears that adding inline, e.g. [[webextensions-browser-global inline]] achieves that. It is rendered as window.browser link. This inline link modifier feature is documented at https://speced.github.io/bikeshed/#biblio-mods

In my first draft I put [=extension context=]s because <dfn>extension context</dfn> was defined as such. But apparently plurals are supported, so I can use [=extension contexts=] instead (and have the s render inside the rendered <a> as desired). This feature is documented at https://speced.github.io/bikeshed/#conjugating

To test locally, I used https://www.w3.org/publications/spec-generator/ (linked from https://speced.github.io/bikeshed/#web ) to preview the spec.

Comment thread specification/index.bs Outdated
Comment thread specification/index.bs Outdated
Comment thread specification/index.bs Outdated
Comment thread specification/index.bs Outdated

* An <dfn>extension context</dfn> is any JavaScript execution context associated with an extension.
* A <dfn>privileged extension context</dfn> has access to the full set of extension APIs available to the extension. The most prominent example is the background page or worker defined by the [[#key-background]] part of the [=manifest=].
* The main execution context of a web page, also known as the <dfn>main world</dfn>, is not an extension context. It does not have access to any extension API, except when an extension allows so through [#key-externally_connectable].

@xeenon xeenon Nov 21, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not entirely true. An extension page loaded in a tab executes in the main world. So does a background page. I think we should separate the concept of worlds and contexts. DevTools panels are main world with an unprivileged context for example.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to emphasize that even though an extension can trigger script execution in a web page, that it is not considered an extension context. How about adding "when its origin is not an extension origin"?

Suggested change
* The main execution context of a web page, also known as the <dfn>main world</dfn>, is not an extension context. It does not have access to any extension API, except when an extension allows so through [#key-externally_connectable].
* The main execution context of a web page, also known as the <dfn>main world</dfn>, is not an extension context when its origin is not an extension origin. It does not have access to any extension API, except when an extension allows so through [#key-externally_connectable].

Comment thread specification/index.bs Outdated
@Rob--W

Rob--W commented May 31, 2026

Copy link
Copy Markdown
Member Author

I have updated the spec text, and spend some time to carefully specify the definition of an isolated world, since explaining an extension context without describing isolated world is rather incomplete.

Comment thread specification/index.bs

Extensions can execute JavaScript code, in any of the following execution contexts:

* An <dfn>extension context</dfn> is a [=realm=] associated with an [=extension origin=].

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like a realm is the definition we should align on, but I was previously under the impression that world's today have some differences from realms. Is that the case and if so, are they different enough that we are just documenting something idealistic?

Feel free to ignore this if the above is not the case :)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like a realm is the definition we should align on, but I was previously under the impression that world's today have some differences from realms.

Could you elaborate what you are thinking of?

A realm is the pre-existing abstract description of the context where JS code executes.

In Firefox, we create XPConnect sandboxes, which creates a realm and sets up the globals. If objects are shared between the page's realm and the content script sandbox's realm, the object is wrapped in a XrayWrapper that offers controlled access (and restrictions) as needed. That mechanism is documented at https://firefox-source-docs.mozilla.org/dom/scriptSecurity/xray_vision.html

In Chrome, the JS execution environments are kept strictly separate, which is how Chromium enforces the isolation. That is documented at https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md . That makes zero mention of a "realm", but at some point JS needs to execute, so if I were to treat Chromium's implementation as a black box, a realm seems like a good abstraction.

Although "isolated world" is originally a Chromium terminology that leaks outside through various API names, we should not specify it in terms of Chromium/v8 internals, but in existing standard concepts. This is the first time I write this kind of specs, so feedback is welcome!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some further reading on realms and I think it's the right definition (@rdcronin to confirm).

Although "isolated world" is originally a Chromium terminology that leaks outside through various API names, we should not specify it in terms of Chromium/v8 internals, but in existing standard concepts.

I agree... almost. We definitely shouldn't specify things in terms of the internals of a given engine. However, we also shouldn't use a standard concept just because it is desirable if there is a meaningful delta between the behavior developers would expect if we properly implemented that concept vs. the reality of how engines work today.

As best as I understand it, a V8 context is essentially a realm, so using realms in the specification matches reality. If that's the case I'm onboard.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same concern as Oliver. While the concept of a realm in Ecma262 is very close to what we would use to describe an execution context for an extension, I don't think this is inherently true, nor that it is guaranteed to remain accurate. The spec for realms goes into details about the manner in which realms are created and initialized, and I'm not sure that this exact process is followed for v8 isolated worlds, nor do I think it is a fundamental requirement for them (that is, if a browser initialized its content script execution contexts differently from the exact realm spec, but in a way that still aligned with the properties we expect of an isolated world, I think that would still be fine from an extension perspective -- even though it would mean it deviated from the realm spec).

I'd prefer we avoid the "realm" usage here, instead using either nomenclature which is suitable abstract ("context") or defining our own with the set of principles required.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same concern as Oliver. While the concept of a realm in Ecma262 is very close to what we would use to describe an execution context for an extension, I don't think this is inherently true, nor that it is guaranteed to remain accurate.

I think that in terms of standard terms, the concept of a ECMAScript Realm is the right choice here. I'll show that Chromium (+Blink+v8) does indeed have an implementation that (trivially) resembles (and augments) it.
(and Safari also has concepts similar to Chromium, as the basics of isolated worlds (DOMWrapperWorld) existed in WebKit before Chromium created Blink as a fork of WebKit)

The literal text in the ECMA spec you linked (which I already cited in my proposed specification text) is:

Before it is evaluated, all ECMAScript code must be associated with a realm. Conceptually, a realm consists of a set of intrinsic objects, an ECMAScript global environment, all of the ECMAScript code that is loaded within the scope of that global environment, and other associated state and resources.

The first sentence already provides a basis for the argument that any JS engine should already recognize the concept of a realm. If we remove all special behavior, an isolated world is a place where JS code executes - which is exactly what a realm represents.

Note that I intentionally chose the ECMAScript definition (which has minimal requirements, it is browser-agnostic) instead of the augmented realm + environment settings object from the HTML spec (https://html.spec.whatwg.org/multipage/webappapis.html#realms-and-their-counterparts), exactly because the HTML spec version of it imposes many expectations that none of our implementations have.

Now I'm going to enumerate some Chromium implementation details:

  • script_state.h class declaration starts with the following comment: "ScriptState is an abstraction class that holds all information about script execution (e.g., v8::Isolate, v8::Context, DOMWrapperWorld, ExecutionContext etc). If you need any info about the script execution, you're expected to pass around ScriptState in the code base. ScriptState is in a 1:1 relationship with v8::Context."
  • ScriptStateImpl::Create is the glue between Blink and v8, and calls V8Initializer::InitializeContext(context, execution_context); (with context a v8::Context and execution_context the "ExecutionContext" described above) and pairs the instance with a DOMWrapperWorld, together forming a ScriptState.
  • script_state.h also has several static methods on ScriptState that use the "realm" terminology (ForCurrentRealm / ForRelevantRealm) that maps an arbitrary v8 object, via v8::Context back to ScriptState.
  • Conclusion: The "realm" concept has a 1:1 mapping to a v8::Context, and together with the documentation at https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md establishes a firm link between the "realm" concept and "world".

Chromium's point where it creates an isolated world is IsolatedWorldManager::GetOrCreateIsolatedWorldForHost, which shows (among others) that the instantiation of an isolated world also includes an identifier for the extension (host_id).

The spec for realms goes into details about the manner in which realms are created and initialized, and I'm not sure that this exact process is followed for v8 isolated worlds, nor do I think it is a fundamental requirement for them (that is, if a browser initialized its content script execution contexts differently from the exact realm spec, but in a way that still aligned with the properties we expect of an isolated world, I think that would still be fine from an extension perspective -- even though it would mean it deviated from the realm spec).

The definition of a Realm covers the Realm record and its fields/properties (including [[HostDefined]] where anything goes) and doe not require the exact steps for creation to be followed. For example, Chromium's v8 engine does not even follow these steps, it takes the smarter approach of deserializing a snapshot. There is a human-readable write-up at https://v8.dev/blog/lazy-deserialization for example.

What we care about are the observed behaviors. We need a place to execute (which realm provides), some indication that makes it different from the main world and other extensions (the world type, extension origin association), and a guarantee that the instrincs (builtin prototypes etc) operate on the same underlying state (which is a bit handwavy but we can expand later if we really want to). The text here is my attempt of expressing the requirements in terms of the bare minimum that is interoperable. I haven't even specified how to create an isolated world - as you remarked that would be too detailed at this stage.

I'd prefer we avoid the "realm" usage here, instead using either nomenclature which is suitable abstract ("context") or defining our own with the set of principles required.

In my first draft of this PR, I initially used An <dfn>extension context</dfn> is any JavaScript execution context associated with an extension. This sounds good at first, but if we look up the ecma262 definition of Execution context, the concept specified there does not match what we want from it. The "realm" concept, to me at least, does.

And then I continued looking for a specification concept capturing built-in DOM APIs and their prototype methods. These are specified by WebIDL and the platform object concept seems to be a perfect fit for that:

Although at the time of this writing the JavaScript specification does not reflect this, every JavaScript object must have an associated realm. The mechanisms for associating objects with realms are, for now, underspecified. However, we note that in the case of platform objects, the associated realm is equal to the object’s relevant realm,

I think that "realm" is still not only a reasonable but also accurate way to serve as the basis for specifying the expected behaviors. I think that my attempt to specify extension contexts and isolated worlds is an accurate representation of how Chromium and Firefox behave. I'll need to refine the text, e.g. the with its own [=global object=] part of A <dfn>world</dfn> is a [=realm=] with its own [=global object=]. is redundant since the definition of a realm already includes [[GlobalObject]]. But before I get there we first need to agree on the primitives used for the specification.

Comment thread specification/index.bs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants