Skip to content

Commit 0ab0aca

Browse files
jdanyowdevongovett
authored andcommitted
Add url dependency for serviceWorker.register calls (#398)
* Add url dependency for serviceWorker.register calls * extract matchesPattern helper * sync SW regexp with matchesPattern arg
1 parent d763a1a commit 0ab0aca

7 files changed

Lines changed: 77 additions & 42 deletions

File tree

ā€Žsrc/assets/JSAsset.jsā€Ž

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const config = require('../utils/config');
1515
const IMPORT_RE = /\b(?:import\b|export\b|require\s*\()/;
1616
const GLOBAL_RE = /\b(?:process|__dirname|__filename|global|Buffer)\b/;
1717
const FS_RE = /\breadFileSync\b/;
18+
const SW_RE = /\bnavigator\s*\.\s*serviceWorker\s*\.\s*register\s*\(/;
1819

1920
class JSAsset extends Asset {
2021
constructor(name, pkg, options) {
@@ -30,7 +31,8 @@ class JSAsset extends Asset {
3031
return (
3132
!/.js$/.test(this.name) ||
3233
IMPORT_RE.test(this.contents) ||
33-
GLOBAL_RE.test(this.contents)
34+
GLOBAL_RE.test(this.contents) ||
35+
SW_RE.test(this.contents)
3436
);
3537
}
3638

ā€Žsrc/visitors/dependencies.jsā€Ž

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
const types = require('babel-types');
22
const template = require('babel-template');
3+
const urlJoin = require('../utils/urlJoin');
4+
const isURL = require('../utils/is-url');
5+
const matchesPattern = require('./matches-pattern');
36

47
const requireTemplate = template('require("_bundle_loader")');
58
const argTemplate = template('require.resolve(MODULE)');
9+
const serviceWorkerPattern = ['navigator', 'serviceWorker', 'register'];
610

711
module.exports = {
812
ImportDeclaration(node, asset) {
@@ -37,6 +41,7 @@ module.exports = {
3741

3842
if (isRequire) {
3943
addDependency(asset, args[0]);
44+
return;
4045
}
4146

4247
let isDynamicImport =
@@ -51,6 +56,21 @@ module.exports = {
5156
node.callee = requireTemplate().expression;
5257
node.arguments[0] = argTemplate({MODULE: args[0]}).expression;
5358
asset.isAstDirty = true;
59+
return;
60+
}
61+
62+
const isRegisterServiceWorker =
63+
types.isStringLiteral(args[0]) &&
64+
matchesPattern(callee, serviceWorkerPattern);
65+
66+
if (isRegisterServiceWorker) {
67+
let assetPath = asset.addURLDependency(args[0].value);
68+
if (!isURL(assetPath)) {
69+
assetPath = urlJoin(asset.options.publicURL, assetPath);
70+
}
71+
args[0].value = assetPath;
72+
asset.isAstDirty = true;
73+
return;
5474
}
5575
}
5676
};

ā€Žsrc/visitors/globals.jsā€Ž

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const Path = require('path');
22
const types = require('babel-types');
3+
const matchesPattern = require('./matches-pattern');
34

45
const VARS = {
56
process: asset => {
@@ -62,47 +63,6 @@ function inScope(ancestors) {
6263
return false;
6364
}
6465

65-
// from babel-types. remove when we upgrade to babel 7.
66-
// https://github.com/babel/babel/blob/0189b387026c35472dccf45d14d58312d249f799/packages/babel-types/src/index.js#L347
67-
function matchesPattern(member, match) {
68-
// not a member expression
69-
if (!types.isMemberExpression(member)) {
70-
return false;
71-
}
72-
73-
const parts = Array.isArray(match) ? match : match.split('.');
74-
const nodes = [];
75-
76-
let node;
77-
for (node = member; types.isMemberExpression(node); node = node.object) {
78-
nodes.push(node.property);
79-
}
80-
81-
nodes.push(node);
82-
83-
if (nodes.length !== parts.length) {
84-
return false;
85-
}
86-
87-
for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
88-
const node = nodes[j];
89-
let value;
90-
if (types.isIdentifier(node)) {
91-
value = node.name;
92-
} else if (types.isStringLiteral(node)) {
93-
value = node.value;
94-
} else {
95-
return false;
96-
}
97-
98-
if (parts[i] !== value) {
99-
return false;
100-
}
101-
}
102-
103-
return true;
104-
}
105-
10666
// replace object properties
10767
function morph(object, newProperties) {
10868
for (let key in object) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const types = require('babel-types');
2+
3+
// from babel-types. remove when we upgrade to babel 7.
4+
// https://github.com/babel/babel/blob/0189b387026c35472dccf45d14d58312d249f799/packages/babel-types/src/index.js#L347
5+
module.exports = function matchesPattern(member, match, allowPartial) {
6+
// not a member expression
7+
if (!types.isMemberExpression(member)) return false;
8+
9+
const parts = Array.isArray(match) ? match : match.split('.');
10+
const nodes = [];
11+
12+
let node;
13+
for (node = member; types.isMemberExpression(node); node = node.object) {
14+
nodes.push(node.property);
15+
}
16+
nodes.push(node);
17+
18+
if (nodes.length < parts.length) return false;
19+
if (!allowPartial && nodes.length > parts.length) return false;
20+
21+
for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
22+
const node = nodes[j];
23+
let value;
24+
if (types.isIdentifier(node)) {
25+
value = node.name;
26+
} else if (types.isStringLiteral(node)) {
27+
value = node.value;
28+
} else {
29+
return false;
30+
}
31+
32+
if (parts[i] !== value) return false;
33+
}
34+
35+
return true;
36+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
navigator.serviceWorker.register('worker.js', { scope: './' });
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
self.addEventListener('message', () => {});

ā€Žtest/javascript.jsā€Ž

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ describe('javascript', function() {
5858
assert.equal(await output(), 3);
5959
});
6060

61+
it('should support bundling service workers', async function() {
62+
let b = await bundle(__dirname + '/integration/service-worker/index.js');
63+
64+
assertBundleTree(b, {
65+
name: 'index.js',
66+
assets: ['index.js'],
67+
childBundles: [
68+
{
69+
assets: ['worker.js'],
70+
childBundles: []
71+
}
72+
]
73+
});
74+
});
75+
6176
it('should dynamic import files which import raw files', async function() {
6277
let b = await bundle(
6378
__dirname + '/integration/dynamic-references-raw/index.js'

0 commit comments

Comments
Ā (0)
⚔