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

от автора

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.

ссылка на оригинал статьи http://habrahabr.ru/post/261817/