From af08f1ae23960c23394b92c57849ee84178d7ff3 Mon Sep 17 00:00:00 2001 From: eight Date: Fri, 31 Aug 2018 20:00:21 +0800 Subject: [PATCH] Refactor: pull out editor worker --- edit/editor-worker-body.js | 77 ++++++++++++++++++++++++++++++++++++++ edit/editor-worker.js | 47 +++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 edit/editor-worker-body.js create mode 100644 edit/editor-worker.js diff --git a/edit/editor-worker-body.js b/edit/editor-worker-body.js new file mode 100644 index 00000000..3798ae35 --- /dev/null +++ b/edit/editor-worker-body.js @@ -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); +} diff --git a/edit/editor-worker.js b/edit/editor-worker.js new file mode 100644 index 00000000..ecf746cd --- /dev/null +++ b/edit/editor-worker.js @@ -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++; + }); + } + } +})();