wallet-core/thirdparty/systemjs/lib/meta.js

156 lines
4.6 KiB
JavaScript

/*
* Meta Extension
*
* Sets default metadata on a load record (load.metadata) from
* loader.metadata via SystemJS.meta function.
*
*
* Also provides an inline meta syntax for module meta in source.
*
* Eg:
*
* loader.meta({
* 'my/module': { deps: ['jquery'] }
* 'my/*': { format: 'amd' }
* });
*
* Which in turn populates loader.metadata.
*
* load.metadata.deps and load.metadata.format will then be set
* for 'my/module'
*
* The same meta could be set with a my/module.js file containing:
*
* my/module.js
* "format amd";
* "deps[] jquery";
* "globals.some value"
* console.log('this is my/module');
*
* Configuration meta always takes preference to inline meta.
*
* Multiple matches in wildcards are supported and ammend the meta.
*
*
* The benefits of the function form is that paths are URL-normalized
* supporting say
*
* loader.meta({ './app': { format: 'cjs' } });
*
* Instead of needing to set against the absolute URL (https://site.com/app.js)
*
*/
(function() {
hookConstructor(function(constructor) {
return function() {
this.meta = {};
constructor.call(this);
};
});
hook('locate', function(locate) {
return function(load) {
var meta = this.meta;
var name = load.name;
// NB for perf, maybe introduce a fast-path wildcard lookup cache here
// which is checked first
// apply wildcard metas
var bestDepth = 0;
var wildcardIndex;
for (var module in meta) {
wildcardIndex = module.indexOf('*');
if (wildcardIndex === -1)
continue;
if (module.substr(0, wildcardIndex) === name.substr(0, wildcardIndex)
&& module.substr(wildcardIndex + 1) === name.substr(name.length - module.length + wildcardIndex + 1)) {
var depth = module.split('/').length;
if (depth > bestDepth)
bestDepth = depth;
extendMeta(load.metadata, meta[module], bestDepth != depth);
}
}
// apply exact meta
if (meta[name])
extendMeta(load.metadata, meta[name]);
return locate.call(this, load);
};
});
// detect any meta header syntax
// only set if not already set
var metaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/;
var metaPartRegEx = /\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g;
function setMetaProperty(target, p, value) {
var pParts = p.split('.');
var curPart;
while (pParts.length > 1) {
curPart = pParts.shift();
target = target[curPart] = target[curPart] || {};
}
curPart = pParts.shift();
if (!(curPart in target))
target[curPart] = value;
}
hook('translate', function(translate) {
return function(load) {
// shortpath for bundled
if (load.metadata.format == 'defined') {
load.metadata.deps = load.metadata.deps || [];
return Promise.resolve(load.source);
}
// NB meta will be post-translate pending transpiler conversion to plugins
var meta = load.source.match(metaRegEx);
if (meta) {
var metaParts = meta[0].match(metaPartRegEx);
for (var i = 0; i < metaParts.length; i++) {
var curPart = metaParts[i];
var len = curPart.length;
var firstChar = curPart.substr(0, 1);
if (curPart.substr(len - 1, 1) == ';')
len--;
if (firstChar != '"' && firstChar != "'")
continue;
var metaString = curPart.substr(1, curPart.length - 3);
var metaName = metaString.substr(0, metaString.indexOf(' '));
if (metaName) {
var metaValue = metaString.substr(metaName.length + 1, metaString.length - metaName.length - 1);
if (metaName.substr(metaName.length - 2, 2) == '[]') {
metaName = metaName.substr(0, metaName.length - 2);
load.metadata[metaName] = load.metadata[metaName] || [];
load.metadata[metaName].push(metaValue);
}
else if (load.metadata[metaName] instanceof Array) {
// temporary backwards compat for previous "deps" syntax
warn.call(this, 'Module ' + load.name + ' contains deprecated "deps ' + metaValue + '" meta syntax.\nThis should be updated to "deps[] ' + metaValue + '" for pushing to array meta.');
load.metadata[metaName].push(metaValue);
}
else {
setMetaProperty(load.metadata, metaName, metaValue);
}
}
else {
load.metadata[metaString] = true;
}
}
}
return translate.apply(this, arguments);
};
});
})();