Skip to content

Commit

Permalink
allow to see exports for non-enumerable properties (vercel/turborepo#…
Browse files Browse the repository at this point in the history
…4783)

### Description

enumerate all properties for namespace object creation.

This follows the webpack logic

test cases in #49106
  • Loading branch information
sokra authored May 2, 2023
1 parent 083225c commit ebfd1df
Show file tree
Hide file tree
Showing 36 changed files with 792 additions and 144 deletions.
26 changes: 22 additions & 4 deletions crates/turbopack-dev/js/src/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -172,8 +183,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -273,11 +291,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ function createGetter(obj, key) {
return () => obj[key];
}

/**
* @param {any} obj
* @returns {any} prototype of the object
*/
const getProto = Object.getPrototypeOf
? (obj) => Object.getPrototypeOf(obj)
: (obj) => obj.__proto__;

/** Prototypes that are not expanded for exports */
const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];

/**
* @param {Exports} raw
* @param {EsmNamespaceObject} ns
Expand All @@ -181,8 +192,15 @@ function createGetter(obj, key) {
function interopEsm(raw, ns, allowExportDefault) {
/** @type {Object.<string, () => any>} */
const getters = { __proto__: null };
for (const key in raw) {
getters[key] = createGetter(raw, key);
for (
let current = raw;
(typeof current === "object" || typeof current === "function") &&
!LEAF_PROTOTYPES.includes(current);
current = getProto(current)
) {
for (const key of Object.getOwnPropertyNames(current)) {
getters[key] = createGetter(raw, key);
}
}
if (!(allowExportDefault && "default" in getters)) {
getters["default"] = () => raw;
Expand Down Expand Up @@ -282,11 +300,11 @@ function externalRequire(id, esm) {
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
if (!esm) {
return raw;
}
const ns = {};
interopEsm(raw, ns, true);
interopEsm(raw, ns, raw.__esModule);
return ns;
}
externalRequire.resolve = (name, opt) => {
Expand Down
Loading

0 comments on commit ebfd1df

Please sign in to comment.