From 773a09a8cf8a4fede7f5a9eead42836fd32ef43a Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Thu, 6 Jul 2017 10:41:01 -0700 Subject: [PATCH] Add support for unserializable values in Page.evaluate This patch adds support for unserializable return values in Page.evaluate. Currently, these values are: - NaN - Infinity - -Infinity - -0 Fixes #51. --- lib/FrameManager.js | 25 +++++++++++++++++++++++-- test/test.js | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/FrameManager.js b/lib/FrameManager.js index 5e0416b6..c7d649b5 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -169,12 +169,33 @@ class FrameManager extends EventEmitter { } let syncExpression = helper.evaluationString(fun, ...args); let expression = `Promise.resolve(${syncExpression})`; - let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: true, awaitPromise: true }); + let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true }); if (exceptionDetails) { let message = await helper.getExceptionMessage(this._client, exceptionDetails); throw new Error('Evaluation failed: ' + message); } - return remoteObject.value; + if (remoteObject.unserializableValue) { + switch (remoteObject.unserializableValue) { + case '-0': + return -0; + case 'NaN': + return NaN; + case 'Infinity': + return Infinity; + case '-Infinity': + return -Infinity; + default: + throw new Error('Unsupported unserializable value: ' + remoteObject.unserializableValue); + } + } + if (!remoteObject.objectId) + return remoteObject.value; + let response = await this._client.send('Runtime.callFunctionOn', { + objectId: remoteObject.objectId, + functionDeclaration: 'function() { return this; }', + returnByValue: true, + }); + return response.result.value; } } diff --git a/test/test.js b/test/test.js index a1497653..4f691cfd 100644 --- a/test/test.js +++ b/test/test.js @@ -80,6 +80,28 @@ describe('Puppeteer', function() { expect(error).toBeTruthy(); expect(error.message).toContain('not is not defined'); })); + it('should return complex objects', SX(async function() { + const object = {foo: 'bar!'}; + let result = await page.evaluate(a => a, object); + expect(result).not.toBe(object); + expect(result).toEqual(object); + })); + it('should return NaN', SX(async function() { + let result = await page.evaluate(() => NaN); + expect(Object.is(result, NaN)).toBe(true); + })); + it('should return -0', SX(async function() { + let result = await page.evaluate(() => -0); + expect(Object.is(result, -0)).toBe(true); + })); + it('should return Infinity', SX(async function() { + let result = await page.evaluate(() => Infinity); + expect(Object.is(result, Infinity)).toBe(true); + })); + it('should return -Infinity', SX(async function() { + let result = await page.evaluate(() => -Infinity); + expect(Object.is(result, -Infinity)).toBe(true); + })); }); describe('Frame.evaluate', function() {