From 1fc0fb0dfde3c55364ff545cc3e649a2b16aee3f Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 19 Jan 2023 16:27:18 +0100 Subject: [PATCH] esm: skip file: URL conversion to path when possible --- lib/internal/modules/esm/get_format.js | 30 +++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 640d240acd4ca1..a381a264f6f3ac 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -4,9 +4,10 @@ const { ObjectPrototypeHasOwnProperty, PromisePrototypeThen, PromiseResolve, + StringPrototypeCharCodeAt, StringPrototypeSlice, } = primordials; -const { basename, extname, relative } = require('path'); +const { basename, relative } = require('path'); const { getOptionValue } = require('internal/options'); const { extensionFormatMap, @@ -41,6 +42,29 @@ function getDataProtocolModuleFormat(parsed) { return mimeToFormat(mime); } +const DOT_CODE = 46; +const SLASH_CODE = 47; + +/** + * Returns the file extension from a file: URL. Should give similar result than + * require('node:path').extname(require('node:url').fileURLToPath(url)). + * @param {URL} url A file: URL. + * @returns {string} + */ +function extname(url) { + const { pathname } = url; + for (let i = pathname.length - 1; i > 0; i--) { + switch (StringPrototypeCharCodeAt(pathname, i)) { + case SLASH_CODE: + return ''; + + case DOT_CODE: + return StringPrototypeSlice(pathname, i); + } + } + return ''; +} + /** * @param {URL} url * @param {{parentURL: string}} context @@ -48,8 +72,7 @@ function getDataProtocolModuleFormat(parsed) { * @returns {string} */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { - const filepath = fileURLToPath(url); - const ext = extname(filepath); + const ext = extname(url); if (ext === '.js') { return getPackageType(url) === 'module' ? 'module' : 'commonjs'; } @@ -59,6 +82,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { // Explicit undefined return indicates load hook should rerun format check if (ignoreErrors) { return undefined; } + const filepath = fileURLToPath(url); let suggestion = ''; if (getPackageType(url) === 'module' && ext === '') { const config = getPackageScopeConfig(url);