Skip to content

Commit b9f3959

Browse files
Merge pull request #55 from iambumblehead/exlicitly-resolve-browser-and-import-priorities
Exlicitly resolve browser and import priorities
2 parents 26fe393 + 7be810d commit b9f3959

File tree

3 files changed

+109
-18
lines changed

3 files changed

+109
-18
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# changelog
22

33
* 2.0.6 _Oct.10.2023_
4+
* [explicitly prioritize "browser"](https://github.com/iambumblehead/resolvewithplus/pull/54) then "import" then "default", when browser and import both true
45
* [update README image link](https://github.com/iambumblehead/resolvewithplus/pull/52) to use "main" repo path
56
* [replace reducer function](https://github.com/iambumblehead/resolvewithplus/pull/53) w/ simple recursion
67
* 2.0.5 _Sep.13.2023_

resolvewithplus.js

+32-18
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const node_modules = 'node_modules'
2929
const packagejson = 'package.json'
3030
const specruntime = 'node'
3131
const specdefault = 'default'
32+
const specbrowser = 'browser'
3233
const specimport = 'import'
3334
const specdot = '.'
3435
const isobj = o => o && typeof o === 'object'
@@ -195,7 +196,7 @@ const esmparselist = (list, spec, specifier, key = list[0]) => {
195196
|| esmparselist(list.slice(1), spec, specifier)
196197
}
197198

198-
const esmparse = (spec, specifier) => {
199+
const esmparse = (spec, specifier, opts = {}) => {
199200
let indexval = false
200201

201202
if (typeof spec === 'string')
@@ -209,7 +210,7 @@ const esmparse = (spec, specifier) => {
209210
// }, "./index.cjs" ]
210211
// }
211212
indexval = spec
212-
.reduce((p, elem) => p || esmparse(elem, specifier), null)
213+
.reduce((p, elem) => p || esmparse(elem, specifier, opts), null)
213214
}
214215

215216
if (!indexval && isobj(spec)) {
@@ -226,21 +227,23 @@ const esmparse = (spec, specifier) => {
226227
// "require": "./feature-node.cjs"
227228
// }
228229
// }
229-
if (!indexval && spec[specruntime])
230-
indexval = esmparse(spec[specruntime], specifier)
231-
if (!indexval && spec[specdefault])
232-
indexval = esmparse(spec[specdefault], specifier)
230+
if (!indexval)
231+
indexval = (opts.specprioritylist || [ specruntime, specdefault ])
232+
.reduce((prev, specname) => (
233+
prev || esmparse(spec[specname], specifier, opts)
234+
), false)
235+
233236
if (!indexval && spec[specifier])
234-
indexval = esmparse(spec[specifier], specifier)
237+
indexval = esmparse(spec[specifier], specifier, opts)
235238

236239
// "exports": "./lib/index.js",
237240
// "exports": { "import": "./lib/index.js" },
238241
// "exports": { ".": "./lib/index.js" },
239242
// "exports": { ".": { "import": "./lib/index.js" } }
240243
if (!indexval && spec[specdot])
241244
indexval = typeof spec[specdot] === 'string'
242-
? specifier === specimport && esmparse(spec[specdot], specifier)
243-
: esmparse(spec[specdot], specifier)
245+
? specifier === specimport && esmparse(spec[specdot], specifier, opts)
246+
: esmparse(spec[specdot], specifier, opts)
244247

245248
// "exports": {
246249
// ".": "./lib/index.test.js",
@@ -255,8 +258,8 @@ const esmparse = (spec, specifier) => {
255258
}
256259

257260
const gettargetindex = (packagejson, opts) => {
258-
let moduleobj = opts && opts.ismodule && packagejson.module,
259-
browserobj = moduleobj || opts && opts.browser && packagejson.browser,
261+
let moduleobj = opts && opts.isimport && packagejson.module,
262+
browserobj = moduleobj || opts && opts.isbrowser && packagejson.browser,
260263
esmexportsobj = packagejson.exports,
261264
indexprop,
262265
indexval
@@ -272,7 +275,7 @@ const gettargetindex = (packagejson, opts) => {
272275
}
273276

274277
if (esmexportsobj) {
275-
indexval = esmparse(esmexportsobj, specimport)
278+
indexval = esmparse(esmexportsobj, specimport, opts)
276279
}
277280

278281
return indexval
@@ -345,9 +348,9 @@ const getasfileordir = (moduleId, parent, opts) => {
345348
// }
346349
// }
347350
// }
348-
const esmparseimport = (targetpath, specifier, pjson) => {
351+
const esmparseimport = (targetpath, specifier, pjson, opts) => {
349352
const pjsonimports = pjson && pjson.imports
350-
const firstmatch = esmparse(pjsonimports, specifier)
353+
const firstmatch = esmparse(pjsonimports, specifier, opts)
351354

352355
return firstmatch && (
353356
isRelPathRe.test(firstmatch)
@@ -373,10 +376,11 @@ const esmparseimport = (targetpath, specifier, pjson) => {
373376
// 7. Let packageSubpath be "." concatenated with the substring of
374377
// packageSpecifier from the position at the length of packageName.
375378
// (removed steps 8-12 related to urls and error cases)
376-
const esmparseexport = (targetpath, pname, pspecifier, pjson) => {
379+
const esmparseexport = (targetpath, pname, pspecifier, pjson, opts) => {
377380
const firstmatch = esmparse(
378381
pjson && pjson.exports,
379-
pspecifier ? './' + pspecifier : specimport)
382+
pspecifier ? './' + pspecifier : specimport,
383+
opts)
380384

381385
return firstmatch && path.join(targetpath, pname, firstmatch)
382386
}
@@ -459,9 +463,19 @@ const begin = (moduleId, parent, opts) => {
459463
}
460464

461465
const createopts = (moduleId, parent, opts) => {
466+
const boolOr = (v, def) => typeof v === 'boolean' ? v : def
467+
462468
opts = opts || {}
463-
opts.isTypescript = typeof opts.isTypescript === 'boolean'
464-
? opts.isTypescript : isTsExtnRe.test(parent)
469+
opts.isTypescript = boolOr(opts.isTypescript, isTsExtnRe.test(parent))
470+
opts.isbrowser = boolOr(opts.isbrowser, false)
471+
opts.isimport = boolOr(opts.isimport, true)
472+
473+
opts.specprioritylist = []
474+
475+
if (opts.isbrowser) opts.specprioritylist.push(specbrowser)
476+
if (opts.isimport) opts.specprioritylist.push(specimport)
477+
opts.specprioritylist.push(specruntime)
478+
opts.specprioritylist.push(specdefault)
465479

466480
return opts
467481
}

tests/tests-basic/tests-basic.test.js

+76
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,79 @@ test('should handle mixed exports', () => {
300300
}
301301
}), './index.mjs')
302302
})
303+
304+
test('should return esm by default', () => {
305+
// used by 'inferno@8.2.2'
306+
assert.strictEqual(resolvewithplus.gettargetindex({
307+
name: 'test',
308+
main: './index.js',
309+
module: './index.esm.js'
310+
}, { isimport: true }), './index.esm.js')
311+
312+
// used by '@apollo/server@4.9.4'
313+
assert.strictEqual(resolvewithplus.gettargetindex({
314+
name: 'test',
315+
exports: {
316+
'.': {
317+
import: './dist/esm/index.js',
318+
require: './dist/cjs/index.js'
319+
}
320+
}
321+
}), './dist/esm/index.js')
322+
323+
// similar patter used by 'react-dom@18.2.0'
324+
assert.strictEqual(resolvewithplus.gettargetindex({
325+
name: 'test',
326+
exports: {
327+
'.': {
328+
deno: './server.deno.js',
329+
worker: './server.worker.js',
330+
browser: './server.browser.js',
331+
import: './server.import.js',
332+
default: './server.default.js'
333+
}
334+
}
335+
}), './server.import.js')
336+
337+
assert.strictEqual(resolvewithplus.gettargetindex({
338+
name: 'test',
339+
exports: {
340+
'.': {
341+
deno: './server.deno.js',
342+
worker: './server.worker.js',
343+
browser: './server.browser.js',
344+
default: './server.node.default.js'
345+
}
346+
}
347+
}), './server.node.default.js')
348+
})
349+
350+
test('should return browser over import when both true', () => {
351+
assert.strictEqual(resolvewithplus.gettargetindex({
352+
name: 'test',
353+
exports: {
354+
'.': {
355+
deno: './server.deno.js',
356+
worker: './server.worker.js',
357+
browser: './server.browser.js',
358+
default: './server.default.js'
359+
}
360+
}
361+
}, {
362+
specprioritylist: [ 'import', 'browser', 'default' ]
363+
}), './server.browser.js')
364+
365+
assert.strictEqual(resolvewithplus.gettargetindex({
366+
name: 'test',
367+
exports: {
368+
'.': {
369+
deno: './server.deno.js',
370+
worker: './server.worker.js',
371+
browser: './server.browser.js',
372+
default: './server.default.js'
373+
}
374+
}
375+
}, {
376+
specprioritylist: [ 'default' ]
377+
}), './server.default.js')
378+
})

0 commit comments

Comments
 (0)