This is normally not called in "normal" dump-usage, but with
XMLSerializer.serializeToString an Attr node _can_ be provided. The spec says,
and FF agrees, this should return an empty string.
When set (defaults to not set/false), --dump will include iframe contents.
I was hoping I could add a mode to strip_mode to this, but since dump is used
extensively (e.g. innerHTML), this is something that has to be off by default
(for correctness).
Depends on: https://github.com/lightpanda-io/zig-v8-fork/pull/152
We previously ran the message loop every 250ms. This commit changes it to run on
every tick (much more frequently). It also runs microtasks after draining the
message loop (since it can generate microtasks).
Also, we use to run microtasks after each script execution. Now we drain the
message Loop + microtasks.
We still only drain the microtasks when executing v8 callbacks.
As part of this change, we also adjust our wait time based on whether or not
there are pending background tasks in v8 in order to try to execute them (in
general) and in a timely manner.
The goal is to ensure that tasks v8 enqueued on the foreground thread are
executed promptly.
This change is particularly useful for calls to webassembly as compilation
happens in the background and eventually requires the message loop to be drained
to continue.
Previously, if a script did `await WebAssembly.instantiate(....)`, there was
a good chance we'd never finish the code - we'd wait too long to run the
message loop AND, after running it, we wouldn't necessarily resolve the promise.
Some CDP clients (e.g. playwright-go) request /json/version/ with a
trailing
slash. Added handling for this variant to match the exact same behavior
as /json/version
Given:
a.href = "over 9000!"
Then:
a.href === BASE_URL + '/over%209000!';
This commits adds an escape: bool option to URL.resolve which will escape the
path, query and fragment when true.
Also changes the Anchor, Image, Link and IFrame getSrc to escape. Escaping is
also used when navigating a frame.
We currently store all of the env's contexts in an ArrayList. When performing
micro/macro tasks, we iterate through this list and perform the micro/macro
tasks. This can result in the ArrayList being invalidated (e.g. a microtask can
result in a context being created, a promise resolving and creating an iframe).
Invalidating the arrylist while we iterate through it is a use-after-free.
This commit stores contexts in a fixed array (64) so that it doesn't move.
Iteration is slower, unfortunately, as the new `env.context_count` has to be
checked.
Fixes WPT crash on
/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.html url=http://web-platform.test:8000/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.html
This commit also prevents microtasks execution from causing microtask execution.
On the above test, I saw runMicrotasks which I don't think we're supposed to do.
Wasn't really needed before frames and multithreading,but it's pretty essential
now to figure out what's going on. Probably needs to be applied more
broadly.
This seems to only happen in error cases, most notably someone changes the
object to return an invalid ownKeys, as we see in WPT
/fetch/api/headers/headers-record.any.html
This is a bit sad, but at least for now, all frames must share the same
page.arena and page.factory (they still get their own v8::Context and
call_arena).
Consider this case (from WPT /css/cssom-view/scrollingElement.html):
```
let nonQuirksFrame = document.createElement("iframe");
nonQuirksFrame.onload = this.step_func_done(function() {
var nonQuirksDoc = nonQuirksFrame.contentDocument;
nonQuirksDoc.removeChild(nonQuirksDoc.documentElement);
});
nonQuirksFrame.src = URL.createObjectURL(new Blob([`<!doctype html>`], { type:
"text/html" }));
document.body.append(nonQuirksFrame);
```
We have the root page (p0) and the frame page (p1). When the frame (p1) is
created, it's [currently] given its own arena/factory and parses the page. Those
nodes are created with p1's factory.
The onload callback executes on p0, so when we call removeChild that's executing
with p0's arena/factory and tries to release memory using that factory - which
is NOT the factory that created them.
A better approach might be that _memory_ operations aren't tied to the current
calling context, but rather the owning document's page. But:
1 - That would mean we have 2 execution contexts: the v8 context where the code
is running, and the memory context that owns the code
2 - Nodes can be disconnected, what page should we use?
3 - Some operations can behave across frames, p0 could adoptNode on p1, so we'd
have to carefully use p1's factory when cleaning up and re-create the node
in p0's factory.
So much hassle.
Using a shared factory/arena solves these problems at the cost of bloat - when
a frame goes away or navigates, we can't free its old memory. At some point, we
should fix that. But I don't have a quick and easy solution, and sharing the
arena/factory is _really_ quick and easy.