Allow backend to send commands to execute preamble scripts.#1122
Allow backend to send commands to execute preamble scripts.#1122
Conversation
| 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.
- 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
- →
linterfailure.
|
I want to see the API used and working before hitting |
| args); | ||
|
|
||
| v8::Local<v8::Object> globals = v8::Object::New(isolate); | ||
| DefineProperty(isolate, context->Global(), "__RECORD_REPLAY_GLOBALS__", |
There was a problem hiding this comment.
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.
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.
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. |
cweld510
left a comment
There was a problem hiding this comment.
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?
| } | ||
| } | ||
|
|
||
| function registerGlobal(name, val) { |
There was a problem hiding this comment.
This is intended to be called by the preamble script, right?
There was a problem hiding this comment.
Yup--the PR description shows a hypothetical usage.
|
|
||
| // 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.
can you pass in the AutoMarkReplayCode object here to ensure that it is held?
There was a problem hiding this comment.
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.
|
|
||
| // 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.
nit: maybe name should be ConnectPreambleGlobalsToCurrentContexts or something like that so it's clear what we are connecting the globals to?
| args); | ||
|
|
||
| v8::Local<v8::Object> globals = v8::Object::New(isolate); | ||
| DefineProperty(isolate, context->Global(), "__RECORD_REPLAY_GLOBALS__", |
There was a problem hiding this comment.
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. |
| 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.
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).registerGlobalstores 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.