GeezerVison is showing github.com — esm: improve `getFormatOfExtensionlessFile` speed · nodejs/node@1e762dd
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/formats.js +11-18Lines changed: 11 additions & 18 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | 'use strict'; | 2 | 2 |
| 3 | | -const { | 4 | | - RegExpPrototypeExec, | 5 | | - Uint8Array, | 6 | | -} = primordials; | | 3 | +const { RegExpPrototypeExec } = primordials; | 7 | 4 | const { getOptionValue } = require('internal/options'); | 8 | | - | 9 | | -const { closeSync, openSync, readSync } = require('fs'); | | 5 | +const { getValidatedPath } = require('internal/fs/utils'); | | 6 | +const pathModule = require('path'); | | 7 | +const fsBindings = internalBinding('fs'); | | 8 | +const { fs: fsConstants } = internalBinding('constants'); | 10 | 9 |
| 11 | 10 | const experimentalWasmModules = getOptionValue('--experimental-wasm-modules'); | 12 | 11 |
| @@ -47,20 +46,14 @@ function mimeToFormat(mime) { | 47 | 46 | function getFormatOfExtensionlessFile(url) { | 48 | 47 | if (!experimentalWasmModules) { return 'module'; } | 49 | 48 |
| 50 | | - const magic = new Uint8Array(4); | 51 | | - let fd; | 52 | | - try { | 53 | | - // TODO(@anonrig): Optimize the following by having a single C++ call | 54 | | - fd = openSync(url); | 55 | | - readSync(fd, magic, 0, 4); // Only read the first four bytes | 56 | | - if (magic[0] === 0x00 && magic[1] === 0x61 && magic[2] === 0x73 && magic[3] === 0x6d) { | | 49 | + const path = pathModule.toNamespacedPath(getValidatedPath(url)); | | 50 | + | | 51 | + switch (fsBindings.getFormatOfExtensionlessFile(path)) { | | 52 | + case fsConstants.EXTENSIONLESS_FORMAT_WASM: | 57 | 53 | return 'wasm'; | 58 | | - } | 59 | | - } finally { | 60 | | - if (fd !== undefined) { closeSync(fd); } | | 54 | + default: | | 55 | + return 'module'; | 61 | 56 | } | 62 | | - | 63 | | - return 'module'; | 64 | 57 | } | 65 | 58 |
| 66 | 59 | module.exports = { | |
Collapse file Copy file name to clipboardExpand all lines: src/node_constants.cc +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1058,6 +1058,10 @@ void DefineSystemConstants(Local<Object> target) { | 1058 | 1058 | NODE_DEFINE_CONSTANT(target, UV_DIRENT_CHAR); | 1059 | 1059 | NODE_DEFINE_CONSTANT(target, UV_DIRENT_BLOCK); | 1060 | 1060 |
| | 1061 | + // Define module specific constants | | 1062 | + NODE_DEFINE_CONSTANT(target, EXTENSIONLESS_FORMAT_JAVASCRIPT); | | 1063 | + NODE_DEFINE_CONSTANT(target, EXTENSIONLESS_FORMAT_WASM); | | 1064 | + | 1061 | 1065 | NODE_DEFINE_CONSTANT(target, S_IFMT); | 1062 | 1066 | NODE_DEFINE_CONSTANT(target, S_IFREG); | 1063 | 1067 | NODE_DEFINE_CONSTANT(target, S_IFDIR); | |
Collapse file Copy file name to clipboardExpand all lines: src/node_constants.h +3Lines changed: 3 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 27 | 27 | #include "node.h" | 28 | 28 | #include "v8.h" | 29 | 29 |
| | 30 | +#define EXTENSIONLESS_FORMAT_JAVASCRIPT (0) | | 31 | +#define EXTENSIONLESS_FORMAT_WASM (1) | | 32 | + | 30 | 33 | #if HAVE_OPENSSL | 31 | 34 |
| 32 | 35 | #ifndef RSA_PSS_SALTLEN_DIGEST | |
Collapse file Copy file name to clipboardExpand all lines: src/node_file.cc +50Lines changed: 50 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -2832,6 +2832,51 @@ static void Mkdtemp(const FunctionCallbackInfo<Value>& args) { | 2832 | 2832 | } | 2833 | 2833 | } | 2834 | 2834 |
| | 2835 | +static void GetFormatOfExtensionlessFile( | | 2836 | + const FunctionCallbackInfo<Value>& args) { | | 2837 | + CHECK_EQ(args.Length(), 1); | | 2838 | + CHECK(args[0]->IsString()); | | 2839 | + | | 2840 | + Environment* env = Environment::GetCurrent(args); | | 2841 | + node::Utf8Value input(args.GetIsolate(), args[0]); | | 2842 | + | | 2843 | + THROW_IF_INSUFFICIENT_PERMISSIONS( | | 2844 | + env, permission::PermissionScope::kFileSystemRead, input.ToStringView()); | | 2845 | + | | 2846 | + uv_fs_t req; | | 2847 | + FS_SYNC_TRACE_BEGIN(open) | | 2848 | + uv_file file = uv_fs_open(nullptr, &req, input.out(), O_RDONLY, 0, nullptr); | | 2849 | + FS_SYNC_TRACE_END(open); | | 2850 | + | | 2851 | + if (req.result < 0) { | | 2852 | + return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT); | | 2853 | + } | | 2854 | + | | 2855 | + auto cleanup = OnScopeLeave([&req, &file]() { | | 2856 | + FS_SYNC_TRACE_BEGIN(close); | | 2857 | + CHECK_EQ(0, uv_fs_close(nullptr, &req, file, nullptr)); | | 2858 | + FS_SYNC_TRACE_END(close); | | 2859 | + uv_fs_req_cleanup(&req); | | 2860 | + }); | | 2861 | + | | 2862 | + char buffer[4]; | | 2863 | + uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer)); | | 2864 | + int err = uv_fs_read(nullptr, &req, file, &buf, 1, 0, nullptr); | | 2865 | + | | 2866 | + if (err < 0) { | | 2867 | + return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT); | | 2868 | + } | | 2869 | + | | 2870 | + // We do this by taking advantage of the fact that all Wasm files start with | | 2871 | + // the header `0x00 0x61 0x73 0x6d` | | 2872 | + if (buffer[0] == 0x00 && buffer[1] == 0x61 && buffer[2] == 0x73 && | | 2873 | + buffer[3] == 0x6d) { | | 2874 | + return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_WASM); | | 2875 | + } | | 2876 | + | | 2877 | + return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT); | | 2878 | +} | | 2879 | + | 2835 | 2880 | static bool FileURLToPath( | 2836 | 2881 | Environment* env, | 2837 | 2882 | const ada::url_aggregator& file_url, | @@ -3244,6 +3289,10 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data, | 3244 | 3289 | Local<ObjectTemplate> target) { | 3245 | 3290 | Isolate* isolate = isolate_data->isolate(); | 3246 | 3291 |
| | 3292 | + SetMethod(isolate, | | 3293 | + target, | | 3294 | + "getFormatOfExtensionlessFile", | | 3295 | + GetFormatOfExtensionlessFile); | 3247 | 3296 | SetMethod(isolate, target, "access", Access); | 3248 | 3297 | SetMethod(isolate, target, "close", Close); | 3249 | 3298 | SetMethod(isolate, target, "existsSync", ExistsSync); | @@ -3364,6 +3413,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | 3364 | 3413 | StatWatcher::RegisterExternalReferences(registry); | 3365 | 3414 | BindingData::RegisterExternalReferences(registry); | 3366 | 3415 |
| | 3416 | + registry->Register(GetFormatOfExtensionlessFile); | 3367 | 3417 | registry->Register(Close); | 3368 | 3418 | registry->Register(ExistsSync); | 3369 | 3419 | registry->Register(Open); | |
Collapse file Copy file name to clipboardExpand all lines: typings/internalBinding/constants.d.ts +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -186,6 +186,8 @@ export interface ConstantsBinding { | 186 | 186 | COPYFILE_FICLONE: 2; | 187 | 187 | UV_FS_COPYFILE_FICLONE_FORCE: 4; | 188 | 188 | COPYFILE_FICLONE_FORCE: 4; | | 189 | + EXTENSIONLESS_FORMAT_JAVASCRIPT: 0; | | 190 | + EXTENSIONLESS_FORMAT_WASM: 1; | 189 | 191 | }; | 190 | 192 | crypto: { | 191 | 193 | OPENSSL_VERSION_NUMBER: 269488319; | |
Collapse file Copy file name to clipboardExpand all lines: typings/internalBinding/fs.d.ts +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +import { ConstantsBinding } from './constants'; | | 2 | + | 1 | 3 | declare namespace InternalFSBinding { | 2 | 4 | class FSReqCallback<ResultType = unknown> { | 3 | 5 | constructor(bigint?: boolean); | @@ -218,6 +220,8 @@ declare namespace InternalFSBinding { | 218 | 220 | function writeString(fd: number, value: string, pos: unknown, encoding: unknown, req: FSReqCallback<number>): void; | 219 | 221 | function writeString(fd: number, value: string, pos: unknown, encoding: unknown, req: undefined, ctx: FSSyncContext): number; | 220 | 222 | function writeString(fd: number, value: string, pos: unknown, encoding: unknown, usePromises: typeof kUsePromises): Promise<number>; | | 223 | + | | 224 | + function getFormatOfExtensionlessFile(url: string): ConstantsBinding['fs']; | 221 | 225 | } | 222 | 226 |
| 223 | 227 | export interface FsBinding { | @@ -269,4 +273,6 @@ export interface FsBinding { | 269 | 273 | writeBuffer: typeof InternalFSBinding.writeBuffer; | 270 | 274 | writeBuffers: typeof InternalFSBinding.writeBuffers; | 271 | 275 | writeString: typeof InternalFSBinding.writeString; | | 276 | + | | 277 | + getFormatOfExtensionlessFile: typeof InternalFSBinding.getFormatOfExtensionlessFile; | 272 | 278 | } |
|