-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The function exported using Object.defineProperty in node_modules cannot be found. #56304
Comments
Some even stranger phenomena have been observed. Kapture.2024-12-18.at.20.53.19.mp4 |
Can you share a repro that doesn’t involve running code downloaded from the internet? Ideally a short list of commands that can be run from a CLI, with the expected output and an explanation for why the actual output is not acceptable |
You should create a new folder to perform the following steps. # 1. create the necessary folders
rm -rf repro
mkdir -p repro/node_modules/should_import
cd repro
# 2. generating a simulated cjs package
cat -<<'EOF' > node_modules/should_import/methods.js
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var shouldImport = function (a, b) { return a + b; };
exports.default = shouldImport;
EOF
cat -<<'EOF' > node_modules/should_import/util.js
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.util = void 0;
var util = function () { return "util"; };
exports.util = util;
EOF
cat -<<'EOF' > node_modules/should_import/index.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.util = exports.shouldImport = void 0;
var methods_1 = require("./methods");
Object.defineProperty(exports, "shouldImport", { enumerable: true, get: function () { return __importDefault(methods_1).default } });
exports.shouldImport_1 = methods_1.default;
var util_1 = require("./util");
Object.defineProperty(exports, "util", { enumerable: true, get: function () { return util_1.util; } });
exports.util_1 = util_1.util;
EOF
# 3. generating a simulated demo project
cat -<<'EOF' > index.mjs
import * as ShouldImport from "should_import";
console.log('Does "should_import" export a "shouldImport" named export:', 'shouldImport' in ShouldImport);
EOF
# 4. run the code
node index.mjs
# 5. Cleanup
cd ..
rm -rf repro As you can observe, it outputs this is the unacceptable output: Let's make some modifications. // node_modules/should_import/index.js
// Remove the wrapper of the __importDefault function.
// Object.defineProperty(exports, "shouldImport", { enumerable: true, get: function () { return __importDefault(methods_1).default } });
Object.defineProperty(exports, "shouldImport", { enumerable: true, get: function () { return methods_1.default } }); It now outputs this is the expected output: Especially importantJust like the video in my second comment, removing the Additional informationUsing bun instead of node for execution, both times can yield the expected result. |
Thanks for the repro, I took the liberty of removing the screenshots which can be harder to read (e.g. folks using screen readers may only have access to the alt text). I suspect this is a known limitation of nodejs/cjs-module-lexer, which is frozen as explained in the project status – although there's an open issue to reconsider that status: nodejs/cjs-module-lexer#101 |
Having thoroughly reviewed the If the code is adjusted to the following form, that is, moving const shouldImport = __importDefault(methods_1).default
Object.defineProperty(exports, "shouldImport", { enumerable: true, get: function () { return shouldImport } }); Additionally, the original code here was compiled using So there should also be an issue opened in the TypeScript repository. |
Yeah, if we can get the transpilation output to not call a function in the getter, that's much better for sure – and would probably better fit the spec. The way the ECMAScript spec is written, we cannot have side-effects of accessing a named export, and it seems like a very hard problem to detect whether calling a function such as /cc @nodejs/loaders |
I searched in the typescript repository using cjs-module-lexer as a keyword, and indeed found similar issues.
Considering the current general situation of cjs and ts, it may only be possible to call on the package authors to try to update and provide native esm for node to call. |
Version
v22.9.0
Platform
Subsystem
No response
What steps will reproduce the bug?
related issue #56286
reproduction code demo_import.zip
Advance declaration: The code inside the current
node_modules
which is in reproduction code, I did not use any package manager(npm/yarn/pnpm) for installation, but rather manually copied and pasted it in, ensuring the exclusion of interference from package management.Steps:
Download and unzip the reproduction code, and directly execute node index.js.
This is my execution result
How often does it reproduce? Is there a required condition?
100%
What is the expected behavior? Why is that the expected behavior?
shouldImport
This function can be directly accessed in the first layer of the module object, rather than only being obtainable in the internal default object.What do you see instead?
shouldImport was lost during the conversion from cjs to esm
Additional information
I also tried to execute the code using
bun
(1.1.40), and the result was correct.The text was updated successfully, but these errors were encountered: