diff --git a/src/node_modules.cc b/src/node_modules.cc index 7e615a691a5a14..4c767011282b93 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -212,6 +212,16 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON( if (value.get_string().get(field_value)) { return throw_invalid_package_config(); } + + if (field_value != "commonjs" && field_value != "module") { + ProcessEmitWarning(realm->env(), + "Invalid \"type\" field in package.json: \"%.*s\". " + "Expected \"commonjs\" or \"module\".", + "InvalidPackageType", + static_cast(field_value.size()), + field_value.data()); + } + // Only update type if it is "commonjs" or "module" // The default value is "none" for backward compatibility. if (field_value == "commonjs" || field_value == "module") { diff --git a/test/parallel/test-find-package-json.js b/test/parallel/test-find-package-json.js index fd9a1a85e77441..07404d0c650015 100644 --- a/test/parallel/test-find-package-json.js +++ b/test/parallel/test-find-package-json.js @@ -204,4 +204,6 @@ describe('findPackageJSON', () => { // Throws when no arguments are provided assert.ok(stdout.includes(foundPjsonPath), stdout); assert.strictEqual(code, 0); }); + + }); diff --git a/test/parallel/test-package-json-type-validation.js b/test/parallel/test-package-json-type-validation.js new file mode 100644 index 00000000000000..ac62e170bc6953 --- /dev/null +++ b/test/parallel/test-package-json-type-validation.js @@ -0,0 +1,70 @@ +'use strict'; + +const common = require('../common'); +const tmpdir = require('../common/tmpdir'); +const assert = require('node:assert'); +const fs = require('node:fs'); +const { describe, it } = require('node:test'); + + +describe('package.json type field validation', () => { + it('should warn for invalid type field values', async () => { + tmpdir.refresh(); + + fs.mkdirSync(tmpdir.resolve('invalid-type-pkg'), { recursive: true }); + fs.writeFileSync( + tmpdir.resolve('invalid-type-pkg/package.json'), + JSON.stringify({ type: 'CommonJS' }) + ); + fs.writeFileSync( + tmpdir.resolve('invalid-type-pkg/index.js'), + 'module.exports = 42;' + ); + + const { stderr } = await common.spawnPromisified(process.execPath, [ + tmpdir.resolve('invalid-type-pkg/index.js'), + ]); + + assert.ok(stderr.includes('MODULE_INVALID_TYPE')); + assert.ok(stderr.includes('CommonJS')); + }); + + it('should not warn for valid type values', async () => { + tmpdir.refresh(); + + fs.mkdirSync(tmpdir.resolve('valid-type-pkg'), { recursive: true }); + fs.writeFileSync( + tmpdir.resolve('valid-type-pkg/package.json'), + JSON.stringify({ type: 'commonjs' }) + ); + fs.writeFileSync( + tmpdir.resolve('valid-type-pkg/index.js'), + 'module.exports = 42;' + ); + + const { stderr } = await common.spawnPromisified(process.execPath, [ + tmpdir.resolve('valid-type-pkg/index.js'), + ]); + + assert.ok(!stderr.includes('MODULE_INVALID_TYPE')); + }); + + it('should not warn when type field is missing', async () => { + tmpdir.refresh(); + fs.mkdirSync(tmpdir.resolve('no-type-pkg'), { recursive: true }); + fs.writeFileSync( + tmpdir.resolve('no-type-pkg/package.json'), + JSON.stringify({ name: 'test' }) + ); + fs.writeFileSync( + tmpdir.resolve('no-type-pkg/index.js'), + 'module.exports = 42;' + ); + + const { stderr } = await common.spawnPromisified(process.execPath, [ + tmpdir.resolve('no-type-pkg/index.js'), + ]); + + assert.ok(!stderr.includes('MODULE_INVALID_TYPE')); + }); +}); \ No newline at end of file