Skip to content

Commit

Permalink
Add url dependency for serviceWorker.register calls (#398)
Browse files Browse the repository at this point in the history
* Add url dependency for serviceWorker.register calls

* extract matchesPattern helper

* sync SW regexp with matchesPattern arg
  • Loading branch information
jdanyow authored and devongovett committed Dec 29, 2017
1 parent d763a1a commit 0ab0aca
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 42 deletions.
4 changes: 3 additions & 1 deletion src/assets/JSAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const config = require('../utils/config');
const IMPORT_RE = /\b(?:import\b|export\b|require\s*\()/;
const GLOBAL_RE = /\b(?:process|__dirname|__filename|global|Buffer)\b/;
const FS_RE = /\breadFileSync\b/;
const SW_RE = /\bnavigator\s*\.\s*serviceWorker\s*\.\s*register\s*\(/;

class JSAsset extends Asset {
constructor(name, pkg, options) {
Expand All @@ -30,7 +31,8 @@ class JSAsset extends Asset {
return (
!/.js$/.test(this.name) ||
IMPORT_RE.test(this.contents) ||
GLOBAL_RE.test(this.contents)
GLOBAL_RE.test(this.contents) ||
SW_RE.test(this.contents)
);
}

Expand Down
20 changes: 20 additions & 0 deletions src/visitors/dependencies.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const types = require('babel-types');
const template = require('babel-template');
const urlJoin = require('../utils/urlJoin');
const isURL = require('../utils/is-url');
const matchesPattern = require('./matches-pattern');

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

module.exports = {
ImportDeclaration(node, asset) {
Expand Down Expand Up @@ -37,6 +41,7 @@ module.exports = {

if (isRequire) {
addDependency(asset, args[0]);
return;
}

let isDynamicImport =
Expand All @@ -51,6 +56,21 @@ module.exports = {
node.callee = requireTemplate().expression;
node.arguments[0] = argTemplate({MODULE: args[0]}).expression;
asset.isAstDirty = true;
return;
}

const isRegisterServiceWorker =
types.isStringLiteral(args[0]) &&
matchesPattern(callee, serviceWorkerPattern);

if (isRegisterServiceWorker) {
let assetPath = asset.addURLDependency(args[0].value);
if (!isURL(assetPath)) {
assetPath = urlJoin(asset.options.publicURL, assetPath);
}
args[0].value = assetPath;
asset.isAstDirty = true;
return;
}
}
};
Expand Down
42 changes: 1 addition & 41 deletions src/visitors/globals.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const Path = require('path');
const types = require('babel-types');
const matchesPattern = require('./matches-pattern');

const VARS = {
process: asset => {
Expand Down Expand Up @@ -62,47 +63,6 @@ function inScope(ancestors) {
return false;
}

// from babel-types. remove when we upgrade to babel 7.
// https://github.com/babel/babel/blob/0189b387026c35472dccf45d14d58312d249f799/packages/babel-types/src/index.js#L347
function matchesPattern(member, match) {
// not a member expression
if (!types.isMemberExpression(member)) {
return false;
}

const parts = Array.isArray(match) ? match : match.split('.');
const nodes = [];

let node;
for (node = member; types.isMemberExpression(node); node = node.object) {
nodes.push(node.property);
}

nodes.push(node);

if (nodes.length !== parts.length) {
return false;
}

for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
const node = nodes[j];
let value;
if (types.isIdentifier(node)) {
value = node.name;
} else if (types.isStringLiteral(node)) {
value = node.value;
} else {
return false;
}

if (parts[i] !== value) {
return false;
}
}

return true;
}

// replace object properties
function morph(object, newProperties) {
for (let key in object) {
Expand Down
36 changes: 36 additions & 0 deletions src/visitors/matches-pattern.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const types = require('babel-types');

// from babel-types. remove when we upgrade to babel 7.
// https://github.com/babel/babel/blob/0189b387026c35472dccf45d14d58312d249f799/packages/babel-types/src/index.js#L347
module.exports = function matchesPattern(member, match, allowPartial) {
// not a member expression
if (!types.isMemberExpression(member)) return false;

const parts = Array.isArray(match) ? match : match.split('.');
const nodes = [];

let node;
for (node = member; types.isMemberExpression(node); node = node.object) {
nodes.push(node.property);
}
nodes.push(node);

if (nodes.length < parts.length) return false;
if (!allowPartial && nodes.length > parts.length) return false;

for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
const node = nodes[j];
let value;
if (types.isIdentifier(node)) {
value = node.name;
} else if (types.isStringLiteral(node)) {
value = node.value;
} else {
return false;
}

if (parts[i] !== value) return false;
}

return true;
};
1 change: 1 addition & 0 deletions test/integration/service-worker/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
navigator.serviceWorker.register('worker.js', { scope: './' });
1 change: 1 addition & 0 deletions test/integration/service-worker/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
self.addEventListener('message', () => {});
15 changes: 15 additions & 0 deletions test/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ describe('javascript', function() {
assert.equal(await output(), 3);
});

it('should support bundling service workers', async function() {
let b = await bundle(__dirname + '/integration/service-worker/index.js');

assertBundleTree(b, {
name: 'index.js',
assets: ['index.js'],
childBundles: [
{
assets: ['worker.js'],
childBundles: []
}
]
});
});

it('should dynamic import files which import raw files', async function() {
let b = await bundle(
__dirname + '/integration/dynamic-references-raw/index.js'
Expand Down

0 comments on commit 0ab0aca

Please sign in to comment.