def self.extended object
object.instance_eval do
outer = nil
scripts = {}
master = global["$master"] = evaluate("new Object", nil, nil, nil, global)
( class << self; self; end ).send :define_method, :master do
master
end
( class << self; self; end ).send :define_method, :evaluate do |*args|
( script, file, line, global, scope, fn ) = *args
scope ||= outer["$inner"]
raise "cannot evaluate nil script" if script.nil?
raise "cannot evaluate without a scope" if scope.nil?
raise "outer given when inner needed" if !scope == global and !scope["isInner"]
global = nil
if fn
compiled_script = scripts[fn]
end
compiled_script ||= compile(script, file, line, global)
raise "hell" if !compiled_script
if fn && !scripts[fn]
scripts[fn] = compiled_script
end
save = master["first_script_window"]
if false
p scope
if master["first_script_window"]
print "ignored: " + ( scope["location"] ? scope["location"]["href"] : "nil" ) + " using " + ( master["first_script_window"]["location"] ? master["first_script_window"]["location"]["href"] : "nil" ) + "\n"
else
print "pushing into " + ( scope["location"] ? scope["location"]["href"] : "nil" ) + "\n"
end
end
master["first_script_window"] ||= scope
raise "hell" if !master["first_script_window"]["isInner"] && master["first_script_window"] != self.global
v = nil
begin
v = evaluate_compiled_script(compiled_script,scope)
rescue Exception => e
raise e
ensure
master["first_script_window"] = save
end
v
end
evaluate( "print = function() {
var l = arguments.length
for( var i = 0; i < l; i++ ) {
var s;
if ( arguments[i] === null ) {
s = "null";
} else if ( arguments[i] === undefined ) {
s = "undefined"
} else {
s = arguments[i].toString();
}
Ruby.print(s);
if( i < l-1 ) {
Ruby.print(" ");
}
}
Ruby.print("\n");
Ruby['$stdout'].flush();
};
", nil, nil, nil, global )
evaluate "debug = function() {
var l = arguments.length
for( var i = 0; i < l; i++ ) {
var s;
if ( arguments[i] === null ) {
s = "null";
} else if ( arguments[i] === undefined ) {
s = "undefined"
} else {
s = arguments[i].toString();
}
Ruby['$stderr'].print(s);
if( i < l-1 ) {
Ruby['$stderr'].print(" ");
}
}
Ruby['$stderr'].print("\n");
Ruby['$stderr'].flush();
};
", nil, nil, nil, global
evaluate "puts = function() {
var l = arguments.length
for( var i = 0; i < l; i++ ) {
var s;
if ( arguments[i] === null ) {
s = "null";
} else if ( arguments[i] === undefined ) {
s = "undefined"
} else {
s = arguments[i].toString();
}
Ruby.print(s);
Ruby.eval("$stdout.flush")
}
};
", nil, nil, nil, global
master["runtime"] = self
window_index = -1
master["next_window_index"] = lambda { window_index += 1 }
master.symbols = [ "Johnson", "Ruby", "print", "debug", "puts", "load", "reload", "whichInterpreter", "multiwindow", "seal" ]
master.symbols.each { |symbol| master[symbol] = global[symbol] }
master["seal"] = lambda do |*args|
object, deep = *args
seal object, deep
end
master.whichInterpreter = "Johnson"
master.multiwindow = true
master.add_req_field = lambda { |r,k,v| r.add_field(k,v) }
top_level_js = nil
add_dep = nil
add_dep = lambda do |w, f|
if $envjsrb_wake
$wake_info << "##file://#{f}"
end
end
(class << self; self; end).send :define_method, :top_level_load do |path|
if $envjsrb_wake
$wake_info << "##{path}" if path
end
end
master.load = lambda { |*files|
if files.length == 2 && !(String === files[1])
f = files[0]
w = files[1]
uri = URI.parse f
if uri.scheme == nil
uri.scheme = "file"
begin
uri.path = Pathname.new(uri.path).realpath.to_s
rescue Errno::ENOENT; end
uri = URI.parse uri.to_s
end
uri_s = uri.to_s.sub %r(^file:/([^/])), 'file:///\1'
if uri.scheme == "file"
uri_s = uri.path
elsif uri.scheme == "data"
raise "implement 0"
end
v = open(uri_s).read.gsub(/\A#!.*$/, '')
loc = nil
add_dep.call w, f
evaluate(v, f, 1, w, w, f)
else
load *files
end
}
( class << self; self; end ).send :define_method, :load do |*files|
files.map { |f|
uri = URI.parse f
if uri.scheme == nil
uri.scheme = "file"
begin
uri.path = Pathname.new(uri.path).realpath.to_s
rescue Errno::ENOENT; end
uri = URI.parse uri.to_s
end
uri_s = uri.to_s.sub %r(^file:/([^/])), 'file:///\1'
if uri.scheme == "file"
begin
super uri.path
rescue Exception => e
if outer["$inner"]["onerror"]
evaluate("function(fn,scope,e){fn.call(scope,e)}").call(outer["$inner"]["onerror"], outer["$inner"], e)
else
raise e
end
end
elsif uri.scheme == "data"
raise "implement 1"
elsif uri.scheme == "javascript"
evaluate(URI.decode(uri.opaque),URI.decode(uri_s),1)
else
raise "hell 1: " + uri.inspect
end
}.last
end
master.reload = lambda { |*files|
if files.length == 2 && !(String === files[1])
f = files[0]
w = files[1]
v = open(f).read.gsub(/\A#!.*$/, '')
loc = nil
add_dep.call w, f
reevaluate(v, f, 1, w, w, f)
else
reload *files
end
}
master.evaluate = lambda { |v,w|
evaluate(v,"inline",1,w,w);
}
master.new_split_global_outer = lambda { new_split_global_outer }
master.new_split_global_inner = lambda { |outer,_| new_split_global_inner outer }
outer = new_split_global_outer
inner = new_split_global_inner( outer )
master.symbols.each do |symbol|
inner[symbol] = master[symbol]
end
inner["$inner"] = inner
inner["$master"] = master
inner["$options"] = evaluate("new Object", nil, nil, nil, inner);
inner["$options"].proxy = outer
inner.evaluate = lambda { |s|
return master.evaluate.call(s,inner);
}
inner.load = lambda { |*files|
files.each do |f|
master['load'].call f, inner
end
}
inner.reload = lambda { |*files|
files.each do |f|
master.reload.call f, inner
end
}
( class << self; self; end ).send :define_method, :wait do
master["finalize"] && master.finalize.call
master.eventLoop && master.eventLoop.wait
end
( class << self; self; end ).send :define_method, :_become_first_script_window do
inner = master.first_script_window
end
( class << self; self; end ).send :define_method, :reevaluate do |*args|
( script, file, line, global, scope, fn ) = *args
raise "cannot evaluate nil script" if script.nil?
global = nil
scope ||= inner
compiled_script = compile(script, file, line, global)
if fn
scripts[fn] = compiled_script
end
begin
evaluate_compiled_script(compiled_script,scope)
rescue Exception => e
p e
raise e
end
end
( class << self; self; end ).send :define_method, :"[]" do |key|
key == "this" && outer || outer[key]
end
( class << self; self; end ).send :define_method, :"[]=" do |k,v|
outer[k] = v
end
master['load'].call Envjs::EVENT_LOOP, global
static = new_global
master.symbols.each do |symbol|
static[symbol] = master[symbol]
end
static["$master"] = master
static["isInner"] = true
master['load'].call Envjs::STATIC, static
master["static"] = static
master['load'].call Envjs::ENVJS, inner
inner = nil
end
end