From d6dae8ea1fbab28d5dfc9d2da650080d2f339e23 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 22 Feb 2023 15:45:42 -0800 Subject: [PATCH] fix: eval serialization w/ overridden URL/RegExp/Date (#21112) Fixes #21109 --- .../isomorphic/utilityScriptSerializers.ts | 18 +++++++++++++++--- tests/page/page-evaluate.spec.ts | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/src/server/isomorphic/utilityScriptSerializers.ts b/packages/playwright-core/src/server/isomorphic/utilityScriptSerializers.ts index 3e6f298a2c..c65b68b8e4 100644 --- a/packages/playwright-core/src/server/isomorphic/utilityScriptSerializers.ts +++ b/packages/playwright-core/src/server/isomorphic/utilityScriptSerializers.ts @@ -35,15 +35,27 @@ type VisitorInfo = { export function source() { function isRegExp(obj: any): obj is RegExp { - return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]'; + try { + return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]'; + } catch (error) { + return false; + } } function isDate(obj: any): obj is Date { - return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]'; + try { + return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]'; + } catch (error) { + return false; + } } function isURL(obj: any): obj is URL { - return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]'; + try { + return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]'; + } catch (error) { + return false; + } } function isError(obj: any): obj is Error { diff --git a/tests/page/page-evaluate.spec.ts b/tests/page/page-evaluate.spec.ts index 7f3e407e55..3bd2679022 100644 --- a/tests/page/page-evaluate.spec.ts +++ b/tests/page/page-evaluate.spec.ts @@ -703,6 +703,25 @@ it('should work with overridden globalThis.Window/Document/Node', async ({ page, } }); +it('should work with overridden URL/Date/RegExp', async ({ page, server }) => { + const testCases = [ + // @ts-ignore + () => globalThis.URL = 'foo', + // @ts-ignore + () => globalThis.RegExp = 'foo', + // @ts-ignore + () => globalThis.Date = 'foo', + ]; + for (const testCase of testCases) { + await it.step(testCase.toString(), async () => { + await page.goto(server.EMPTY_PAGE); + await page.evaluate(testCase); + expect(await page.evaluate('1+2')).toBe(3); + expect(await page.evaluate(() => ({ 'a': 2023 }))).toEqual({ 'a': 2023 }); + }); + } +}); + it('should expose utilityScript', async ({ page }) => { const result = await (page.mainFrame() as any)._evaluateExposeUtilityScript((utilityScript, { a }) => { return { utils: 'parseEvaluationResultValue' in utilityScript, a };