Skip to content

Instantly share code, notes, and snippets.

@SMotaal
Created June 8, 2018 00:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SMotaal/a8880ff65e366ef1c446614ac57408cc to your computer and use it in GitHub Desktop.
Save SMotaal/a8880ff65e366ef1c446614ac57408cc to your computer and use it in GitHub Desktop.
JS Bin
* {
font-family: sans-serif;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script>
console.clear();
</script>
</head>
<body>
</body>
</html>
/*
This is a very basic isomorphic Loader
which works by rewriting the specifiers
for static imports and exports.
*/
(function (helpers) {
const {
runtime: { global, DynamicImport, RegisterModule },
performance: { START, END, ENTRIES },
symbols: { StateSymbol, MethodSymbol, RecordSymbol }
} = helpers;
console.log(helpers);
/**
* Global Modules Namespace
*/
const Modules = global.Modules = {
// Methods
Define: MethodSymbol('define'),
Resolve: MethodSymbol('resolve'),
Load: MethodSymbol('load'),
Import: MethodSymbol('import'),
// Status
Uninstantiated: StateSymbol('uninstantiated'),
Instantiating: StateSymbol('instantiating'),
Instantiated: StateSymbol('instantiated'),
Evaluating: StateSymbol('evaluating'),
Evaluated: StateSymbol('evaluated'),
// Records
Status: RecordSymbol('Status'),
EvaluationError: RecordSymbol('EvaluationError'),
};
/**
* ModuleSources
*/
const ModuleSources = global['[[ModuleSources]]'] = {
// 'xyz': `export default 'xyz'`,
};
(() => {
const {
// Methods
Resolve, Import, Load, Define,
// Status
Evaluated, Evaluating, Instantiated, Instantiating, Uninstantiated,
// Records
Status, EvaluationError
} = Modules;
const ModuleLoader = global['[[ModuleLoader]]'] = {
[Resolve]: (specifier, referrer) => {
},
[Load]: (sourceURL) => {
if (sourceURL in ModuleMap)
return ModuleMap[sourceURL];
if (sourceURL in ModuleSources)
return ModuleMap[Define](ModuleSources[sourceURL], sourceURL);
throw `Failed to load module from "${sourceURL}"`;
},
[Import]: (specifier, referrer) => {
return ModuleLoader[Load](specifier).namespace();
}
};
const ModuleMap = global['[[ModuleMap]]'] = {
[Define]: (source, sourceURL = SRC()) => {
START('[1] define', sourceURL);
const links = [];
let k = 0;
START('[2] prelink', sourceURL);
const rawSource = source
// Replace ModuleDeclarations with ««—k—type———…»»
.replace(
/((?:import +(?:\* +as \w+|(?:\w+, *)?\{[^}]*?\}|\w+)|export +(?:\*|\{[^}]*?\})) +from +(['"]))(.*?)(\2)/ug,
(declaration, head, quote, specifier, tail, index) => {
const length = declaration.length;
const type = declaration[0] === 'i' ? 'import' : 'export';
const marker = `${`««—${k++}—${type}—`.padEnd(length - 2, '—')}»»`;
links.push({
declaration, type, head, quote, specifier, tail, marker, index, length
});
return marker;
}
);
END('[2] prelink', sourceURL);
const module = {
links, source, rawSource, sourceURL,
[Status]: Uninstantiated,
async link() {
const module = this;
const sourceURL = module.sourceURL;
if (module.url) return module.url;
START('[3] link', sourceURL);
let linkedSource = module.rawSource;
module[Status] = Instantiating;
for (const { marker, specifier: originalSpecifier, head, tail } of links) {
const requiredModule = ModuleMap[originalSpecifier];
const specifier = requiredModule && (
requiredModule.url
|| (await requiredModule.link())
) || (
await (await ModuleLoader[Load](originalSpecifier)).link()
) || originalSpecifier;
const declaration = `${head}${specifier}${tail}`
linkedSource = linkedSource.replace(marker, declaration);
}
module.linkedSource = linkedSource;
const url = module.url = RegisterModule(linkedSource, sourceURL);
ModuleMap[sourceURL] = ModuleMap[url] = module;
END('[3] link', sourceURL);
return url;
},
async evaluate() {
const module = this;
const sourceURL = module.sourceURL;
// if (module[Status] !== Uninstantiated)
// throw EvalError('Failed to link module with invalid status');
// Link
const url = await this.link();
// Instantiate
START('[4] evaluate', sourceURL);
const instantiate = DynamicImport(url);
module[Status] = Instantiated;
// Evaluate
await 0;
module[Status] = Evaluating;
module.namespace = async () => await instantiate;
try {
await instantiate;
} catch (exception) {
module[EvaluationError] = exception;
} finally {
module[Status] = Evaluated;
}
END('[4] evaluate', sourceURL);
return ModuleMap[sourceURL] = ModuleMap[url] = module;
},
async namespace() {
return (await this.evaluate()).namespace();
},
};
END('[1] define', sourceURL);
return ModuleMap[sourceURL] = module;
},
}
return ModuleSources;
})();
(async (sources = {
'typescript': `
export const typescript = true;
export default "TypeScript"
`,
'ts1': `
export * from 'typescript'
`,
'index': `
import ts from 'typescript';
// import ts, {a, b, c} from 'typescript';
export * from 'typescript';
export const index = true;
export { ts };
`,
'fails': `
import x from 'xyz';
`
}) => {
const ModuleLoader = global['[[ModuleLoader]]'];
Object.assign(ModuleSources, sources);
const results = {}, namespaces = {};
const specifiers = Object.keys(sources); // .reverse();
// for (const specifier of [...specifiers, ...specifiers]) {
for (const specifier of specifiers) {
try {
results[specifier] = await ModuleLoader[Modules.Load](specifier);
namespaces[specifier] = await ModuleLoader[Modules.Import](specifier);
} catch (exception) {
results[specifier] = exception;
}
}
console.dir(results);
console.dir(ENTRIES.reduce(
(timing, { name, duration }) => (timing[name] = duration, timing), {}
));
console.dir(namespaces);
})();
console.log(global['[[ModuleMap]]'])
console.log(global['[[ModuleSources]]']);
})({
runtime: RuntimeHelpers(),
performance: PerformanceHelpers(),
symbols: SymbolHelpers(),
});
function RuntimeHelpers() {
const
JS = 'text/javascript',
UID = () => ~~(1e6 * Math.random()),
SRC = (uid = UID()) =>
`VirtualModule-${uid}`,
SourceText = (source, url = SRC()) =>
`${source}\n\n//# sourceURL=${url}\n`;
if (typeof process === 'undefined' && typeof window !== 'undefined') {
let importModule = async (url) => eval(`import("${url}")`);
importModule(`data:text/javascript,export default ''`)
.catch(() => {
/**
* Can't find my experiment for that one so thanks to uupaa et al
*
* @source https://github.com/uupaa/dynamic-import-polyfill/blob/dda7fd22eaceb6e9642dc3189fadc89db405f9b5/importModule.js#L7
*/
importModule = (url) => new Promise((resolve, reject) => {
const vector = "$importModule$" + Math.random().toString(32).slice(2);
const script = document.createElement("script");
const destructor = () => {
delete window[vector];
script.onerror = null;
script.onload = null;
script.remove();
URL.revokeObjectURL(script.src);
script.src = "";
};
script.defer = "defer";
script.type = "module";
script.onerror = () => {
reject(new Error(`Failed to import: ${url}`));
destructor();
};
script.onload = () => {
resolve(window[vector]);
destructor();
};
const absURL = url; // toAbsoluteURL(url);
const loader = `import * as m from "${absURL}"; window.${vector} = m;`; // export Module
const blob = new Blob([loader], { type: "text/javascript" });
script.src = URL.createObjectURL(blob);
document.head.appendChild(script);
});
});
const
SourceFile = (source, url = SRC(), type = JS) =>
new File([SourceText(source, url)], url, { type }),
SourceFileURL = (source, url = SRC(), type = JS) =>
URL.createObjectURL(SourceFile(source, url, type)),
RegisterModule = (source, sourceURL) =>
SourceFileURL(SourceText(source, sourceURL)),
DynamicImport = (url) => importModule(url);
return { global: window, RegisterModule, DynamicImport };
}
if (typeof process === 'undefined')
throw Error('Unsupported runtime');
const ModuleWrap = ((natives) => {
const requireNative = process.NativeModule
? process.NativeModule.require
: require || require('');
if (natives.includes('internal/loader/ModuleWrap'))
return requireNative('internal/loader/ModuleWrap').ModuleWrap;
if (natives.includes('internal/modules/esm/create_dynamic_module'))
return requireNative('internal/modules/esm/create_dynamic_module')
('').module.constructor;
})(Object.keys(process.binding('natives')));
const
ModuleMap = {},
LinkModule = async (module) => {
const wrap = module.wrap;
const links = module.links = [];
await wrap.link(async (dependencySpecifier) => {
const module = ModuleMap[dependencySpecifier];
if (!module)
throw ReferenceError(`Failed to link module: "${url}"`);
links.push(module);
return module.wrap;
});
return Promise.all(links);
},
RegisterModule = (source, sourceURL) => {
const url = sourceURL; // `vm:${UID()}`;
if (url in ModuleMap)
return RegisterModule(source, sourceURL);
const module = ModuleMap[url] = {
wrap: new ModuleWrap(SourceText(source, sourceURL), url),
}
console.log(`Constructed: ${module.wrap.url}`);
module.linked = LinkModule(module);
return url;
},
InitializeModule = async (module) => {
const wrap = module.wrap;
await module.linked;
console.log(`Linked: ${module.wrap.url}`);
const links = module.links || [];
// TODO: Instantiate ModuleWrap for Node
await (module.instantiated || (
module.instantiated = await Promise.all([
...links.map(InitializeModule),
]).then(() => wrap.instantiate())
));
console.log(`Instantiated: ${module.wrap.url}`, Object.keys(wrap));
await (module.evaluated || (
module.evaluated = wrap.evaluate(-1, false)
));
console.log(`Evaluated: ${module.wrap.url}`);
const namespace = await (module.namespace || (
module.namespace = await wrap.namespace()
));
console.log(`Imported: ${module.wrap.url}`, namespace);
return namespace;
},
DynamicImport = async (url) => {
const module = ModuleMap[url];
if (!module)
throw ReferenceError(`Failed to load module: "${url}"`);
console.log(`Import: ${module.wrap.url}`);
return InitializeModule(module);
}
return { global, RegisterModule, DynamicImport }
}
function PerformanceHelpers() {
const performanceEntries = [];
if (typeof performance !== 'undefined') {
if (typeof PerformanceObserver !== 'undefined') {
const performanceObserver = new PerformanceObserver((list, observer) => {
const entries = list.getEntries();
performanceEntries.push(...entries);
// console.info(entries);
});
performanceObserver.observe({ entryTypes: ['measure'] });
}
return {
START: (OP, ID) => performance.mark(`START: «${ID}» — ${OP}`),
END: (OP, ID) => performance.measure(
`«${ID}» — ${OP}`, `START: «${ID}» — ${OP}`,
performance.mark(`END: «${ID}» — ${OP}`)
),
ENTRIES: performanceEntries,
};
}
const noop = () => { };
return {
START: noop, END: noop, ENTRIES: performanceEntries,
}
}
function SymbolHelpers(
StateSymbol = (state) => `"${state.toUpperCase()}"`,
MethodSymbol = (name) => `@@${name.replace(/^[A-Z]+/, s => s.toLowerCase())}`,
RecordSymbol = (name) => `[[${name}]]`
) {
return {
StateSymbol, MethodSymbol, RecordSymbol
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment