File size: 4,973 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
'use strict';
const $dedent = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('codedent'));
const { unescape: $unescape } = require('html-escaper');
const { io } = require('./interpreter/_io.js');
/** @type {(tpl: string | TemplateStringsArray, ...values:any[]) => string} */
const dedent = $dedent;
/** @type {(value:string) => string} */
const unescape = $unescape;
const { isArray } = Array;
const { assign, create, defineProperties, defineProperty, entries } = Object;
const { all, resolve } = new Proxy(Promise, {
get: ($, name) => $[name].bind($),
});
const absoluteURL = (path, base = location.href) =>
new URL(path, base.replace(/^blob:/, '')).href;
/* c8 ignore start */
let id = 0;
const nodeInfo = (node, type) => ({
id: node.id || (node.id = `${type}-w${id++}`),
tag: node.tagName
});
/**
* Notify the main thread about element "readiness".
* @param {HTMLScriptElement | HTMLElement} target the script or custom-type element
* @param {string} type the custom/type as event prefix
* @param {string} what the kind of event to dispatch, i.e. `ready` or `done`
* @param {boolean} [worker = false] `true` if dispatched form a worker, `false` by default if in main
* @param {globalThis.CustomEvent} [CustomEvent = globalThis.CustomEvent] the `CustomEvent` to use
*/
const dispatch = (target, type, what, worker = false, CE = CustomEvent) => {
target.dispatchEvent(
new CE(`${type}:${what}`, {
bubbles: true,
detail: { worker },
})
);
};
const createFunction = value => Function(`'use strict';return (${value})`)();
exports.createFunction = createFunction;
const createResolved = (module, type, config, interpreter) => ({
type,
config,
interpreter,
io: io.get(interpreter),
run: (code, ...args) => module.run(interpreter, code, ...args),
runAsync: (code, ...args) => module.runAsync(interpreter, code, ...args),
runEvent: (...args) => module.runEvent(interpreter, ...args),
});
exports.createResolved = createResolved;
const dropLine0 = code => code.replace(/^(?:\n|\r\n)/, '');
const createOverload = (module, name, before, after) => {
const method = module[name].bind(module);
module[name] = name === 'run' ?
// patch the sync method
(interpreter, code, ...args) => {
if (before) method(interpreter, before, ...args);
const result = method(interpreter, dropLine0(code), ...args);
if (after) method(interpreter, after, ...args);
return result;
} :
// patch the async one
async (interpreter, code, ...args) => {
if (before) await method(interpreter, before, ...args);
const result = await method(interpreter, dropLine0(code), ...args);
if (after) await method(interpreter, after, ...args);
return result;
};
};
exports.createOverload = createOverload;
const js_modules = Symbol.for('polyscript.js_modules');
exports.js_modules = js_modules;
const jsModules = new Map;
defineProperty(globalThis, js_modules, { value: jsModules });
const JSModules = new Proxy(jsModules, {
get: (map, name) => map.get(name),
has: (map, name) => map.has(name),
ownKeys: map => [...map.keys()],
});
exports.JSModules = JSModules;
const has = (_, field) => !field.startsWith('_');
const proxy = (modules, name) => new Proxy(
modules,
{ has, get: (modules, field) => modules[name][field] }
);
const registerJSModules = (type, module, interpreter, modules) => {
// Pyodide resolves JS modules magically
if (type === 'pyodide') return;
// other runtimes need this pretty ugly dance (it works though)
const jsModules = 'polyscript.js_modules';
for (const name of Reflect.ownKeys(modules))
module.registerJSModule(interpreter, `${jsModules}.${name}`, proxy(modules, name));
module.registerJSModule(interpreter, jsModules, modules);
};
exports.registerJSModules = registerJSModules;
const importJS = (source, name) => import(source).then(esm => {
jsModules.set(name, { ...esm });
});
exports.importJS = importJS;
const importCSS = href => new Promise((onload, onerror) => {
if (document.querySelector(`link[href="${href}"]`)) onload();
document.head.append(
assign(
document.createElement('link'),
{ rel: 'stylesheet', href, onload, onerror },
)
)
});
exports.importCSS = importCSS;
const isCSS = source => /\.css/i.test(new URL(source).pathname);
exports.isCSS = isCSS;
/* c8 ignore stop */
exports.dedent = dedent;
exports.unescape = unescape;
exports.dispatch = dispatch;
exports.isArray = isArray;
exports.assign = assign;
exports.create = create;
exports.defineProperties = defineProperties;
exports.defineProperty = defineProperty;
exports.entries = entries;
exports.all = all;
exports.resolve = resolve;
exports.absoluteURL = absoluteURL;
exports.nodeInfo = nodeInfo;
|