Skip to content

Commit 5993a6a

Browse files
authored
fix: throw from eval methods if >1 argument is passed (#2043)
1 parent 0228ba4 commit 5993a6a

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

src/frames.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { ConsoleMessage } from './console';
2121
import * as dom from './dom';
2222
import { TimeoutError, NotConnectedError } from './errors';
2323
import { Events } from './events';
24-
import { assert, helper, RegisteredListener } from './helper';
24+
import { assert, helper, RegisteredListener, assertMaxArguments } from './helper';
2525
import * as js from './javascript';
2626
import * as network from './network';
2727
import { Page } from './page';
@@ -415,13 +415,15 @@ export class Frame {
415415
async evaluateHandle<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<types.SmartHandle<R>>;
416416
async evaluateHandle<R>(pageFunction: types.Func1<void, R>, arg?: any): Promise<types.SmartHandle<R>>;
417417
async evaluateHandle<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<types.SmartHandle<R>> {
418+
assertMaxArguments(arguments.length, 2);
418419
const context = await this._mainContext();
419420
return context.evaluateHandleInternal(pageFunction, arg);
420421
}
421422

422423
async evaluate<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<R>;
423424
async evaluate<R>(pageFunction: types.Func1<void, R>, arg?: any): Promise<R>;
424425
async evaluate<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<R> {
426+
assertMaxArguments(arguments.length, 2);
425427
const context = await this._mainContext();
426428
return context.evaluateInternal(pageFunction, arg);
427429
}
@@ -464,6 +466,7 @@ export class Frame {
464466
async $eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
465467
async $eval<R>(selector: string, pageFunction: types.FuncOn<Element, void, R>, arg?: any): Promise<R>;
466468
async $eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element, Arg, R>, arg: Arg): Promise<R> {
469+
assertMaxArguments(arguments.length, 3);
467470
const handle = await this.$(selector);
468471
if (!handle)
469472
throw new Error(`Error: failed to find element matching selector "${selector}"`);
@@ -475,6 +478,7 @@ export class Frame {
475478
async $$eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R>;
476479
async $$eval<R>(selector: string, pageFunction: types.FuncOn<Element[], void, R>, arg?: any): Promise<R>;
477480
async $$eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R> {
481+
assertMaxArguments(arguments.length, 3);
478482
const arrayHandle = await selectors._queryArray(this, selector);
479483
const result = await arrayHandle.evaluate(pageFunction, arg);
480484
arrayHandle.dispose();

src/helper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,10 @@ export function assert(value: any, message?: string): asserts value {
337337
throw new Error(message);
338338
}
339339

340+
export function assertMaxArguments(count: number, max: number): asserts count {
341+
assert(count <= max, 'Too many arguments. If you need to pass more than 1 argument to the function wrap them in an object.');
342+
}
343+
340344
export function getFromENV(name: string) {
341345
let value = process.env[name];
342346
value = value || process.env[`npm_config_${name.toLowerCase()}`];

src/page.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import * as dom from './dom';
1919
import * as frames from './frames';
20-
import { assert, helper, Listener } from './helper';
20+
import { assert, helper, Listener, assertMaxArguments } from './helper';
2121
import * as input from './input';
2222
import * as js from './javascript';
2323
import * as network from './network';
@@ -228,18 +228,21 @@ export class Page extends ExtendedEventEmitter implements InnerLogger {
228228
async evaluateHandle<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<types.SmartHandle<R>>;
229229
async evaluateHandle<R>(pageFunction: types.Func1<void, R>, arg?: any): Promise<types.SmartHandle<R>>;
230230
async evaluateHandle<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<types.SmartHandle<R>> {
231+
assertMaxArguments(arguments.length, 2);
231232
return this.mainFrame().evaluateHandle(pageFunction, arg);
232233
}
233234

234235
async $eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
235236
async $eval<R>(selector: string, pageFunction: types.FuncOn<Element, void, R>, arg?: any): Promise<R>;
236237
async $eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element, Arg, R>, arg: Arg): Promise<R> {
238+
assertMaxArguments(arguments.length, 3);
237239
return this.mainFrame().$eval(selector, pageFunction, arg);
238240
}
239241

240242
async $$eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R>;
241243
async $$eval<R>(selector: string, pageFunction: types.FuncOn<Element[], void, R>, arg?: any): Promise<R>;
242244
async $$eval<R, Arg>(selector: string, pageFunction: types.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R> {
245+
assertMaxArguments(arguments.length, 3);
243246
return this.mainFrame().$$eval(selector, pageFunction, arg);
244247
}
245248

@@ -373,6 +376,7 @@ export class Page extends ExtendedEventEmitter implements InnerLogger {
373376
async evaluate<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<R>;
374377
async evaluate<R>(pageFunction: types.Func1<void, R>, arg?: any): Promise<R>;
375378
async evaluate<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<R> {
379+
assertMaxArguments(arguments.length, 2);
376380
return this.mainFrame().evaluate(pageFunction, arg);
377381
}
378382

@@ -568,12 +572,14 @@ export class Worker extends EventEmitter {
568572
async evaluate<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<R>;
569573
async evaluate<R>(pageFunction: types.Func1<void, R>, arg?: any): Promise<R>;
570574
async evaluate<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<R> {
575+
assertMaxArguments(arguments.length, 2);
571576
return (await this._executionContextPromise).evaluateInternal(pageFunction, arg);
572577
}
573578

574579
async evaluateHandle<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<types.SmartHandle<R>>;
575580
async evaluateHandle<R>(pageFunction: types.Func1<void, R>, arg?: any): Promise<types.SmartHandle<R>>;
576581
async evaluateHandle<R, Arg>(pageFunction: types.Func1<Arg, R>, arg: Arg): Promise<types.SmartHandle<R>> {
582+
assertMaxArguments(arguments.length, 2);
577583
return (await this._executionContextPromise).evaluateHandleInternal(pageFunction, arg);
578584
}
579585
}

test/evaluation.spec.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,24 @@ describe('Page.evaluate', function() {
162162
const result = await page.evaluate(() => -Infinity);
163163
expect(Object.is(result, -Infinity)).toBe(true);
164164
});
165+
it('should throw when passed more than one parameter', async({page, server}) => {
166+
const expectThrow = async f => {
167+
let error;
168+
await f().catch(e => error = e);
169+
expect('' + error).toContain('Too many arguments');
170+
}
171+
await expectThrow(() => page.evaluate((a, b) => false, 1, 2));
172+
await expectThrow(() => page.evaluateHandle((a, b) => false, 1, 2));
173+
await expectThrow(() => page.$eval('sel', (a, b) => false, 1, 2));
174+
await expectThrow(() => page.$$eval('sel', (a, b) => false, 1, 2));
175+
await expectThrow(() => page.evaluate((a, b) => false, 1, 2));
176+
const frame = page.mainFrame();
177+
await expectThrow(() => frame.evaluate((a, b) => false, 1, 2));
178+
await expectThrow(() => frame.evaluateHandle((a, b) => false, 1, 2));
179+
await expectThrow(() => frame.$eval('sel', (a, b) => false, 1, 2));
180+
await expectThrow(() => frame.$$eval('sel', (a, b) => false, 1, 2));
181+
await expectThrow(() => frame.evaluate((a, b) => false, 1, 2));
182+
});
165183
it('should accept "undefined" as one of multiple parameters', async({page, server}) => {
166184
const result = await page.evaluate(({ a, b }) => Object.is(a, undefined) && Object.is(b, 'foo'), { a: undefined, b: 'foo' });
167185
expect(result).toBe(true);

0 commit comments

Comments
 (0)