opal 0.7.0.beta3 → 0.7.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitmodules +4 -0
- data/.travis.yml +7 -3
- data/.yardopts +6 -0
- data/CHANGELOG.md +28 -0
- data/Gemfile +1 -1
- data/README.md +3 -12
- data/Rakefile +4 -150
- data/bin/opal-mspec +1 -1
- data/docs/compiler_directives.md +127 -0
- data/examples/rack/.gitignore +1 -0
- data/examples/rack/app/user.rb +1 -0
- data/lib/mspec/opal/special_calls.rb +15 -2
- data/lib/opal/builder.rb +15 -8
- data/lib/opal/compiler.rb +75 -4
- data/lib/opal/erb.rb +22 -2
- data/lib/opal/fragment.rb +17 -5
- data/lib/opal/nodes/def.rb +174 -53
- data/lib/opal/nodes/if.rb +14 -0
- data/lib/opal/nodes/module.rb +0 -1
- data/lib/opal/nodes/rescue.rb +10 -2
- data/lib/opal/nodes/scope.rb +0 -17
- data/lib/opal/parser.rb +83 -19
- data/lib/opal/parser/grammar.rb +2511 -2414
- data/lib/opal/parser/grammar.y +71 -9
- data/lib/opal/parser/lexer.rb +44 -12
- data/lib/opal/parser/parser_scope.rb +3 -0
- data/lib/opal/parser/sexp.rb +7 -1
- data/lib/opal/paths.rb +5 -5
- data/lib/opal/sprockets/environment.rb +2 -10
- data/lib/opal/sprockets/path_reader.rb +1 -1
- data/lib/opal/sprockets/processor.rb +1 -0
- data/lib/opal/sprockets/server.rb +2 -0
- data/lib/opal/util.rb +7 -2
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -0
- data/opal/README.md +1 -1
- data/opal/corelib/dir.rb +1 -1
- data/opal/corelib/enumerable.rb +3 -1
- data/opal/corelib/error.rb +3 -0
- data/opal/corelib/file.rb +2 -0
- data/opal/corelib/hash.rb +3 -0
- data/opal/corelib/io.rb +15 -1
- data/opal/corelib/kernel.rb +8 -0
- data/opal/corelib/module.rb +42 -17
- data/opal/corelib/runtime.js +223 -49
- data/opal/corelib/string.rb +1 -1
- data/opal/corelib/struct.rb +1 -7
- data/spec/README.md +8 -0
- data/spec/filters/bugs/language.rb +1 -0
- data/spec/filters/bugs/module.rb +4 -0
- data/spec/filters/unsupported/frozen.rb +2 -0
- data/spec/lib/compiler/pre_processed_conditionals_spec.rb +87 -0
- data/spec/lib/compiler_spec.rb +1 -67
- data/spec/lib/fixtures/file_with_directives.js +2 -0
- data/spec/lib/fixtures/required_file.js +1 -0
- data/spec/lib/parser/def_spec.rb +29 -16
- data/spec/lib/parser/variables_spec.rb +5 -5
- data/spec/lib/sprockets/path_reader_spec.rb +24 -8
- data/spec/lib/sprockets/server_spec.rb +10 -3
- data/spec/opal/core/date_spec.rb +14 -0
- data/spec/opal/core/language/versions/def_2_0_spec.rb +62 -0
- data/spec/opal/core/language_spec.rb +23 -0
- data/spec/opal/core/runtime/donate_spec.rb +53 -0
- data/spec/opal/stdlib/native/native_alias_spec.rb +19 -0
- data/spec/opal/stdlib/native/native_class_spec.rb +18 -0
- data/spec/opal/stdlib/native/native_module_spec.rb +13 -0
- data/spec/rubyspecs +2 -0
- data/stdlib/buffer.rb +1 -0
- data/stdlib/date.rb +18 -0
- data/stdlib/encoding.rb +3 -2
- data/stdlib/minitest.rb +780 -0
- data/stdlib/minitest/assertions.rb +662 -0
- data/stdlib/minitest/autorun.rb +12 -0
- data/stdlib/minitest/benchmark.rb +426 -0
- data/stdlib/minitest/expectations.rb +281 -0
- data/stdlib/minitest/hell.rb +11 -0
- data/stdlib/minitest/mock.rb +220 -0
- data/stdlib/minitest/parallel.rb +65 -0
- data/stdlib/minitest/pride.rb +4 -0
- data/stdlib/minitest/pride_plugin.rb +142 -0
- data/stdlib/minitest/spec.rb +310 -0
- data/stdlib/minitest/test.rb +293 -0
- data/stdlib/minitest/unit.rb +45 -0
- data/stdlib/native.rb +12 -3
- data/stdlib/nodejs/process.rb +16 -2
- data/stdlib/promise.rb +99 -0
- data/stdlib/test/unit.rb +10 -0
- data/stdlib/thread.rb +4 -0
- data/tasks/building.rake +58 -0
- data/tasks/documentation.rake +38 -0
- data/tasks/documenting.rake +37 -0
- data/tasks/testing.rake +102 -0
- metadata +57 -2
data/opal/corelib/module.rb
CHANGED
@@ -47,11 +47,17 @@ class Module
|
|
47
47
|
|
48
48
|
def alias_method(newname, oldname)
|
49
49
|
%x{
|
50
|
-
|
50
|
+
var newjsid = '$' + newname,
|
51
|
+
body = self.$$proto['$' + oldname];
|
51
52
|
|
52
|
-
if (self.$$
|
53
|
-
|
53
|
+
if (self.$$is_singleton) {
|
54
|
+
self.$$proto[newjsid] = body;
|
54
55
|
}
|
56
|
+
else {
|
57
|
+
Opal.defn(self, newjsid, body);
|
58
|
+
}
|
59
|
+
|
60
|
+
return self;
|
55
61
|
}
|
56
62
|
self
|
57
63
|
end
|
@@ -88,18 +94,16 @@ class Module
|
|
88
94
|
|
89
95
|
def attr_reader(*names)
|
90
96
|
%x{
|
91
|
-
var proto = self.$$proto, cls = self;
|
92
97
|
for (var i = 0, length = names.length; i < length; i++) {
|
93
98
|
(function(name) {
|
94
|
-
proto[name] = nil;
|
99
|
+
self.$$proto[name] = nil;
|
95
100
|
var func = function() { return this[name] };
|
96
101
|
|
97
|
-
if (
|
98
|
-
proto.constructor.prototype['$' + name] = func;
|
102
|
+
if (self.$$is_singleton) {
|
103
|
+
self.$$proto.constructor.prototype['$' + name] = func;
|
99
104
|
}
|
100
105
|
else {
|
101
|
-
|
102
|
-
Opal.donate(self, ['$' + name ]);
|
106
|
+
Opal.defn(self, '$' + name, func);
|
103
107
|
}
|
104
108
|
})(names[i]);
|
105
109
|
}
|
@@ -110,18 +114,16 @@ class Module
|
|
110
114
|
|
111
115
|
def attr_writer(*names)
|
112
116
|
%x{
|
113
|
-
var proto = self.$$proto, cls = self;
|
114
117
|
for (var i = 0, length = names.length; i < length; i++) {
|
115
118
|
(function(name) {
|
116
|
-
proto[name] = nil;
|
119
|
+
self.$$proto[name] = nil;
|
117
120
|
var func = function(value) { return this[name] = value; };
|
118
121
|
|
119
|
-
if (
|
120
|
-
proto.constructor.prototype['$' + name + '='] = func;
|
122
|
+
if (self.$$is_singleton) {
|
123
|
+
self.$$proto.constructor.prototype['$' + name + '='] = func;
|
121
124
|
}
|
122
125
|
else {
|
123
|
-
|
124
|
-
Opal.donate(self, ['$' + name + '=']);
|
126
|
+
Opal.defn(self, '$' + name + '=', func);
|
125
127
|
}
|
126
128
|
})(names[i]);
|
127
129
|
}
|
@@ -144,6 +146,25 @@ class Module
|
|
144
146
|
}
|
145
147
|
end
|
146
148
|
|
149
|
+
def class_variable_get(name)
|
150
|
+
name = Opal.coerce_to!(name, String, :to_str)
|
151
|
+
raise NameError, 'class vars should start with @@' if `name.length < 3 || name.slice(0,2) !== '@@'`
|
152
|
+
%x{
|
153
|
+
var value = Opal.cvars[name.slice(2)];
|
154
|
+
#{raise NameError, 'uninitialized class variable @@a in' if `value == null`}
|
155
|
+
return value;
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def class_variable_set(name, value)
|
160
|
+
name = Opal.coerce_to!(name, String, :to_str)
|
161
|
+
raise NameError if `name.length < 3 || name.slice(0,2) !== '@@'`
|
162
|
+
%x{
|
163
|
+
Opal.cvars[name.slice(2)] = value;
|
164
|
+
return value;
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
147
168
|
def constants
|
148
169
|
`self.$$scope.constants`
|
149
170
|
end
|
@@ -241,8 +262,12 @@ class Module
|
|
241
262
|
block.$$s = null;
|
242
263
|
block.$$def = block;
|
243
264
|
|
244
|
-
self.$$
|
245
|
-
|
265
|
+
if (self.$$is_singleton) {
|
266
|
+
self.$$proto[jsid] = block;
|
267
|
+
}
|
268
|
+
else {
|
269
|
+
Opal.defn(self, jsid, block);
|
270
|
+
}
|
246
271
|
|
247
272
|
return name;
|
248
273
|
}
|
data/opal/corelib/runtime.js
CHANGED
@@ -43,7 +43,22 @@
|
|
43
43
|
// Globals table
|
44
44
|
Opal.gvars = {};
|
45
45
|
|
46
|
-
|
46
|
+
/**
|
47
|
+
Get a constant on the given scope. Every class and module in Opal has a
|
48
|
+
scope used to store, and inherit, constants. For example, the top level
|
49
|
+
`Object` in ruby has a scope accessible as `Opal.Object.$$scope`.
|
50
|
+
|
51
|
+
To get the `Array` class using this scope, you could use:
|
52
|
+
|
53
|
+
Opal.Object.$$scope.get("Array")
|
54
|
+
|
55
|
+
If a constant with the given name cannot be found, then a dispatch to the
|
56
|
+
class/module's `#const_method` is called, which by default will raise an
|
57
|
+
error.
|
58
|
+
|
59
|
+
@param [String] name the name of the constant to lookup
|
60
|
+
@returns [RubyObject]
|
61
|
+
*/
|
47
62
|
Opal.get = function(name) {
|
48
63
|
var constant = this[name];
|
49
64
|
|
@@ -148,7 +163,7 @@
|
|
148
163
|
|
149
164
|
// Copy all parent constants to child, unless parent is Object
|
150
165
|
if (superklass !== ObjectClass && superklass !== BasicObjectClass) {
|
151
|
-
|
166
|
+
donate_constants(superklass, klass);
|
152
167
|
}
|
153
168
|
|
154
169
|
// call .inherited() hook with new class on the superclass
|
@@ -253,7 +268,26 @@
|
|
253
268
|
module.$$inc = [];
|
254
269
|
}
|
255
270
|
|
256
|
-
|
271
|
+
/**
|
272
|
+
Define new module (or return existing module). The given `base` is basically
|
273
|
+
the current `self` value the `module` statement was defined in. If this is
|
274
|
+
a ruby module or class, then it is used, otherwise if the base is a ruby
|
275
|
+
object then that objects real ruby class is used (e.g. if the base is the
|
276
|
+
main object, then the top level `Object` class is used as the base).
|
277
|
+
|
278
|
+
If a module of the given name is already defined in the base, then that
|
279
|
+
instance is just returned.
|
280
|
+
|
281
|
+
If there is a class of the given name in the base, then an error is
|
282
|
+
generated instead (cannot have a class and module of same name in same base).
|
283
|
+
|
284
|
+
Otherwise, a new module is created in the base with the given name, and that
|
285
|
+
new instance is returned back (to be referenced at runtime).
|
286
|
+
|
287
|
+
@param [RubyModule or Class] base class or module this definition is inside
|
288
|
+
@param [String] id the name of the new (or existing) module
|
289
|
+
@returns [RubyModule]
|
290
|
+
*/
|
257
291
|
Opal.module = function(base, id) {
|
258
292
|
var module;
|
259
293
|
|
@@ -303,11 +337,19 @@
|
|
303
337
|
return module;
|
304
338
|
}
|
305
339
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
340
|
+
/**
|
341
|
+
Return the singleton class for the passed object.
|
342
|
+
|
343
|
+
If the given object alredy has a singleton class, then it will be stored on
|
344
|
+
the object as the `$$meta` property. If this exists, then it is simply
|
345
|
+
returned back.
|
346
|
+
|
347
|
+
Otherwise, a new singleton object for the class or object is created, set on
|
348
|
+
the object at `$$meta` for future use, and then returned.
|
349
|
+
|
350
|
+
@param [RubyObject] object the ruby object
|
351
|
+
@returns [RubyClass] the singleton class for object
|
352
|
+
*/
|
311
353
|
Opal.get_singleton_class = function(object) {
|
312
354
|
if (object.$$meta) {
|
313
355
|
return object.$$meta;
|
@@ -320,11 +362,14 @@
|
|
320
362
|
return build_object_singleton_class(object);
|
321
363
|
};
|
322
364
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
365
|
+
/**
|
366
|
+
Build the singleton class for an existing class.
|
367
|
+
|
368
|
+
NOTE: Actually in MRI a class' singleton class inherits from its
|
369
|
+
superclass' singleton class which in turn inherits from Class.
|
370
|
+
|
371
|
+
@param [RubyClass] klass
|
372
|
+
@returns [RubyClass]
|
328
373
|
*/
|
329
374
|
function build_class_singleton_class(klass) {
|
330
375
|
var meta = new Opal.Class.$$alloc;
|
@@ -340,8 +385,11 @@
|
|
340
385
|
return klass.$$meta = meta;
|
341
386
|
}
|
342
387
|
|
343
|
-
|
344
|
-
|
388
|
+
/**
|
389
|
+
Build the singleton class for a Ruby (non class) Object.
|
390
|
+
|
391
|
+
@param [RubyObject] object
|
392
|
+
@returns [RubyClass]
|
345
393
|
*/
|
346
394
|
function build_object_singleton_class(object) {
|
347
395
|
var orig_class = object.$$class,
|
@@ -358,9 +406,26 @@
|
|
358
406
|
return object.$$meta = meta;
|
359
407
|
}
|
360
408
|
|
361
|
-
|
362
|
-
|
363
|
-
|
409
|
+
/**
|
410
|
+
The actual inclusion of a module into a class.
|
411
|
+
|
412
|
+
## Class `$$parent` and `iclass`
|
413
|
+
|
414
|
+
To handle `super` calls, every class has a `$$parent`. This parent is
|
415
|
+
used to resolve the next class for a super call. A normal class would
|
416
|
+
have this point to its superclass. However, if a class includes a module
|
417
|
+
then this would need to take into account the module. The module would
|
418
|
+
also have to then point its `$$parent` to the actual superclass. We
|
419
|
+
cannot modify modules like this, because it might be included in more
|
420
|
+
then one class. To fix this, we actually insert an `iclass` as the class'
|
421
|
+
`$$parent` which can then point to the superclass. The `iclass` acts as
|
422
|
+
a proxy to the actual module, so the `super` chain can then search it for
|
423
|
+
the required method.
|
424
|
+
|
425
|
+
@param [RubyModule] module the module to include
|
426
|
+
@param [RubyClass] klass the target class to include module into
|
427
|
+
@returns [null]
|
428
|
+
*/
|
364
429
|
Opal.append_features = function(module, klass) {
|
365
430
|
var included = klass.$$inc;
|
366
431
|
|
@@ -406,10 +471,10 @@
|
|
406
471
|
}
|
407
472
|
|
408
473
|
if (klass.$$dep) {
|
409
|
-
|
474
|
+
donate_methods(klass, methods.slice(), true);
|
410
475
|
}
|
411
476
|
|
412
|
-
|
477
|
+
donate_constants(module, klass);
|
413
478
|
};
|
414
479
|
|
415
480
|
// Boot a base class (makes instances).
|
@@ -534,30 +599,11 @@
|
|
534
599
|
return base_scope[name] = value;
|
535
600
|
};
|
536
601
|
|
537
|
-
/*
|
538
|
-
* constant get
|
539
|
-
*/
|
540
|
-
Opal.cget = function(base_scope, path) {
|
541
|
-
if (path == null) {
|
542
|
-
path = base_scope;
|
543
|
-
base_scope = Opal.Object;
|
544
|
-
}
|
545
|
-
|
546
|
-
var result = base_scope;
|
547
|
-
|
548
|
-
path = path.split('::');
|
549
|
-
while (path.length !== 0) {
|
550
|
-
result = result.$const_get(path.shift());
|
551
|
-
}
|
552
|
-
|
553
|
-
return result;
|
554
|
-
};
|
555
|
-
|
556
602
|
/*
|
557
603
|
* When a source module is included into the target module, we must also copy
|
558
604
|
* its constants to the target.
|
559
605
|
*/
|
560
|
-
|
606
|
+
function donate_constants(source_mod, target_mod) {
|
561
607
|
var source_constants = source_mod.$$scope.constants,
|
562
608
|
target_scope = target_mod.$$scope,
|
563
609
|
target_constants = target_scope.constants;
|
@@ -844,6 +890,34 @@
|
|
844
890
|
return [value];
|
845
891
|
};
|
846
892
|
|
893
|
+
/**
|
894
|
+
Used to get a list of rest keyword arguments. Method takes the given
|
895
|
+
keyword args, i.e. the hash literal passed to the method containing all
|
896
|
+
keyword arguemnts passed to method, as well as the used args which are
|
897
|
+
the names of required and optional arguments defined. This method then
|
898
|
+
just returns all key/value pairs which have not been used, in a new
|
899
|
+
hash literal.
|
900
|
+
|
901
|
+
@param given_args [Hash] all kwargs given to method
|
902
|
+
@param used_args [Object<String: true>] all keys used as named kwargs
|
903
|
+
@return [Hash]
|
904
|
+
*/
|
905
|
+
Opal.kwrestargs = function(given_args, used_args) {
|
906
|
+
var keys = [],
|
907
|
+
map = {},
|
908
|
+
key = null,
|
909
|
+
given_map = given_args.smap;
|
910
|
+
|
911
|
+
for (key in given_map) {
|
912
|
+
if (!used_args[key]) {
|
913
|
+
keys.push(key);
|
914
|
+
map[key] = given_map[key];
|
915
|
+
}
|
916
|
+
}
|
917
|
+
|
918
|
+
return Opal.hash2(keys, map);
|
919
|
+
};
|
920
|
+
|
847
921
|
/*
|
848
922
|
* Call a ruby method on a ruby object with some arguments:
|
849
923
|
*
|
@@ -885,7 +959,7 @@
|
|
885
959
|
/*
|
886
960
|
* Donate methods for a class/module
|
887
961
|
*/
|
888
|
-
|
962
|
+
function donate_methods(klass, defined, indirect) {
|
889
963
|
var methods = klass.$$methods, included_in = klass.$$dep;
|
890
964
|
|
891
965
|
// if (!indirect) {
|
@@ -905,21 +979,121 @@
|
|
905
979
|
}
|
906
980
|
|
907
981
|
if (includee.$$dep) {
|
908
|
-
|
982
|
+
donate_methods(includee, defined, true);
|
909
983
|
}
|
910
984
|
}
|
911
985
|
}
|
912
986
|
};
|
913
987
|
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
988
|
+
/**
|
989
|
+
Define the given method on the module.
|
990
|
+
|
991
|
+
This also handles donating methods to all classes that include this
|
992
|
+
module. Method conflicts are also handled here, where a class might already
|
993
|
+
have defined a method of the same name, or another included module defined
|
994
|
+
the same method.
|
995
|
+
|
996
|
+
@param [RubyModule] module the module method defined on
|
997
|
+
@param [String] jsid javascript friendly method name (e.g. "$foo")
|
998
|
+
@param [Function] body method body of actual function
|
999
|
+
*/
|
1000
|
+
function define_module_method(module, jsid, body) {
|
1001
|
+
module.$$proto[jsid] = body;
|
1002
|
+
body.$$owner = module;
|
1003
|
+
|
1004
|
+
module.$$methods.push(jsid);
|
1005
|
+
|
1006
|
+
if (module.$$module_function) {
|
1007
|
+
module[jsid] = body;
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
var included_in = module.$$dep;
|
1011
|
+
|
1012
|
+
if (included_in) {
|
1013
|
+
for (var i = 0, length = included_in.length; i < length; i++) {
|
1014
|
+
var includee = included_in[i];
|
1015
|
+
var dest = includee.$$proto;
|
1016
|
+
var current = dest[jsid];
|
1017
|
+
|
1018
|
+
|
1019
|
+
if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
|
1020
|
+
// target class has already defined the same method name - do nothing
|
1021
|
+
}
|
1022
|
+
else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
|
1023
|
+
// target class includes another module that has defined this method
|
1024
|
+
var klass_includees = includee.$$inc;
|
1025
|
+
|
1026
|
+
for (var j = 0, jj = klass_includees.length; j < jj; j++) {
|
1027
|
+
if (klass_includees[j] === current.$$owner) {
|
1028
|
+
var current_owner_index = j;
|
1029
|
+
}
|
1030
|
+
if (klass_includees[j] === module) {
|
1031
|
+
var module_index = j;
|
1032
|
+
}
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
// only redefine method on class if the module was included AFTER
|
1036
|
+
// the module which defined the current method body. Also make sure
|
1037
|
+
// a module can overwrite a method it defined before
|
1038
|
+
if (current_owner_index <= module_index) {
|
1039
|
+
dest[jsid] = body;
|
1040
|
+
dest[jsid].$$donated = true;
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
else {
|
1044
|
+
// neither a class, or module included by class, has defined method
|
1045
|
+
dest[jsid] = body;
|
1046
|
+
dest[jsid].$$donated = true;
|
1047
|
+
}
|
918
1048
|
|
919
|
-
|
920
|
-
|
1049
|
+
if (includee.$$dep) {
|
1050
|
+
donate_methods(includee, [jsid], true);
|
1051
|
+
}
|
921
1052
|
}
|
922
1053
|
}
|
1054
|
+
}
|
1055
|
+
|
1056
|
+
/**
|
1057
|
+
Used to define methods on an object. This is a helper method, used by the
|
1058
|
+
compiled source to define methods on special case objects when the compiler
|
1059
|
+
can not determine the destination object, or the object is a Module
|
1060
|
+
instance. This can get called by `Module#define_method` as well.
|
1061
|
+
|
1062
|
+
## Modules
|
1063
|
+
|
1064
|
+
Any method defined on a module will come through this runtime helper.
|
1065
|
+
The method is added to the module body, and the owner of the method is
|
1066
|
+
set to be the module itself. This is used later when choosing which
|
1067
|
+
method should show on a class if more than 1 included modules define
|
1068
|
+
the same method. Finally, if the module is in `module_function` mode,
|
1069
|
+
then the method is also defined onto the module itself.
|
1070
|
+
|
1071
|
+
## Classes
|
1072
|
+
|
1073
|
+
This helper will only be called for classes when a method is being
|
1074
|
+
defined indirectly; either through `Module#define_method`, or by a
|
1075
|
+
literal `def` method inside an `instance_eval` or `class_eval` body. In
|
1076
|
+
either case, the method is simply added to the class' prototype. A special
|
1077
|
+
exception exists for `BasicObject` and `Object`. These two classes are
|
1078
|
+
special because they are used in toll-free bridged classes. In each of
|
1079
|
+
these two cases, extra work is required to define the methods on toll-free
|
1080
|
+
bridged class' prototypes as well.
|
1081
|
+
|
1082
|
+
## Objects
|
1083
|
+
|
1084
|
+
If a simple ruby object is the object, then the method is simply just
|
1085
|
+
defined on the object as a singleton method. This would be the case when
|
1086
|
+
a method is defined inside an `instance_eval` block.
|
1087
|
+
|
1088
|
+
@param [RubyObject or Class] obj the actual obj to define method for
|
1089
|
+
@param [String] jsid the javascript friendly method name (e.g. '$foo')
|
1090
|
+
@param [Function] body the literal javascript function used as method
|
1091
|
+
@returns [null]
|
1092
|
+
*/
|
1093
|
+
Opal.defn = function(obj, jsid, body) {
|
1094
|
+
if (obj.$$is_mod) {
|
1095
|
+
define_module_method(obj, jsid, body);
|
1096
|
+
}
|
923
1097
|
else if (obj.$$is_class) {
|
924
1098
|
obj.$$proto[jsid] = body;
|
925
1099
|
|
@@ -927,7 +1101,7 @@
|
|
927
1101
|
define_basic_object_method(jsid, body);
|
928
1102
|
}
|
929
1103
|
else if (obj === ObjectClass) {
|
930
|
-
|
1104
|
+
donate_methods(obj, [jsid]);
|
931
1105
|
}
|
932
1106
|
}
|
933
1107
|
else {
|