mirror of
https://github.com/systemjs/systemjs.git
synced 2026-01-18 14:53:14 +00:00
new normalization algorithm
This commit is contained in:
parent
a93a085d47
commit
a1f57f79bf
7
Makefile
7
Makefile
@ -59,7 +59,7 @@ dist/system.src.js: lib/*.js $(ESML)/*.js
|
||||
$(ESML)/transpiler.js \
|
||||
lib/global-eval.js \
|
||||
lib/core.js \
|
||||
lib/config.js \
|
||||
lib/misc.js \
|
||||
lib/scriptLoader.js \
|
||||
lib/meta.js \
|
||||
lib/register.js \
|
||||
@ -90,7 +90,7 @@ dist/system-prod.src.js: lib/*.js $(ESML)/*.js
|
||||
$(ESML)/dynamic-only.js \
|
||||
$(ESML)/system.js \
|
||||
lib/core.js \
|
||||
lib/config.js \
|
||||
lib/misc.js \
|
||||
lib/scriptLoader.js \
|
||||
lib/meta.js \
|
||||
lib/scriptOnly.js \
|
||||
@ -115,9 +115,6 @@ dist/system-register-only.src.js: lib/*.js $(ESML)/*.js
|
||||
$(ESML)/loader.js \
|
||||
$(ESML)/dynamic-only.js \
|
||||
$(ESML)/system.js \
|
||||
lib/core.js \
|
||||
lib/scriptLoader.js \
|
||||
lib/scriptOnly.js \
|
||||
lib/register.js \
|
||||
lib/createSystem.js \
|
||||
$(ESML)/wrapper-end.js \
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Config
|
||||
*/
|
||||
(function() {
|
||||
/*
|
||||
Extend config merging one deep only
|
||||
|
||||
loader.config({
|
||||
some: 'random',
|
||||
config: 'here',
|
||||
deep: {
|
||||
config: { too: 'too' }
|
||||
}
|
||||
});
|
||||
|
||||
<=>
|
||||
|
||||
loader.some = 'random';
|
||||
loader.config = 'here'
|
||||
loader.deep = loader.deep || {};
|
||||
loader.deep.config = { too: 'too' };
|
||||
*/
|
||||
SystemLoader.prototype.config = function(cfg) {
|
||||
for (var c in cfg) {
|
||||
var v = cfg[c];
|
||||
if (typeof v == 'object' && !(v instanceof Array)) {
|
||||
this[c] = this[c] || {};
|
||||
for (var p in v)
|
||||
this[c][p] = v[p];
|
||||
}
|
||||
else
|
||||
this[c] = v;
|
||||
}
|
||||
};
|
||||
|
||||
var baseURL;
|
||||
hookConstructor(function(constructor) {
|
||||
return function() {
|
||||
var loader = this;
|
||||
constructor.call(loader);
|
||||
baseURL = loader.baseURL;
|
||||
|
||||
// support the empty module, as a concept
|
||||
loader.set('@empty', loader.newModule({}));
|
||||
};
|
||||
});
|
||||
|
||||
// allow baseURL to be a relative URL
|
||||
var normalizedBaseURL;
|
||||
hook('locate', function(locate) {
|
||||
return function(load) {
|
||||
if (this.baseURL != normalizedBaseURL) {
|
||||
normalizedBaseURL = new URL(this.baseURL, baseURL).href;
|
||||
|
||||
if (normalizedBaseURL.substr(normalizedBaseURL.length - 1, 1) != '/')
|
||||
normalizedBaseURL += '/';
|
||||
this.baseURL = normalizedBaseURL;
|
||||
}
|
||||
|
||||
return Promise.resolve(locate.call(this, load));
|
||||
};
|
||||
});
|
||||
})();
|
||||
24
lib/core.js
24
lib/core.js
@ -26,26 +26,4 @@ function dedupe(deps) {
|
||||
if (indexOf.call(newDeps, deps[i]) == -1)
|
||||
newDeps.push(deps[i])
|
||||
return newDeps;
|
||||
}
|
||||
|
||||
/*
|
||||
__useDefault
|
||||
|
||||
When a module object looks like:
|
||||
newModule(
|
||||
__useDefault: true,
|
||||
default: 'some-module'
|
||||
})
|
||||
|
||||
Then importing that module provides the 'some-module'
|
||||
result directly instead of the full module.
|
||||
|
||||
Useful for eg module.exports = function() {}
|
||||
*/
|
||||
hook('import', function(systemImport) {
|
||||
return function(name, parentName) {
|
||||
return systemImport.call(this, name, parentName).then(function(module) {
|
||||
return module.__useDefault ? module['default'] : module;
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
32
lib/map.js
32
lib/map.js
@ -19,29 +19,33 @@ hookConstructor(function(constructor) {
|
||||
};
|
||||
});
|
||||
|
||||
var baseURLCache = {};
|
||||
|
||||
hook('normalize', function(normalize) {
|
||||
return function(name, parentName, parentAddress) {
|
||||
var loader = this;
|
||||
return Promise.resolve(normalize.call(loader, name, parentName, parentAddress))
|
||||
.then(function(name) {
|
||||
var bestMatch, bestMatchLength = 0;
|
||||
if (name.substr(0, 1) != '.' && name.substr(0, 1) != '/' && !name.match(absURLRegEx)) {
|
||||
var bestMatch, bestMatchLength = 0;
|
||||
|
||||
// now do the global map
|
||||
for (var p in loader.map) {
|
||||
if (typeof loader.map[p] != 'string')
|
||||
throw new TypeError('Map configuration no longer permits object submaps. Use package map instead (`System.packages[name].map`).');
|
||||
// now do the global map
|
||||
for (var p in loader.map) {
|
||||
if (typeof loader.map[p] != 'string')
|
||||
throw new TypeError('Map configuration no longer permits object submaps. Use package map instead (`System.packages[name].map`).');
|
||||
|
||||
if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) {
|
||||
var curMatchLength = p.split('/').length;
|
||||
if (curMatchLength <= bestMatchLength)
|
||||
continue;
|
||||
bestMatch = p;
|
||||
bestMatchLength = curMatchLength;
|
||||
if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) {
|
||||
var curMatchLength = p.split('/').length;
|
||||
if (curMatchLength <= bestMatchLength)
|
||||
continue;
|
||||
bestMatch = p;
|
||||
bestMatchLength = curMatchLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatch)
|
||||
return loader.map[bestMatch] + name.substr(bestMatch.length);
|
||||
if (bestMatch)
|
||||
return loader.map[bestMatch] + name.substr(bestMatch.length);
|
||||
}
|
||||
|
||||
return name;
|
||||
});
|
||||
|
||||
183
lib/misc.js
Normal file
183
lib/misc.js
Normal file
@ -0,0 +1,183 @@
|
||||
var absURLRegEx = /^[^\/]+:\/\//;
|
||||
|
||||
(function() {
|
||||
|
||||
var baseURI;
|
||||
|
||||
hookConstructor(function(constructor) {
|
||||
return function() {
|
||||
constructor.call(this);
|
||||
|
||||
// by default ModuleLoader sets this.baseURL to baseURI
|
||||
baseURI = this.baseURL;
|
||||
|
||||
// support the empty module, as a concept
|
||||
this.set('@empty', this.newModule({}));
|
||||
};
|
||||
});
|
||||
|
||||
// caches baseURL URL object
|
||||
// also allows baseURL to be relative to the baseURI
|
||||
function getAbsBaseURL(baseURL) {
|
||||
return baseURLCache[baseURL] = baseURLCache[baseURL] || new URL(baseURL + (baseURL[baseURL.length - 1] != '/' ? '/' : ''), baseURI);
|
||||
}
|
||||
|
||||
/*
|
||||
Normalization
|
||||
|
||||
Dot-Normalization is applied for relative module names, when the parent name
|
||||
is not a URL itself.
|
||||
../, ./ are resolved relative to plain path parentNames
|
||||
where "plain paths" are defined as not beginning with protocol://, /, ./
|
||||
Inner ../ or ./ are not supported
|
||||
Names that dot below the parent name skip to use URL normalization
|
||||
|
||||
The goal is for normalize to normalize all names into a space containing a union
|
||||
of "plain paths", and absolute URLs.
|
||||
|
||||
Plain paths will then either be packages or paths in locate
|
||||
or they will be baseURL-relative in locate
|
||||
|
||||
Absolute paths corresponding to paths within baseURL are converted
|
||||
back into plain paths to ensure a unique representation in this space.
|
||||
|
||||
In SystemJS we assume and define normalize to never output a module
|
||||
name not an absolute URL or plain path.
|
||||
*/
|
||||
hook('normalize', function() {
|
||||
return function(name, parentName, parentAddress) {
|
||||
// percent encode just '#' in module names
|
||||
// according to https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js#L238
|
||||
// we should encode everything, but it breaks for servers that don't expect it
|
||||
// like in (https://github.com/systemjs/systemjs/issues/168)
|
||||
if (isBrowser)
|
||||
name = name.replace(/#/g, '%23');
|
||||
|
||||
// Relative Normalization
|
||||
if (name[0] == '.' && parentName) {
|
||||
// if parent is a URL, apply URL normalization
|
||||
if (parentName.match(absURLRegEx))
|
||||
return new URL(name, parentName).href;
|
||||
|
||||
// Dot Normalization
|
||||
|
||||
// skip leading ./
|
||||
var parts = name.split('/');
|
||||
var i = 0;
|
||||
var dotdots = 0;
|
||||
while (parts[i] == '.') {
|
||||
i++;
|
||||
if (i == parts.length)
|
||||
throw new TypeError('Invalid module name');
|
||||
}
|
||||
|
||||
// count dot dots
|
||||
while (parts[i] == '..') {
|
||||
i++;
|
||||
dotdots++;
|
||||
if (i == parts.length)
|
||||
throw new TypeError('Invalid module name');
|
||||
}
|
||||
|
||||
var parentParts = parentName.split('/');
|
||||
|
||||
parts = parts.splice(i, parts.length - i);
|
||||
|
||||
// if backtracking below the parent name, just set to the base-level like URLs
|
||||
// NB if parentAddress is supported in the spec, we can URL normalize against it here instead
|
||||
if (dotdots <= parentParts.length)
|
||||
parts = parentParts.splice(0, parentParts.length - dotdots - 1).concat(parts);
|
||||
|
||||
name = parts.join('/');
|
||||
}
|
||||
|
||||
// if url-relative, normalize to baseURL
|
||||
// if within baseURL, convert into corresponding plain path
|
||||
if (name[0] == '.' || name[0] == '/') {
|
||||
var baseURL = getAbsBaseURL(this.baseURL);
|
||||
var normalizedURL = new URL(name, baseURL);
|
||||
if (normalizedURL.origin == baseURL.origin && normalizedURL.pathname.substr(0, baseURL.pathname.length) == baseURL.pathname)
|
||||
name = normalizedURL.pathname.substr(baseURL.pathname.length);
|
||||
else
|
||||
name = normalizedURL.href;
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
Locate
|
||||
|
||||
Any plain names from normalize are normalized into absolute URLs
|
||||
First they are checked against paths
|
||||
Paths is moved from normalize in the module spec to locate in the System spec
|
||||
This isn't inconsistent because the module spec normalizes everything to absolute URLs,
|
||||
while the System spec defines its own intermediate union of URLs and plain paths
|
||||
*/
|
||||
hook('locate', function() {
|
||||
return function(load) {
|
||||
if (load.name.match(absURLRegEx))
|
||||
return load.name;
|
||||
|
||||
name = applyPaths(this, load.name);
|
||||
|
||||
return new URL(name, getAbsBaseURL(this.baseURL)).href;
|
||||
};
|
||||
});
|
||||
|
||||
/*
|
||||
__useDefault
|
||||
|
||||
When a module object looks like:
|
||||
newModule(
|
||||
__useDefault: true,
|
||||
default: 'some-module'
|
||||
})
|
||||
|
||||
Then importing that module provides the 'some-module'
|
||||
result directly instead of the full module.
|
||||
|
||||
Useful for eg module.exports = function() {}
|
||||
*/
|
||||
hook('import', function(systemImport) {
|
||||
return function(name, parentName, parentAddress) {
|
||||
return systemImport.call(this, name, parentName, parentAddress).then(function(module) {
|
||||
return module.__useDefault ? module['default'] : module;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/*
|
||||
Extend config merging one deep only
|
||||
|
||||
loader.config({
|
||||
some: 'random',
|
||||
config: 'here',
|
||||
deep: {
|
||||
config: { too: 'too' }
|
||||
}
|
||||
});
|
||||
|
||||
<=>
|
||||
|
||||
loader.some = 'random';
|
||||
loader.config = 'here'
|
||||
loader.deep = loader.deep || {};
|
||||
loader.deep.config = { too: 'too' };
|
||||
*/
|
||||
SystemLoader.prototype.config = function(cfg) {
|
||||
for (var c in cfg) {
|
||||
var v = cfg[c];
|
||||
if (typeof v == 'object' && !(v instanceof Array)) {
|
||||
this[c] = this[c] || {};
|
||||
for (var p in v)
|
||||
this[c][p] = v[p];
|
||||
}
|
||||
else
|
||||
this[c] = v;
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user