Skip to content

Commit 01aef6f

Browse files
committed
add alternative browser field support, e.g. chromeapp
1 parent 7d84116 commit 01aef6f

File tree

15 files changed

+139
-36
lines changed

15 files changed

+139
-36
lines changed

Diff for: README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Options:
1414
* `paths` - `require.paths` array to use if nothing is found on the normal `node_modules` recursive walk
1515
* `packageFilter` - transform the parsed `package.json` contents before looking at the `main` field
1616
* `modules` - object with module id/name -> path mappings to consult before doing manual resolution (use to provide core modules)
17+
* `browser` - the 'browser' property to use from package.json (defaults to 'browser')
1718

1819
### resolve.sync(id, opts={})
1920

@@ -63,13 +64,16 @@ browser-specific versions of modules
6364
"version": "0.0.0",
6465
"browser": {
6566
"./main.js": "custom.js"
67+
},
68+
"chromeapp": {
69+
"./main.js": "custom-chromeapp.js"
6670
}
6771
}
6872
```
6973

7074
``` js
7175
var resolve = require('browser-resolve');
72-
var parent = { filename: __dirname + '/custom/file.js' };
76+
var parent = { filename: __dirname + '/custom/file.js' /*, browser: 'chromeapp' */ };
7377
resolve('./main.js', parent, function(err, path) {
7478
console.log(path);
7579
});

Diff for: example/custom-chromeapp.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var resolve = require('../');
2+
var parent = { filename: __dirname + '/custom/file.js', browser: 'chromeapp' };
3+
resolve('./main.js', parent, function(err, path) {
4+
console.log(path);
5+
});

Diff for: example/custom/custom-chromeapp.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('chromeapp version');

Diff for: example/custom/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{
22
"name": "custom",
33
"version": "0.0.0",
4+
"chromeapp": {
5+
"./main.js": "custom-chromeapp.js"
6+
},
47
"browser": {
58
"./main.js": "custom.js"
69
}

Diff for: index.js

+47-34
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function nodeModulesPaths (start, cb) {
2525
return dirs;
2626
}
2727

28-
function find_shims_in_package(pkgJson, cur_path, shims) {
28+
function find_shims_in_package(pkgJson, cur_path, shims, browser) {
2929
try {
3030
var info = JSON.parse(pkgJson);
3131
}
@@ -34,32 +34,28 @@ function find_shims_in_package(pkgJson, cur_path, shims) {
3434
throw err;
3535
}
3636

37-
// support legacy browserify field for easier migration from legacy
38-
// many packages used this field historically
39-
if (typeof info.browserify === 'string' && !info.browser) {
40-
info.browser = info.browserify;
41-
}
37+
replacements = getReplacements(info, browser);
4238

4339
// no replacements, skip shims
44-
if (!info.browser) {
40+
if (!replacements) {
4541
return;
4642
}
4743

48-
// if browser field is a string
44+
// if browser mapping is a string
4945
// then it just replaces the main entry point
50-
if (typeof info.browser === 'string') {
46+
if (typeof replacements === 'string') {
5147
var key = path.resolve(cur_path, info.main || 'index.js');
52-
shims[key] = path.resolve(cur_path, info.browser);
48+
shims[key] = path.resolve(cur_path, replacements);
5349
return;
5450
}
5551

5652
// http://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders
57-
Object.keys(info.browser).forEach(function(key) {
58-
if (info.browser[key] === false) {
53+
Object.keys(replacements).forEach(function(key) {
54+
if (replacements[key] === false) {
5955
return shims[key] = __dirname + '/empty.js';
6056
}
6157

62-
var val = info.browser[key];
58+
var val = replacements[key];
6359

6460
// if target is a relative path, then resolve
6561
// otherwise we assume target is a module
@@ -79,7 +75,7 @@ function find_shims_in_package(pkgJson, cur_path, shims) {
7975

8076
// paths is mutated
8177
// load shims from first package.json file found
82-
function load_shims(paths, cb) {
78+
function load_shims(paths, browser, cb) {
8379
// identify if our file should be replaced per the browser field
8480
// original filename|id -> replacement
8581
var shims = {};
@@ -103,7 +99,7 @@ function load_shims(paths, cb) {
10399
return cb(err);
104100
}
105101
try {
106-
find_shims_in_package(data, cur_path, shims);
102+
find_shims_in_package(data, cur_path, shims, browser);
107103
return cb(null, shims);
108104
}
109105
catch (err) {
@@ -115,7 +111,7 @@ function load_shims(paths, cb) {
115111

116112
// paths is mutated
117113
// synchronously load shims from first package.json file found
118-
function load_shims_sync(paths) {
114+
function load_shims_sync(paths, browser) {
119115
// identify if our file should be replaced per the browser field
120116
// original filename|id -> replacement
121117
var shims = {};
@@ -126,7 +122,7 @@ function load_shims_sync(paths) {
126122

127123
try {
128124
var data = fs.readFileSync(pkg_path, 'utf8');
129-
find_shims_in_package(data, cur_path, shims);
125+
find_shims_in_package(data, cur_path, shims, browser);
130126
return shims;
131127
}
132128
catch (err) {
@@ -144,34 +140,34 @@ function load_shims_sync(paths) {
144140

145141
function build_resolve_opts(opts, base) {
146142
var packageFilter = opts.packageFilter;
143+
var browser = normalizeBrowserFieldName(opts.browser)
147144

148145
opts.basedir = base;
149146
opts.packageFilter = function (info, pkgdir) {
150147
if (packageFilter) info = packageFilter(info, pkgdir);
151148

152-
// support legacy browserify field
153-
if (typeof info.browserify === 'string' && !info.browser) {
154-
info.browser = info.browserify;
155-
}
149+
var replacements = getReplacements(info, browser);
156150

157151
// no browser field, keep info unchanged
158-
if (!info.browser) {
152+
if (!replacements) {
159153
return info;
160154
}
161155

156+
info[browser] = replacements;
157+
162158
// replace main
163-
if (typeof info.browser === 'string') {
164-
info.main = info.browser;
159+
if (typeof replacements === 'string') {
160+
info.main = replacements;
165161
return info;
166162
}
167163

168-
var replace_main = info.browser[info.main || './index.js'] ||
169-
info.browser['./' + info.main || './index.js'];
164+
var replace_main = replacements[info.main || './index.js'] ||
165+
replacements['./' + info.main || './index.js'];
170166

171167
info.main = replace_main || info.main;
172168
return info;
173169
};
174-
170+
175171
var pathFilter = opts.pathFilter;
176172
opts.pathFilter = function(info, path, relativePath) {
177173
if(relativePath[0] != '.') {
@@ -187,7 +183,7 @@ function build_resolve_opts(opts, base) {
187183
if(!info.browser) {
188184
return;
189185
}
190-
186+
191187
if(typeof info.browser) {
192188
mappedPath = info.browser[relativePath];
193189
if(!mappedPath && (relativePath.lastIndexOf(".js") === relativePath.length-3) ) {
@@ -210,11 +206,11 @@ function resolve(id, opts, cb) {
210206
opts = opts || {};
211207

212208
var base = path.dirname(opts.filename);
213-
209+
214210
if (opts.basedir) {
215211
base = opts.basedir;
216212
}
217-
213+
218214
var paths = nodeModulesPaths(base);
219215

220216
if (opts.paths) {
@@ -226,7 +222,7 @@ function resolve(id, opts, cb) {
226222
});
227223

228224
// we must always load shims because the browser field could shim out a module
229-
load_shims(paths, function(err, shims) {
225+
load_shims(paths, opts.browser, function(err, shims) {
230226
if (err) {
231227
return cb(err);
232228
}
@@ -269,11 +265,11 @@ resolve.sync = function (id, opts) {
269265

270266
opts = opts || {};
271267
var base = path.dirname(opts.filename);
272-
268+
273269
if (opts.basedir) {
274270
base = opts.basedir;
275271
}
276-
272+
277273
var paths = nodeModulesPaths(base);
278274

279275
if (opts.paths) {
@@ -285,7 +281,7 @@ resolve.sync = function (id, opts) {
285281
});
286282

287283
// we must always load shims because the browser field could shim out a module
288-
var shims = load_shims_sync(paths);
284+
var shims = load_shims_sync(paths, opts.browser);
289285

290286
if (shims[id]) {
291287
// if the shim was is an absolute path, it was fully resolved
@@ -310,5 +306,22 @@ resolve.sync = function (id, opts) {
310306
return (shims) ? shims[full] || full : full;
311307
};
312308

309+
function normalizeBrowserFieldName(browser) {
310+
return browser || 'browser';
311+
}
312+
313+
function getReplacements(info, browser) {
314+
browser = normalizeBrowserFieldName(browser);
315+
var replacements = info[browser];
316+
317+
// support legacy browserify field for easier migration from legacy
318+
// many packages used this field historically
319+
if (typeof info.browserify === 'string' && !replacements) {
320+
replacements = info.browserify;
321+
}
322+
323+
return replacements;
324+
}
325+
313326
module.exports = resolve;
314327

Diff for: test/fixtures/node_modules/alt-browser-field/index.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/alt-browser-field/package.json

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/alt-browser-field/url-browser.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/alt-browser-field/url-chromeapp.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/module-c/chromeapp.js

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/module-c/foo.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/module-c/package.json

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/fixtures/node_modules/module-h/package.json

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/modules-sync.js

+10
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,13 @@ test('override engine shim', function() {
137137
assert.equal(path, require.resolve('./fixtures/node_modules/override-engine-shim/url-browser'));
138138
});
139139

140+
test('alt-browser field', function() {
141+
var parent = {
142+
filename: fixtures_dir + '/alt-browser-field/index.js',
143+
package: { main: './index.js' },
144+
browser: 'chromeapp'
145+
};
146+
147+
var path = resolve.sync('url', parent);
148+
assert.equal(path, require.resolve('./fixtures/node_modules/alt-browser-field/url-chromeapp'));
149+
});

Diff for: test/modules.js

+47
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,23 @@ test('string browser field as main - require subfile', function(done) {
4949
});
5050
});
5151

52+
// package.json has an alternative 'browser' field which is a string
53+
test('string alt browser field as main - require subfile', function(done) {
54+
var parent = {
55+
filename: fixtures_dir + '/module-c/chromeapp.js',
56+
paths: [ fixtures_dir + '/module-c/node_modules' ],
57+
package: { main: './chromeapp.js' },
58+
browser: 'chromeapp'
59+
};
60+
61+
resolve('./foo', parent, function(err, path, pkg) {
62+
assert.ifError(err);
63+
assert.equal(path, require.resolve('./fixtures/node_modules/module-c/foo'));
64+
assert.equal(pkg.main, './chromeapp.js');
65+
done();
66+
});
67+
});
68+
5269
// package.json has browser field as object
5370
// one of the keys replaces the main file
5471
// this would be done if the user needed to replace main and some other module
@@ -129,6 +146,22 @@ test('test core -> module-c replacement', function(done) {
129146
});
130147
});
131148

149+
// same as above but with alt browser
150+
test('test core -> module-c replacement with alt browser', function(done) {
151+
var parent = {
152+
filename: fixtures_dir + '/module-h/index.js',
153+
package: { main: './index.js' },
154+
browser: 'chromeapp'
155+
};
156+
157+
resolve('querystring', parent, function(err, path, pkg) {
158+
assert.ifError(err);
159+
assert.equal(path, require.resolve('./fixtures/node_modules/module-c/chromeapp'));
160+
assert.equal(pkg.main, './chromeapp.js');
161+
done();
162+
});
163+
});
164+
132165
// browser field in package.json maps "module" -> "alternate module"
133166
test('test foobar -> module-b replacement with transform', function(done) {
134167
var parent = {
@@ -203,3 +236,17 @@ test('override engine shim', function(done) {
203236
});
204237
});
205238

239+
test('alt-browser field', function(done) {
240+
var parent = {
241+
filename: fixtures_dir + '/alt-browser-field/index.js',
242+
package: { main: './index.js' },
243+
browser: 'chromeapp'
244+
};
245+
246+
resolve('url', parent, function(err, path, pkg) {
247+
assert.ifError(err);
248+
assert.equal(path, require.resolve('./fixtures/node_modules/alt-browser-field/url-chromeapp'));
249+
assert.equal(pkg.main, './index.js');
250+
done();
251+
});
252+
});

0 commit comments

Comments
 (0)