lib/opal/native.rb in opal-native-0.0.2 vs lib/opal/native.rb in opal-native-0.0.3

- old
+ new

@@ -6,117 +6,25 @@ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION # # 0. You just DO WHAT THE FUCK YOU WANT TO. #++ -class Module - %x{ - function define_attr_bridge (klass, target, name, getter, setter) { - if (getter) { - $opal.defn(klass, $opal.mid_to_jsid(name), function() { - var real = target; - - if (#{Symbol == `target`}) { - real = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this); - } - - var result = real[name]; - - return result == null ? nil : result; - }); - } - - if (setter) { - $opal.defn(klass, $opal.mid_to_jsid(name + '='), function (block, val) { - var real = target; - - if (#{Symbol === `target`}) { - real = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this); - } - - return real[name] = val; - }); - } - } - } - - def attr_accessor_bridge (target, *attrs) - %x{ - for (var i = 0, length = attrs.length; i < length; i++) { - define_attr_bridge(this, target, attrs[i], true, true); - } - } - - self +module Native + def self.=== (other) + `#{other} == null || !#{other}.o$klass` end - def attr_reader_bridge (target, *attrs) - %x{ - for (var i = 0, length = attrs.length; i < length; i++) { - define_attr_bridge(this, target, attrs[i], true, false); - } - } + def self.send (object, name, *args, &block) + args << block if block - self - end - - def attr_writer_bridge (target, *attrs) - %x{ - for (var i = 0, length = attrs.length; i < length; i++) { - define_attr_bridge(this, target, attrs[i], false, true); - } + args = args.map {|obj| + Native === obj ? obj : obj.to_native } - self + Kernel.Native(`object[name].apply(object, args)`) end - def attr_bridge (target, name, setter = false) - `define_attr_bridge(this, target, name, true, setter)` - - self - end - - def define_method_bridge (object, name, ali = nil) - %x{ - var self = this; - - $opal.defn(self, $opal.mid_to_jsid(#{ali || name}), function () { - var real = object; - - if (#{Symbol === object}) { - real = object[0] == '@' ? self[object.substr(1)] : self[$opal.mid_to_jsid(object)].apply(self); - } - - return real[name].apply(real, arguments); - }); - } - - nil - end -end - -module Kernel - def define_singleton_method_bridge (object, name, ali = nil) - %x{ - var self = this; - - $opal.defs(this, $opal.mid_to_jsid(#{ali || name}), function () { - var real = object; - - if (#{Symbol === object}) { - real = object[0] == '@' ? self[object.substr(1)] : self[$opal.mid_to_jsid(object)].apply(self); - } - - return real[name].apply(real, arguments); - }); - } - - nil - end -end - -module Native def self.included (klass) class << klass def from_native (object) instance = allocate instance.instance_variable_set :@native, object @@ -132,14 +40,16 @@ def to_native @native end - def native_send (name, *args) - return method_missing(name, *args) unless Opal.function? `#@native[name]` + def native_send (name, *args, &block) + unless Proc === `#@native[name]` + raise NoMethodError, "undefined method `#{name}` for #{`#@native.toString()`}" + end - `#@native[name].apply(#@native, args)` + Native.send(@native, name, *args, &block) end alias __native_send__ native_send end @@ -151,44 +61,30 @@ super update! end - def update! (name = nil) - unless name - %x{ - for (var name in #@native) { - #{update!(`name`)} - } - } + def [] (name) + Kernel.Native(`#@native[name]`) + end - return - end + def []= (name, value) + value = value.to_native unless Native === value - if Opal.function? `#@native[name]` - define_singleton_method_bridge @native, name + `#@native[name] = #{value}` - if respond_to? "#{name}=" - singleton_class.undef_method "#{name}=" - end - else - define_singleton_method name do - self[name] - end + update!(name) - define_singleton_method "#{name}=" do |value| - self[name] = value - end - end + value end def each return enum_for :each unless block_given? %x{ for (var name in #@native) { - #{yield Kernel.Object(`name`), Kernel.Object(`#@native[name]`)} + #{yield Kernel.Native(`name`), Kernel.Native(`#@native[name]`)} } } self end @@ -196,11 +92,11 @@ def each_key return enum_for :each_key unless block_given? %x{ for (var name in #@native) { - #{yield Kernel.Object(`name`)} + #{yield Kernel.Native(`name`)} } } self end @@ -208,49 +104,75 @@ def each_value return enum_for :each_value unless block_given? %x{ for (var name in #@native) { - #{yield Kernel.Object(`#@native[name]`)} + #{yield Kernel.Native(`#@native[name]`)} } } end - def [] (name) - Kernel.Object(`#@native[name] || nil`) + def inspect + "#<Native: #{`#@native.toString()`}>" end - def []= (name, value) - value = value.to_native unless Opal.native?(value) - - `#@native[name] = #{value}` - - update!(name) - - value + def keys + each_key.to_a end def nil? `#@native === null || #@native === undefined` end - def inspect - "#<Native: #{`#@native.toString()`}>" - end - def to_s `#@native.toString()` end def to_hash Hash[to_a] end + + def values + each_value.to_a + end + + def update! (name = nil) + unless name + %x{ + for (var name in #@native) { + #{update!(`name`)} + } + } + + return + end + + if Proc === `#@native[name]` + define_singleton_method name do |*args, &block| + __native_send__(name, *args, &block) + end + + if respond_to? "#{name}=" + singleton_class.undef_method "#{name}=" + end + else + define_singleton_method name do + self[name] + end + + define_singleton_method "#{name}=" do |value| + self[name] = value + end + end + end end module Kernel - def Object (object) - Opal.native?(object) ? Native::Object.new(object) : object + def Native (object) + return if `object == null` + + Native === object ? Native::Object.new(object) : object end end class Object def to_native @@ -264,11 +186,11 @@ end end class Array def to_native - map { |obj| Opal.object?(obj) ? obj.to_native : obj } + map { |obj| Native === obj ? obj : obj.to_native } end end class Hash def to_native @@ -278,11 +200,11 @@ for (var assoc in map) { var key = map[assoc][0], value = map[assoc][1]; - result[key] = #{Opal.native?(`value`)} ? value : #{`value`.to_native}; + result[key] = #{Native === `value` ? `value` : `value`.to_native}; } return result; } end @@ -308,11 +230,13 @@ def to_native %x{ var self = this; return (function () { - return self.apply(self.$S, arguments); + return self.apply(self.$S, [null].concat(#{ + `$slice.call(arguments)`.map { |o| Kernel.Native(o) } + })); }); } end end @@ -325,5 +249,7 @@ class String def to_native `this.valueOf()` end end + +require 'native/bridge'