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: dd76afce0fb9
Choose a base ref
...
head repository: opal/opal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e58a10108c37
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 27, 2014

  1. Copy the full SHA
    511efde View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    infinisil Silvan Mosberger
    Copy the full SHA
    e58a101 View commit details
Showing with 63 additions and 10 deletions.
  1. +20 −9 lib/opal/nodes/def.rb
  2. +43 −1 opal/corelib/runtime.js
29 changes: 20 additions & 9 deletions lib/opal/nodes/def.rb
Original file line number Diff line number Diff line change
@@ -99,26 +99,37 @@ def compile
if recvr
unshift 'Opal.defs(', recv(recvr), ", '$#{mid}', "
push ')'
elsif scope.class? and %w(Object BasicObject).include?(scope.name)
elsif uses_defn?(scope)
wrap "Opal.defn(self, '$#{mid}', ", ')'
elsif scope.module?
wrap "Opal.defn(self, '$#{mid}', ", ")"
elsif scope.class_scope?
scope.methods << "$#{mid}"
elsif scope.class?
unshift "#{scope.proto}#{jsid} = "
elsif scope.iter?
wrap "Opal.defn(self, '$#{mid}', ", ')'
elsif scope.type == :sclass
elsif scope.sclass?
unshift "self.$$proto#{jsid} = "
elsif scope.top?
unshift "Opal.Object.$$proto#{jsid} = "
else
unshift "def#{jsid} = "
raise "Unknown def type for `#{jsid}'"
end

wrap '(', ", nil) && '#{mid}'" if expr?
end

# Simple helper to check whether this method should be defined through
# `Opal.defn()` runtime helper.
#
# @param [Opal::Scope] scope
# @returns [Boolean]
#
def uses_defn?(scope)
if scope.iter? or scope.module?
true
elsif scope.class? and %w(Object BasicObject).include?(scope.name)
true
else
false
end
end

# Returns code used in debug mode to check arity of method call
def arity_check(args, opt, splat, block_name, mid)
meth = mid.to_s.inspect
44 changes: 43 additions & 1 deletion opal/corelib/runtime.js
Original file line number Diff line number Diff line change
@@ -911,6 +911,48 @@
}
};

/**
Donate a newly defined method defined on a module.
@param [RubyModule] module the module method defined on
@param [String] jsid javascript friendly method name (e.g. "$foo")
@param [Function] body method body of actual function
*/
function donate_module_defn(module, jsid, body) {
var included_in = module.$$dep;

module.$$methods = module.$$methods.concat([jsid]);

if (included_in) {
for (var i = 0, length = included_in.length; i < length; i++) {
var includee = included_in[i];
var dest = includee.$$proto;
var current = dest[jsid];


if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
// target class has already defined the same method name - do nothing
}
else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
// target class includes another module that has defined this method
// FIXME: we should resolve the order of modules to check if we
// should define it
dest[jsid] = body;
dest[jsid].$$donated = true;
}
else {
// neither a class, or module included by class, has defined method
dest[jsid] = body;
dest[jsid].$$donated = true;
}

if (includee.$$dep) {
Opal.donate(includee, [jsid], true);
}
}
}
}

/**
Used to define methods on an object. This is a helper method, used by the
compiled source to define methods on special case objects when the compiler
@@ -951,7 +993,7 @@
Opal.defn = function(obj, jsid, body) {
if (obj.$$is_mod) {
obj.$$proto[jsid] = body;
Opal.donate(obj, [jsid]);
donate_module_defn(obj, jsid, body);

body.$$owner = obj;