-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow backend to send commands to execute preamble scripts. #1122
base: master
Are you sure you want to change the base?
Conversation
@@ -823,6 +824,10 @@ const char* gOnNewWindowScript = R""""( | |||
// __RECORD_REPLAY__? | |||
window.__RECORD_REPLAY__ = window.top.__RECORD_REPLAY__; | |||
window.__RECORD_REPLAY_ARGUMENTS__ = window.top.__RECORD_REPLAY_ARGUMENTS__; | |||
|
|||
for (g of window.top.__RECORD_REPLAY_GLOBALS__) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We also need to pass down
__RECORD_REPLAY_GLOBALS__
itself.- In fact, I'd vote to only pass down
__RECORD_REPLAY_GLOBALS__
, and just force any user of this API to go through that, rather than adding random globals into a global context that is shared with arbitrary user JS.
- In fact, I'd vote to only pass down
- →
linter
failure.
I want to see the API used and working before hitting |
@@ -2502,6 +2547,10 @@ static void InitializeRecordReplayApiObjects(v8::Isolate* isolate, LocalFrame* l | |||
DefineProperty(isolate, context->Global(), "__RECORD_REPLAY_ARGUMENTS__", | |||
args); | |||
|
|||
v8::Local<v8::Object> globals = v8::Object::New(isolate); | |||
DefineProperty(isolate, context->Global(), "__RECORD_REPLAY_GLOBALS__", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will reset the globals on every root-level navigation. We probably want to keep them around or re-run the preamble.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I was also confused about this. do we need to store the scripts somewhere so we can rerun them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Domi and I have been chatting about our context handling, which is a tad naiive to say the least; we aren't going to worry about it in this PR, but rather address it wholly in another.
I can try to integrate with it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'll attempt to try out these changes locally.
side question, not blocking: do we assume that all of this code is running single-threaded because it is only called into from v8, we only ever have one v8 instance, and the v8 instance is single-threaded?
@@ -3043,6 +3050,10 @@ function replayEval(fn) { | |||
} | |||
} | |||
|
|||
function registerGlobal(name, val) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is intended to be called by the preamble script, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup--the PR description shows a hypothetical usage.
@@ -2350,6 +2355,46 @@ static void fromJsEndReplayCode( | |||
recordreplay::ExitReplayCode(); | |||
} | |||
|
|||
// Connects replay globals that must be accessible from all contexts; MUST be called | |||
// with AutoMarkReplayCode. | |||
static void ConnectPreambleGlobals(LocalFrame* frame, v8::Isolate *isolate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you pass in the AutoMarkReplayCode
object here to ensure that it is held?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ehh, I waffled on this, due to recursion (it just looks distasteful/re-entrant to me); once we fix our context handling, I think we'll end up with a set of Conexts we can just safely iterate over, rather than this traversal.
@@ -2350,6 +2355,46 @@ static void fromJsEndReplayCode( | |||
recordreplay::ExitReplayCode(); | |||
} | |||
|
|||
// Connects replay globals that must be accessible from all contexts; MUST be called | |||
// with AutoMarkReplayCode. | |||
static void ConnectPreambleGlobals(LocalFrame* frame, v8::Isolate *isolate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe name should be ConnectPreambleGlobalsToCurrentContexts
or something like that so it's clear what we are connecting the globals to?
@@ -2502,6 +2547,10 @@ static void InitializeRecordReplayApiObjects(v8::Isolate* isolate, LocalFrame* l | |||
DefineProperty(isolate, context->Global(), "__RECORD_REPLAY_ARGUMENTS__", | |||
args); | |||
|
|||
v8::Local<v8::Object> globals = v8::Object::New(isolate); | |||
DefineProperty(isolate, context->Global(), "__RECORD_REPLAY_GLOBALS__", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I was also confused about this. do we need to store the scripts somewhere so we can rerun them?
cf0ac5c
to
8805488
Compare
Yes, this is by V8's design. |
@@ -825,7 +827,7 @@ const char* gOnNewWindowScript = R""""( | |||
window.__RECORD_REPLAY__ = window.top.__RECORD_REPLAY__; | |||
window.__RECORD_REPLAY_ARGUMENTS__ = window.top.__RECORD_REPLAY_ARGUMENTS__; | |||
|
|||
for (g of window.top.__RECORD_REPLAY_GLOBALS__) { | |||
for (const g of window.top.__RECORD_REPLAY_GLOBALS__) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: My previous concern was not addressed -
- We also need to pass down
__RECORD_REPLAY_GLOBALS__
itself. - In fact, I'd vote to only pass down
__RECORD_REPLAY_GLOBALS__
, and just force any user of this API to go through that, rather than adding random globals into a global context that is shared with arbitrary user JS.
Introduce a new function on
__RECORD_REPLAY__
calledregisterGlobal
, which receives one argument, the name of a global, that can be accessed by any descendant context (read: iframe, with appropriate sandboxing).registerGlobal
stores the string in a new top-level global,__RECORD_REPLAY_GLOBALS__
. Example usage:Introduce a new command,
Target.loadPreamble
, which is given a string as an argument. The string is a script that will be immediately executed in the root (global) context by the browser. After execution, a second script is run which propagates all Replay globals declared in__RECORD_REPLAY_GLOBALS__
to all descendent child contexts, so that they can be accessed as if they were in the context's top-level scope.Any time a new context is created, we re-execute the propagation code, which ensures the registered globals are available in that context.