-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathREADME
131 lines (101 loc) · 4.26 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
------------------------------------
RubyJS - Ruby to Javascript Compiler
------------------------------------
COPYRIGHT
Copyright (c) 2007, 2008 by Michael Neumann ([email protected]).
All rights reserved.
ABOUT
RubyJS translates Ruby code into Javascript code. NOTE that it executes
the Ruby code before it translates it into Javascript. This has the
advantage of being able to (mis-)use all of Ruby's meta-programming
tricks in the global scope (i.e. for defining classes and methods, NOT
within methods!). This fork adds several nifty features.
REQUIREMENTS
* Ruby >= 1.8.6
* ParseTree >= 2.1.1
MAPPING
The mapping from Ruby objects (left) to Javascript values (right) are
given below.
true -> true (class Boolean)
false -> false (class Boolean)
nil -> nil (a special variable!)
1, 1.2 -> Javascript Number (unboxed)
"String" -> immutable Javascript String (unboxed)
/regexp/ -> /regexp/ (unboxed)
[array] -> [array] (unboxed)
{hash} -> Javascript Hash object (unboxed, but indirect)
iterator -> function (unboxed)
1..2 -> custom Range object
BUGS
--
Debug mode sometimes generates code that does not run!
--
Spidermonkey doesn't run all tests.
TODO
--
Issue a warning whenever a destructive Ruby string method like gsub!
is used. The reason behind this warning is that, due to efficience
reasons, Ruby strings (which are mutable) are mapped to immutable
Javascript strings.
--
Command-line switch that doesn't call methods for some operators.
Most important ones are "+", "-" and "/". This is of course an unsafe
operation as you could define a method "+" in your own class. For
heavy math operations, this of course increases performance a lot!
--
Command-line switch that removes unused methods. This is possible, as
we record the names of all (possibly) called methods. This of course
disables send() support. This switch has the potential to reduce the
size of the generated Javascript significantly (which also reduces
memory consumption on the client side). For this to work, we have to
generate a call chain, which method name calls which other method
names. This works only on method names, as we can't infer the used
classes.
--
Command-line switch that disables the generation of name-information
used by methods like send(), instance_variables(), methods() or
respond_to?(). This makes it hard to decompile the Javascript code
back to Ruby or assign meaningful names.
LIMITATIONS
--
Module's are mapped to Classes for now.
--
You can't inherit from core classes like Array, String, Regexp and so
on. It's easy to allow by adding one further indirection, e.g. in that
on object creation an attribute "m" is assigned, which contains a hash
of all methods of that object, and on method call use "obj.m.method".
As long as this limitation is no problem, I go the way via prototypes,
which should be slightly more efficient.
--
You are not allowed to redefine the classes name method:
class MyClass
def self.name
# NOT ALLOWED!!!
end
end
The same is true for other methods like ancestors, superclass,
instance_methods, methods. But you wouldn't do that anyways in Ruby,
so that's no big restriction!
--
Constant assignment inside methods is forbidden. This is due to
using static constant lookup. Constant assignment inside the class
scope or module scope is not affected, as this is executed by the
Ruby interpreter.
Constants are either inlined in the case it is a value type (Fixnum, Float)
or a reference is generated (i.e. a variable holding it's value + a name).
References are only generated on demand, i.e. only when a constant is
accessed.
--
+break+ inside of loops cannot have arguments in RubyJS:
# RubyJS
while true
break 1 # => CompileTime Error
end
This could be accomplished, by introducing a "return loop"
variable for each while loop, and setting this variable
in "break".
A loop break cannot occur as expression. This could be accomplished
by using a throw instead of break and surrounding the loop by a catch.
The same applies for +next+!
--
Methods can be called regardless of their privacy (private, protected)