From 4c725f8cf810310c4924c925bb480f06ca442528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 7 May 2021 12:34:30 +0200 Subject: [PATCH] Support objects from other contexts in `t.valueToNode` (#13275) --- .../babel-types/src/converters/valueToNode.ts | 11 ++++++++-- packages/babel-types/test/regressions.js | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/babel-types/src/converters/valueToNode.ts b/packages/babel-types/src/converters/valueToNode.ts index 07978efa4544..6eb52b873e7a 100644 --- a/packages/babel-types/src/converters/valueToNode.ts +++ b/packages/babel-types/src/converters/valueToNode.ts @@ -40,11 +40,18 @@ function isRegExp(value): value is RegExp { } function isPlainObject(value): value is object { - if (typeof value !== "object" || value === null) { + if ( + typeof value !== "object" || + value === null || + Object.prototype.toString.call(value) !== "[object Object]" + ) { return false; } const proto = Object.getPrototypeOf(value); - return proto === null || proto === Object.prototype; + // Object.prototype's __proto__ is null. Every other class's __proto__.__proto__ is + // not null by default. We cannot check if proto === Object.prototype because it + // could come from another realm. + return proto === null || Object.getPrototypeOf(proto) === null; } function valueToNode(value: unknown): t.Expression { diff --git a/packages/babel-types/test/regressions.js b/packages/babel-types/test/regressions.js index ca2e250ceec7..d28899b090d7 100644 --- a/packages/babel-types/test/regressions.js +++ b/packages/babel-types/test/regressions.js @@ -1,4 +1,5 @@ import * as t from "../lib"; +import * as vm from "vm"; describe("regressions", () => { const babel7 = process.env.BABEL_TYPES_8_BREAKING ? it.skip : it; @@ -8,4 +9,23 @@ describe("regressions", () => { t.file(t.program([]), [{ type: "Line" }]); }).not.toThrow(); }); + + it(".valueToNode works with objects from different contexts", () => { + const context = {}; + const script = new vm.Script(`this.obj = { foo: 2 }`); + script.runInNewContext(context); + + expect(t.valueToNode(context.obj)).toMatchObject({ + properties: [ + { + computed: false, + key: { name: "foo", type: "Identifier" }, + shorthand: false, + type: "ObjectProperty", + value: { type: "NumericLiteral", value: 2 }, + }, + ], + type: "ObjectExpression", + }); + }); });