From d490d171aeaa7bfdbcc6276b128251930ade7184 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 6 Oct 2023 00:18:47 -0700 Subject: [PATCH 1/4] explicitly resolve browser and import --- resolvewithplus.js | 39 +++++++++------ tests/tests-basic/tests-basic.test.js | 72 +++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/resolvewithplus.js b/resolvewithplus.js index ba2713d..9246187 100644 --- a/resolvewithplus.js +++ b/resolvewithplus.js @@ -29,6 +29,7 @@ const node_modules = 'node_modules' const packagejson = 'package.json' const specruntime = 'node' const specdefault = 'default' +const specbrowser = 'browser' const specimport = 'import' const specdot = '.' const isobj = o => o && typeof o === 'object' @@ -195,7 +196,7 @@ const esmparselist = (list, spec, specifier, key = list[0]) => { || esmparselist(list.slice(1), spec, specifier) } -const esmparse = (spec, specifier) => { +const esmparse = (spec, specifier, opts = {}) => { let indexval = false if (typeof spec === 'string') @@ -209,7 +210,7 @@ const esmparse = (spec, specifier) => { // }, "./index.cjs" ] // } indexval = spec - .reduce((p, elem) => p || esmparse(elem, specifier), null) + .reduce((p, elem) => p || esmparse(elem, specifier, opts), null) } if (!indexval && isobj(spec)) { @@ -226,12 +227,14 @@ const esmparse = (spec, specifier) => { // "require": "./feature-node.cjs" // } // } + if (!indexval && opts.isbrowser && spec[specbrowser]) + indexval = esmparse(spec[specbrowser], specifier, opts) if (!indexval && spec[specruntime]) - indexval = esmparse(spec[specruntime], specifier) + indexval = esmparse(spec[specruntime], specifier, opts) if (!indexval && spec[specdefault]) - indexval = esmparse(spec[specdefault], specifier) + indexval = esmparse(spec[specdefault], specifier, opts) if (!indexval && spec[specifier]) - indexval = esmparse(spec[specifier], specifier) + indexval = esmparse(spec[specifier], specifier, opts) // "exports": "./lib/index.js", // "exports": { "import": "./lib/index.js" }, @@ -239,8 +242,8 @@ const esmparse = (spec, specifier) => { // "exports": { ".": { "import": "./lib/index.js" } } if (!indexval && spec[specdot]) indexval = typeof spec[specdot] === 'string' - ? specifier === specimport && esmparse(spec[specdot], specifier) - : esmparse(spec[specdot], specifier) + ? specifier === specimport && esmparse(spec[specdot], specifier, opts) + : esmparse(spec[specdot], specifier, opts) // "exports": { // ".": "./lib/index.test.js", @@ -256,7 +259,7 @@ const esmparse = (spec, specifier) => { const gettargetindex = (packagejson, opts) => { let moduleobj = opts && opts.ismodule && packagejson.module, - browserobj = moduleobj || opts && opts.browser && packagejson.browser, + browserobj = moduleobj || opts && opts.isbrowser && packagejson.browser, esmexportsobj = packagejson.exports, indexprop, indexval @@ -272,7 +275,7 @@ const gettargetindex = (packagejson, opts) => { } if (esmexportsobj) { - indexval = esmparse(esmexportsobj, specimport) + indexval = esmparse(esmexportsobj, specimport, opts) } return indexval @@ -345,9 +348,9 @@ const getasfileordir = (moduleId, parent, opts) => { // } // } // } -const esmparseimport = (targetpath, specifier, pjson) => { +const esmparseimport = (targetpath, specifier, pjson, opts) => { const pjsonimports = pjson && pjson.imports - const firstmatch = esmparse(pjsonimports, specifier) + const firstmatch = esmparse(pjsonimports, specifier, opts) return firstmatch && ( isRelPathRe.test(firstmatch) @@ -373,10 +376,11 @@ const esmparseimport = (targetpath, specifier, pjson) => { // 7. Let packageSubpath be "." concatenated with the substring of // packageSpecifier from the position at the length of packageName. // (removed steps 8-12 related to urls and error cases) -const esmparseexport = (targetpath, pname, pspecifier, pjson) => { +const esmparseexport = (targetpath, pname, pspecifier, pjson, opts) => { const firstmatch = esmparse( pjson && pjson.exports, - pspecifier ? './' + pspecifier : specimport) + pspecifier ? './' + pspecifier : specimport, + opts) return firstmatch && path.join(targetpath, pname, firstmatch) } @@ -459,10 +463,13 @@ const begin = (moduleId, parent, opts) => { } const createopts = (moduleId, parent, opts) => { - opts = opts || {} - opts.isTypescript = typeof opts.isTypescript === 'boolean' - ? opts.isTypescript : isTsExtnRe.test(parent) + const boolOr = (v, def) => typeof v === 'boolean' ? v : def + opts = opts || {} + opts.isTypescript = boolOr(opts.isTypescript, isTsExtnRe.test(parent)) + opts.isbrowser = boolOr(opts.isbrowser, false) + opts.ismodule = boolOr(opts.ismodule, true) + return opts } diff --git a/tests/tests-basic/tests-basic.test.js b/tests/tests-basic/tests-basic.test.js index 860364c..44429bc 100644 --- a/tests/tests-basic/tests-basic.test.js +++ b/tests/tests-basic/tests-basic.test.js @@ -300,3 +300,75 @@ test('should handle mixed exports', () => { } }), './index.mjs') }) + +test('should return esm by default', () => { + // used by 'inferno@8.2.2' + assert.strictEqual(resolvewithplus.gettargetindex({ + name: 'test', + main: './index.js', + module: './index.esm.js' + }, { ismodule: true }), './index.esm.js') + + // used by '@apollo/server@4.9.4' + assert.strictEqual(resolvewithplus.gettargetindex({ + name: 'test', + exports: { + '.': { + import: './dist/esm/index.js', + require: './dist/cjs/index.js' + } + } + }, { ismodule: true }), './dist/esm/index.js') + + // similar patter used by 'react-dom@18.2.0' + assert.strictEqual(resolvewithplus.gettargetindex({ + name: 'test', + exports: { + '.': { + deno: './server.deno.js', + worker: './server.worker.js', + browser: './server.browser.js', + import: './server.import.js', + default: './server.default.js' + } + } + }, { ismodule: true }), './server.import.js') + + assert.strictEqual(resolvewithplus.gettargetindex({ + name: 'test', + exports: { + '.': { + deno: './server.deno.js', + worker: './server.worker.js', + browser: './server.browser.js', + default: './server.node.default.js' + } + } + }, { ismodule: true }), './server.node.default.js') +}) + +test('should return browser over import when both true', () => { + assert.strictEqual(resolvewithplus.gettargetindex({ + name: 'test', + exports: { + '.': { + deno: './server.deno.js', + worker: './server.worker.js', + browser: './server.browser.js', + default: './server.default.js' + } + } + }, { ismodule: true, isbrowser: true }), './server.browser.js') + + assert.strictEqual(resolvewithplus.gettargetindex({ + name: 'test', + exports: { + '.': { + deno: './server.deno.js', + worker: './server.worker.js', + browser: './server.browser.js', + default: './server.default.js' + } + } + }, { ismodule: true }), './server.default.js') +}) From baa26271a9e8c6e12f10b28f7d52aba69ab486c2 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 6 Oct 2023 00:20:59 -0700 Subject: [PATCH 2/4] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de51df..65e472a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # changelog * 2.0.6 _Oct.10.2023_ + * [explicitly prioritize "browser"](https://github.com/iambumblehead/resolvewithplus/pull/54) then "import" then "default", when browser and import both true * [update README image link](https://github.com/iambumblehead/resolvewithplus/pull/52) to use "main" repo path * [replace reducer function](https://github.com/iambumblehead/resolvewithplus/pull/53) w/ simple recursion * 2.0.5 _Sep.13.2023_ From b4da306eb0a962385e9351638d7680730881ac46 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 6 Oct 2023 00:48:08 -0700 Subject: [PATCH 3/4] use list to more clearly define priority --- resolvewithplus.js | 21 ++++++++++++++++++--- tests/tests-basic/tests-basic.test.js | 16 ++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/resolvewithplus.js b/resolvewithplus.js index 9246187..d1459ef 100644 --- a/resolvewithplus.js +++ b/resolvewithplus.js @@ -227,12 +227,20 @@ const esmparse = (spec, specifier, opts = {}) => { // "require": "./feature-node.cjs" // } // } + if (!indexval) + indexval = (opts.specprioritylist || [ + specruntime, specdefault + ]).reduce((prev, specname) => ( + prev || esmparse(spec[specname], specifier, opts) + ), false) +/* if (!indexval && opts.isbrowser && spec[specbrowser]) indexval = esmparse(spec[specbrowser], specifier, opts) if (!indexval && spec[specruntime]) indexval = esmparse(spec[specruntime], specifier, opts) if (!indexval && spec[specdefault]) indexval = esmparse(spec[specdefault], specifier, opts) +*/ if (!indexval && spec[specifier]) indexval = esmparse(spec[specifier], specifier, opts) @@ -258,7 +266,7 @@ const esmparse = (spec, specifier, opts = {}) => { } const gettargetindex = (packagejson, opts) => { - let moduleobj = opts && opts.ismodule && packagejson.module, + let moduleobj = opts && opts.isimport && packagejson.module, browserobj = moduleobj || opts && opts.isbrowser && packagejson.browser, esmexportsobj = packagejson.exports, indexprop, @@ -468,8 +476,15 @@ const createopts = (moduleId, parent, opts) => { opts = opts || {} opts.isTypescript = boolOr(opts.isTypescript, isTsExtnRe.test(parent)) opts.isbrowser = boolOr(opts.isbrowser, false) - opts.ismodule = boolOr(opts.ismodule, true) - + opts.isimport = boolOr(opts.isimport, true) + + opts.specprioritylist = [] + + if (opts.isbrowser) opts.specprioritylist.push(specbrowser) + if (opts.isimport) opts.specprioritylist.push(specimport) + opts.specprioritylist.push(specruntime) + opts.specprioritylist.push(specdefault) + return opts } diff --git a/tests/tests-basic/tests-basic.test.js b/tests/tests-basic/tests-basic.test.js index 44429bc..3d2bda3 100644 --- a/tests/tests-basic/tests-basic.test.js +++ b/tests/tests-basic/tests-basic.test.js @@ -307,7 +307,7 @@ test('should return esm by default', () => { name: 'test', main: './index.js', module: './index.esm.js' - }, { ismodule: true }), './index.esm.js') + }, { isimport: true }), './index.esm.js') // used by '@apollo/server@4.9.4' assert.strictEqual(resolvewithplus.gettargetindex({ @@ -318,7 +318,7 @@ test('should return esm by default', () => { require: './dist/cjs/index.js' } } - }, { ismodule: true }), './dist/esm/index.js') + }), './dist/esm/index.js') // similar patter used by 'react-dom@18.2.0' assert.strictEqual(resolvewithplus.gettargetindex({ @@ -332,7 +332,7 @@ test('should return esm by default', () => { default: './server.default.js' } } - }, { ismodule: true }), './server.import.js') + }), './server.import.js') assert.strictEqual(resolvewithplus.gettargetindex({ name: 'test', @@ -344,7 +344,7 @@ test('should return esm by default', () => { default: './server.node.default.js' } } - }, { ismodule: true }), './server.node.default.js') + }), './server.node.default.js') }) test('should return browser over import when both true', () => { @@ -358,7 +358,9 @@ test('should return browser over import when both true', () => { default: './server.default.js' } } - }, { ismodule: true, isbrowser: true }), './server.browser.js') + }, { + specprioritylist: [ 'import', 'browser', 'default' ] + }), './server.browser.js') assert.strictEqual(resolvewithplus.gettargetindex({ name: 'test', @@ -370,5 +372,7 @@ test('should return browser over import when both true', () => { default: './server.default.js' } } - }, { ismodule: true }), './server.default.js') + }, { + specprioritylist: [ 'default' ] + }), './server.default.js') }) From 7be810d4ab2851d9481b70826a0910f3fd96046b Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 6 Oct 2023 00:51:00 -0700 Subject: [PATCH 4/4] remove commented-out block --- resolvewithplus.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/resolvewithplus.js b/resolvewithplus.js index d1459ef..3aa2e62 100644 --- a/resolvewithplus.js +++ b/resolvewithplus.js @@ -228,19 +228,11 @@ const esmparse = (spec, specifier, opts = {}) => { // } // } if (!indexval) - indexval = (opts.specprioritylist || [ - specruntime, specdefault - ]).reduce((prev, specname) => ( - prev || esmparse(spec[specname], specifier, opts) - ), false) -/* - if (!indexval && opts.isbrowser && spec[specbrowser]) - indexval = esmparse(spec[specbrowser], specifier, opts) - if (!indexval && spec[specruntime]) - indexval = esmparse(spec[specruntime], specifier, opts) - if (!indexval && spec[specdefault]) - indexval = esmparse(spec[specdefault], specifier, opts) -*/ + indexval = (opts.specprioritylist || [ specruntime, specdefault ]) + .reduce((prev, specname) => ( + prev || esmparse(spec[specname], specifier, opts) + ), false) + if (!indexval && spec[specifier]) indexval = esmparse(spec[specifier], specifier, opts)