Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: opal/opal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4ab8117d40ca
Choose a base ref
...
head repository: opal/opal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 97f6ea3efe64
Choose a head ref
  • 7 commits
  • 11 files changed
  • 1 contributor

Commits on Aug 19, 2015

  1. Copy the full SHA
    9d7460c View commit details
  2. Copy the full SHA
    eaa9f8e View commit details
  3. Copy the full SHA
    17c0db1 View commit details
  4. Copy the full SHA
    a87861c View commit details
  5. Add reflection methods to Module

    meh committed Aug 19, 2015
    Copy the full SHA
    52eb1be View commit details
  6. Update filters

    meh committed Aug 19, 2015
    Copy the full SHA
    e762c25 View commit details
  7. Update CHANGELOG

    meh committed Aug 19, 2015
    Copy the full SHA
    97f6ea3 View commit details
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
## 0.9.0 (edge)

* `method_added`, `method_removed` and `method_undefined` reflection now works.

* `singleton_method_added`, `singleton_method_removed` and `singleton_method_undefined` reflection now works.

* Now you can bridge a native class to a Ruby class that inherits from another Ruby class

* `Numeric` semantics are now compliant with Ruby.

* `Complex` has been fully implemented.

* `Rational` has been fully implemented.

## 0.8.0 2015-07-16

* Update to Sprockets v3.0.
3 changes: 1 addition & 2 deletions lib/opal/nodes/definitions.rb
Original file line number Diff line number Diff line change
@@ -18,9 +18,8 @@ class UndefNode < Base

children :mid

# FIXME: we should be setting method to a stub method here
def compile
push "delete #{scope.proto}#{mid_to_jsid mid[1].to_s}"
push "Opal.udef(self, '$#{mid[1].to_s}');"
end
end

8 changes: 7 additions & 1 deletion opal/corelib/basic_object.rb
Original file line number Diff line number Diff line change
@@ -74,7 +74,13 @@ def instance_exec(*args, &block)
}
end

def singleton_method_added(name)
def singleton_method_added(*)
end

def singleton_method_removed(*)
end

def singleton_method_undefined(*)
end

def method_missing(symbol, *args, &block)
5 changes: 1 addition & 4 deletions opal/corelib/boolean.rb
Original file line number Diff line number Diff line change
@@ -4,11 +4,8 @@ class Boolean < `Boolean`
def __id__
`self.valueOf() ? 2 : 0`
end
alias object_id __id__

class << self
undef_method :new
end
alias object_id __id__

def !
`self != true`
62 changes: 39 additions & 23 deletions opal/corelib/module.rb
Original file line number Diff line number Diff line change
@@ -282,18 +282,21 @@ def define_method(name, method = undefined, &block)
end

block ||= case method
when Proc
method
when Method
`#{method.to_proc}.$$unbound`
when UnboundMethod
lambda do |*args|
bound = method.bind(self)
bound.call *args
end
else
raise TypeError, "wrong argument type #{block.class} (expected Proc/Method)"
end
when Proc
method

when Method
`#{method.to_proc}.$$unbound`

when UnboundMethod
lambda {|*args|
bound = method.bind(self)
bound.call(*args)
}

else
raise TypeError, "wrong argument type #{block.class} (expected Proc/Method)"
end

%x{
var id = '$' + name;
@@ -302,23 +305,26 @@ def define_method(name, method = undefined, &block)
block.$$s = null;
block.$$def = block;
if (self.$$is_singleton) {
self.$$proto[id] = block;
}
else {
Opal.defn(self, id, block);
}
Opal.def(self, id, block);
return name;
}
end

def remove_method(name)
`Opal.undef(self, '$' + name)`
def remove_method(*names)
%x{
for (var i = 0, length = names.length; i < length; i++) {
Opal.rdef(self, "$" + names[i]);
}
}

self
end

def singleton_class?
`!!self.$$is_singleton`
end

def include(*mods)
%x{
for (var i = mods.length - 1; i >= 0; i--) {
@@ -407,7 +413,13 @@ def included(mod)
def extended(mod)
end

def method_added(name)
def method_added(*)
end

def method_removed(*)
end

def method_undefined(*)
end

def module_eval(&block)
@@ -548,8 +560,12 @@ def to_s
`self.$$name` || "#<#{`self.$$is_mod ? 'Module' : 'Class'`}:0x#{__id__.to_s(16)}>"
end

def undef_method(symbol)
`Opal.add_stub_for(self.$$proto, "$" + symbol)`
def undef_method(*names)
%x{
for (var i = 0, length = names.length; i < length; i++) {
Opal.udef(self, "$" + names[i]);
}
}

self
end
63 changes: 51 additions & 12 deletions opal/corelib/runtime.js
Original file line number Diff line number Diff line change
@@ -1154,10 +1154,6 @@
@returns [null]
*/
Opal.defn = function(obj, jsid, body) {
if (obj.$method_added && !obj.$method_added.$$stub) {
obj.$method_added(jsid.substr(1));
}

obj.$$proto[jsid] = body;

if (obj.$$is_module) {
@@ -1178,6 +1174,10 @@
}
}

if (obj.$method_added && !obj.$method_added.$$stub) {
obj.$method_added(jsid.substr(1));
}

return nil;
};

@@ -1186,23 +1186,23 @@
*/
Opal.defs = function(obj, jsid, body) {
if (obj.$$is_singleton) {
obj.$$proto[jsid] = body;

if (obj.$$proto.$singleton_method_added && !obj.$$proto.$singleton_method_added.$$stub) {
obj.$$proto.$singleton_method_added(jsid.substr(1));
}

obj.$$proto[jsid] = body;
}
else {
if (obj.$singleton_method_added && !obj.$singleton_method_added.$$stub) {
obj.$singleton_method_added(jsid.substr(1));
}

if (obj.$$is_class || obj.$$is_module) {
obj.constructor.prototype[jsid] = body;
}
else {
obj[jsid] = body;
}

if (obj.$singleton_method_added && !obj.$singleton_method_added.$$stub) {
obj.$singleton_method_added(jsid.substr(1));
}
}
};

@@ -1219,10 +1219,49 @@
};

/*
* Called to remove a method.
* Called from #remove_method.
*/
Opal.undef = function(obj, jsid) {
Opal.rdef = function(obj, jsid) {
// TODO: remove from bridges as well

if (!$hasOwn.call(obj.$$proto, jsid)) {
throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
}

delete obj.$$proto[jsid];

if (obj.$$is_singleton) {
if (obj.$$proto.$singleton_method_removed && !obj.$$proto.$singleton_method_removed.$$stub) {
obj.$$proto.$singleton_method_removed(jsid.substr(1));
}
}
else {
if (obj.$method_removed && !obj.$method_removed.$$stub) {
obj.$method_removed(jsid.substr(1));
}
}
};

/*
* Called from #undef_method.
*/
Opal.udef = function(obj, jsid) {
if (!obj.$$proto[jsid] || obj.$$proto[jsid].$$stub) {
throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
}

Opal.add_stub_for(obj.$$proto, jsid);

if (obj.$$is_singleton) {
if (obj.$$proto.$singleton_method_undefined && !obj.$$proto.$singleton_method_undefined.$$stub) {
obj.$$proto.$singleton_method_undefined(jsid.substr(1));
}
}
else {
if (obj.$method_undefined && !obj.$method_undefined.$$stub) {
obj.$method_undefined(jsid.substr(1));
}
}
};

// This black magic is required to avoid clashes of internal special fields,
77 changes: 1 addition & 76 deletions spec/filters/bugs/module.rb
Original file line number Diff line number Diff line change
@@ -129,6 +129,7 @@
fails "Module#include ignores modules it has already included via module mutual inclusion"
fails "Module#include preserves ancestor order"
fails "Module#include raises a TypeError when the argument is not a Module"
fails "Module#include does not override existing constants in modules and classes"
fails "Module#include recursively includes new mixins"
fails "Module#include? raises a TypeError when no module was given"
fails "Module#include? returns true if the given module is included by self or one of it's ancestors"
@@ -142,10 +143,6 @@
fails "Module#method_defined? returns true if a public or private method with the given name is defined in self, self's ancestors or one of self's included modules"
fails "Module#method_defined? converts the given name to a string using to_str"
fails "Module#method_defined? raises a TypeError when the given object is not a string/symbol/fixnum"
fails "Module#method_removed is called when a method is removed from self"
fails "Module#method_removed returns nil in the default implementation"
fails "Module#method_undefined is called when a method is undefined from self"
fails "Module#method_undefined returns nil in the default implementation"
fails "Module#module_eval adds methods respecting the lexical constant scope"
fails "Module#module_eval converts a non-string filename to a string using to_str"
fails "Module#module_eval converts non string eval-string to string using to_str"
@@ -200,91 +197,19 @@
fails "Module#prepend_features on Class raises a TypeError if calling after rebinded to Class"
fails "Module#prepend_features raises an ArgumentError on a cyclic prepend"
fails "Module#prepended is invoked when self is prepended to another module or class"
fails "Module#protected makes a public Object instance method protected in Kernel"
fails "Module#protected makes a public Object instance method protected in a new module"
fails "Module#protected makes an existing class method protected"
fails "Module#protected raises a NameError when given an undefined name"
fails "Module#protected returns self"
fails "Module#protected without arguments affects evaled method definitions when itself is outside the eval"
fails "Module#protected without arguments affects normally if itself and following method definitions are inside a eval"
fails "Module#protected without arguments affects normally if itself and method definitions are inside a module_eval"
fails "Module#protected without arguments continues setting visibility if the body encounters other visibility setters with arguments"
fails "Module#protected without arguments does not affect method definitions when itself is inside an eval and method definitions are outside"
fails "Module#protected without arguments does not affect module_evaled method definitions when itself is outside the eval"
fails "Module#protected without arguments sets visibility to following method definitions"
fails "Module#protected without arguments stops setting visibility if the body encounters other visibility setters without arguments"
fails "Module#protected_instance_methods default list should be the same as passing true as an argument"
fails "Module#protected_instance_methods returns a list of protected methods in module and its ancestors"
fails "Module#protected_instance_methods when not passed an argument returns a unique list for a class including a module"
fails "Module#protected_instance_methods when not passed an argument returns a unique list for a subclass"
fails "Module#protected_instance_methods when passed false as a parameter, should return only methods defined in that module"
fails "Module#protected_instance_methods when passed true returns a unique list for a class including a module"
fails "Module#protected_instance_methods when passed true returns a unique list for a subclass"
fails "Module#protected_method_defined? accepts symbols for the method name"
fails "Module#protected_method_defined? calls #to_str to convert an Object"
fails "Module#protected_method_defined? raises a TypeError if passed a Fixnum"
fails "Module#protected_method_defined? raises a TypeError if passed an object that defines #to_sym"
fails "Module#protected_method_defined? raises a TypeError if passed an object that does not defined #to_str"
fails "Module#protected_method_defined? raises a TypeError if passed false"
fails "Module#protected_method_defined? raises a TypeError if passed nil"
fails "Module#protected_method_defined? returns true if the named protected method is defined by module or its ancestors"
fails "Module#public is a private method"
fails "Module#public makes a private Object instance method public in Kernel"
fails "Module#public makes a private Object instance method public in a new module"
fails "Module#public raises a NameError when given an undefined name"
fails "Module#public returns self"
fails "Module#public without arguments affects evaled method definitions when itself is outside the eval"
fails "Module#public without arguments affects normally if itself and following method definitions are inside a eval"
fails "Module#public without arguments does not affect method definitions when itself is inside an eval and method definitions are outside"
fails "Module#public without arguments does not affect module_evaled method definitions when itself is outside the eval"
fails "Module#public without arguments stops setting visibility if the body encounters other visibility setters without arguments"
fails "Module#public_class_method accepts more than one method at a time"
fails "Module#public_class_method makes an existing class method public up the inheritance tree"
fails "Module#public_class_method makes an existing class method public"
fails "Module#public_class_method raises a NameError if class method doesn't exist"
fails "Module#public_class_method raises a NameError when the given name is an instance method"
fails "Module#public_class_method raises a NameError when the given name is not a method"
fails "Module#public_constant accepts multiple names"
fails "Module#public_constant accepts strings as constant names"
fails "Module#public_instance_method is a public method"
fails "Module#public_instance_method raises a TypeError when given a name is not Symbol or String"
fails "Module#public_instance_method requires an argument"
fails "Module#public_instance_method sets the NameError#name attribute to the name of the missing method"
fails "Module#public_instance_method when given a public method name accepts if the name is a Symbol or String"
fails "Module#public_instance_method when given a public method name returns an UnboundMethod corresponding to the defined Module"
fails "Module#public_instance_methods when passed false as a parameter, should return only methods defined in that module"
fails "Module#public_method_defined? calls #to_str to convert an Object"
fails "Module#public_method_defined? raises a TypeError if passed a Fixnum"
fails "Module#public_method_defined? raises a TypeError if passed an object that defines #to_sym"
fails "Module#public_method_defined? raises a TypeError if passed an object that does not defined #to_str"
fails "Module#public_method_defined? raises a TypeError if passed false"
fails "Module#public_method_defined? raises a TypeError if passed nil"
fails "Module#public_method_defined? returns false if method is not a public method"
fails "Module#remove_class_variable raises a NameError when an uninitialized class variable is given"
fails "Module#remove_class_variable raises a NameError when passed a symbol with no leading @"
fails "Module#remove_class_variable raises a NameError when passed a symbol with one leading @"
fails "Module#remove_class_variable removes a class variable defined in a metaclass"
fails "Module#remove_class_variable removes class variable"
fails "Module#remove_class_variable returns the value of removing class variable"
fails "Module#remove_const calls #to_str to convert the given name to a String"
fails "Module#remove_const is a private method"
fails "Module#remove_const raises a NameError and does not call #const_missing if the constant is not defined directly in the module"
fails "Module#remove_const raises a NameError and does not call #const_missing if the constant is not defined"
fails "Module#remove_const raises a NameError if the name contains non-alphabetic characters except '_'"
fails "Module#remove_const raises a NameError if the name does not start with a capital letter"
fails "Module#remove_const raises a NameError if the name starts with a non-alphabetic character"
fails "Module#remove_const raises a TypeError if conversion to a String by calling #to_str fails"
fails "Module#remove_method accepts multiple arguments"
fails "Module#remove_method does not remove any instance methods when argument not given"
fails "Module#remove_method is a private method"
fails "Module#remove_method raises a NameError when attempting to remove a missing method"
fails "Module#remove_method raises a NameError when attempting to remove method further up the inheritance tree"
fails "Module#undef_method does not undef any instance methods when argument not given"
fails "Module#undef_method is a private method"
fails "Module#undef_method raises a NameError when passed a missing name"
fails "Module#undef_method requires multiple arguments"
fails "Module#undef_method with string removes a method defined in a super class"
fails "Module#undef_method with symbol removes a method defined in a super class"
fails "Module.allocate returns a fully-formed instance of Module"
fails "Module.constants returns Module's constants when given a parameter"
fails "Module.constants returns an array of Symbol names"
3 changes: 3 additions & 0 deletions spec/filters/bugs/proc.rb
Original file line number Diff line number Diff line change
@@ -35,4 +35,7 @@
fails "Proc.new with an associated block returns a new Proc instance from the block passed to the containing method"
fails "Proc.new with an associated block returns a subclass of Proc"
fails "Proc.new without a block uses the implicit block from an enclosing method"

fails "Module#remove_method accepts multiple arguments"
fails "Module#undef_method requires multiple arguments"
end
12 changes: 0 additions & 12 deletions spec/filters/unsupported/basicobject.rb

This file was deleted.

Loading