Permalink
Browse files

[#37] Cleanup.

  • Loading branch information...
1 parent e652bb7 commit ef05ce085753f4ec28be703074d0f66cb33f9b01 @assaf committed Feb 16, 2011
Showing with 36 additions and 42 deletions.
  1. +1 −0 .gitignore
  2. +5 −0 CHANGELOG.md
  3. +3 −1 Cakefile
  4. +0 −7 TODO.md
  5. +4 −34 src/zombie/browser.coffee
  6. +23 −0 src/zombie/windowcontext.cc
View
1 .gitignore
@@ -7,3 +7,4 @@ man7
node_modules
build
.lock-wscript
+tags
View
5 CHANGELOG.md
@@ -3,6 +3,11 @@ zombie.js-changelog(7) -- Changelog
### Version 0.8.14 Pending
+New isolated contexts for executing JavaScript.
+
+ 293 Tests
+ 4.4 sec to complete
+
### Version 0.8.13 2011-02-11
View
4 Cakefile
@@ -52,7 +52,9 @@ task "install", "Install Zombie in your local repository", ->
build = (callback)->
log "Compiling CoffeeScript to JavaScript ...", green
exec "rm -rf lib && coffee -c -l -b -o lib src", (err, stdout)->
- callback err
+ onerror err
+ log "Compiling native extension ...", green
+ exec "node-waf clean build", callback
task "build", "Compile CoffeeScript to JavaScript", -> build onerror
task "watch", "Continously compile CoffeeScript to JavaScript", ->
View
7 TODO.md
@@ -9,13 +9,6 @@ zombie.js-todo(7) -- Wishlist
* Make sure `DOMContentLoaded` event fires after all stylesheets
are loaded
-* New script context
- * The execution context for all scripts on the page is the `Window`
- object itself
- * Node's `runInContext` accepts a sandbox, then creates an actual V8
- context by copying properties to/from, which breaks asynchronous
- scripts (timer, XHR, etc) which run in the contex, not the sandbox
-
* Navigation: Browser.open/close should work as a pair; look into supporting
window.open; fire unload event when navigating away from page.
View
38 src/zombie/browser.coffee
@@ -5,7 +5,8 @@ require "./jsdom_patches"
require "./forms"
require "./xpath"
History = require("./history").History
-
+require.paths.push "../../build/default"
+WindowContext = require("../../build/default/windowcontext").WindowContext
# Use the browser to open up new windows and load documents.
@@ -78,10 +79,6 @@ class Browser extends require("events").EventEmitter
# Windows
# -------
- require.paths.push "build/default"
- WindowContext = require("windowcontext").WindowContext
-
-
window = null
# ### browser.open() => Window
#
@@ -94,36 +91,9 @@ class Browser extends require("events").EventEmitter
history = features.history || new History
newWindow = jsdom.createWindow(html)
+ # Add context for evaluating scripts.
newWindow._evalContext = new WindowContext(newWindow)
- global = newWindow._evalContext.global
- global.decodeURI = decodeURI
- global.decodeURIComponent = decodeURIComponent
- global.encodeURI = encodeURI
- global.encodeURIComponent = encodeURIComponent
- global.escape = escape
- global.eval = eval
- global.isFinite = isFinite
- global.isNaN = isNaN
- global.parseFloat = parseFloat
- global.parseInt = parseInt
- global.unescape = unescape
- global.Array = [].constructor
- global.Boolean = Boolean
- global.Date = Date
- global.Error = Error
- global.Function = Function
- global.Math = Math
- global.Number = Number
- global.Object = {}.constructor
- global.RegExp = //.constructor
- global.String = newWindow._evalContext.evaluate("''.constructor")
-
- newWindow._evaluate = (code, filename)->
- try
- newWindow._evalContext.evaluate(code, filename)
- catch ex
- console.log ex.message[0..500]
- console.log ex.stack
+ newWindow._evaluate = (code, filename)-> newWindow._evalContext.evaluate(code, filename)
# Switch to the newly created window if it's interactive.
# Examples of non-interactive windows are frames.
View
23 src/zombie/windowcontext.cc
@@ -4,6 +4,8 @@
using namespace node;
using namespace v8;
+// Isolated V8 Context/global scope for evaluating JavaScript, with access to
+// all window methods/properties.
class WindowContext: ObjectWrap {
private:
@@ -35,6 +37,27 @@ class WindowContext: ObjectWrap {
this->global = Persistent<Object>::New(global);
tmpl->SetNamedPropertyHandler(GetProperty, SetProperty, NULL, DeleteProperty, EnumerateProperties, this->global);
context = Context::New(NULL, tmpl);
+
+ // Define constructor functions for primitives. We need to do this within
+ // the context, so "foo".constructor == String
+ context->Enter();
+ global->Set(String::New("Array"), Script::New(String::New("[].constructor"))->Run());
+ global->Set(String::New("Boolean"), Script::New(String::New("true.constructor"))->Run());
+ global->Set(String::New("Function"), Script::New(String::New("(function() {}).constructor"))->Run());
+ global->Set(String::New("Number"), Script::New(String::New("(1).constructor"))->Run());
+ global->Set(String::New("Object"), Script::New(String::New("({}).constructor"))->Run());
+ global->Set(String::New("RegExp"), Script::New(String::New("/./.constructor"))->Run());
+ global->Set(String::New("String"), Script::New(String::New("''.constructor"))->Run());
+ context->Exit();
+ // FIX ME: Define constructors for non-primitive types. We copy the
+ // constructor from Zombie's context, which is not a good thing.
+ const char* const list[] = { "Date", "Error", "Math", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent",
+ "escape", "eval", "isFinite", "isNaN", "parseFloat", "parseInt", "unescape" };
+ const size_t len = sizeof(list) / sizeof(list[0]);
+ for (int i = len ; i-- >0 ; ) {
+ Handle<String> str = String::New(list[i]);
+ global->Set(str, Script::New(str)->Run());
+ }
}
~WindowContext() {

0 comments on commit ef05ce0

Please sign in to comment.