UNPKG

hyperscript.org

Version:

a small scripting language for the web

172 lines (154 loc) 5.01 kB
///========================================================================= /// This module provides the worker feature for hyperscript ///========================================================================= 'use strict'; (function (self, factory) { const plugin = factory(self) if (typeof exports === 'object' && typeof exports['nodeName'] !== 'string') { module.exports = plugin } else { if ('_hyperscript' in self) self._hyperscript.use(plugin) } })(typeof self !== 'undefined' ? self : this, self => { return (_hyperscript) => { var invocationIdCounter = 0; var workerFunc = function (self) { self.onmessage = function (e) { switch (e.data.type) { case "init": self.importScripts(e.data._hyperscript); self.importScripts.apply(self, e.data.extraScripts); const _hyperscript = self['_hyperscript'] var tokens = new _hyperscript.internals.Tokens(e.data.tokens, [], e.data.source); var hyperscript = _hyperscript.internals.parser.parseElement("hyperscript", tokens); hyperscript.apply(self, self); postMessage({ type: "didInit" }); break; case "call": try { var result = self['_hyperscript'].internals.runtime .getHyperscriptFeatures(self)[e.data.function] .apply(self, e.data.args); Promise.resolve(result) .then(function (value) { postMessage({ type: "resolve", id: e.data.id, value: value, }); }) .catch(function (error) { postMessage({ type: "reject", id: e.data.id, error: error.toString(), }); }); } catch (error) { postMessage({ type: "reject", id: e.data.id, error: error.toString(), }); } break; } }; }; // extract the body of the function, which was only defined so // that we can get syntax highlighting var workerCode = "(" + workerFunc.toString() + ")(self)"; var blob = new Blob([workerCode], { type: "text/javascript" }); var workerUri = URL.createObjectURL(blob); _hyperscript.addFeature("worker", function (parser, runtime, tokens) { if (tokens.matchToken("worker")) { var name = parser.requireElement("dotOrColonPath", tokens); var qualifiedName = name.evaluate(); var nameSpace = qualifiedName.split("."); var workerName = nameSpace.pop(); // Parse extra scripts var extraScripts = []; if (tokens.matchOpToken("(")) { if (tokens.matchOpToken(")")) { // no external scripts } else { do { var extraScript = tokens.requireTokenType("STRING").value; var absoluteUrl = new URL(extraScript, location.href).href; extraScripts.push(absoluteUrl); } while (tokens.matchOpToken(",")); tokens.requireOpToken(")"); } } // Consume worker methods var funcNames = []; var bodyStartIndex = tokens.consumed.length; var bodyEndIndex = tokens.consumed.length; do { var feature = parser.parseAnyOf(["defFeature", "jsFeature"], tokens); if (feature) { if (feature.type === "defFeature") { funcNames.push(feature.name); bodyEndIndex = tokens.consumed.length; } else { if (tokens.hasMore()) continue; } } else break; } while (tokens.matchToken("end") && tokens.hasMore()); // worker end var bodyTokens = tokens.consumed.slice(bodyStartIndex, bodyEndIndex + 1); // Create worker var worker = new Worker(workerUri); // Send init message to worker worker.postMessage({ type: "init", _hyperscript: runtime.hyperscriptUrl, extraScripts: extraScripts, tokens: bodyTokens, source: tokens.source, }); var workerPromise = new Promise(function (resolve, reject) { worker.addEventListener( "message", function (e) { if (e.data.type === "didInit") resolve(); }, { once: true } ); }); // Create function stubs var stubs = {}; funcNames.forEach(function (funcName) { console.log(funcName) stubs[funcName] = function () { var args = arguments; return new Promise(function (resolve, reject) { var id = invocationIdCounter++; worker.addEventListener("message", function returnListener(e) { if (e.data.id !== id) return; worker.removeEventListener("message", returnListener); if (e.data.type === "resolve") resolve(e.data.value); else reject(e.data.error); }); workerPromise.then(function () { // Worker has been initialized, send invocation. worker.postMessage({ type: "call", function: funcName, args: Array.from(args), id: id, }); }); }); }; }); return { name: workerName, worker: worker, install: function (target) { runtime.assignToNamespace(target, nameSpace, workerName, stubs); }, }; } }); } })