From 6f36a3317e34fe6a42bb0730ee1ead9ec1424e4c Mon Sep 17 00:00:00 2001 From: oveddan Date: Mon, 15 Jun 2015 12:56:02 -0400 Subject: [PATCH] To make the chrome debugger environment consisten with the JSC executer environment, where there is no global.document, make the chrome debugger run the javascript inside a web worker. This fixes #1473 Some issues: - Ideally the websocket could be open inside the worker and communicated directly with it, but one of the messages requires access to localStorage, which is not accessable from within a worker. So the socket is still loaded from the webpage itself, and messages that the worker should handle are forwarded to it. - The worker does not have access to the global window object. In a worker, the global scope is a DedicatedWorkerGlobalScope and can be accessed via `self` --- packager/debugger.html | 41 +++++++++++++++----------------------- packager/debuggerWorker.js | 39 ++++++++++++++++++++++++++++++++++++ packager/packager.js | 4 ++++ 3 files changed, 59 insertions(+), 25 deletions(-) create mode 100644 packager/debuggerWorker.js diff --git a/packager/debugger.html b/packager/debugger.html index d72e40ead23b..35ea4b84a687 100644 --- a/packager/debugger.html +++ b/packager/debugger.html @@ -31,31 +31,28 @@ document.getElementById('status').innerHTML = status; } +// This worker will run the application javascript code, +// making sure that it's run in an environment without a global +// document, to make it consistent with the JSC executor environment. +var worker = new Worker('debuggerWorker.js'); + var messageHandlers = { // This method is a bit hacky. Catalyst asks for a new clean JS runtime. // The easiest way to do this is to reload this page. That also means that // web socket connection will be lost. To send reply back we need to remember - // message id + // message id. + // This message also needs to be handled outside of the worker, since the worker + // doesn't have access to local storage. 'prepareJSRuntime': function(message) { window.onbeforeunload = undefined; window.localStorage.setItem('sessionID', message.id); window.location.reload(); }, - 'executeApplicationScript': function(message, sendReply) { - for (var key in message.inject) { - window[key] = JSON.parse(message.inject[key]); - } - loadScript(message.url, sendReply.bind(null, null)); + 'executeApplicationScript': function(message) { + worker.postMessage(message); }, - 'executeJSCall': function(message, sendReply) { - var returnValue = [[], [], [], [], []]; - try { - if (window && window.require) { - returnValue = window.require(message.moduleName)[message.moduleMethod].apply(null, message.arguments); - } - } finally { - sendReply(JSON.stringify(returnValue)); - } + 'executeJSCall': function(message){ + worker.postMessage(message); } } @@ -72,12 +69,10 @@ ws.onmessage = function(message) { var object = JSON.parse(message.data); - var sendReply = function(result) { - ws.send(JSON.stringify({replyID: object.id, result: result})); - } var handler = messageHandlers[object.method]; + if (handler) { - handler(object, sendReply); + handler(object); } else { console.warn('Unknown method: ' + object.method); } @@ -87,12 +82,8 @@ setStatus('Disconnected from proxy. Is node server running?'); } -function loadScript(src, callback) { - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = src; - script.onload = callback; - document.head.appendChild(script); +worker.onmessage = function(message) { + ws.send(JSON.stringify(message.data)); } })(); diff --git a/packager/debuggerWorker.js b/packager/debuggerWorker.js new file mode 100644 index 000000000000..506a0a0e8162 --- /dev/null +++ b/packager/debuggerWorker.js @@ -0,0 +1,39 @@ + +var messageHandlers = { + 'executeApplicationScript': function(message, sendReply) { + for (var key in message.inject) { + self[key] = JSON.parse(message.inject[key]); + } + loadScript(message.url, sendReply.bind(null, null)); + }, + 'executeJSCall': function(message, sendReply) { + var returnValue = [[], [], [], [], []]; + try { + if (require) { + returnValue = require(message.moduleName)[message.moduleMethod].apply(null, message.arguments); + } + } finally { + sendReply(JSON.stringify(returnValue)); + } + } +} + +onmessage = function(message) { + var object = message.data; + + var sendReply = function(result) { + postMessage({replyID: object.id, result: result}); + } + + var handler = messageHandlers[object.method]; + if (handler) { + handler(object, sendReply); + } else { + console.warn('Unknown method: ' + object.method); + } +} + +function loadScript(src, callback) { + importScripts(src); + callback(); +} diff --git a/packager/packager.js b/packager/packager.js index 7dd013c67c7d..6978b5fcc2bc 100644 --- a/packager/packager.js +++ b/packager/packager.js @@ -171,6 +171,10 @@ function getDevToolsLauncher(options) { var debuggerPath = path.join(__dirname, 'debugger.html'); res.writeHead(200, {'Content-Type': 'text/html'}); fs.createReadStream(debuggerPath).pipe(res); + } else if (req.url === '/debuggerWorker.js') { + var workerPath = path.join(__dirname, 'debuggerWorker.js'); + res.writeHead(200, {'Content-Type': 'application/javascript'}); + fs.createReadStream(workerPath).pipe(res); } else if (req.url === '/launch-chrome-devtools') { var debuggerURL = 'http://localhost:' + options.port + '/debugger-ui'; var script = 'launchChromeDevTools.applescript';