| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,10 +55,8 @@ const assert = require('internal/assert'); | |||
| 55 | 55 | const fs = require('fs'); | |
| 56 | 56 | const internalFS = require('internal/fs/utils'); | |
| 57 | 57 | const path = require('path'); | |
| 58 | - const { | ||
| 59 | - internalModuleReadJSON, | ||
| 60 | - internalModuleStat | ||
| 61 | - } = internalBinding('fs'); | ||
| 58 | + const { internalModuleStat } = internalBinding('fs'); | ||
| 59 | + const packageJsonReader = require('internal/modules/package_json_reader'); | ||
| 62 | 60 | const { safeGetenv } = internalBinding('credentials'); | |
| 63 | 61 | const { | |
| 64 | 62 | makeRequireFunction, | |
@@ -248,7 +246,8 @@ function readPackage(requestPath) { | |||
| 248 | 246 | const existing = packageJsonCache.get(jsonPath); | |
| 249 | 247 | if (existing !== undefined) return existing; | |
| 250 | 248 | ||
| 251 | - const json = internalModuleReadJSON(path.toNamespacedPath(jsonPath)); | ||
| 249 | + const result = packageJsonReader.read(path.toNamespacedPath(jsonPath)); | ||
| 250 | + const json = result.containsKeys === false ? '{}' : result.string; | ||
| 252 | 251 | if (json === undefined) { | |
| 253 | 252 | packageJsonCache.set(jsonPath, false); | |
| 254 | 253 | return false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,10 +26,6 @@ const assert = require('internal/assert'); | |||
| 26 | 26 | const internalFS = require('internal/fs/utils'); | |
| 27 | 27 | const { NativeModule } = require('internal/bootstrap/loaders'); | |
| 28 | 28 | const { | |
| 29 | - closeSync, | ||
| 30 | - fstatSync, | ||
| 31 | - openSync, | ||
| 32 | - readFileSync, | ||
| 33 | 29 | realpathSync, | |
| 34 | 30 | statSync, | |
| 35 | 31 | Stats, | |
@@ -53,6 +49,7 @@ const { | |||
| 53 | 49 | ERR_UNSUPPORTED_ESM_URL_SCHEME, | |
| 54 | 50 | } = require('internal/errors').codes; | |
| 55 | 51 | ||
| 52 | + const packageJsonReader = require('internal/modules/package_json_reader'); | ||
| 56 | 53 | const DEFAULT_CONDITIONS = ObjectFreeze(['node', 'import']); | |
| 57 | 54 | const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); | |
| 58 | 55 | ||
@@ -78,37 +75,25 @@ function tryStatSync(path) { | |||
| 78 | 75 | } | |
| 79 | 76 | } | |
| 80 | 77 | ||
| 81 | - function readIfFile(path) { | ||
| 82 | - let fd; | ||
| 83 | - try { | ||
| 84 | - fd = openSync(path, 'r'); | ||
| 85 | - } catch { | ||
| 86 | - return undefined; | ||
| 87 | - } | ||
| 88 | - try { | ||
| 89 | - if (!fstatSync(fd).isFile()) return undefined; | ||
| 90 | - return readFileSync(fd, 'utf8'); | ||
| 91 | - } finally { | ||
| 92 | - closeSync(fd); | ||
| 93 | - } | ||
| 78 | + /** | ||
| 79 | + * | ||
| 80 | + * '/foo/package.json' -> '/foo' | ||
| 81 | + */ | ||
| 82 | + function removePackageJsonFromPath(path) { | ||
| 83 | + return StringPrototypeSlice(path, 0, path.length - 13); | ||
| 94 | 84 | } | |
| 95 | 85 | ||
| 96 | - function getPackageConfig(path, base) { | ||
| 86 | + function getPackageConfig(path) { | ||
| 97 | 87 | const existing = packageJSONCache.get(path); | |
| 98 | 88 | if (existing !== undefined) { | |
| 99 | - if (!existing.isValid) { | ||
| 100 | - throw new ERR_INVALID_PACKAGE_CONFIG(path, fileURLToPath(base), false); | ||
| 101 | - } | ||
| 102 | 89 | return existing; | |
| 103 | 90 | } | |
| 104 | - | ||
| 105 | - const source = readIfFile(path); | ||
| 91 | + const source = packageJsonReader.read(path).string; | ||
| 106 | 92 | if (source === undefined) { | |
| 107 | 93 | const packageConfig = { | |
| 108 | 94 | exists: false, | |
| 109 | 95 | main: undefined, | |
| 110 | 96 | name: undefined, | |
| 111 | - isValid: true, | ||
| 112 | 97 | type: 'none', | |
| 113 | 98 | exports: undefined | |
| 114 | 99 | }; | |
@@ -119,17 +104,9 @@ function getPackageConfig(path, base) { | |||
| 119 | 104 | let packageJSON; | |
| 120 | 105 | try { | |
| 121 | 106 | packageJSON = JSONParse(source); | |
| 122 | - } catch { | ||
| 123 | - const packageConfig = { | ||
| 124 | - exists: true, | ||
| 125 | - main: undefined, | ||
| 126 | - name: undefined, | ||
| 127 | - isValid: false, | ||
| 128 | - type: 'none', | ||
| 129 | - exports: undefined | ||
| 130 | - }; | ||
| 131 | - packageJSONCache.set(path, packageConfig); | ||
| 132 | - return packageConfig; | ||
| 107 | + } catch (error) { | ||
| 108 | + const errorPath = removePackageJsonFromPath(path); | ||
| 109 | + throw new ERR_INVALID_PACKAGE_CONFIG(errorPath, error.message, true); | ||
| 133 | 110 | } | |
| 134 | 111 | ||
| 135 | 112 | let { main, name, type } = packageJSON; | |
@@ -143,7 +120,6 @@ function getPackageConfig(path, base) { | |||
| 143 | 120 | exists: true, | |
| 144 | 121 | main, | |
| 145 | 122 | name, | |
| 146 | - isValid: true, | ||
| 147 | 123 | type, | |
| 148 | 124 | exports | |
| 149 | 125 | }; | |
@@ -171,7 +147,6 @@ function getPackageScopeConfig(resolved, base) { | |||
| 171 | 147 | exists: false, | |
| 172 | 148 | main: undefined, | |
| 173 | 149 | name: undefined, | |
| 174 | - isValid: true, | ||
| 175 | 150 | type: 'none', | |
| 176 | 151 | exports: undefined | |
| 177 | 152 | }; | |
@@ -590,8 +565,7 @@ function packageResolve(specifier, base, conditions) { | |||
| 590 | 565 | let packageJSONPath = fileURLToPath(packageJSONUrl); | |
| 591 | 566 | let lastPath; | |
| 592 | 567 | do { | |
| 593 | - const stat = tryStatSync( | ||
| 594 | - StringPrototypeSlice(packageJSONPath, 0, packageJSONPath.length - 13)); | ||
| 568 | + const stat = tryStatSync(removePackageJsonFromPath(packageJSONPath)); | ||
| 595 | 569 | if (!stat.isDirectory()) { | |
| 596 | 570 | lastPath = packageJSONPath; | |
| 597 | 571 | packageJSONUrl = new URL((isScoped ? | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,23 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const { SafeMap } = primordials; | ||
| 4 | + const { internalModuleReadJSON } = internalBinding('fs'); | ||
| 5 | + | ||
| 6 | + const cache = new SafeMap(); | ||
| 7 | + | ||
| 8 | + /** | ||
| 9 | + * | ||
| 10 | + * @param {string} path | ||
| 11 | + */ | ||
| 12 | + function read(path) { | ||
| 13 | + if (cache.has(path)) { | ||
| 14 | + return cache.get(path); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + const [string, containsKeys] = internalModuleReadJSON(path); | ||
| 18 | + const result = { string, containsKeys }; | ||
| 19 | + cache.set(path, result); | ||
| 20 | + return result; | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + module.exports = { read }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -155,6 +155,7 @@ | |||
| 155 | 155 | 'lib/internal/main/run_third_party_main.js', | |
| 156 | 156 | 'lib/internal/main/worker_thread.js', | |
| 157 | 157 | 'lib/internal/modules/run_main.js', | |
| 158 | + 'lib/internal/modules/package_json_reader.js', | ||
| 158 | 159 | 'lib/internal/modules/cjs/helpers.js', | |
| 159 | 160 | 'lib/internal/modules/cjs/loader.js', | |
| 160 | 161 | 'lib/internal/modules/esm/loader.js', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -51,6 +51,7 @@ namespace node { | |||
| 51 | 51 | namespace fs { | |
| 52 | 52 | ||
| 53 | 53 | using v8::Array; | |
| 54 | + using v8::Boolean; | ||
| 54 | 55 | using v8::Context; | |
| 55 | 56 | using v8::EscapableHandleScope; | |
| 56 | 57 | using v8::Function; | |
@@ -826,9 +827,7 @@ void Close(const FunctionCallbackInfo<Value>& args) { | |||
| 826 | 827 | } | |
| 827 | 828 | ||
| 828 | 829 | ||
| 829 | - // Used to speed up module loading. Returns the contents of the file as | ||
| 830 | - // a string or undefined when the file cannot be opened or "main" is not found | ||
| 831 | - // in the file. | ||
| 830 | + // Used to speed up module loading. Returns an array [string, boolean] | ||
| 832 | 831 | static void InternalModuleReadJSON(const FunctionCallbackInfo<Value>& args) { | |
| 833 | 832 | Environment* env = Environment::GetCurrent(args); | |
| 834 | 833 | Isolate* isolate = env->isolate(); | |
@@ -837,14 +836,16 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo<Value>& args) { | |||
| 837 | 836 | CHECK(args[0]->IsString()); | |
| 838 | 837 | node::Utf8Value path(isolate, args[0]); | |
| 839 | 838 | ||
| 840 | - if (strlen(*path) != path.length()) | ||
| 839 | + if (strlen(*path) != path.length()) { | ||
| 840 | + args.GetReturnValue().Set(Array::New(isolate)); | ||
| 841 | 841 | return; // Contains a nul byte. | |
| 842 | - | ||
| 842 | + } | ||
| 843 | 843 | uv_fs_t open_req; | |
| 844 | 844 | const int fd = uv_fs_open(loop, &open_req, *path, O_RDONLY, 0, nullptr); | |
| 845 | 845 | uv_fs_req_cleanup(&open_req); | |
| 846 | 846 | ||
| 847 | 847 | if (fd < 0) { | |
| 848 | + args.GetReturnValue().Set(Array::New(isolate)); | ||
| 848 | 849 | return; | |
| 849 | 850 | } | |
| 850 | 851 | ||
@@ -870,9 +871,10 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo<Value>& args) { | |||
| 870 | 871 | numchars = uv_fs_read(loop, &read_req, fd, &buf, 1, offset, nullptr); | |
| 871 | 872 | uv_fs_req_cleanup(&read_req); | |
| 872 | 873 | ||
| 873 | - if (numchars < 0) | ||
| 874 | + if (numchars < 0) { | ||
| 875 | + args.GetReturnValue().Set(Array::New(isolate)); | ||
| 874 | 876 | return; | |
| 875 | - | ||
| 877 | + } | ||
| 876 | 878 | offset += numchars; | |
| 877 | 879 | } while (static_cast<size_t>(numchars) == kBlockSize); | |
| 878 | 880 | ||
@@ -908,18 +910,16 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo<Value>& args) { | |||
| 908 | 910 | } | |
| 909 | 911 | } | |
| 910 | 912 | ||
| 911 | - Local<String> return_value; | ||
| 912 | - if (p < pe) { | ||
| 913 | - return_value = | ||
| 914 | - String::NewFromUtf8(isolate, | ||
| 915 | - &chars[start], | ||
| 916 | - v8::NewStringType::kNormal, | ||
| 917 | - size).ToLocalChecked(); | ||
| 918 | - } else { | ||
| 919 | - return_value = env->empty_object_string(); | ||
| 920 | - } | ||
| 921 | 913 | ||
| 922 | - args.GetReturnValue().Set(return_value); | ||
| 914 | + Local<Value> return_value[] = { | ||
| 915 | + String::NewFromUtf8(isolate, | ||
| 916 | + &chars[start], | ||
| 917 | + v8::NewStringType::kNormal, | ||
| 918 | + size).ToLocalChecked(), | ||
| 919 | + Boolean::New(isolate, p < pe ? true : false) | ||
| 920 | + }; | ||
| 921 | + args.GetReturnValue().Set( | ||
| 922 | + Array::New(isolate, return_value, arraysize(return_value))); | ||
| 923 | 923 | } | |
| 924 | 924 | ||
| 925 | 925 | // Used to speed up module loading. Returns 0 if the path refers to | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,29 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const { mustCall, isWindows } = require('../common'); | ||
| 4 | + const fixtures = require('../common/fixtures'); | ||
| 5 | + const { spawn } = require('child_process'); | ||
| 6 | + const { strictEqual, ok } = require('assert'); | ||
| 7 | + | ||
| 8 | + const entry = fixtures.path('/es-modules/import-invalid-pjson.mjs'); | ||
| 9 | + const invalidJson = fixtures.path('/node_modules/invalid-pjson/package.json'); | ||
| 10 | + | ||
| 11 | + const child = spawn(process.execPath, [entry]); | ||
| 12 | + child.stderr.setEncoding('utf8'); | ||
| 13 | + let stderr = ''; | ||
| 14 | + child.stderr.on('data', (data) => { | ||
| 15 | + stderr += data; | ||
| 16 | + }); | ||
| 17 | + child.on('close', mustCall((code, signal) => { | ||
| 18 | + strictEqual(code, 1); | ||
| 19 | + strictEqual(signal, null); | ||
| 20 | + ok( | ||
| 21 | + stderr.includes( | ||
| 22 | + [ | ||
| 23 | + '[ERR_INVALID_PACKAGE_CONFIG]: ', | ||
| 24 | + `Invalid package config ${invalidJson}, `, | ||
| 25 | + `Unexpected token } in JSON at position ${isWindows ? 16 : 14}` | ||
| 26 | + ].join(''), | ||
| 27 | + ), | ||
| 28 | + stderr); | ||
| 29 | + })); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + import 'invalid-pjson'; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,6 +49,7 @@ const expectedModules = new Set([ | |||
| 49 | 49 | 'NativeModule internal/idna', | |
| 50 | 50 | 'NativeModule internal/linkedlist', | |
| 51 | 51 | 'NativeModule internal/modules/run_main', | |
| 52 | + 'NativeModule internal/modules/package_json_reader', | ||
| 52 | 53 | 'NativeModule internal/modules/cjs/helpers', | |
| 53 | 54 | 'NativeModule internal/modules/cjs/loader', | |
| 54 | 55 | 'NativeModule internal/modules/esm/create_dynamic_module', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,11 +6,32 @@ const { internalBinding } = require('internal/test/binding'); | |||
| 6 | 6 | const { internalModuleReadJSON } = internalBinding('fs'); | |
| 7 | 7 | const { readFileSync } = require('fs'); | |
| 8 | 8 | const { strictEqual } = require('assert'); | |
| 9 | - | ||
| 10 | - strictEqual(internalModuleReadJSON('nosuchfile'), undefined); | ||
| 11 | - strictEqual(internalModuleReadJSON(fixtures.path('empty.txt')), '{}'); | ||
| 12 | - strictEqual(internalModuleReadJSON(fixtures.path('empty-with-bom.txt')), '{}'); | ||
| 9 | + { | ||
| 10 | + const [string, containsKeys] = internalModuleReadJSON('nosuchfile'); | ||
| 11 | + strictEqual(string, undefined); | ||
| 12 | + strictEqual(containsKeys, undefined); | ||
| 13 | + } | ||
| 14 | + { | ||
| 15 | + const [string, containsKeys] = | ||
| 16 | + internalModuleReadJSON(fixtures.path('empty.txt')); | ||
| 17 | + strictEqual(string, ''); | ||
| 18 | + strictEqual(containsKeys, false); | ||
| 19 | + } | ||
| 20 | + { | ||
| 21 | + const [string, containsKeys] = | ||
| 22 | + internalModuleReadJSON(fixtures.path('empty.txt')); | ||
| 23 | + strictEqual(string, ''); | ||
| 24 | + strictEqual(containsKeys, false); | ||
| 25 | + } | ||
| 26 | + { | ||
| 27 | + const [string, containsKeys] = | ||
| 28 | + internalModuleReadJSON(fixtures.path('empty-with-bom.txt')); | ||
| 29 | + strictEqual(string, ''); | ||
| 30 | + strictEqual(containsKeys, false); | ||
| 31 | + } | ||
| 13 | 32 | { | |
| 14 | 33 | const filename = fixtures.path('require-bin/package.json'); | |
| 15 | - strictEqual(internalModuleReadJSON(filename), readFileSync(filename, 'utf8')); | ||
| 34 | + const [string, containsKeys] = internalModuleReadJSON(filename); | ||
| 35 | + strictEqual(string, readFileSync(filename, 'utf8')); | ||
| 36 | + strictEqual(containsKeys, true); | ||
| 16 | 37 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments