johnson 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +12 -0
- data/Manifest.txt +6 -4
- data/README.rdoc +2 -8
- data/Rakefile +11 -11
- data/bin/johnson +1 -3
- data/ext/spidermonkey/context.c +3 -2
- data/ext/spidermonkey/conversions.c +61 -27
- data/ext/spidermonkey/conversions.h +13 -0
- data/ext/spidermonkey/debugger.c +13 -5
- data/ext/spidermonkey/debugger.h +1 -0
- data/ext/spidermonkey/extconf.rb +2 -3
- data/ext/spidermonkey/jroot.h +11 -1
- data/ext/spidermonkey/js_land_proxy.c +21 -11
- data/ext/spidermonkey/ruby_land_proxy.c +116 -41
- data/ext/spidermonkey/ruby_land_proxy.h +21 -0
- data/ext/spidermonkey/runtime.c +85 -19
- data/ext/spidermonkey/runtime.h +2 -0
- data/ext/spidermonkey/spidermonkey.c +3 -1
- data/lib/johnson.rb +19 -27
- data/lib/johnson/cli.rb +2 -1
- data/{js/johnson → lib/johnson/js}/cli.js +0 -0
- data/lib/johnson/js/core.js +34 -0
- data/lib/johnson/js/prelude.js +149 -0
- data/lib/johnson/ruby_land_proxy.rb +113 -0
- data/lib/johnson/runtime.rb +92 -33
- data/lib/johnson/spidermonkey.rb +12 -0
- data/lib/johnson/spidermonkey/js_land_proxy.rb +10 -8
- data/lib/johnson/spidermonkey/ruby_land_proxy.rb +10 -47
- data/lib/johnson/spidermonkey/runtime.rb +11 -31
- data/test/johnson/conversions/array_test.rb +41 -3
- data/test/johnson/conversions/string_test.rb +12 -0
- data/test/johnson/custom_conversions_test.rb +50 -0
- data/test/johnson/prelude_test.rb +23 -0
- data/test/johnson/runtime_test.rb +82 -2
- data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +17 -1
- data/test/johnson/spidermonkey/runtime_test.rb +24 -0
- data/vendor/spidermonkey/jsprf.c +2 -0
- metadata +22 -9
- data/js/johnson/prelude.js +0 -80
- data/lib/johnson/version.rb +0 -3
- data/lib/rails/init.rb +0 -37
data/ext/spidermonkey/runtime.h
CHANGED
@@ -6,7 +6,9 @@
|
|
6
6
|
|
7
7
|
void Init_spidermonkey()
|
8
8
|
{
|
9
|
-
|
9
|
+
JS_SetCStringsAreUTF8();
|
10
|
+
|
11
|
+
VALUE johnson = rb_const_get(rb_mKernel, rb_intern("Johnson"));
|
10
12
|
VALUE spidermonkey = rb_define_module_under(johnson, "SpiderMonkey");
|
11
13
|
|
12
14
|
init_Johnson_SpiderMonkey_Context(spidermonkey);
|
data/lib/johnson.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
require "generator"
|
2
|
-
require "johnson/version"
|
3
2
|
|
4
|
-
# the
|
5
|
-
require "johnson/
|
6
|
-
|
7
|
-
|
8
|
-
require "johnson/
|
3
|
+
# the 'public' interface
|
4
|
+
require "johnson/error"
|
5
|
+
require "johnson/runtime"
|
6
|
+
require "johnson/ruby_land_proxy"
|
7
|
+
require "johnson/parser"
|
9
8
|
|
10
9
|
# visitable module and visitors
|
11
10
|
require "johnson/visitable"
|
@@ -14,39 +13,32 @@ require "johnson/visitors"
|
|
14
13
|
# parse tree nodes
|
15
14
|
require "johnson/nodes"
|
16
15
|
|
17
|
-
#
|
18
|
-
require "johnson/spidermonkey
|
19
|
-
require "johnson/spidermonkey/context"
|
20
|
-
require "johnson/spidermonkey/js_land_proxy"
|
21
|
-
require "johnson/spidermonkey/ruby_land_proxy"
|
22
|
-
require "johnson/spidermonkey/mutable_tree_visitor"
|
23
|
-
require "johnson/spidermonkey/debugger"
|
24
|
-
require "johnson/spidermonkey/immutable_node"
|
25
|
-
|
26
|
-
# the 'public' interface
|
27
|
-
require "johnson/error"
|
28
|
-
require "johnson/runtime"
|
29
|
-
require "johnson/parser"
|
30
|
-
|
31
|
-
# make sure all the Johnson JavaScript libs are in the load path
|
32
|
-
$LOAD_PATH.push(File.expand_path("#{File.dirname(__FILE__)}/../js"))
|
16
|
+
# SpiderMonkey, the default JS engine
|
17
|
+
require "johnson/spidermonkey"
|
33
18
|
|
34
19
|
module Johnson
|
35
|
-
|
36
|
-
|
20
|
+
VERSION = "1.2.0"
|
21
|
+
|
22
|
+
###
|
23
|
+
# Evaluate the given JavaScript +expression+ in a new runtime, after
|
24
|
+
# setting the given +vars+ into the global object.
|
25
|
+
#
|
26
|
+
# Returns the result of evaluating the given expression.
|
37
27
|
def self.evaluate(expression, vars={})
|
38
28
|
runtime = Johnson::Runtime.new
|
39
29
|
vars.each { |key, value| runtime[key] = value }
|
40
|
-
|
30
|
+
|
41
31
|
runtime.evaluate(expression)
|
42
32
|
end
|
43
|
-
|
33
|
+
|
44
34
|
def self.parse(js, *args)
|
45
35
|
Johnson::Parser.parse(js, *args)
|
46
36
|
end
|
47
37
|
|
48
38
|
###
|
49
|
-
# Create a new runtime and load all +files+.
|
39
|
+
# Create a new runtime and load all +files+.
|
40
|
+
#
|
41
|
+
# Returns the new Johnson::Runtime.
|
50
42
|
def self.load(*files)
|
51
43
|
rt = Johnson::Runtime.new
|
52
44
|
rt.load(*files)
|
data/lib/johnson/cli.rb
CHANGED
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
// Ruby ProxyHelper => JS original
|
3
|
+
Johnson.addConversion(function(v) {
|
4
|
+
return v.javascript_proxy;
|
5
|
+
}, (function(Helper_send) {
|
6
|
+
return function(v) {
|
7
|
+
return Helper_send('===', v);
|
8
|
+
};
|
9
|
+
})(Ruby.Johnson.RubyLandProxy.ProxyHelper.method('send')));
|
10
|
+
|
11
|
+
|
12
|
+
// Ruby Time => JS Date
|
13
|
+
Johnson.addWrapper(function(v) {
|
14
|
+
var d = new Date(v.to_f() * 1000);
|
15
|
+
d.wrappedRuby = v;
|
16
|
+
return d;
|
17
|
+
}, (function(Helper_send, RubyTime_send) {
|
18
|
+
return function(v) {
|
19
|
+
return !Helper_send('===', v) && RubyTime_send('===', v);
|
20
|
+
};
|
21
|
+
})(Ruby.Johnson.RubyLandProxy.ProxyHelper.method('send'), Ruby.Time.method('send')));
|
22
|
+
|
23
|
+
|
24
|
+
// Ruby Date/DateTime => JS Date
|
25
|
+
Johnson.addWrapper(function(v) {
|
26
|
+
var d = new Date(parseFloat(v.strftime('%Q')));
|
27
|
+
d.wrappedRuby = v;
|
28
|
+
return d;
|
29
|
+
}, (function(Helper_send, RubyDate_send) {
|
30
|
+
return function(v) {
|
31
|
+
return !Helper_send('===', v) && RubyDate_send('===', v);
|
32
|
+
};
|
33
|
+
})(Ruby.Johnson.RubyLandProxy.ProxyHelper.method('send'), Ruby.Date.method('send')));
|
34
|
+
|
@@ -0,0 +1,149 @@
|
|
1
|
+
var Johnson = {};
|
2
|
+
|
3
|
+
Johnson.Symbol = function(string) {
|
4
|
+
this.string = string;
|
5
|
+
};
|
6
|
+
|
7
|
+
Johnson.Symbol.prototype = {
|
8
|
+
toString: function() {
|
9
|
+
return this.string;
|
10
|
+
},
|
11
|
+
|
12
|
+
inspect: function() {
|
13
|
+
return ":" + this.toString();
|
14
|
+
}
|
15
|
+
};
|
16
|
+
|
17
|
+
Johnson.symbolCache = {};
|
18
|
+
|
19
|
+
Johnson.symbolize = function(string) {
|
20
|
+
if (!Johnson.symbolCache[string])
|
21
|
+
Johnson.symbolCache[string] = new Johnson.Symbol(string);
|
22
|
+
|
23
|
+
return Johnson.symbolCache[string];
|
24
|
+
};
|
25
|
+
|
26
|
+
Object.defineProperty(String.prototype, "toSymbol", function() {
|
27
|
+
return Johnson.symbolize(this.toString());
|
28
|
+
}, Object.READ_ONLY | Object.NON_DELETABLE);
|
29
|
+
|
30
|
+
(function(origApply) {
|
31
|
+
Object.defineProperty(Function.prototype, "apply", function(thisObj, arrayLike) {
|
32
|
+
var realArray = arrayLike;
|
33
|
+
if (arrayLike != null &&
|
34
|
+
!(arrayLike instanceof Array) &&
|
35
|
+
typeof arrayLike == 'object' &&
|
36
|
+
arrayLike.length != null) {
|
37
|
+
realArray = [];
|
38
|
+
for (var i = arrayLike.length - 1; i >= 0; i--) {
|
39
|
+
realArray[i] = arrayLike[i];
|
40
|
+
}
|
41
|
+
}
|
42
|
+
return origApply.call(this, thisObj, realArray);
|
43
|
+
}, Object.READ_ONLY | Object.NON_DELETABLE);
|
44
|
+
})(Function.prototype.apply);
|
45
|
+
|
46
|
+
(function() {
|
47
|
+
var wrappers = [];
|
48
|
+
var conversions = [];
|
49
|
+
Johnson.addConversion = function(conversion, test) {
|
50
|
+
conversions.push([conversion, test]);
|
51
|
+
};
|
52
|
+
Johnson.applyConversions = function(proxy) {
|
53
|
+
var converted = false;
|
54
|
+
conversions.forEach(function(pair) {
|
55
|
+
if (converted) return;
|
56
|
+
|
57
|
+
var [conversion, test] = pair;
|
58
|
+
|
59
|
+
if (test(proxy)) {
|
60
|
+
proxy = conversion(proxy);
|
61
|
+
converted = true;
|
62
|
+
}
|
63
|
+
});
|
64
|
+
return proxy;
|
65
|
+
};
|
66
|
+
Johnson.addWrapper = function(wrapper, test) {
|
67
|
+
wrappers.push([wrapper, test]);
|
68
|
+
};
|
69
|
+
Johnson.applyWrappers = function(proxy) {
|
70
|
+
wrappers.forEach(function(pair) {
|
71
|
+
var [wrapper, test] = pair;
|
72
|
+
|
73
|
+
if (test && !test(proxy)) return;
|
74
|
+
if (wrapper.test && !wrapper.test(proxy)) return;
|
75
|
+
|
76
|
+
if (typeof wrapper == 'function')
|
77
|
+
proxy = wrapper(proxy);
|
78
|
+
else
|
79
|
+
for (var [m, v] in wrapper)
|
80
|
+
proxy[m] = v;
|
81
|
+
});
|
82
|
+
return proxy;
|
83
|
+
};
|
84
|
+
})();
|
85
|
+
|
86
|
+
Johnson.Generator = function(enumerableProxy, namesOnly) {
|
87
|
+
if (enumerableProxy.js_properties) {
|
88
|
+
this.items = enumerableProxy.js_properties();
|
89
|
+
} else {
|
90
|
+
this.items = (enumerableProxy.keys ? enumerableProxy.keys() : []).concat(enumerableProxy.methods());
|
91
|
+
}
|
92
|
+
this.index = 0;
|
93
|
+
if (!namesOnly)
|
94
|
+
this.obj = enumerableProxy;
|
95
|
+
};
|
96
|
+
|
97
|
+
Johnson.Generator.prototype.__iterator__ = function() {
|
98
|
+
return this;
|
99
|
+
};
|
100
|
+
|
101
|
+
Johnson.Generator.prototype.hasNext = function() {
|
102
|
+
return this.index < this.items.length;
|
103
|
+
}
|
104
|
+
|
105
|
+
Johnson.Generator.prototype.next = function() {
|
106
|
+
if (this.hasNext()) {
|
107
|
+
var name = this.items[this.index++];
|
108
|
+
if (this.obj) {
|
109
|
+
return [name, this.obj[name]];
|
110
|
+
} else {
|
111
|
+
return name;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
throw StopIteration;
|
115
|
+
}
|
116
|
+
|
117
|
+
Johnson.Generator.create = function(namesOnly) {
|
118
|
+
return new Johnson.Generator(this, namesOnly);
|
119
|
+
}
|
120
|
+
|
121
|
+
Johnson.required = {};
|
122
|
+
|
123
|
+
Johnson.require = function(file) {
|
124
|
+
file = Ruby.File.join(Ruby.File.dirname(file),
|
125
|
+
Ruby.File.basename(file, ".js") + ".js");
|
126
|
+
|
127
|
+
if(Johnson.required[file]) return false;
|
128
|
+
|
129
|
+
for(var directory in Ruby["$LOAD_PATH"]) {
|
130
|
+
var path = Ruby.File.join(directory, file);
|
131
|
+
|
132
|
+
if(Ruby.File.send("file?", path)) {
|
133
|
+
Johnson.required[file] = true;
|
134
|
+
Johnson.runtime.load(path);
|
135
|
+
|
136
|
+
return true;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
throw Ruby.LoadError;
|
141
|
+
}
|
142
|
+
|
143
|
+
this.__defineGetter__("__FILE__", function() {
|
144
|
+
try { throw new Error; } catch(e) {
|
145
|
+
return e.stack.split("\n")[2].split("@")[1].split(":").slice(0,-1).join(":");
|
146
|
+
}
|
147
|
+
})
|
148
|
+
|
149
|
+
null; // no need to marshal a result
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Johnson #:nodoc:
|
2
|
+
class RubyLandProxy
|
3
|
+
class << self
|
4
|
+
def apply_wrappers(proxy)
|
5
|
+
wrappers.each do |(wrapper, test)|
|
6
|
+
next if test && !test.call(proxy)
|
7
|
+
next if wrapper.respond_to?(:test?) && !wrapper.test?(proxy)
|
8
|
+
|
9
|
+
if wrapper.respond_to?(:call)
|
10
|
+
proxy = wrapper.call(proxy)
|
11
|
+
break unless Johnson::RubyLandProxy === proxy
|
12
|
+
else
|
13
|
+
proxy.send :extend, wrapper
|
14
|
+
end
|
15
|
+
end
|
16
|
+
proxy
|
17
|
+
end
|
18
|
+
def add_wrapper(wrapper, &test)
|
19
|
+
wrappers.push [wrapper, test]
|
20
|
+
end
|
21
|
+
def insert_wrapper(wrapper, &test)
|
22
|
+
wrappers.unshift [wrapper, test]
|
23
|
+
end
|
24
|
+
def wrappers
|
25
|
+
@wrappers ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def apply_conversions(proxy)
|
29
|
+
conversions.each do |(conversion, test)|
|
30
|
+
if test.call(proxy)
|
31
|
+
converted = conversion.call(proxy)
|
32
|
+
return converted unless converted.eql? proxy
|
33
|
+
end
|
34
|
+
end
|
35
|
+
proxy
|
36
|
+
end
|
37
|
+
def add_conversion(conversion, &test)
|
38
|
+
conversions << [conversion, test]
|
39
|
+
end
|
40
|
+
def conversions
|
41
|
+
@conversions ||= []
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Callable
|
46
|
+
def self.test?(proxy)
|
47
|
+
proxy.respond_to?(:call_using)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_proc
|
51
|
+
@proc ||= Proc.new { |*args| call(*args) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def call(*args)
|
55
|
+
call_using(runtime.global, *args)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module ProxyHelper
|
60
|
+
def self.wrap(proxy, result)
|
61
|
+
result.extend self
|
62
|
+
result.javascript_proxy = proxy
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_accessor :javascript_proxy
|
67
|
+
end
|
68
|
+
|
69
|
+
add_wrapper Callable
|
70
|
+
|
71
|
+
# JS wrapper => Ruby original
|
72
|
+
add_conversion lambda {|o| o.wrappedRuby } do |o| o.respond_to? :wrappedRuby end
|
73
|
+
|
74
|
+
# JS Date => Ruby DateTime
|
75
|
+
add_conversion lambda {|o| ProxyHelper.wrap(o, DateTime.parse(o.toUTCString)) } do |o| o.respond_to? :setUTCMilliseconds end
|
76
|
+
|
77
|
+
include Enumerable
|
78
|
+
|
79
|
+
# FIXME: need to revisit array vs non-array proxy, to_a/to_ary semantics, etc.
|
80
|
+
def size; length; end
|
81
|
+
def to_ary; to_a; end
|
82
|
+
|
83
|
+
def initialize
|
84
|
+
raise Johnson::Error, "#{self.class.name} is an internal support class."
|
85
|
+
end
|
86
|
+
private :initialize
|
87
|
+
|
88
|
+
def inspect
|
89
|
+
toString
|
90
|
+
end
|
91
|
+
|
92
|
+
def method_missing(sym, *args, &block)
|
93
|
+
args << block if block_given?
|
94
|
+
|
95
|
+
name = sym.to_s
|
96
|
+
assignment = "=" == name[-1, 1]
|
97
|
+
|
98
|
+
# default behavior if the slot's not there
|
99
|
+
return super unless assignment || respond_to?(sym)
|
100
|
+
|
101
|
+
unless function_property?(name)
|
102
|
+
# for arity 0, treat it as a get
|
103
|
+
return self[name] if args.empty?
|
104
|
+
|
105
|
+
# arity 1 and quacking like an assignment, treat it as a set
|
106
|
+
return self[name[0..-2]] = args[0] if assignment && 1 == args.size
|
107
|
+
end
|
108
|
+
|
109
|
+
# okay, must really be a function
|
110
|
+
call_function_property(name, *args)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/johnson/runtime.rb
CHANGED
@@ -1,36 +1,104 @@
|
|
1
1
|
module Johnson
|
2
|
+
###
|
3
|
+
# An interface to a JavaScript engine.
|
2
4
|
class Runtime
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
PRELUDE_PATH = File.expand_path File.dirname(__FILE__) +
|
7
|
+
"/js/prelude.js" # :nodoc:
|
8
|
+
CORE_PATH = File.expand_path File.dirname(__FILE__) +
|
9
|
+
"/js/core.js" # :nodoc:
|
10
|
+
|
11
|
+
PRELUDE = IO.read PRELUDE_PATH # :nodoc:
|
12
|
+
CORE = IO.read CORE_PATH # :nodoc:
|
13
|
+
|
14
|
+
###
|
15
|
+
# Deprecated: Previously, returned the underlying JavaScript engine
|
16
|
+
# instance. Now returns self.
|
17
|
+
def delegate
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
###
|
22
|
+
# Create a new Runtime instance, using the default JavaScript
|
23
|
+
# engine.
|
24
|
+
#
|
25
|
+
# Optionally takes a parameter specifying which engine to use, but
|
26
|
+
# this is deprecated; instead, just create an instance of that
|
27
|
+
# engine's runtime directly.
|
28
|
+
#
|
29
|
+
# :call-seq:
|
30
|
+
# new(runtime_class=nil)
|
31
|
+
#
|
32
|
+
def self.new(*args)
|
33
|
+
return super if self < Johnson::Runtime
|
34
|
+
|
35
|
+
delegate = args.first
|
36
|
+
if delegate.is_a? Class
|
37
|
+
delegate.new
|
38
|
+
elsif delegate
|
39
|
+
delegate
|
40
|
+
else
|
41
|
+
Johnson::SpiderMonkey::Runtime.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
###
|
46
|
+
# Install the Johnson prelude into this runtime environment.
|
47
|
+
def initialize # :notnew:
|
48
|
+
evaluate PRELUDE, PRELUDE_PATH, 1
|
8
49
|
global.Johnson.runtime = self
|
50
|
+
global['Ruby'] = Object
|
51
|
+
evaluate CORE, CORE_PATH, 1
|
9
52
|
end
|
10
|
-
|
53
|
+
|
54
|
+
###
|
55
|
+
# Access the +key+ property of the JavaScript +global+ object.
|
11
56
|
def [](key)
|
12
|
-
|
57
|
+
global[key]
|
13
58
|
end
|
14
|
-
|
59
|
+
|
60
|
+
###
|
61
|
+
# Set the +key+ property of the JavaScript +global+ object to
|
62
|
+
# +value+.
|
15
63
|
def []=(key, value)
|
16
|
-
|
64
|
+
global[key] = value
|
17
65
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
66
|
+
|
67
|
+
|
68
|
+
###
|
69
|
+
# Execute the JavaScript source in +script+. If supplied, the script
|
70
|
+
# is marked as starting on line +linenum+ of +filename+.
|
71
|
+
#
|
72
|
+
# Equivalent to calling RubyLandScript#execute on the result of
|
73
|
+
# Runtime#compile.
|
74
|
+
def evaluate(script, filename = nil, linenum = nil)
|
75
|
+
return nil if script.nil?
|
76
|
+
compiled_script = compile(script, filename, linenum)
|
77
|
+
evaluate_compiled_script(compiled_script)
|
22
78
|
end
|
23
|
-
|
79
|
+
|
80
|
+
|
81
|
+
###
|
82
|
+
# The JavaScript unique Global Object.
|
24
83
|
def global
|
25
|
-
|
84
|
+
raise NotImplementedError
|
26
85
|
end
|
27
|
-
|
86
|
+
|
87
|
+
###
|
88
|
+
# Load and execute the named JavaScript +files+.
|
89
|
+
#
|
90
|
+
# Checks for (and skips) a shebang line at the top of any of them.
|
28
91
|
def load(*files)
|
29
|
-
files.map { |f|
|
92
|
+
files.map { |f|
|
93
|
+
evaluate(File.read(f).gsub(/\A#!.*$/, ''), f, 1)
|
94
|
+
}.last
|
30
95
|
end
|
31
96
|
|
32
97
|
###
|
33
|
-
#
|
98
|
+
# Search the Ruby load path for each of the named +files+, and
|
99
|
+
# evaluate them *if they have not yet been loaded*.
|
100
|
+
#
|
101
|
+
# Calls Johnson.require() in JavaScript on each filename in turn.
|
34
102
|
def require(*files)
|
35
103
|
files.each do |file|
|
36
104
|
evaluate("Johnson.require('#{file}');")
|
@@ -38,26 +106,17 @@ module Johnson
|
|
38
106
|
end
|
39
107
|
|
40
108
|
###
|
41
|
-
# Compile +script
|
109
|
+
# Compile the JavaScript source in +script+. If supplied, the script
|
110
|
+
# is marked as starting on line +linenum+ of +filename+.
|
42
111
|
def compile(script, filename=nil, linenum=nil)
|
43
|
-
|
112
|
+
raise NotImplementedError
|
44
113
|
end
|
45
114
|
|
46
115
|
###
|
47
|
-
#
|
48
|
-
|
49
|
-
delegate.break(filename, linenum, &block)
|
50
|
-
end
|
51
|
-
|
116
|
+
# Evaluates the given JS script, that should have been returned by a
|
117
|
+
# previous call to #compile().
|
52
118
|
def evaluate_compiled_script(script)
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
# Called by SpiderMonkey's garbage collector to determine whether or
|
58
|
-
# not it should GC
|
59
|
-
def should_sm_gc?
|
60
|
-
false
|
119
|
+
raise NotImplementedError
|
61
120
|
end
|
62
121
|
end
|
63
122
|
end
|