You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 7, 2025. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 7, 2025. It is now read-only.
Restrict JavaScript environment for Reusing FLEDGE Worklet Contexts #310
On the Chrome implementation side, we’re looking at other options for reusing the JavaScript context for running worklets. One option we are pursuing and would like some feedback on is freezing the global object (equivalent to calling Object.Freeze recursively on globalThis and its properties) before running any scripts. This, combined with some other changes to script local storage would prevent worklet functions from persisting information between runs, so we can reuse the context for any interest groups that use the same bidding script.
If we freeze the global context, some JavaScript changes will be necessary:
Global variable definitions through var and function definitions function generateBid(...) {..} will not be allowed. Instead use script-level definitions through let or const, defining worklet functions like: const generateBid = function(...) {...};.
Instead of these:
var x = …
function generateBid(...) {...}
globalThis.generateBid = function(...) {...}
Use these:
let x = … or const x = …
const generateBid = function(...) {...};
"Overwriting" a property on an object whose prototype is frozen may not work as expected.
Instead of this:
let e = Error(“foo”);
e.name = “bar”; // this line will throw a TypeError
Use this:
let e = Error(“foo”);
Object.defineProperty(e, “name”, {value: “foo”});
One clarification related to this option is whether there needs to be a mechanism for buyer bidding and seller scoring scripts to initialize / pre-compute some data structures before running for later reuse, and, consequently, at which point would freeze happen.
For example, would something along the lines of…
let expensiveObject = computeExpensiveObject(someArguments);
… be possible outside of generateBid, such that all generateBid invocations have access to such precomputed expensiveObject?
In this proposal, would freeze happen after expensiveObject assignment takes place?
We're still investigating this space. We will want to start with the global context frozen, since recursively freezing it is expensive (~3ms on a developer workstation). We expect we can start with a frozen global context before running the script and then drop any state changes to allow us to reuse the context. That would require the script to be run again (computing expensiveObject) each time, though.
We are also looking into performing a second freeze after running the script, so we don't have to run the overall script again. This would effectively only compute the expensive object once, regardless of how many times we need to call generateBid. We will likely need to impose additional restrictions on variables - basically we can't allow anything we can't reliably freeze. We're still evaluating what the restrictions would need to be, but we likely won't be able to allow non-const primitives that are not properties of objects, iterators, or generator objects to be reachable when we perform the freeze. We are still very early in this investigation so it is possible that something might come up that prevents us from using this approach.
Also, I'm assuming the expensive object does not depend on anything other than the contents of the script. If that is not the case, then it is unlikely we can save it across runs.
I've recently landed crrev.com/c/3664757 which adds the "frozen-context" execution mode, so it should be showing up in Canary builds of Chrome. In this mode the context is frozen after the top-level script is run. Freezing the context can add up to 10ms of delay, but our metrics suggest this will be beneficial for most bidders that have at least 2 interest groups and are unable to take advantage of the "group-by-origin" execution mode.
There are a number of restrictions in this "frozen-context" execution mode, due to either limitations in the current implementation or fundamental limitations of the v8 engine. These restrictions are calculated at the time the context is frozen, which is after the top-level script has run and the custom worklet functions have been added. So any variables in scopes that are no longer reachable shouldn't cause problems. Note that some care should be taken because JavaScript closures capture the scope they are declared in. The restrictions are:
Variable declarations that use let instead of const or var may cause problems if they are still in scope after the top-level script has run.
Some data-types are not able to be frozen. Also, since we need to manually allow-list specific datatypes, some data-types that should be able to be frozen may not be initially supported. Freezing will fail if there are active iterators, generators, or array buffers, since they cannot be frozen. Since we need to evaluate data types one at a time, if there is a data type that you need that seems like it should be allowed, feel free to file feedback here and we will see if we can support it.
Since there is a lot of complexity and ambiguity of these restrictions I'm putting together a basic worklet testing environment here to make it easier to check if your bidding scripts will be supported in this mode.
Activity
sbelov commentedon Jun 1, 2022
One clarification related to this option is whether there needs to be a mechanism for buyer bidding and seller scoring scripts to initialize / pre-compute some data structures before running for later reuse, and, consequently, at which point would freeze happen.
For example, would something along the lines of…
… be possible outside of
generateBid, such that allgenerateBidinvocations have access to such precomputedexpensiveObject?In this proposal, would freeze happen after
expensiveObjectassignment takes place?brusshamilton commentedon Jun 2, 2022
We're still investigating this space. We will want to start with the global context frozen, since recursively freezing it is expensive (~3ms on a developer workstation). We expect we can start with a frozen global context before running the script and then drop any state changes to allow us to reuse the context. That would require the script to be run again (computing expensiveObject) each time, though.
We are also looking into performing a second freeze after running the script, so we don't have to run the overall script again. This would effectively only compute the expensive object once, regardless of how many times we need to call generateBid. We will likely need to impose additional restrictions on variables - basically we can't allow anything we can't reliably freeze. We're still evaluating what the restrictions would need to be, but we likely won't be able to allow non-const primitives that are not properties of objects, iterators, or generator objects to be reachable when we perform the freeze. We are still very early in this investigation so it is possible that something might come up that prevents us from using this approach.
Also, I'm assuming the expensive object does not depend on anything other than the contents of the script. If that is not the case, then it is unlikely we can save it across runs.
brusshamilton commentedon Mar 29, 2023
I've recently landed crrev.com/c/3664757 which adds the "frozen-context" execution mode, so it should be showing up in Canary builds of Chrome. In this mode the context is frozen after the top-level script is run. Freezing the context can add up to 10ms of delay, but our metrics suggest this will be beneficial for most bidders that have at least 2 interest groups and are unable to take advantage of the "group-by-origin" execution mode.
There are a number of restrictions in this "frozen-context" execution mode, due to either limitations in the current implementation or fundamental limitations of the v8 engine. These restrictions are calculated at the time the context is frozen, which is after the top-level script has run and the custom worklet functions have been added. So any variables in scopes that are no longer reachable shouldn't cause problems. Note that some care should be taken because JavaScript closures capture the scope they are declared in. The restrictions are:
letinstead ofconstorvarmay cause problems if they are still in scope after the top-level script has run.Since there is a lot of complexity and ambiguity of these restrictions I'm putting together a basic worklet testing environment here to make it easier to check if your bidding scripts will be supported in this mode.