Pull to refresh

Создание Worker-а с другого домена

Reading time 2 min
Views 4.5K
Worker'ы — внятная реализация многопоточности в JavaScript. На момент сейчас они имеют достаточное количество ограничений. Для ознакомления с ними (как worker'ами, так и ограничениями) можно прочитать эту статью от хабраюзера Antelle. Там же есть и ссылки на первоисточники информации для интересующихся.


Сегодня же мне довелось столкнуться другой задачей. А именно: с проблемой создания worker'а из js-файла с другого домена, что на данный момент запрещено его спецификацией.

История началась с создания небольшого расширения Google Chrome для Chess.com, которое использовало стороннюю библиотеку. К несчастью, оказалось, что эта библиотека работает только как worker.

Проблема заключается в том, что у самого Chrome есть определенные ограничения на получение файлов из контекста страницы. Он разрешает внедрение стороннего javascript-кода на страницу, но не более того. А это значит, что код из дополнения может получать worker на страницу только с того домена, на котором он выполнялся. То есть в моем случае: Chess.com. Конечно, можно было бы рассчитывать, что когда-нибудь я получу доступ к боевым серверам Chess.com, но мне бы хотелось, чтобы все заработало уже сегодня. Пришлось гуглить.

К счастью, статья с html5rocks помогла найти решение: создание inline worker'а через Blob. Подробности здесь. Если говорить кратко, то можно создать любую текстовую строку и запихать ее в так называемый Blob — наскальный рисунок модельный прототип сырого внешнего файла.

Например так (взято с html5rocks):
var blob = new Blob([
    "onmessage = function(e) { postMessage('msg from worker'); }"]);

// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);

var worker = new Worker(blobURL);
worker.onmessage = function(e) {
  // e.data == 'msg from worker'
};
worker.postMessage(); // Start the worker.


Здесь мы видим, что создается объект Blob, который в представлении браузера является «как-бы-файлом», и в него записывается исходный текст.

Но если мы можем создать из любого текста Blob, значит, можно загрузить любой текст с другого сайта, а потом запихнуть его в Blob?

Окей, давайте попробуем:
$.get("https://example.com/js/worker.js", {},
     function (workerCode) {
         var blob = new Blob([workerCode], {type : 'javascript/worker'});
         var worker = new Worker(window.URL.createObjectURL(blob));
     }
);


Работает. То есть, фактически, мы можем загрузить любой внешний файл на страницу и запустить его как worker, независимо от принадлежности файлов к одному или нескольким доменам. Нда, вот так день.

Напоследок замечу, что, несмотря на всю сенсационность заголовка, в принципе в этом трюке нет ничего удивительного. То же самое можно проделать и для однопоточного javascript-кода: загрузить его как текст и вызвать через eval. В этом случае остается непонятным лишь неспешное принятие решения о поддержке CORS в Web Workers.
Tags:
Hubs:
+4
Comments 7
Comments Comments 7

Articles