fix: guard against undefined contexts (#9826)

We do not create contexts when we are unable to attribute them to a frame or they come from a stale oopif.
Async hop in the binding method can also cause the context to be destroyed already.

Reproduced with codegen.
This commit is contained in:
Dmitry Gozman 2021-10-27 13:28:52 -07:00 committed by GitHub
parent be64b5f6e2
commit 4743036bbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 17 deletions

View file

@ -773,7 +773,9 @@ class FrameSession {
// @see https://github.com/GoogleChrome/puppeteer/issues/3865
return;
}
const context = this._contextIdToContext.get(event.executionContextId)!;
const context = this._contextIdToContext.get(event.executionContextId);
if (!context)
return;
const values = event.args.map(arg => context.createHandle(arg));
this._page._addConsoleMessage(event.type, values, toConsoleMessageLocation(event.stackTrace));
}
@ -786,10 +788,12 @@ class FrameSession {
}
async _onBindingCalled(event: Protocol.Runtime.bindingCalledPayload) {
const context = this._contextIdToContext.get(event.executionContextId)!;
const pageOrError = await this._crPage.pageOrError();
if (!(pageOrError instanceof Error))
await this._page._onBindingCalled(event.payload, context);
if (!(pageOrError instanceof Error)) {
const context = this._contextIdToContext.get(event.executionContextId);
if (context)
await this._page._onBindingCalled(event.payload, context);
}
}
_onDialog(event: Protocol.Page.javascriptDialogOpeningPayload) {

View file

@ -237,7 +237,9 @@ export class FFPage implements PageDelegate {
_onConsole(payload: Protocol.Runtime.consolePayload) {
const { type, args, executionContextId, location } = payload;
const context = this._contextIdToContext.get(executionContextId)!;
const context = this._contextIdToContext.get(executionContextId);
if (!context)
return;
this._page._addConsoleMessage(type, args.map(arg => context.createHandle(arg)), location);
}
@ -253,15 +255,19 @@ export class FFPage implements PageDelegate {
}
async _onBindingCalled(event: Protocol.Page.bindingCalledPayload) {
const context = this._contextIdToContext.get(event.executionContextId)!;
const pageOrError = await this.pageOrError();
if (!(pageOrError instanceof Error))
await this._page._onBindingCalled(event.payload, context);
if (!(pageOrError instanceof Error)) {
const context = this._contextIdToContext.get(event.executionContextId);
if (context)
await this._page._onBindingCalled(event.payload, context);
}
}
async _onFileChooserOpened(payload: Protocol.Page.fileChooserOpenedPayload) {
const { executionContextId, element } = payload;
const context = this._contextIdToContext.get(executionContextId)!;
const context = this._contextIdToContext.get(executionContextId);
if (!context)
return;
const handle = context.createHandle(element).asElement()!;
await this._page._onFileChooserOpened(handle);
}

View file

@ -498,9 +498,9 @@ export class WKPage implements PageDelegate {
const { type, level, text, parameters, url, line: lineNumber, column: columnNumber, source } = event.message;
if (level === 'debug' && parameters && parameters[0].value === BINDING_CALL_MESSAGE) {
const parsedObjectId = JSON.parse(parameters[1].objectId!);
const context = this._contextIdToContext.get(parsedObjectId.injectedScriptId)!;
this.pageOrError().then(pageOrError => {
if (!(pageOrError instanceof Error))
const context = this._contextIdToContext.get(parsedObjectId.injectedScriptId);
if (!(pageOrError instanceof Error) && context)
this._page._onBindingCalled(parameters[2].value, context);
});
return;
@ -531,16 +531,19 @@ export class WKPage implements PageDelegate {
else if (type === 'timing')
derivedType = 'timeEnd';
const handles = (parameters || []).map(p => {
let context: dom.FrameExecutionContext | null = null;
const handles: JSHandle[] = [];
for (const p of parameters || []) {
let context: dom.FrameExecutionContext | undefined;
if (p.objectId) {
const objectId = JSON.parse(p.objectId);
context = this._contextIdToContext.get(objectId.injectedScriptId)!;
context = this._contextIdToContext.get(objectId.injectedScriptId);
} else {
context = this._contextIdToContext.get(this._mainFrameContextId!)!;
context = this._contextIdToContext.get(this._mainFrameContextId!);
}
return context.createHandle(p);
});
if (!context)
return;
handles.push(context.createHandle(p));
}
this._lastConsoleMessage = {
derivedType,
text,