2012-04-29 2 views
11

Одно из ограничений JS, которое меня больше всего беспокоит, - это низкая способность изолировать выполнение кода.Изолировать выполнение JavaScript

Я хочу, чтобы иметь возможность контролировать контекст, в котором выполняется код, то, что достичь такого же эффекта, что Script.createContextScript.runInContext & в node.js делает (узел использует связывание с двигателем V8, так что я могу» t имитировать их реализацию).

Вот некоторые из причин, почему я хочу, чтобы изолировать выполнение кода:

  1. Изолировать код из глобального пространства имен (в window объекта и также в DOM), но тем не менее должен быть в состоянии ссылки на функции вызовите объекты, выставленные в контексте, которые должны выполняться синхронно, что делает его почти невозможным с использованием WebWorker для изоляции.
  2. Выделив выполнение кода, вы также сможете освободить его определения, когда они больше не нужны (управление памятью).

Я знаю, что один может достичь частично изолированного исполнения путем загрузки сценария в iframe, этот подход, однако, очень тяжелый и использует много памяти для второго экземпляра DOM, который не нужен для того, что я пытаюсь делать.

Мне нужно разделить определение конструктора, а также определения объекта, которые совместно используются изолированными контейнерами/контекстами, которые оба должны запускаться в основном потоке пользовательского интерфейса. В основном я хочу использовать эти изолированные контейнеры для размещения плагинов/модулей (мини-приложений), каждый из которых представляет и динамически обновляет окно просмотра, вызывая команды рисования на свой собственный объект Context2D.

Если эти контейнеры не работают в главном потоке UI это низина мучительно трудно прокси-вызовы, такие как ctx.measureText() и ctx.drawImage() все будет бесполезным, так как объекты изображения не могут быть созданы в Worker.

Кто-нибудь знает о будущих спецификациях, которые сделают это возможным?

Существуют ли какие-либо текущие (скрытые) API-интерфейсы на стороне браузера, которые можно использовать для достижения этого?

Было бы лучше использовать виртуальную машину, такую ​​как Dart VM Goggle, а также повторно реализовать мою текущую кодовую базу? Моя текущая база кода немного выше 20 000 строк кода.

Было бы лучше, чтобы вновь ввести в действие рамки в *

+4

У вас есть * существующая проблема *, которая должна быть исправлена ​​следующим образом? [IIABDFI] (http://acronyms.thefreedictionary.com/IIABDFI). – Ryan

+0

Согласитесь с комментарием, но downvote немного ненужен. – Starx

+0

@minitech У меня действительно есть проблема с отсутствием sandoxes (что является лучшим словом для того, что я описал выше) во время выполнения браузера, из-за того, что я пытаюсь создать архитектуру плагина для своей клиентской платформы, которая написан на JavaScript и использует для этого время выполнения браузера. Платформа является общей и основной целью является размещение среды для динамической загрузки и управления плагинами/модулями/мини-приложением, которая предоставляет платформе дополнительные функции. – Raweden

ответ

3

Вы можете изолировать код от глобального пространства имен с простой самостоятельной исполняющим функции объекта:

(function() { 
    // all your code goes here 
    // nobody outside of your code can reach your top level variables here 
    // your top level variables are not on the window object 

    // this is a protected, but top level variable 
    var x = 3; 

    // if you want anything to be global, you can assign it to the window object. 
    window.myGlobal = {}; 

    function myTopLevelFunction(x,y,z) { 
     // code here 
    } 

})(); 

Если вы хотите иметь несколько из этих контекстов выполнения и иметь возможность делиться между ними, тогда вам придется рандеву через одно общедоступное местоположение, либо по-настоящему глобальную переменную, либо свойство на известном объекте DOM или что-то в этом роде. Общепринято объявлять один глобальный объект пространства имен и использовать свойства, недоступные для любого доступа к вещам, которые вы используете между модулями. Я знаю, что он не совсем совершенен, но он работает.Вот пример rendevous с использованием единого глобального пространства имен объекта:

// module AAA 
(function() { 
    // module AAA code goes here 

    // set up global namespace object and whatever references we want to be global 
    window.myModuleTop = window.myModuleTop || {}; 
    myModuleTop.AAA = {}; 
    myModuleTop.AAA.myFuncA = function() {}; 

})(); 


// module BBB 
(function() { 
    // module BBB code goes here 

    // set up global namespace object and whatever references we want to be global 
    window.myModuleTop = window.myModuleTop || {}; 
    myModuleTop.BBB = {}; 
    myModuleTop.BBB.myFuncB = function() {}; 

})(); 
+0

Я не уверен, является ли это типом изоляции ОП. _ (Но я не уверен, что я его тоже понимаю) _ – Starx

+0

@Matt, я не пытаюсь вернуть код OP в окно. Это всегда легко. Я пытаюсь удержать других людей от кода OP и оставить код OP изолированным от кода других людей. – jfriend00

+0

@ jfriend00 да, я думаю, что есть некоторая путаница в том, что ищет OP – Matt

2

Ближайшим библиотека Я видел за это Caja.

В принципе, в нестрочном javascript-коде есть много способов получить доступ к глобальному объекту (window в браузерах), что делает настоящую изоляцию очень трудной проблемой. Caja делает некоторые интригующие трюки, чтобы исправить это, но, честно говоря, я не совсем уверен, как это работает.

+0

Если вы навязываете строгий режим, делая что-то вроде уклонения от скрипта, может ли это быть намного проще? –

+0

@BT 'use strict', безусловно, улучшило ситуацию, но есть еще так много вещей, которые вам придется заплатить. Это далеко не безопасная гарантия. Например, вызов setTimeout или подобных вещей может выполняться в окне неявно, даже если вы его переопределите: '(function (window) {'use strict'; setTimeout (function() {console.log (this);});} ({})); '<- это будет печатать глобальное окно, несмотря на лексическое переопределение – Matt

+0

Но тем не менее вы можете лексически переопределить' setTimeout' так же, как вы делаете для окна для получения более полного результата. –

1

Является ли «стандартным» именным вариантом? Нравится:

var myNamespace = {}; 

myNamespace.myFunc = function() { return true; } 

Этот подход является самым простым, о котором я могу думать и может быть решением многих проблем. Хотя это и не настоящая песочница, это может привести к тому, что код будет меньше подвержен ошибкам.

0

Не могли бы вы использовать закрытие, как упомянутые другие ответы, а затем использовать теневое хранилище, чтобы пользователь не мог добраться до остальной части дома? Что-то вроде этого:

var containerNode = someDomNode 
var root = containerNode.createShadowRoot() 
;(function(root){ 
    var window = null, document = null, history = null, 
     screen = null, navigator = null, location = null 

    // isolated code goes here 

})(root) 

Предостережение:

  • Если вы создаете другие глобальные объекты вне контекста изолированного кода, вам нужно явно теневых переменным, как я сделал с окном, документом и т.д., иначе изолированный код будет иметь к нему доступ.
  • Это не будет работать в браузерах, у которых нет тени, очевидно, если только ваш изолированный код не должен взаимодействовать с dom.
  • Вы должны быть очень осторожны, чтобы объекты, которых вы do, имеют доступ к изолированному коду, не содержат ссылки на вещи, которые вы не хотите, чтобы иметь к нему доступ. Иногда это супер-ошибка, склонная к этому.
  • Я делаю это предложение, потому что его правдоподобно, что он работает, но я понятия не имею, есть ли дополнительные способы добраться до таких вещей, как окна и объекты документа.
Смежные вопросы