2012-04-29 43 views
11

Một trong những hạn chế của JS làm tôi khó chịu nhất là khả năng cô lập kém khả năng thực thi mã.Thực hiện cách ly JavaScript

Tôi muốn có thể kiểm soát ngữ cảnh trong đó mã được thực hiện, Cái gì đó đạt được hiệu ứng tương tự như những gì Script.createContext & Script.runInContext trong node.js (nút đang sử dụng liên kết với động cơ V8, vì vậy tôi có thể ' t thi đua triển khai của họ).

Dưới đây là một số lý do tại sao tôi muốn cô lập thực thi mã:

  1. Cô lập mã từ namespace toàn cục (đối tượng window và cũng là DOM), nhưng tuy nhiên tôi cần phải có chức năng tham khảo có thể kêu gọi các vật thể tiếp xúc trong bối cảnh phải được thực hiện đồng bộ, làm cho nó gần như không thể sử dụng WebWorker để cách ly.
  2. Bằng cách cách ly việc thực thi mã, nó cũng có thể giải quyết các định nghĩa của nó khi không còn cần thiết nữa (quản lý bộ nhớ).

Tôi biết người ta có thể đạt được thực hiện một phần cô lập bằng cách tải đoạn script vào một iframe, phương pháp này tuy nhiên là rất nặng nề và sử dụng một bộ nhớ rất nhiều cho một trường hợp thứ hai của DOM mà là không cần thiết cho những gì tôi đang cố gắng làm.

Tôi cần chia sẻ định nghĩa hàm tạo và định nghĩa của đối tượng được chia sẻ giữa các vùng chứa/ngữ cảnh riêng biệt mà cả hai đều phải chạy trên chuỗi giao diện người dùng chính. Chủ yếu là tôi muốn sử dụng các thùng chứa riêng biệt này để lưu trữ các plugin/mô-đun (các ứng dụng nhỏ) mà mỗi trình bày và tự động cập nhật một khung nhìn bằng cách gọi các lệnh vẽ trên đối tượng Context2D của riêng chúng.

Nếu các vùng chứa này không chạy trên luồng giao diện người dùng chính, thì sẽ khó khăn khi thực hiện các cuộc gọi proxy như ctx.measureText()ctx.drawImage() vì không thể tạo đối tượng hình ảnh trong Worker.

Có ai đó biết đặc điểm kỹ thuật trong tương lai có thể làm điều này có thể không?

Có bất kỳ API bên trình duyệt hiện tại (ẩn) nào có thể được sử dụng để đạt được điều này không?

Bạn có nên tận dụng tốt hơn máy ảo như máy ảo Dart của Goggle và cũng có thể triển khai lại hệ thống mã hiện tại của mình không? Codebase hiện tại của tôi hơi cao hơn 20 000 dòng mã.

Nó sẽ được tốt hơn để tái thực hiện khuôn khổ trong *

+4

Bạn có * vấn đề hiện tại * phải được khắc phục như thế này không? [IIABDFI] (http://acronyms.thefreedictionary.com/IIABDFI). – Ryan

+0

Đồng ý với nhận xét, nhưng downvote là một chút không cần thiết. – Starx

+0

@minitech Tôi thực sự có một vấn đề với việc thiếu các sandox (đó là một từ tốt hơn cho những gì tôi đã mô tả ở trên) trong thời gian chạy trình duyệt, do tôi đang cố gắng để đạt được một kiến ​​trúc plugin cho nền tảng phía máy khách của tôi, được viết bằng JavaScript và sử dụng thời gian chạy của trình duyệt cho điều này. Nền tảng này là chung chung và mục đích chính của nó là lưu trữ môi trường để tự động tải và kiểm soát các plugins/modules/mini-application cung cấp nền tảng với các tính năng bổ sung. – Raweden

Trả lời

3

Bạn có thể tách mã của bạn từ không gian tên toàn cầu với một hàm đối tượng đơn giản tự thực hiện:

(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 
    } 

})(); 

Nếu bạn muốn có nhiều những bối cảnh thực thi này và có thể chia sẻ giữa chúng, sau đó bạn sẽ phải hẹn qua một vị trí được biết đến công khai, hoặc là biến toàn cầu thực sự hoặc thuộc tính trên đối tượng DOM đã biết hoặc thứ gì đó tương tự. Nó là tương đối phổ biến để khai báo một đối tượng không gian tên toàn cầu và sử dụng các thuộc tính off cho bất kỳ quyền truy cập vào những thứ bạn đang chia sẻ giữa các mô-đun. Tôi biết nó không hoàn toàn hoàn hảo, nhưng nó hoạt động.Dưới đây là một ví dụ về rendevous sử dụng một đối tượng không gian tên toàn cầu duy nhất:

// 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

Tôi không chắc đây có phải là loại cách ly mà OP đang hỏi hay không. _ (Nhưng tôi không chắc tôi cũng hiểu anh ấy) _ – Starx

+0

@Matt, tôi không cố gắng giữ mã của OP không quay lại cửa sổ. Điều đó luôn luôn dễ dàng. Tôi đang cố gắng để giữ cho người khác ra khỏi mã của OP và giữ mã của OP bị cô lập từ mã của người khác. – jfriend00

+0

@ jfriend00 yeah Tôi nghĩ rằng có một số nhầm lẫn về những gì OP đang tìm kiếm – Matt

2

Thư viện gần nhất tôi đã nhìn thấy việc này là Caja. Về cơ bản, trong mã javascript không nghiêm ngặt, có nhiều cách để truy cập vào đối tượng toàn cầu (window trong trình duyệt), làm cho sự cô lập thực sự trở thành một vấn đề rất khó khăn. Caja thực hiện một số thủ thuật iframing để vá lỗi này, nhưng thành thật mà nói tôi không chắc chắn nó hoạt động như thế nào.

+0

Nếu bạn ép buộc chế độ nghiêm ngặt, bằng cách làm một cái gì đó như đánh giá một kịch bản, điều này có thể dễ dàng hơn nhiều? –

+0

@BT 'sử dụng strict' chắc chắn đã cải thiện tình hình, nhưng vẫn còn rất nhiều thứ bạn phải vá. Nó là một bảo đảm an toàn. Ví dụ, gọi setTimeout hoặc những thứ tương tự có thể được thực hiện trên cửa sổ ngầm, ngay cả khi bạn ghi đè lên nó: '(function (window) {'use strict'; setTimeout (function() {console.log (this);});} ({})); '<- điều này sẽ in cửa sổ toàn cầu mặc dù ghi đè từ vựng – Matt

+0

Nhưng bằng cùng một mã thông báo, bạn có thể ghi đè lên' setTimeout' giống như bạn đang làm cho cửa sổ để có kết quả đầy đủ hơn. –

1

Có phải tùy chọn đặt tên "chuẩn" không? Giống như:

var myNamespace = {}; 

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

Cách tiếp cận này là đơn giản nhất tôi có thể nghĩ và có thể là giải pháp cho nhiều vấn đề. Mặc dù không phải là một sandbox thực, nó có thể cho phép mã ít bị lỗi hơn.

0

Bạn không thể sử dụng đóng cửa như các câu trả lời khác được đề cập và sau đó sử dụng một mái vòm bóng để đảm bảo rằng người dùng không thể đến phần còn lại của dom? Một cái gì đó như thế này:

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) 

Hãy cẩn thận:

  • Nếu bạn tạo các đối tượng toàn cầu khác bên ngoài bối cảnh của mã riêng biệt, bạn cần phải shadow rõ ràng biến như tôi đã làm với cửa sổ, tài liệu, vv, nếu không mã bị cô lập sẽ truy cập vào nó.
  • Điều này sẽ không hoạt động trong các trình duyệt không có bóng tối rõ ràng, trừ khi mã bị cô lập của bạn không cần tương tác với toàn bộ mái vòm.
  • Bạn phải rất cẩn thận khi đối tượng bạn do cấp quyền truy cập mã bị cô lập không chứa tham chiếu đến những thứ bạn không muốn có quyền truy cập. Đôi khi đây là lỗi siêu dễ xảy ra.
  • Tôi đang đưa ra đề xuất này vì nó hợp lý vì nó hoạt động, nhưng tôi không biết có cách nào khác để truy cập vào những thứ như cửa sổ và đối tượng tài liệu hay không.
Các vấn đề liên quan