| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d53e536 commit 90b632e
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ const { | |||
| 5 | 5 | ObjectPrototypeHasOwnProperty, | |
| 6 | 6 | PromisePrototypeThen, | |
| 7 | 7 | PromiseResolve, | |
| 8 | + SafeSet, | ||
| 8 | 9 | StringPrototypeIncludes, | |
| 9 | 10 | StringPrototypeCharCodeAt, | |
| 10 | 11 | StringPrototypeSlice, | |
@@ -19,7 +20,7 @@ const { | |||
| 19 | 20 | const experimentalNetworkImports = | |
| 20 | 21 | getOptionValue('--experimental-network-imports'); | |
| 21 | 22 | const { containsModuleSyntax } = internalBinding('contextify'); | |
| 22 | - const { getPackageType } = require('internal/modules/esm/resolve'); | ||
| 23 | + const { getPackageScopeConfig, getPackageType } = require('internal/modules/esm/resolve'); | ||
| 23 | 24 | const { fileURLToPath } = require('internal/url'); | |
| 24 | 25 | const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes; | |
| 25 | 26 | ||
@@ -81,6 +82,7 @@ function underNodeModules(url) { | |||
| 81 | 82 | return StringPrototypeIncludes(url.pathname, '/node_modules/'); | |
| 82 | 83 | } | |
| 83 | 84 | ||
| 85 | + let typelessPackageJsonFilesWarnedAbout; | ||
| 84 | 86 | /** | |
| 85 | 87 | * @param {URL} url | |
| 86 | 88 | * @param {{parentURL: string; source?: Buffer}} context | |
@@ -92,7 +94,7 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE | |||
| 92 | 94 | const ext = extname(url); | |
| 93 | 95 | ||
| 94 | 96 | if (ext === '.js') { | |
| 95 | - const packageType = getPackageType(url); | ||
| 97 | + const { type: packageType, pjsonPath } = getPackageScopeConfig(url); | ||
| 96 | 98 | if (packageType !== 'none') { | |
| 97 | 99 | return packageType; | |
| 98 | 100 | } | |
@@ -111,9 +113,23 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE | |||
| 111 | 113 | // `source` is undefined when this is called from `defaultResolve`; | |
| 112 | 114 | // but this gets called again from `defaultLoad`/`defaultLoadSync`. | |
| 113 | 115 | if (getOptionValue('--experimental-detect-module')) { | |
| 114 | - return source ? | ||
| 116 | + const format = source ? | ||
| 115 | 117 | (containsModuleSyntax(`${source}`, fileURLToPath(url)) ? 'module' : 'commonjs') : | |
| 116 | 118 | null; | |
| 119 | + if (format === 'module') { | ||
| 120 | + // This module has a .js extension, a package.json with no `type` field, and ESM syntax. | ||
| 121 | + // Warn about the missing `type` field so that the user can avoid the performance penalty of detection. | ||
| 122 | + typelessPackageJsonFilesWarnedAbout ??= new SafeSet(); | ||
| 123 | + if (!typelessPackageJsonFilesWarnedAbout.has(pjsonPath)) { | ||
| 124 | + const warning = `${url} parsed as an ES module because module syntax was detected;` + | ||
| 125 | + ` to avoid the performance penalty of syntax detection, add "type": "module" to ${pjsonPath}`; | ||
| 126 | + process.emitWarning(warning, { | ||
| 127 | + code: 'MODULE_TYPELESS_PACKAGE_JSON', | ||
| 128 | + }); | ||
| 129 | + typelessPackageJsonFilesWarnedAbout.add(pjsonPath); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + return format; | ||
| 117 | 133 | } | |
| 118 | 134 | return 'commonjs'; | |
| 119 | 135 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -101,6 +101,7 @@ describe('--experimental-detect-module', { concurrency: true }, () => { | |||
| 101 | 101 | ]) { | |
| 102 | 102 | it(testName, async () => { | |
| 103 | 103 | const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [ | |
| 104 | + '--no-warnings', | ||
| 104 | 105 | '--experimental-detect-module', | |
| 105 | 106 | entryPath, | |
| 106 | 107 | ]); | |
@@ -142,6 +143,7 @@ describe('--experimental-detect-module', { concurrency: true }, () => { | |||
| 142 | 143 | ]) { | |
| 143 | 144 | it(testName, async () => { | |
| 144 | 145 | const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [ | |
| 146 | + '--no-warnings', | ||
| 145 | 147 | '--experimental-detect-module', | |
| 146 | 148 | entryPath, | |
| 147 | 149 | ]); | |
@@ -291,6 +293,7 @@ describe('--experimental-detect-module', { concurrency: true }, () => { | |||
| 291 | 293 | ||
| 292 | 294 | it('permits declaration of CommonJS module variables', async () => { | |
| 293 | 295 | const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [ | |
| 296 | + '--no-warnings', | ||
| 294 | 297 | '--experimental-detect-module', | |
| 295 | 298 | fixtures.path('es-modules/package-without-type/commonjs-wrapper-variables.js'), | |
| 296 | 299 | ]); | |
@@ -327,6 +330,48 @@ describe('--experimental-detect-module', { concurrency: true }, () => { | |||
| 327 | 330 | strictEqual(signal, null); | |
| 328 | 331 | }); | |
| 329 | 332 | }); | |
| 333 | + | ||
| 334 | + describe('warn about typeless packages for .js files with ESM syntax', { concurrency: true }, () => { | ||
| 335 | + for (const { testName, entryPath } of [ | ||
| 336 | + { | ||
| 337 | + testName: 'warns for ESM syntax in a .js entry point in a typeless package', | ||
| 338 | + entryPath: fixtures.path('es-modules/package-without-type/module.js'), | ||
| 339 | + }, | ||
| 340 | + { | ||
| 341 | + testName: 'warns for ESM syntax in a .js file imported by a CommonJS entry point in a typeless package', | ||
| 342 | + entryPath: fixtures.path('es-modules/package-without-type/imports-esm.js'), | ||
| 343 | + }, | ||
| 344 | + { | ||
| 345 | + testName: 'warns for ESM syntax in a .js file imported by an ESM entry point in a typeless package', | ||
| 346 | + entryPath: fixtures.path('es-modules/package-without-type/imports-esm.mjs'), | ||
| 347 | + }, | ||
| 348 | + ]) { | ||
| 349 | + it(testName, async () => { | ||
| 350 | + const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [ | ||
| 351 | + '--experimental-detect-module', | ||
| 352 | + entryPath, | ||
| 353 | + ]); | ||
| 354 | + | ||
| 355 | + match(stderr, /MODULE_TYPELESS_PACKAGE_JSON/); | ||
| 356 | + strictEqual(stdout, 'executed\n'); | ||
| 357 | + strictEqual(code, 0); | ||
| 358 | + strictEqual(signal, null); | ||
| 359 | + }); | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + it('warns only once for a package.json that affects multiple files', async () => { | ||
| 363 | + const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [ | ||
| 364 | + '--experimental-detect-module', | ||
| 365 | + fixtures.path('es-modules/package-without-type/detected-as-esm.js'), | ||
| 366 | + ]); | ||
| 367 | + | ||
| 368 | + match(stderr, /MODULE_TYPELESS_PACKAGE_JSON/); | ||
| 369 | + strictEqual(stderr.match(/MODULE_TYPELESS_PACKAGE_JSON/g).length, 1); | ||
| 370 | + strictEqual(stdout, 'executed\nexecuted\n'); | ||
| 371 | + strictEqual(code, 0); | ||
| 372 | + strictEqual(signal, null); | ||
| 373 | + }); | ||
| 374 | + }); | ||
| 330 | 375 | }); | |
| 331 | 376 | ||
| 332 | 377 | // Validate temporarily disabling `--abort-on-uncaught-exception` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + import './module.js'; | ||
| 2 | + console.log('executed'); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments