mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: use handle instead of globals for injection (#8946)
This commit is contained in:
parent
a4e444d217
commit
6fd05d963e
@ -220,7 +220,7 @@ export class Frame {
|
|||||||
this.#client = client;
|
this.#client = client;
|
||||||
this.worlds = {
|
this.worlds = {
|
||||||
[MAIN_WORLD]: new IsolatedWorld(this),
|
[MAIN_WORLD]: new IsolatedWorld(this),
|
||||||
[PUPPETEER_WORLD]: new IsolatedWorld(this, true),
|
[PUPPETEER_WORLD]: new IsolatedWorld(this),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,8 +776,8 @@ export class Frame {
|
|||||||
|
|
||||||
return this.worlds[MAIN_WORLD].transferHandle(
|
return this.worlds[MAIN_WORLD].transferHandle(
|
||||||
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
||||||
async ({url, id, type, content}) => {
|
async ({createDeferredPromise}, {url, id, type, content}) => {
|
||||||
const promise = InjectedUtil.createDeferredPromise<void>();
|
const promise = createDeferredPromise<void>();
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.type = type;
|
script.type = type;
|
||||||
script.text = content;
|
script.text = content;
|
||||||
@ -809,6 +809,7 @@ export class Frame {
|
|||||||
await promise;
|
await promise;
|
||||||
return script;
|
return script;
|
||||||
},
|
},
|
||||||
|
await this.worlds[PUPPETEER_WORLD].puppeteerUtil,
|
||||||
{...options, type, content}
|
{...options, type, content}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -858,8 +859,8 @@ export class Frame {
|
|||||||
|
|
||||||
return this.worlds[MAIN_WORLD].transferHandle(
|
return this.worlds[MAIN_WORLD].transferHandle(
|
||||||
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
||||||
async ({url, content}) => {
|
async ({createDeferredPromise}, {url, content}) => {
|
||||||
const promise = InjectedUtil.createDeferredPromise<void>();
|
const promise = createDeferredPromise<void>();
|
||||||
let element: HTMLStyleElement | HTMLLinkElement;
|
let element: HTMLStyleElement | HTMLLinkElement;
|
||||||
if (!url) {
|
if (!url) {
|
||||||
element = document.createElement('style');
|
element = document.createElement('style');
|
||||||
@ -892,6 +893,7 @@ export class Frame {
|
|||||||
await promise;
|
await promise;
|
||||||
return element;
|
return element;
|
||||||
},
|
},
|
||||||
|
await this.worlds[PUPPETEER_WORLD].puppeteerUtil,
|
||||||
options
|
options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import {Protocol} from 'devtools-protocol';
|
import {Protocol} from 'devtools-protocol';
|
||||||
import {source as injectedSource} from '../generated/injected.js';
|
import {source as injectedSource} from '../generated/injected.js';
|
||||||
|
import type PuppeteerUtil from '../injected/injected.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferredPromise} from '../util/DeferredPromise.js';
|
import {createDeferredPromise} from '../util/DeferredPromise.js';
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
@ -114,7 +115,6 @@ export interface IsolatedWorldChart {
|
|||||||
*/
|
*/
|
||||||
export class IsolatedWorld {
|
export class IsolatedWorld {
|
||||||
#frame: Frame;
|
#frame: Frame;
|
||||||
#injected: boolean;
|
|
||||||
#document?: ElementHandle<Document>;
|
#document?: ElementHandle<Document>;
|
||||||
#context = createDeferredPromise<ExecutionContext>();
|
#context = createDeferredPromise<ExecutionContext>();
|
||||||
#detached = false;
|
#detached = false;
|
||||||
@ -125,6 +125,11 @@ export class IsolatedWorld {
|
|||||||
// Contains mapping from functions that should be bound to Puppeteer functions.
|
// Contains mapping from functions that should be bound to Puppeteer functions.
|
||||||
#boundFunctions = new Map<string, Function>();
|
#boundFunctions = new Map<string, Function>();
|
||||||
#waitTasks = new Set<WaitTask>();
|
#waitTasks = new Set<WaitTask>();
|
||||||
|
#puppeteerUtil = createDeferredPromise<JSHandle<PuppeteerUtil>>();
|
||||||
|
|
||||||
|
get puppeteerUtil(): Promise<JSHandle<PuppeteerUtil>> {
|
||||||
|
return this.#puppeteerUtil;
|
||||||
|
}
|
||||||
|
|
||||||
get _waitTasks(): Set<WaitTask> {
|
get _waitTasks(): Set<WaitTask> {
|
||||||
return this.#waitTasks;
|
return this.#waitTasks;
|
||||||
@ -138,11 +143,10 @@ export class IsolatedWorld {
|
|||||||
return `${name}_${contextId}`;
|
return `${name}_${contextId}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(frame: Frame, injected = false) {
|
constructor(frame: Frame) {
|
||||||
// Keep own reference to client because it might differ from the FrameManager's
|
// Keep own reference to client because it might differ from the FrameManager's
|
||||||
// client for OOP iframes.
|
// client for OOP iframes.
|
||||||
this.#frame = frame;
|
this.#frame = frame;
|
||||||
this.#injected = injected;
|
|
||||||
this.#client.on('Runtime.bindingCalled', this.#onBindingCalled);
|
this.#client.on('Runtime.bindingCalled', this.#onBindingCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,13 +168,12 @@ export class IsolatedWorld {
|
|||||||
|
|
||||||
clearContext(): void {
|
clearContext(): void {
|
||||||
this.#document = undefined;
|
this.#document = undefined;
|
||||||
|
this.#puppeteerUtil = createDeferredPromise();
|
||||||
this.#context = createDeferredPromise();
|
this.#context = createDeferredPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
setContext(context: ExecutionContext): void {
|
setContext(context: ExecutionContext): void {
|
||||||
if (this.#injected) {
|
this.#injectPuppeteerUtil(context);
|
||||||
context.evaluate(injectedSource).catch(debugError);
|
|
||||||
}
|
|
||||||
this.#ctxBindings.clear();
|
this.#ctxBindings.clear();
|
||||||
this.#context.resolve(context);
|
this.#context.resolve(context);
|
||||||
for (const waitTask of this._waitTasks) {
|
for (const waitTask of this._waitTasks) {
|
||||||
@ -178,6 +181,22 @@ export class IsolatedWorld {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async #injectPuppeteerUtil(context: ExecutionContext): Promise<void> {
|
||||||
|
try {
|
||||||
|
this.#puppeteerUtil.resolve(
|
||||||
|
(await context.evaluateHandle(
|
||||||
|
`(() => {
|
||||||
|
const module = {};
|
||||||
|
${injectedSource}
|
||||||
|
return module.exports.default;
|
||||||
|
})()`
|
||||||
|
)) as JSHandle<PuppeteerUtil>
|
||||||
|
);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
debugError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hasContext(): boolean {
|
hasContext(): boolean {
|
||||||
return this.#context.resolved();
|
return this.#context.resolved();
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import {createDeferredPromise} from '../util/DeferredPromise.js';
|
import {createDeferredPromise} from '../util/DeferredPromise.js';
|
||||||
import * as Poller from './Poller.js';
|
|
||||||
import * as util from './util.js';
|
import * as util from './util.js';
|
||||||
|
|
||||||
Object.assign(
|
const PuppeteerUtil = Object.freeze({
|
||||||
self,
|
|
||||||
Object.freeze({
|
|
||||||
InjectedUtil: {
|
|
||||||
...Poller,
|
|
||||||
...util,
|
...util,
|
||||||
createDeferredPromise,
|
createDeferredPromise,
|
||||||
},
|
});
|
||||||
})
|
|
||||||
);
|
type PuppeteerUtil = typeof PuppeteerUtil;
|
||||||
|
|
||||||
|
export default PuppeteerUtil;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import {createDeferredPromise} from '../util/DeferredPromise.js';
|
/**
|
||||||
|
* CommonJS JavaScript code that provides the puppeteer utilities. See the
|
||||||
declare global {
|
* [README](https://github.com/puppeteer/puppeteer/blob/main/src/injected/README.md)
|
||||||
const InjectedUtil: {
|
* for injection for more information.
|
||||||
createDeferredPromise: typeof createDeferredPromise;
|
*
|
||||||
};
|
* @internal
|
||||||
}
|
*/
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export const source = SOURCE_CODE;
|
export const source = SOURCE_CODE;
|
||||||
|
@ -8,6 +8,5 @@
|
|||||||
"references": [
|
"references": [
|
||||||
{"path": "../vendor/tsconfig.cjs.json"},
|
{"path": "../vendor/tsconfig.cjs.json"},
|
||||||
{"path": "../compat/cjs/tsconfig.json"}
|
{"path": "../compat/cjs/tsconfig.json"}
|
||||||
],
|
]
|
||||||
"exclude": ["injected/injected.ts"]
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,5 @@
|
|||||||
"references": [
|
"references": [
|
||||||
{"path": "../vendor/tsconfig.esm.json"},
|
{"path": "../vendor/tsconfig.esm.json"},
|
||||||
{"path": "../compat/esm/tsconfig.json"}
|
{"path": "../compat/esm/tsconfig.json"}
|
||||||
],
|
]
|
||||||
"exclude": ["injected/injected.ts"]
|
|
||||||
}
|
}
|
||||||
|
@ -23,18 +23,35 @@ import {
|
|||||||
setupTestPageAndContextHooks,
|
setupTestPageAndContextHooks,
|
||||||
} from './mocha-utils.js';
|
} from './mocha-utils.js';
|
||||||
|
|
||||||
describe('InjectedUtil tests', function () {
|
describe('PuppeteerUtil tests', function () {
|
||||||
setupTestBrowserHooks();
|
setupTestBrowserHooks();
|
||||||
setupTestPageAndContextHooks();
|
setupTestPageAndContextHooks();
|
||||||
|
|
||||||
it('should work', async () => {
|
it('should work', async () => {
|
||||||
const {page} = getTestState();
|
const {page} = getTestState();
|
||||||
|
|
||||||
const handle = await page
|
const world = page.mainFrame().worlds[PUPPETEER_WORLD];
|
||||||
.mainFrame()
|
const value = await world.evaluate(PuppeteerUtil => {
|
||||||
.worlds[PUPPETEER_WORLD].evaluate(() => {
|
return typeof PuppeteerUtil === 'object';
|
||||||
return typeof InjectedUtil === 'object';
|
}, world.puppeteerUtil);
|
||||||
|
expect(value).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('createFunction tests', function () {
|
||||||
|
it('should work', async () => {
|
||||||
|
const {page} = getTestState();
|
||||||
|
|
||||||
|
const world = page.mainFrame().worlds[PUPPETEER_WORLD];
|
||||||
|
const value = await world.evaluate(
|
||||||
|
({createFunction}, fnString) => {
|
||||||
|
return createFunction(fnString)(4);
|
||||||
|
},
|
||||||
|
await world.puppeteerUtil,
|
||||||
|
(() => {
|
||||||
|
return 4;
|
||||||
|
}).toString()
|
||||||
|
);
|
||||||
|
expect(value).toBe(4);
|
||||||
});
|
});
|
||||||
expect(handle).toBeTruthy();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user