`.
19 | 3. Place ``
20 | anywhere after the `` tag.
21 | 4. Read the API documentation below.
22 |
23 |
24 | [download]: http://github.com/eligrey/jsandbox/zipball/master
25 |
26 |
27 | Example Code
28 | ------------
29 |
30 | This [example code][example] demonstrates the JSandbox API.
31 |
32 | [example]: http://gist.github.com/175160
33 |
34 |
35 | Tested Working Browsers
36 | -----------------------
37 |
38 | * Firefox 3.5+
39 | * Google Chrome 4+
40 |
41 |
42 | API
43 | ---
44 |
45 | ### Worker script location
46 |
47 | Instead of using a `` tag, you may define `JSandbox.url` to specify the location
48 | of the JSandbox worker script.
49 |
50 |
51 | ### Methods
52 |
53 | All of these methods can be accessed on the `JSandbox` constructor (in one-use sandboxes)
54 | and `JSandbox` instances:
55 |
56 |
57 |
eval(options)
58 |
59 | eval()s options.data. If options.callback is a
60 | function, it is passed the results as long as no errors occur. If
61 | options.onerror is a function and an error occurs, it is passed the error
62 | object. The code is eval()ed in a top-level pseudo-function-scope. If you
63 | define a variable using a var statement, the variable is private to the
64 | eval. this is still the global object. If this method is called on
65 | JSandbox, the JSandbox object is returned. Otherwise, the ID
66 | of the request is returned.
67 |
68 |
69 |
exec(options)
70 |
71 | Executes code in a faster method than eval, but does not pass a
72 | return value to the callback function (though the function is still called if
73 | defined). Unlike eval, the code is run in the global scope
74 | (var statements affect this).
75 |
76 |
77 |
load(options)
78 |
79 | If options.data is a string, options.data will attempt to be
80 | loaded in the sandbox. If options.data is an array, every string it
81 | contains will attempt be loaded. If options.onerror is a function and an
82 | error is thrown while parsing a script or a script could not be resolved,
83 | options.onerror is passed the error object. Otherwise,
84 | options.callback is called when the scripts are finished loading.
85 |
86 |
87 |
88 | #### Instance-only methods
89 |
90 | These methods can only be on JSandbox instances:
91 |
92 |
93 |
abort(requestID)
94 |
Aborts a pending request with the ID, requestID.
95 |
96 |
terminate()
97 |
98 | Terminates the worker thread and any pending requests are aborted. You cannot use the
99 | JSandbox instance on which you called this method after it is called.
100 |
101 |
102 |
103 | ### `options` object
104 |
105 | The following are all of the properties that may be included in an `options` object.
106 |
107 |
108 |
data [Required]
109 |
110 | In the case of eval and exec, it is the code to execute. In
111 | the case of load, it is an array of the script(s) to load. If you only
112 | need to load one script, just pass a string instead.
113 |
114 |
115 |
input
116 |
117 | The input data available to the code via the input variable. The input should be
118 | JSON-convertible.
119 |
120 |
121 |
callback
122 |
123 | The callback to pass the return value of the executed code if no exceptions were
124 | thrown.
125 |
126 |
127 |
onerror
128 |
The callback to pass an exception if one is thrown upon executing the code.
129 |
130 |
131 |
132 | ### Alternative syntax
133 |
134 | Any method that takes an options object can also be called using the following
135 | positional-arguments syntax:
136 |
137 | someMethod(data [, callback] [, input] [, onerror]);
138 |
139 | The global `JSandbox` object can also be referenced as `Sandbox`.
140 |
141 |
142 | 
143 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | JSandbox Changelog
2 | ==================
3 |
4 | (Worker) 0.2.0.4
5 | ----------------
6 |
7 | * json2.js is now included directly in the script.
8 |
9 |
10 | 0.2.3
11 | -----
12 |
13 | * Removed `JSandbox.ready()` as json2.js is now included directly in the script.
14 | * The script now works as a worker.
15 |
16 |
17 | (Worker) 0.2.0.3
18 | ----------------
19 |
20 | * Now also dereferencing `ActiveXObject` for when or if IE ever supports web workers.
21 | * Same thing as jsandbox.js v0.2.2 in regards to the json2.js API.
22 | * Added a media type to the data: URI used in exec.
23 |
24 |
25 | 0.2.2
26 | -----
27 |
28 | * Added a `JSandbox.ready(aFunction)` method that calls `aFunction` when JSandbox is
29 | ready (json2.js API is functional).
30 | * Added a global `JSandbox` constructor which is just another reference to `Sandbox`.
31 | * json2.js API methods are now called using JSON as it's `this` object, just in case
32 | it causes trouble for a JSON implementation.
33 |
34 |
35 | (Worker) 0.2.0.2
36 | ----------------
37 |
38 | * Blocked access to the `Worker` constructor.
39 | * Now using `importScripts.apply` as
40 | [Chromium issue 20192](http://code.google.com/p/chromium/issues/detail?id=20192)
41 | has been fixed.
42 |
43 |
44 | 0.2.1
45 | -----
46 |
47 | * Removed `document.querySelector` dependancy.
48 | * Preparing test suite for the new, standalone, QUnit library. The library still has
49 | asynchronous bugs so it can't be used yet.
50 | * `self.onmessage` is deleted after every time code is run in case the code defines it.
51 | * Instance catch-alls are now passed the request object as their second argument.
52 |
53 |
54 | 0.2
55 | -----
56 |
57 | * Renamed the library from "jsandbox" to "JSandbox".
58 | * Renamed the `jsandbox` constructor to `Sandbox`.
59 | * Created unit tests.
60 | * All instances of `uri` in the API have been replaced with `url`.
61 | * Added jsandbox instances (long-lived sandboxes).
62 | * Added `Sandbox.load` to load scripts. `data` must either be a string (one script) or an
63 | array of strings (multiple scripts).
64 | * Added `Sandbox.exec`. Same as eval but no return value and faster.
65 | * Added fixed-position arguments-style API:
66 | `Sandbox[method](data [,callback] [,input] [,onerror])`
67 | * `instance.onresponse` is called on all successfull responses from an instance.
68 | * `instance.onerror` is called all errors from an instance.
69 | * The worker script has been split from jsandbox.js and is now jsandbox-worker.js.
70 | * To specify the location of the worker script, add a
71 | `` tag to your document before
72 | including jsandbox.js.
73 |
--------------------------------------------------------------------------------
/jsandbox.async.js:
--------------------------------------------------------------------------------
1 | // JSandbox async.js Module
2 | // Usage: var result = yield [[JSandbox]].async().A_SANDBOX_METHOD(data [, input]);
3 |
4 | JSandbox.prototype.async = function () {
5 | var sandbox = this;
6 | return {
7 | __noSuchMethod__: function (method, args) {
8 | return [function ([code, input], callback) {
9 | sandbox[method](code, callback, input);
10 | }, args];
11 | }
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/min/jsandbox-worker.min.js:
--------------------------------------------------------------------------------
1 | /*! @source http://purl.eligrey.com/github/jsandbox/blob/master/src/jsandbox-worker.js*/
2 | (function(b,x){"use strict";var y=b.postMessage,u=b.importScripts,l=b.JSON||{};(function(){function o(f){return f<10?"0"+f:f}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(f){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+o(this.getUTCMonth()+1)+"-"+o(this.getUTCDate())+"T"+o(this.getUTCHours())+":"+o(this.getUTCMinutes())+":"+o(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(f){return this.valueOf()}}var r=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,s=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,j,p,z={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},m;function t(a){s.lastIndex=0;return s.test(a)?'"'+a.replace(s,function(f){var d=z[f];return typeof d==="string"?d:"\\u"+("0000"+f.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function q(f,d){var a,g,h,k,n=j,i,c=d[f];if(c&&typeof c==="object"&&typeof c.toJSON==="function"){c=c.toJSON(f)}if(typeof m==="function"){c=m.call(d,f,c)}switch(typeof c){case"string":return t(c);case"number":return isFinite(c)?String(c):"null";case"boolean":case"null":return String(c);case"object":if(!c){return"null"}j+=p;i=[];if(Object.prototype.toString.apply(c)==="[object Array]"){k=c.length;for(a=0;a1){a={data:a,input:b,callback:d,onerror:c}}if(k===L&&typeof a[p]===G){a[p]=[a[p]]}var g=a[p],h=this.createRequestID();b=a[M];delete a[p];delete a[M];this[o][h]=a;this[t].postMessage({id:h,method:k,data:g,input:b,toString:R});return h};l[k]=function(){var a=new l();a[F]=a[s]=function(){a[E]();a=null};l[w][k].apply(a,Array[w].slice[x](arguments));return l}},V=[S,L,T],q=3;while(q--){U(V[q])}z[E]=function(){this[o]={};this[t].onmessage=null;this[t][E]()};z.abort=function(a){delete this[o][a]};z.createRequestID=function(){var a=Math.random().toString();if(a in this[o]){return this.createRequestID()}return a};if(typeof J!==I){var H=J.getElementsByTagName("link");q=H.length;while(q--){if(H[q].getAttribute("rel")==="jsandbox"){l.url=H[q].getAttribute("href");break}}}return l}(self)),Sandbox=JSandbox;
3 |
--------------------------------------------------------------------------------
/src/jsandbox-worker.js:
--------------------------------------------------------------------------------
1 | /*
2 | * JSandbox worker v0.2.0.4
3 | * 2010-01-25
4 | * By Elijah Grey, http://eligrey.com
5 | * Licensed under the X11/MIT License
6 | * See LICENSE.md
7 | */
8 |
9 | // This file is requested every time a new sandbox is created.
10 | // Make sure to include a Cache-Control header when serving this over HTTP.
11 |
12 | /*global self */
13 |
14 | /*jslint evil: true, undef: true, eqeqeq: true, immed: true */
15 |
16 | /*! @source http://purl.eligrey.com/github/jsandbox/blob/master/src/jsandbox-worker.js*/
17 |
18 | (function (self, globalEval) {
19 | "use strict";
20 |
21 | var
22 | postMessage = self.postMessage,
23 | importScripts = self.importScripts,
24 | messageEventType = "message",
25 |
26 | messageHandler = function (event) {
27 | var request = event.data,
28 | response = {
29 | };
30 |
31 | response.id = request.id;
32 |
33 | var data = request.data;
34 | self.input = request.input;
35 |
36 | try {
37 | switch (request.method) {
38 |
39 | case "eval": // JSLint has something against indenting cases
40 | response.results = globalEval(data);
41 | break;
42 | case "exec":
43 | importScripts("data:application/javascript," +
44 | encodeURIComponent(data));
45 | break;
46 | case "load":
47 | importScripts.apply(self, data);
48 | break;
49 |
50 | }
51 | } catch (e) {
52 | response.error = {
53 | name: e.name,
54 | message: e.message,
55 | stack: e.stack
56 | };
57 | }
58 |
59 | delete self.input;
60 | if (self.onmessage) {
61 | delete self.onmessage; // in case the code defined it
62 | }
63 |
64 | postMessage(response);
65 | };
66 |
67 | if (self.addEventListener) {
68 | self.addEventListener(messageEventType, messageHandler, false);
69 | } else if (self.attachEvent) { // for future compatibility with IE
70 | self.attachEvent("on" + messageEventType, messageHandler);
71 | }
72 |
73 | self.window = self; // provide a window object for scripts
74 |
75 | // dereference unsafe functions
76 | // some might not be dereferenced: https://bugzilla.mozilla.org/show_bug.cgi?id=512464
77 | self.Worker =
78 | self.addEventListener =
79 | self.removeEventListener =
80 | self.importScripts =
81 | self.XMLHttpRequest =
82 | self.postMessage =
83 | //self.dispatchEvent =
84 | // in case IE implements web workers
85 | self.attachEvent =
86 | self.detachEvent =
87 | self.ActiveXObject =
88 |
89 | undefined;
90 |
91 | }(self, eval));
92 |
--------------------------------------------------------------------------------
/src/jsandbox.js:
--------------------------------------------------------------------------------
1 | /*
2 | * JSandbox JavaScript Library v0.2.3
3 | * 2009-01-25
4 | * By Elijah Grey, http://eligrey.com
5 | * Licensed under the MIT License
6 | * See LICENSE.md
7 | */
8 |
9 | /*global self */
10 |
11 | /*jslint undef: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true,
12 | newcap: true, immed: true, maxerr: 1000, strict: true */
13 |
14 | /*! @source http://purl.eligrey.com/github/jsandbox/blob/master/src/jsandbox.js*/
15 |
16 | "use strict";
17 |
18 | var JSandbox = (function (self) {
19 | var undef_type = "undefined",
20 | doc = self.document,
21 | Worker = self.Worker;
22 |
23 | if (typeof Worker === undef_type) {
24 | return;
25 | }
26 |
27 | var
28 | // repeatedly used properties/strings (for minification)
29 | $eval = "eval",
30 | $exec = "exec",
31 | $load = "load",
32 | $requests = "requests",
33 | $input = "input",
34 | $terminate = "terminate",
35 | $data = "data",
36 | $callback = "callback",
37 | $onerror = "onerror",
38 | $worker = "worker",
39 | $onresponse = "onresponse",
40 | $prototype = "prototype",
41 | $call = "call",
42 |
43 | str_type = "string",
44 | fun_type = "function",
45 |
46 |
47 | Sandbox = function () {
48 | var sandbox = this;
49 |
50 | if (!(sandbox instanceof Sandbox)) {
51 | return new Sandbox();
52 | }
53 |
54 | sandbox[$worker] = new Worker(Sandbox.url);
55 | sandbox[$requests] = {};
56 |
57 | sandbox[$worker].onmessage = function (event) {
58 | var data = event[$data], request;
59 | if (typeof data !== "object") {
60 | return;
61 | }
62 | request = sandbox[$requests][data.id];
63 | if (request) {
64 | if (data.error) {
65 | if (typeof sandbox[$onerror] === fun_type) {
66 | sandbox[$onerror](data, request);
67 | }
68 | if (typeof request[$onerror] === fun_type) {
69 | request[$onerror][$call](sandbox, data.error);
70 | }
71 | } else {
72 | if (typeof sandbox[$onresponse] === fun_type) {
73 | sandbox[$onresponse](data, request);
74 | }
75 |
76 | if (typeof request[$callback] === fun_type) {
77 | request[$callback][$call](sandbox, data.results);
78 | }
79 | }
80 | delete sandbox[$requests][data.id];
81 | }
82 | };
83 | },
84 | proto = Sandbox[$prototype],
85 |
86 | createRequestMethod = function (method) {
87 | proto[method] = function (options, callback, input, onerror) {
88 | if (typeof options === str_type ||
89 | Object[$prototype].toString[$call](options) === "[object Array]" ||
90 | arguments.length > 1)
91 | { // called in (data, callback, input, onerror) style
92 | options = {
93 | data : options,
94 | input : input,
95 | callback : callback,
96 | onerror : onerror
97 | };
98 | }
99 |
100 | if (method === $load && typeof options[$data] === str_type) {
101 | options[$data] = [options[$data]];
102 | }
103 |
104 | var data = options[$data],
105 | id = this.createRequestID();
106 |
107 | input = options[$input];
108 |
109 | delete options[$data];
110 | delete options[$input];
111 |
112 | this[$requests][id] = options;
113 |
114 | this[$worker].postMessage({
115 | id : id,
116 | method : method,
117 | data : data,
118 | input : input
119 | });
120 |
121 | return id;
122 | };
123 | Sandbox[method] = function () {
124 | var sandbox = new Sandbox();
125 |
126 | sandbox[$onresponse] = sandbox[$onerror] = function () {
127 | sandbox[$terminate]();
128 | sandbox = null;
129 | };
130 |
131 | Sandbox[$prototype][method].apply(
132 | sandbox,
133 | Array[$prototype].slice[$call](arguments)
134 | );
135 | return Sandbox;
136 | };
137 | },
138 | methods = [$eval, $load, $exec],
139 | i = 3; // methods.length
140 |
141 | while (i--) {
142 | createRequestMethod(methods[i]);
143 | }
144 |
145 | proto[$terminate] = function () {
146 | this[$requests] = {};
147 | this[$worker].onmessage = null;
148 | this[$worker][$terminate]();
149 | };
150 |
151 | proto.abort = function (id) {
152 | delete this[$requests][id];
153 | };
154 |
155 | proto.createRequestID = function () {
156 | var id = Math.random().toString();
157 | if (id in this[$requests]) {
158 | return this.createRequestID();
159 | }
160 | return id;
161 | };
162 |
163 | if (typeof doc !== undef_type) {
164 | var linkElems = doc.getElementsByTagName("link");
165 | i = linkElems.length;
166 | while (i--) {
167 | if (linkElems[i].getAttribute("rel") === "jsandbox")
168 | {
169 | Sandbox.url = linkElems[i].getAttribute("href");
170 | break;
171 | }
172 | }
173 | }
174 |
175 | return Sandbox;
176 | }(self)),
177 | Sandbox = JSandbox;
178 |
--------------------------------------------------------------------------------
/test-suite.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSandbox test suite
6 |
7 |
8 |
9 |
10 |
11 |
12 |