Refactor: pull out editor worker

This commit is contained in:
eight 2018-08-31 20:00:21 +08:00
parent fd01abe553
commit af08f1ae23
2 changed files with 124 additions and 0 deletions

View File

@ -0,0 +1,77 @@
/* global importScripts parseMozFormat parserlib CSSLint */
'use strict';
const loadScript = createLoadScript();
const loadParserLib = createLoadParserLib();
createAPI({
csslint: (code, config) => {
loadParserLib();
loadScript(['/vendor-overwrites/csslint/csslint.js']);
return CSSLint.verify(code, config).messages
.map(m => Object.assign(m, {rule: {id: m.rule.id}}));
},
stylelint: () => {
},
parseMozFormat: data => {
loadParserLib();
loadScript(['/js/moz-parser.js']);
return parseMozFormat(data);
}
});
function createLoadParserLib() {
let loaded = false;
return () => {
if (loaded) {
return;
}
importScripts('/vendor-overwrites/csslint/parserlib.js');
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
loaded = true;
};
}
function createLoadScript() {
const loaded = new Set();
return urls => {
urls = urls.filter(u => !loaded.has(u));
importScripts(...urls);
urls.forEach(u => loaded.add(u));
};
}
function createAPI(methods) {
self.onmessage = e => {
const message = e.data;
Promise.resolve()
.then(() => methods[message.action](...message.args))
.then(result =>
({
requestId: message.requestId,
error: false,
data: result
})
)
.catch(err =>
({
requestId: message.requestId,
error: true,
data: cloneError(err)
})
)
.then(data => self.postMessage(data));
};
}
function cloneError(err) {
return Object.assign({
name: err.name,
stack: err.stack,
message: err.message,
lineNumber: err.lineNumber,
columnNumber: err.columnNumber,
fileName: err.fileName
}, err);
}

47
edit/editor-worker.js Normal file
View File

@ -0,0 +1,47 @@
'use strict';
var editorWorker = (() => { // eslint-disable-line no-var
let worker;
return createAPI(['csslint', 'stylelint', 'parseMozFormat']);
function createAPI(keys) {
const output = {};
for (const key of keys) {
output[key] = (...args) => {
if (!worker) {
worker = createWorker();
}
return worker.invoke(key, args);
};
}
return output;
}
function createWorker() {
let requestId = 0;
const pending = new Map();
const worker = new Worker('/edit/editor-worker-body.js');
worker.onmessage = e => {
const message = e.data;
if (message.error) {
pending.get(message.requestId).reject(message.data);
} else {
pending.get(message.requestId).resolve(message.data);
}
pending.delete(message.requestId);
};
return {invoke};
function invoke(action, args) {
return new Promise((resolve, reject) => {
pending.set(requestId, {resolve, reject});
worker.postMessage({
requestId,
action,
args
});
requestId++;
});
}
}
})();