Revert feat(addInitScript): support cjs modules (#32364)

Reverting https://github.com/microsoft/playwright/pull/32282 and
https://github.com/microsoft/playwright/pull/32240.
This commit is contained in:
Yury Semikhatsky 2024-08-28 15:39:48 -07:00 committed by GitHub
parent d8137f228f
commit 896190edbb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 13 additions and 197 deletions

View File

@ -415,42 +415,13 @@ The order of evaluation of multiple scripts installed via [`method: BrowserConte
[`method: Page.addInitScript`] is not defined.
:::
**Bundling**
If you have a complex script split into several files, it needs to be bundled into a single file first. We recommend running [`esbuild`](https://esbuild.github.io/) or [`webpack`](https://webpack.js.org/) to produce a commonjs module and pass [`option: path`] and [`option: arg`].
```js browser title="mocks/mockRandom.ts"
// This script can import other files.
import { defaultValue } from './defaultValue';
export default function(value?: number) {
window.Math.random = () => value ?? defaultValue;
}
```
```sh
# bundle with esbuild
esbuild mocks/mockRandom.ts --bundle --format=cjs --outfile=mocks/mockRandom.js
```
```js title="tests/example.spec.ts"
const mockPath = { path: path.resolve(__dirname, '../mocks/mockRandom.js') };
// Passing 42 as an argument to the default export function.
await context.addInitScript({ path: mockPath }, 42);
// Make sure to pass something even if you do not need to pass an argument.
// This instructs Playwright to treat the file as a commonjs module.
await context.addInitScript({ path: mockPath }, '');
```
### param: BrowserContext.addInitScript.script
* since: v1.8
* langs: js
- `script` <[function]|[string]|[Object]>
- `path` ?<[path]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the
current working directory.
- `content` ?<[string]> Raw script content.
current working directory. Optional.
- `content` ?<[string]> Raw script content. Optional.
Script to be evaluated in all pages in the browser context.
@ -466,9 +437,7 @@ Script to be evaluated in all pages in the browser context.
* langs: js
- `arg` ?<[Serializable]>
Optional JSON-serializable argument to pass to [`param: script`].
* When `script` is a function, the argument is passed to it directly.
* When `script` is a file path, the file is assumed to be a commonjs module. The default export, either `module.exports` or `module.exports.default`, should be a function that's going to be executed with this argument.
Optional argument to pass to [`param: script`] (only supported when passing a function).
### param: BrowserContext.addInitScript.path
* since: v1.8

View File

@ -619,42 +619,13 @@ The order of evaluation of multiple scripts installed via [`method: BrowserConte
[`method: Page.addInitScript`] is not defined.
:::
**Bundling**
If you have a complex script split into several files, it needs to be bundled into a single file first. We recommend running [`esbuild`](https://esbuild.github.io/) or [`webpack`](https://webpack.js.org/) to produce a commonjs module and pass [`option: path`] and [`option: arg`].
```js browser title="mocks/mockRandom.ts"
// This script can import other files.
import { defaultValue } from './defaultValue';
export default function(value?: number) {
window.Math.random = () => value ?? defaultValue;
}
```
```sh
# bundle with esbuild
esbuild mocks/mockRandom.ts --bundle --format=cjs --outfile=mocks/mockRandom.js
```
```js title="tests/example.spec.ts"
const mockPath = { path: path.resolve(__dirname, '../mocks/mockRandom.js') };
// Passing 42 as an argument to the default export function.
await page.addInitScript({ path: mockPath }, 42);
// Make sure to pass something even if you do not need to pass an argument.
// This instructs Playwright to treat the file as a commonjs module.
await page.addInitScript({ path: mockPath }, '');
```
### param: Page.addInitScript.script
* since: v1.8
* langs: js
- `script` <[function]|[string]|[Object]>
- `path` ?<[path]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the
current working directory.
- `content` ?<[string]> Raw script content.
current working directory. Optional.
- `content` ?<[string]> Raw script content. Optional.
Script to be evaluated in the page.
@ -670,9 +641,7 @@ Script to be evaluated in all pages in the browser context.
* langs: js
- `arg` ?<[Serializable]>
Optional JSON-serializable argument to pass to [`param: script`].
* When `script` is a function, the argument is passed to it directly.
* When `script` is a file path, the file is assumed to be a commonjs module. The default export, either `module.exports` or `module.exports.default`, should be a function that's going to be executed with this argument.
Optional argument to pass to [`param: script`] (only supported when passing a function).
### param: Page.addInitScript.path
* since: v1.8

View File

@ -28,37 +28,20 @@ export function envObjectToArray(env: types.Env): { name: string, value: string
return result;
}
export async function evaluationScript(fun: Function | string | { path?: string, content?: string }, arg: any, addSourceUrl: boolean = true): Promise<string> {
export async function evaluationScript(fun: Function | string | { path?: string, content?: string }, arg?: any, addSourceUrl: boolean = true): Promise<string> {
if (typeof fun === 'function') {
const source = fun.toString();
const argString = Object.is(arg, undefined) ? 'undefined' : JSON.stringify(arg);
return `(${source})(${argString})`;
}
if (isString(fun)) {
if (arg !== undefined)
throw new Error('Cannot evaluate a string with arguments');
if (arg !== undefined)
throw new Error('Cannot evaluate a string with arguments');
if (isString(fun))
return fun;
}
if (fun.content !== undefined) {
if (arg !== undefined)
throw new Error('Cannot evaluate a string with arguments');
if (fun.content !== undefined)
return fun.content;
}
if (fun.path !== undefined) {
let source = await fs.promises.readFile(fun.path, 'utf8');
if (arg !== undefined) {
// Assume a CJS module that has a function default export.
source = `(() => {
var exports = {}; var module = { exports };
${source}
let __pw_result__ = module.exports;
if (__pw_result__ && typeof __pw_result__ === 'object' && ('default' in __pw_result__))
__pw_result__ = __pw_result__['default'];
if (typeof __pw_result__ !== 'function')
return __pw_result__;
return __pw_result__(${JSON.stringify(arg)});
})()`;
}
if (addSourceUrl)
source = addSourceUrlToScript(source, fun.path);
return source;

View File

@ -288,41 +288,8 @@ export interface Page {
* [browserContext.addInitScript(script[, arg])](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-init-script)
* and [page.addInitScript(script[, arg])](https://playwright.dev/docs/api/class-page#page-add-init-script) is not
* defined.
*
* **Bundling**
*
* If you have a complex script split into several files, it needs to be bundled into a single file first. We
* recommend running [`esbuild`](https://esbuild.github.io/) or [`webpack`](https://webpack.js.org/) to produce a
* commonjs module and pass `path` and `arg`.
*
* ```js
* // mocks/mockRandom.ts
* // This script can import other files.
* import { defaultValue } from './defaultValue';
*
* export default function(value?: number) {
* window.Math.random = () => value ?? defaultValue;
* }
* ```
*
* ```js
* // tests/example.spec.ts
* const mockPath = { path: path.resolve(__dirname, '../mocks/mockRandom.js') };
*
* // Passing 42 as an argument to the default export function.
* await page.addInitScript({ path: mockPath }, 42);
*
* // Make sure to pass something even if you do not need to pass an argument.
* // This instructs Playwright to treat the file as a commonjs module.
* await page.addInitScript({ path: mockPath }, '');
* ```
*
* @param script Script to be evaluated in the page.
* @param arg Optional JSON-serializable argument to pass to `script`.
* - When `script` is a function, the argument is passed to it directly.
* - When `script` is a file path, the file is assumed to be a commonjs module. The default export, either
* `module.exports` or `module.exports.default`, should be a function that's going to be executed with this
* argument.
* @param arg Optional argument to pass to `script` (only supported when passing a function).
*/
addInitScript<Arg>(script: PageFunction<Arg, any> | { path?: string, content?: string }, arg?: Arg): Promise<void>;
@ -7733,41 +7700,8 @@ export interface BrowserContext {
* [browserContext.addInitScript(script[, arg])](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-init-script)
* and [page.addInitScript(script[, arg])](https://playwright.dev/docs/api/class-page#page-add-init-script) is not
* defined.
*
* **Bundling**
*
* If you have a complex script split into several files, it needs to be bundled into a single file first. We
* recommend running [`esbuild`](https://esbuild.github.io/) or [`webpack`](https://webpack.js.org/) to produce a
* commonjs module and pass `path` and `arg`.
*
* ```js
* // mocks/mockRandom.ts
* // This script can import other files.
* import { defaultValue } from './defaultValue';
*
* export default function(value?: number) {
* window.Math.random = () => value ?? defaultValue;
* }
* ```
*
* ```js
* // tests/example.spec.ts
* const mockPath = { path: path.resolve(__dirname, '../mocks/mockRandom.js') };
*
* // Passing 42 as an argument to the default export function.
* await context.addInitScript({ path: mockPath }, 42);
*
* // Make sure to pass something even if you do not need to pass an argument.
* // This instructs Playwright to treat the file as a commonjs module.
* await context.addInitScript({ path: mockPath }, '');
* ```
*
* @param script Script to be evaluated in all pages in the browser context.
* @param arg Optional JSON-serializable argument to pass to `script`.
* - When `script` is a function, the argument is passed to it directly.
* - When `script` is a file path, the file is assumed to be a commonjs module. The default export, either
* `module.exports` or `module.exports.default`, should be a function that's going to be executed with this
* argument.
* @param arg Optional argument to pass to `script` (only supported when passing a function).
*/
addInitScript<Arg>(script: PageFunction<Arg, any> | { path?: string, content?: string }, arg?: Arg): Promise<void>;

View File

@ -1,33 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// one.ts
var one_exports = {};
__export(one_exports, {
default: () => one_default
});
module.exports = __toCommonJS(one_exports);
// two.ts
var value = 42;
// one.ts
function one_default(arg) {
window.injected = arg ?? value;
}

View File

@ -31,12 +31,6 @@ it('should work with a path', async ({ page, server, asset }) => {
expect(await page.evaluate(() => window['result'])).toBe(123);
});
it('should assume CJS module with a path and arg', async ({ page, server, asset }) => {
await page.addInitScript({ path: asset('injectedmodule.js') }, 17);
await page.goto(server.EMPTY_PAGE);
expect(await page.evaluate(() => window['injected'])).toBe(17);
});
it('should work with content @smoke', async ({ page, server }) => {
await page.addInitScript({ content: 'window["injected"] = 123' });
await page.goto(server.PREFIX + '/tamperable.html');