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 |
|
45 |
|
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 |
|
58 | var extraScripts = [];
|
59 | if (tokens.matchOpToken("(")) {
|
60 | if (tokens.matchOpToken(")")) {
|
61 |
|
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 |
|
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());
|
88 |
|
89 |
|
90 | var bodyTokens = tokens.consumed.slice(bodyStartIndex, bodyEndIndex + 1);
|
91 |
|
92 |
|
93 |
|
94 | var worker = new Worker(workerUri);
|
95 |
|
96 |
|
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 |
|
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 |
|
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 |