UNPKG

5.67 kBJavaScriptView Raw
1
2(function () {
3
4 var invocationIdCounter = 0
5
6 var workerFunc = function() {
7 self.onmessage = function (e) {
8 switch (e.data.type) {
9 case 'init':
10 importScripts(e.data._hyperscript);
11 importScripts.apply(self, e.data.extraScripts);
12 var tokens = _hyperscript.internals.lexer.makeTokensObject(e.data.tokens, [], e.data.source);
13 var parsed = _hyperscript.internals.parser.parseElement('hyperscript', tokens);
14 postMessage({ type: 'didInit' });
15 break;
16 case 'call':
17 try {
18 var result = self[e.data.function].apply(self, e.data.args)
19 Promise.resolve(result).then(function (value) {
20 postMessage({
21 type: 'resolve',
22 id: e.data.id,
23 value: value
24 })
25 }).catch(function(error){
26 postMessage({
27 type: 'reject',
28 id: e.data.id,
29 error: error.toString()
30 })
31 })
32 } catch (error) {
33 postMessage({
34 type: 'reject',
35 id: e.data.id,
36 error: error.toString()
37 })
38 }
39 break;
40 }
41 }
42 }
43
44 // extract the body of the function, which was only defined so
45 // that we can get syntax highlighting
46 var workerCode = "(" + workerFunc.toString() + ")()";
47 var blob = new Blob([workerCode], {type: 'text/javascript'});
48 var workerUri = URL.createObjectURL(blob);
49
50 _hyperscript.addFeature("worker", function(parser, runtime, tokens) {
51 if (tokens.matchToken('worker')) {
52 var name = parser.requireElement("dotOrColonPath", tokens);
53 var qualifiedName = name.evaluate();
54 var nameSpace = qualifiedName.split(".");
55 var workerName = nameSpace.pop();
56
57 // Parse extra scripts
58 var extraScripts = [];
59 if (tokens.matchOpToken("(")) {
60 if (tokens.matchOpToken(")")) {
61 // no external scripts
62 } else {
63 do {
64 var extraScript = tokens.requireTokenType('STRING').value;
65 var absoluteUrl = new URL(extraScript, location.href).href;
66 extraScripts.push(absoluteUrl);
67 } while (tokens.matchOpToken(","));
68 tokens.requireOpToken(')');
69 }
70 }
71
72 // Consume worker methods
73
74 var funcNames = [];
75 var bodyStartIndex = tokens.consumed.length;
76 var bodyEndIndex = tokens.consumed.length;
77 do {
78 var feature = parser.parseAnyOf(['defFeature', 'jsFeature'], tokens);
79 if (feature) {
80 if (feature.type === 'defFeature') {
81 funcNames.push(feature.name);
82 bodyEndIndex = tokens.consumed.length;
83 } else {
84 if (tokens.hasMore()) continue;
85 }
86 } else break;
87 } while (tokens.matchToken("end") && tokens.hasMore()); // worker end
88
89
90 var bodyTokens = tokens.consumed.slice(bodyStartIndex, bodyEndIndex + 1);
91
92 // Create worker
93
94 var worker = new Worker(workerUri);
95
96 // Send init message to worker
97
98 worker.postMessage({
99 type: 'init',
100 _hyperscript: runtime.hyperscriptUrl,
101 extraScripts: extraScripts,
102 tokens: bodyTokens,
103 source: tokens.source
104 });
105
106 var workerPromise = new Promise(function (resolve, reject) {
107 worker.addEventListener('message', function (e) {
108 if (e.data.type === 'didInit') resolve();
109 }, {once: true});
110 });
111
112 // Create function stubs
113 var stubs = {};
114 funcNames.forEach(function (funcName) {
115 stubs[funcName] = function () {
116 var args = arguments;
117 return new Promise(function (resolve, reject) {
118 var id = invocationIdCounter++;
119 worker.addEventListener('message', function returnListener(e) {
120 if (e.data.id !== id) return;
121 worker.removeEventListener('message', returnListener);
122 if (e.data.type === 'resolve') resolve(e.data.value);
123 else reject(e.data.error);
124 });
125 workerPromise.then(function () {
126 // Worker has been initialized, send invocation.
127 worker.postMessage({
128 type: 'call',
129 function: funcName,
130 args: Array.from(args),
131 id: id
132 });
133 });
134 });
135 };
136 });
137
138 return {
139 name: workerName,
140 worker: worker,
141 execute: function (ctx) {
142 runtime.assignToNamespace(nameSpace, workerName, stubs)
143 }
144 };
145 }
146 })
147})()
\No newline at end of file