node
node copied to clipboard
lib: merge cjs and esm package json reader caches
This PR contains a refactor to merge package.json reader caches in both CJS and ESM.
I extracted the relevant parts from https://github.com/nodejs/node/pull/47991.
cc @nodejs/loaders @nodejs/modules
PS: This PR has no effect on execution speed.
hyperfine './out/Release/node ../fastify/fastify.js' 'node ../fastify/fastify.js' 'bun ../fastify/fastify.js' -i --warmup 10
Benchmark 1: ./out/Release/node ../fastify/fastify.js
Time (mean ± σ): 87.5 ms ± 1.3 ms [User: 85.0 ms, System: 19.7 ms]
Range (min … max): 84.3 ms … 89.5 ms 32 runs
Benchmark 2: node ../fastify/fastify.js
Time (mean ± σ): 87.8 ms ± 1.3 ms [User: 82.2 ms, System: 21.3 ms]
Range (min … max): 84.5 ms … 91.5 ms 33 runs
Benchmark 3: bun ../fastify/fastify.js
Time (mean ± σ): 98.1 ms ± 0.9 ms [User: 83.9 ms, System: 18.9 ms]
Range (min … max): 96.9 ms … 101.4 ms 29 runs
Summary
./out/Release/node ../fastify/fastify.js ran
1.00 ± 0.02 times faster than node ../fastify/fastify.js
1.12 ± 0.02 times faster than bun ../fastify/fastify.js
Review requested:
- [ ] @nodejs/loaders
- [ ] @nodejs/modules
I fixed the conflict, and force pushed it. Appreciate reviewing it again.
CI: https://ci.nodejs.org/job/node-test-pull-request/52325/
CI: https://ci.nodejs.org/job/node-test-pull-request/52334/
CI: https://ci.nodejs.org/job/node-test-pull-request/52336/
CI: https://ci.nodejs.org/job/node-test-pull-request/52347/
CI: https://ci.nodejs.org/job/node-test-pull-request/52361/
CI: https://ci.nodejs.org/job/node-test-pull-request/52370/
@nodejs/build @nodejs/platform-aix I don't have access to aix
platform, and can't figure out why the test fails on AIX. Any suggestions?
@nodejs/build @nodejs/platform-aix I don't have access to
aix
platform, and can't figure out why the test fails on AIX. Any suggestions?
FWIW the error is SyntaxError: Error parsing /home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/fixtures/packages/is-dir/package.json: Unexpected token 'U', "U�."... is not valid JSON
15:23:18 not ok 2008 parallel/test-module-loading-error
15:23:18 ---
15:23:18 duration_ms: 230.33100
15:23:18 severity: fail
15:23:18 exitcode: 1
15:23:18 stack: |-
15:23:18 node:assert:635
15:23:18 throw err;
15:23:18 ^
15:23:18
15:23:18 AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
15:23:18 + actual - expected
15:23:18
15:23:18 Comparison {
15:23:18 + message: `Error parsing /home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/fixtures/packages/is-dir/package.json: Unexpected token 'U', "U�.\x00\x00\x00\x00\x00\x00\x00"... is not valid JSON`
15:23:18 - code: 'MODULE_NOT_FOUND',
15:23:18 - message: /Cannot find module '\.\.\/fixtures\/packages\/is-dir'/
15:23:18 }
15:23:18 at Object.<anonymous> (/home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/parallel/test-module-loading-error.js:87:8)
15:23:18 at Module._compile (node:internal/modules/cjs/loader:1233:14)
15:23:18 at Module._extensions..js (node:internal/modules/cjs/loader:1287:10)
15:23:18 at Module.load (node:internal/modules/cjs/loader:1091:32)
15:23:18 at Module._load (node:internal/modules/cjs/loader:938:12)
15:23:18 at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
15:23:18 at node:internal/main/run_main_module:23:47 {
15:23:18 generatedMessage: true,
15:23:18 code: 'ERR_ASSERTION',
15:23:18 actual: SyntaxError: Error parsing /home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/fixtures/packages/is-dir/package.json: Unexpected token 'U', "U�."... is not valid JSON
15:23:18 at parse (<anonymous>)
15:23:18 at Object.read (node:internal/modules/package_json_reader:63:16)
15:23:18 at readPackage (node:internal/modules/cjs/loader:362:28)
15:23:18 at tryPackage (node:internal/modules/cjs/loader:401:15)
15:23:18 at Module._findPath (node:internal/modules/cjs/loader:665:18)
15:23:18 at Module._resolveFilename (node:internal/modules/cjs/loader:1034:27)
15:23:18 at Module._load (node:internal/modules/cjs/loader:901:27)
15:23:18 at Module.require (node:internal/modules/cjs/loader:1115:19)
15:23:18 at require (node:internal/modules/helpers:121:18)
15:23:18 at assert.throws.code (/home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/parallel/test-module-loading-error.js:88:11) {
15:23:18 path: '/home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/fixtures/packages/is-dir/package.json'
15:23:18 },
15:23:18 expected: {
15:23:18 code: 'MODULE_NOT_FOUND',
15:23:18 message: /Cannot find module '\.\.\/fixtures\/packages\/is-dir'/
15:23:18 },
15:23:18 operator: 'throws'
15:23:18 }
15:23:18
15:23:18 Node.js v21.0.0-pre
15:23:18 ...
The message is truncated -- what is happening is that reading test/fixtures/packages/is-dir/package.json
(which is a directory) is succeeding on AIX:
> fs.readFileSync('/home/iojs/build/workspace/node-test-commit-aix/nodes/aix72-ppc64/test/fixtures/packages/is-dir/package.json', { encoding: 'utf8'})
'U�.\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U�..\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U�.placeholder\x00\x00'
This is a difference between AIX and Linux (which throws an EISDIR error), see https://github.com/libuv/libuv/pull/2025 where libuv removed the special handling. That PR also mentions BSD although it doesn't look like the same CI failed for FreeBSD 🤷.
@richardlau Thanks for the help. I'll disable the last test case for folder on AIX.
CI: https://ci.nodejs.org/job/node-test-pull-request/52401/
@richardlau Thanks for the help. I'll disable the last test case for folder on AIX.
Isn't this a regression? The test worked before this PR.
Isn't this a regression? The test worked before this PR.
Yes it is a regression. I just want to make sure this is the only issue. I’ll take a look at AIX.
So, let me summarize the issue here:
Previously, CJS loader was checking if any of the keys existed in a package.json, and if not tried to JSONParse a {}
value (Ref: https://github.com/nodejs/node/pull/48477/files#diff-5b5902273122e094ff474fda358605ffa45a4a58b51cd0bf4c1acb93779df142L369), causing a ERR_MODULE_NOT_FOUND error on a directory file (which only succeeds for AIX)
With the current changes, I removed the need to check if any of the keys existed (such as name
, type
etc). This worked for all platforms except AIX, because AIX is the only platform that resolves a folder as a file (Ref: https://github.com/nodejs/node/pull/48477#issuecomment-1604586650)
This particular issue on AIX requires us to traverse the package.json file in the C++ while causing a little bit of performance impact, but most importantly forces us to implement this particular code block: https://github.com/nodejs/node/pull/48477/files#diff-70e3325bd2115867617ae2a16321c5de53c070ff2841976fe5b849675a5111e6L1087
As a summary, on AIX instead of throwing ERR_MODULE_NOT_FOUND
on a directory, it now throws a Error parsing ...
error (due to the fact that the file read operation succeeds on a directory entry).
Should we add a semver-major
label to this pull request, or is it ok to omit it?
cc @nodejs/tsc @nodejs/platform-aix @nodejs/loaders
CI: https://ci.nodejs.org/job/node-test-pull-request/52405/
CI: https://ci.nodejs.org/job/node-test-pull-request/52408/
CI: https://ci.nodejs.org/job/node-test-pull-request/52410/
CI: https://ci.nodejs.org/job/node-test-pull-request/52414/
As a summary, on AIX instead of throwing
ERR_MODULE_NOT_FOUND
on a directory, it now throws aError parsing ...
error (due to the fact that the file read operation succeeds on a directory entry).Should we add a
semver-major
label to this pull request, or is it ok to omit it?
I would recommend making the necessary checks so this PR behaves as previously for each platform (and too bad for performance), and then land a semver-major PR that optimize and simplify things further. I think the consensus is that changing a error code is deemed as semver-major.
I'll revert some changes regarding AIX to not make this pull request a semver-major change, and after this has been merged, I'll follow-up with removing the change specific for AIX.
CI: https://ci.nodejs.org/job/node-test-pull-request/52433/
CI: https://ci.nodejs.org/job/node-test-pull-request/52435/
CI: https://ci.nodejs.org/job/node-test-pull-request/52439/
CI: https://ci.nodejs.org/job/node-test-pull-request/52441/
CI: https://ci.nodejs.org/job/node-test-pull-request/52468/
@nodejs/build any idea why windows-fanned is failing?
The failure on the worker seems to be related. For the Windows failure, maybe @nodejs/platform-windows can help?
CI: https://ci.nodejs.org/job/node-test-pull-request/52530/
CI: https://ci.nodejs.org/job/node-test-pull-request/52531/