Skip to content

Commit

Permalink
Support for relative dependencies for define().
Browse files Browse the repository at this point in the history
Note that this implementation is a little naive; it completely ignores
the id given to define, and always assumes that URLs will be relative
to the script's document. That will not work for vulcanized bundles.
Separate PR for that.
  • Loading branch information
Ian MacLeod committed Feb 26, 2015
1 parent a387f75 commit 7464430
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 10 deletions.
53 changes: 44 additions & 9 deletions src/lib/module.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,21 @@
dependencies = Array.isArray(id) ? id : [];
}

var inferredId = _inferModuleId();
if (typeof id !== 'string') {
id = _inferModuleId();
id = inferredId;
}
if (id.indexOf('\\') !== -1) {
throw new TypeError('Please use / as module path delimiters');
}

if (id in _modules) {
throw new Error('The module "' + id + '" has already been defined');
}

_modules[id] = _withDependencies(dependencies, factory);
// TODO(nevir): This is naive; doesn't support the vulcanize case.
var base = inferredId.match(/^(.*?)[^\/]*$/)[1];
_modules[id] = _withDependencies(base, dependencies, factory);
return _modules[id];
}
// Semi-private. We expose this for tests & introspection.
Expand All @@ -66,23 +72,25 @@

// Utility

// TODO(nevir): Temporary for anonymous module ids until we determine them via
// current script URL.
var _anonymousModuleCount = 0;

/** @return {string} A module id inferred from the current document/import. */
function _inferModuleId() {
return '__anonymous_' + _anonymousModuleCount++ + '__';
var doc = document.currentScript && document.currentScript.ownerDocument || document;
if (!doc.baseURI) {
throw new Error('Unable to determine a module id: No baseURI for the document');
}
return doc.baseURI;
}

/**
* Calls `factory` with the exported values of `dependencies`.
*
* @param {string} base
* @param {Array<string>} dependencies
* @param {function(...*)} factory
*/
function _withDependencies(dependencies, factory) {
function _withDependencies(base, dependencies, factory) {
var modules = dependencies.map(function(id) {
id = _resolveRelativeId(base, id);
if (!(id in _modules)) {
throw new ReferenceError('The module "' + id + '" has not been loaded');
}
Expand All @@ -91,6 +99,34 @@
return factory.apply(null, modules);
}

/**
* @param {string} base The module path/URI that acts as the relative base.
* @param {string} id The module ID that should be relatively resolved.
* @return {string} The expanded module ID.
*/
function _resolveRelativeId(base, id) {
if (id[0] !== '.') return id;
// We need to be careful to only process the path of URLs.
var match = base.match(/^([^\/]*\/\/[^\/]+\/)?(.*?)\/?$/);
var prefix = match[1] || '';
// We start with the base, and then mutate it into the final path.
var terms = match[2] ? match[2].split('/') : [];
var idTerms = id.match(/^\/?(.*?)\/?$/)[1].split('/');

for (var i = 0; i < idTerms.length; i++) {
var idTerm = idTerms[i];
if (idTerm === '.') {
continue;
} else if (idTerm === '..') {
terms.pop();
} else {
terms.push(idTerm);
}
}

return prefix + terms.join('/');
}

// Exports

scope.define = define;
Expand All @@ -111,6 +147,5 @@
define(dependencies, factory);
};


})(this);
</script>
19 changes: 19 additions & 0 deletions test/assets/modules/one.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../../../src/lib/module.html">

<script>

define(function() {
return 'module 1';
});

</script>
19 changes: 19 additions & 0 deletions test/assets/modules/sub/three.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../../../../src/lib/module.html">

<script>

define(function() {
return 'module 3';
});

</script>
25 changes: 25 additions & 0 deletions test/assets/modules/two.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../../../src/lib/module.html">
<link rel="import" href="one.html">
<link rel="import" href="sub/three.html">

<script>

define(['./one.html', './sub/three.html'], function(one, three) {
return {
one: one,
me: 'module 2',
three: three,
};
});

</script>
28 changes: 27 additions & 1 deletion test/unit/module.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../src/lib/module.html">
<link rel="import" href="../assets/modules/one.html">
<link rel="import" href="../assets/modules/two.html">
</head>
<body>

Expand All @@ -22,7 +24,11 @@
suite('define()', function() {

beforeEach(function() {
for (var key in define._modules) { delete define._modules[key]; };
for (var key in define._modules) {
if (/\/assets\/modules\//.test(key)) continue;
delete define._modules[key];
}

define('a', function() { return 'module A'; });
define('b', function() { return 'module B'; });
});
Expand Down Expand Up @@ -86,6 +92,26 @@
}, Error, /"a".*defined/i);
});

suite('relative dependencies', function() {

test('loads modules relative to the current', function(done) {
define(['../assets/modules/one.html'], function(one) {
assert.equal(one, 'module 1');
done();
});
});

test('loads relative modules transitively', function(done) {
define(['../assets/modules/two.html'], function(two) {
assert.equal(two.one, 'module 1');
assert.equal(two.me, 'module 2');
assert.equal(two.three, 'module 3');
done();
});
});

});

});

</script>
Expand Down

0 comments on commit 7464430

Please sign in to comment.