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