dienashorner 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,105 @@
1
+ module Nashorn
2
+
3
+ class JSError < StandardError
4
+
5
+ def initialize(native)
6
+ @native = native # might be a NativeException wrapping a Java Throwable
7
+ if ( value = self.value(true) ) != nil
8
+ if value.is_a?(Exception)
9
+ super "#{value.class.name}: #{value.message}"
10
+ elsif value.is_a?(JS::ScriptObject) # && @native.to_s.index('Error:')
11
+ super @native.message
12
+ else
13
+ super value
14
+ end
15
+ else
16
+ super cause ? cause.message : @native
17
+ end
18
+ end
19
+
20
+ def inspect
21
+ "#<#{self.class.name}: #{message}>"
22
+ end
23
+
24
+ def message; super.to_s end
25
+
26
+ # Returns the (nested) cause of this error if any.
27
+ def cause
28
+ return @cause if defined?(@cause)
29
+
30
+ if @native.respond_to?(:cause) && @native.cause
31
+ @cause = @native.cause
32
+ else
33
+ @native.is_a?(JS::NashornException) ? @native : nil
34
+ end
35
+ end
36
+
37
+ # Attempts to unwrap the (native) JavaScript/Java exception.
38
+ def unwrap
39
+ return @unwrap if defined?(@unwrap)
40
+ cause = self.cause
41
+ if cause && cause.is_a?(JS::NashornException)
42
+ e = cause.getCause
43
+ if e && e.is_a?(Java::OrgJrubyExceptions::RaiseException)
44
+ @unwrap = e.getException
45
+ else
46
+ @unwrap = e
47
+ end
48
+ else
49
+ @unwrap = nil
50
+ end
51
+ end
52
+
53
+ # Return the thown (native) JavaScript value.
54
+ def value(unwrap = false)
55
+ return @value if defined?(@value) && ! unwrap
56
+ @value = get_thrown unless defined?(@value)
57
+ return @value.unwrap if unwrap && @value.respond_to?(:unwrap)
58
+ @value
59
+ end
60
+ alias_method :thrown, :value
61
+
62
+ # The backtrace is constructed using #javascript_backtrace + the Ruby part.
63
+ def backtrace
64
+ if js_backtrace = javascript_backtrace
65
+ js_backtrace.push(*super)
66
+ else
67
+ super
68
+ end
69
+ end
70
+
71
+ # Returns the JavaScript back-trace part for this error (the script stack).
72
+ def javascript_backtrace(raw_elements = false)
73
+ return nil unless cause.is_a?(JS::NashornException)
74
+ JS::NashornException.getScriptFrames(cause).map do |element|
75
+ raw_elements ? element : element.to_s # ScriptStackElement
76
+ end
77
+ end
78
+
79
+ # jdk.nashorn.internal.runtime::ECMAException < NashornException has these :
80
+
81
+ def file_name
82
+ cause.respond_to?(:getFileName) ? cause.getFileName : nil
83
+ end
84
+
85
+ def line_number
86
+ cause.respond_to?(:getLineNumber) ? cause.getLineNumber : nil
87
+ end
88
+
89
+ def column_number
90
+ cause.respond_to?(:getColumnNumber) ? cause.getColumnNumber : nil
91
+ end
92
+
93
+ private
94
+
95
+ def get_thrown
96
+ if ( cause = self.cause ) && cause.respond_to?(:thrown)
97
+ cause.thrown # e.g. NashornException.getThrown
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,201 @@
1
+ module Nashorn
2
+ module JS
3
+
4
+ JSObject.module_eval do
5
+
6
+ def [](key)
7
+ Nashorn.to_rb key.is_a?(Fixnum) ? getSlot(key) : getMember(key.to_s)
8
+ end
9
+
10
+ def []=(key, value)
11
+ js_val = Nashorn.to_js value
12
+ key.is_a?(Fixnum) ? setSlot(key, js_val) : setMember(key.to_s, js_val)
13
+ js_val
14
+ end
15
+
16
+ def has_key?(key); hasMember(key) end
17
+ alias_method :key?, :has_key?
18
+ alias_method :include?, :has_key?
19
+
20
+ def has_value?(val); raw_values.include?(val) end
21
+ alias_method :value?, :has_value?
22
+
23
+ def delete(key); removeMember(key) end
24
+
25
+ def length; keySet.size end
26
+ alias_method :size, :length
27
+
28
+ # enumerate the key value pairs contained in this javascript object. e.g.
29
+ #
30
+ # eval_js("{foo: 'bar', baz: 'bang'}").each do |key,value|
31
+ # puts "#{key} -> #{value} "
32
+ # end
33
+ #
34
+ # outputs foo -> bar baz -> bang
35
+ #
36
+ def each
37
+ each_raw { |key, val| yield key, Nashorn.to_rb(val) }
38
+ end
39
+ alias_method :each_pair, :each
40
+
41
+ def each_key
42
+ each_raw { |key, val| yield key }
43
+ end
44
+
45
+ def each_value
46
+ each_raw { |key, val| yield Nashorn.to_rb(val) }
47
+ end
48
+
49
+ def each_raw
50
+ for id in keySet do
51
+ yield id, getMember(id)
52
+ end
53
+ end
54
+
55
+ def keys
56
+ keySet.to_a
57
+ end
58
+
59
+ def values
60
+ raw_values.map { |val| Nashorn.to_rb(val) }
61
+ end
62
+
63
+ # Converts the native object to a hash. This isn't really a stretch since it's
64
+ # pretty much a hash in the first place.
65
+ def to_h
66
+ hash = {}
67
+ each do |key, val|
68
+ hash[key] = val.is_a?(JSObject) && ! val.equal?(self) ? val.to_h : val
69
+ end
70
+ hash
71
+ end
72
+
73
+ # def ==(other)
74
+ # equivalentValues(other) == true # JS ==
75
+ # end
76
+ #
77
+ # def eql?(other)
78
+ # self.class == other.class && self.==(other)
79
+ # end
80
+
81
+ # Convert this javascript object into a json string.
82
+ def to_json(*args)
83
+ to_h.to_json(*args)
84
+ end
85
+
86
+ # Delegate methods to JS object if possible when called from Ruby.
87
+ def method_missing(name, *args)
88
+ name_str = name.to_s
89
+ if name_str.end_with?('=') && args.size == 1 # writer -> JS put
90
+ self[ name_str[0...-1] ] = args[0]
91
+ else
92
+ if hasMember(name_str) && property = getMember(name_str)
93
+ if property.is_a?(JSObject) && property.isFunction
94
+ js_args = Nashorn.args_to_js(args)
95
+ Nashorn.to_rb property.__call__(self, js_args)
96
+ else
97
+ if args.size > 0
98
+ raise ArgumentError, "can't call '#{name_str}' with args: #{args.inspect} as it's a property"
99
+ end
100
+ Nashorn.to_rb property
101
+ end
102
+ else
103
+ super
104
+ end
105
+ end
106
+ end
107
+
108
+ # function :
109
+
110
+ # alias_method :__call__, :call
111
+
112
+ # make JavaScript functions callable Ruby style e.g. `fn.call('42')`
113
+ #
114
+ # NOTE: That invoking #call does not have the same semantics as
115
+ # JavaScript's Function#call but rather as Ruby's Method#call !
116
+ # Use #apply or #bind before calling to achieve the same effect.
117
+ def call(*args)
118
+ this = nil
119
+ Nashorn.to_rb __call__ this, Nashorn.args_to_js(args)
120
+ rescue JS::NashornException => e
121
+ raise Nashorn::JSError.new(e)
122
+ end
123
+
124
+ # bind a JavaScript function into the given (this) context
125
+ #def bind(this, *args)
126
+ # args = Nashorn.args_to_js(args)
127
+ # Rhino::JS::BoundFunction.new(self, Nashorn.to_js(this), args)
128
+ #end
129
+
130
+ # use JavaScript functions constructors from Ruby as `fn.new`
131
+ def new(*args)
132
+ newObject Nashorn.args_to_js(args)
133
+ rescue JS::NashornException => e
134
+ raise Nashorn::JSError.new(e)
135
+ end
136
+
137
+ # apply a function with the given context and (optional) arguments
138
+ # e.g. `fn.apply(obj, 1, 2)`
139
+ #
140
+ # NOTE: That #call from Ruby does not have the same semantics as
141
+ # JavaScript's Function#call but rather as Ruby's Method#call !
142
+ def apply(this, *args)
143
+ __call__ Nashorn.to_js(this), Nashorn.args_to_js(args)
144
+ rescue JS::NashornException => e
145
+ raise Nashorn::JSError.new(e)
146
+ end
147
+ alias_method :methodcall, :apply # V8::Function compatibility
148
+
149
+ end
150
+
151
+ AbstractJSObject.module_eval do
152
+ alias_method :raw_values, :values
153
+ alias_method :__call__, :call
154
+ end
155
+
156
+ ScriptObjectMirror.module_eval do # implements java.util.Map
157
+
158
+ # @private NOTE: duplicated from JSObject
159
+ def [](key)
160
+ Nashorn.to_rb key.is_a?(Fixnum) ? getSlot(key) : getMember(key.to_s)
161
+ end
162
+
163
+ # @private NOTE: duplicated from JSObject
164
+ def []=(key, value)
165
+ js_val = Nashorn.to_js value
166
+ key.is_a?(Fixnum) ? setSlot(key, js_val) : setMember(key.to_s, js_val)
167
+ js_val
168
+ end
169
+
170
+ # @private NOTE: duplicated from JSObject
171
+ def call(*args)
172
+ this = nil
173
+ Nashorn.to_rb __call__ this, Nashorn.args_to_js(args)
174
+ rescue JS::NashornException => e
175
+ raise Nashorn::JSError.new(e)
176
+ end
177
+
178
+ # def callMember(this, *args)
179
+ # this = nil
180
+ # Nashorn.to_rb __call__ this, Nashorn.args_to_js(args)
181
+ # rescue JS::NashornException => e
182
+ # raise Nashorn::JSError.new(e)
183
+ # end
184
+
185
+ #def to_s
186
+ # toString
187
+ #end
188
+
189
+ #def inspect
190
+ # id_hash = Java::JavaLang::System.identityHashCode(self)
191
+ # "<##{self.class.name}:0x#{Java::JavaLang::Integer.toHexString(id_hash)} #{to_s}>"
192
+ #end
193
+
194
+ end
195
+
196
+ NashornException.class_eval do
197
+ alias_method :value, :thrown
198
+ end
199
+
200
+ end
201
+ end
@@ -0,0 +1,84 @@
1
+ begin
2
+ require 'nashorn/rhino'
3
+ rescue LoadError => e
4
+ warn "[WARNING] Please install gem 'dienashorner' to use Less under JRuby."
5
+ raise e
6
+ end
7
+
8
+ require 'less/java_script'
9
+
10
+ module Less
11
+ module JavaScript
12
+ class NashornContext
13
+
14
+ def self.instance
15
+ return new # NOTE: for Rhino a context should be kept open per thread !
16
+ end
17
+
18
+ def initialize(globals = nil)
19
+ @context = Nashorn::Context.new :java => true
20
+ #if @context.respond_to?(:version)
21
+ # @context.version = '1.8'
22
+ # apply_1_8_compatibility! if @context.version.to_s != '1.8'
23
+ #else
24
+ # apply_1_8_compatibility!
25
+ #end
26
+ globals.each { |key, val| @context[key] = val } if globals
27
+ end
28
+
29
+ def unwrap
30
+ @context
31
+ end
32
+
33
+ def exec(&block)
34
+ @context.open(&block)
35
+ rescue Nashorn::JSError => e
36
+ handle_js_error(e)
37
+ end
38
+
39
+ def eval(source, options = nil)
40
+ source = source.encode('UTF-8') if source.respond_to?(:encode)
41
+ @context.eval("(#{source})")
42
+ rescue Nashorn::JSError => e
43
+ handle_js_error(e)
44
+ end
45
+
46
+ def call(properties, *args)
47
+ args.last.is_a?(::Hash) ? args.pop : {} # extract_option!
48
+ @context.eval(properties).call(*args)
49
+ rescue Nashorn::JSError => e
50
+ handle_js_error(e)
51
+ end
52
+
53
+ def method_missing(symbol, *args)
54
+ if @context.respond_to?(symbol)
55
+ @context.send(symbol, *args)
56
+ else
57
+ super
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def handle_js_error(e)
64
+
65
+ raise e # TODO NOT IMPLEMENTED
66
+
67
+ #if e.value && ( e.value['message'] || e.value['type'].is_a?(String) )
68
+ # raise Less::ParseError.new(e, e.value) # LessError
69
+ #end
70
+ #if e.unwrap.to_s =~ /missing opening `\(`/
71
+ # raise Less::ParseError.new(e.unwrap.to_s)
72
+ #end
73
+ #if e.message && e.message[0, 12] == "Syntax Error"
74
+ # raise Less::ParseError.new(e)
75
+ #else
76
+ # raise Less::Error.new(e)
77
+ #end
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+
84
+ Less::JavaScript.context_wrapper = Less::JavaScript::NashornContext
@@ -0,0 +1,34 @@
1
+ require 'nashorn'
2
+ require 'nashorn/context'
3
+
4
+ module Nashorn
5
+ module Ruby
6
+ Scriptable.module_eval do
7
+
8
+ def get(name, scope = nil)
9
+ getMember(name)
10
+ end
11
+
12
+ def has(name, scope = nil)
13
+ hasMember(name)
14
+ end
15
+
16
+ def put(name, value, scope = nil)
17
+ setMember(name, value)
18
+ end
19
+
20
+ end
21
+ end
22
+ module JS
23
+ Scriptable = JSObject
24
+ JavaScriptException = NashornException
25
+ RhinoException = NashornException
26
+ end
27
+ end
28
+
29
+ if Object.const_defined?(:Rhino)
30
+ warn "therubyrhino seems to be loaded, Nashorn won't emulate Rhino"
31
+ else
32
+ $LOADED_FEATURES << 'rhino'
33
+ Rhino = Nashorn # the-borg!
34
+ end
@@ -0,0 +1,68 @@
1
+ module Nashorn
2
+ module Ruby
3
+
4
+ autoload :DefaultAccess, 'nashorn/ruby/default_access'
5
+ autoload :AttributeAccess, 'nashorn/ruby/attribute_access'
6
+
7
+ class AccessBase
8
+
9
+ def has(object, name)
10
+ # try [](name) method :
11
+ if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
12
+ unless internal?(name)
13
+ value = object.[](name) { return true }
14
+ return true unless value.nil?
15
+ end
16
+ end
17
+ yield
18
+ end
19
+
20
+ def get(object, name)
21
+ # try [](name) method :
22
+ if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
23
+ value = begin
24
+ object[name]
25
+ rescue LocalJumpError
26
+ nil
27
+ end unless internal?(name)
28
+ return Nashorn.to_js(value) unless value.nil?
29
+ end
30
+ yield
31
+ end
32
+
33
+ def set(object, name, value)
34
+ # try []=(name, value) method :
35
+ if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
36
+ rb_value = Nashorn.to_rb(value)
37
+ begin
38
+ return object[name] = rb_value
39
+ rescue LocalJumpError
40
+ end unless internal?(name)
41
+ end
42
+ yield
43
+ end
44
+
45
+ def has_slot(object, index, &block)
46
+ has(object, index, &block)
47
+ end
48
+
49
+ def get_slot(object, index, &block)
50
+ get(object, index, &block)
51
+ end
52
+
53
+ def set_slot(object, index, value, &block)
54
+ set(object, index, value, &block)
55
+ end
56
+
57
+ private
58
+
59
+ UNDERSCORES = '__'.freeze
60
+
61
+ def internal?(name) # e.g. '__iterator__', '__proto__'
62
+ name.is_a?(String) && name.start_with?(UNDERSCORES) && name.end_with?(UNDERSCORES)
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,41 @@
1
+ module Nashorn
2
+ module Ruby
3
+ class AttributeAccess < AccessBase
4
+
5
+ def has(object, name)
6
+ if object.respond_to?(name.to_s) ||
7
+ object.respond_to?(:"#{name}=") # might have a writer but no reader
8
+ return true
9
+ end
10
+ super
11
+ end
12
+
13
+ def get(object, name)
14
+ name_sym = name.to_s.to_sym
15
+ if object.respond_to?(name_sym)
16
+ method = object.method(name_sym)
17
+ if method.arity == 0 && # check if it is an attr_reader
18
+ ( object.respond_to?(:"#{name}=") ||
19
+ object.instance_variables.find { |var| var.to_sym == :"@#{name}" } )
20
+ return Nashorn.to_js(method.call)
21
+ else
22
+ return Function.wrap(method.unbind)
23
+ end
24
+ elsif object.respond_to?(:"#{name}=")
25
+ return nil # it does have the property but is non readable
26
+ end
27
+ super
28
+ end
29
+
30
+ def set(object, name, value)
31
+ if object.respond_to?(set_name = :"#{name}=")
32
+ rb_value = Nashorn.to_rb(value)
33
+ return object.send(set_name, rb_value)
34
+ end
35
+ super
36
+ end
37
+ alias_method :put, :set
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,37 @@
1
+ module Nashorn
2
+ module Ruby
3
+ class DefaultAccess < AccessBase
4
+
5
+ def has(object, name)
6
+ if object.respond_to?(name.to_s) ||
7
+ object.respond_to?(:"#{name}=")
8
+ return true
9
+ end
10
+ super
11
+ end
12
+
13
+ def get(object, name)
14
+ if object.respond_to?(name_s = name.to_s)
15
+ method = object.method(name_s)
16
+ if method.arity == 0
17
+ return Nashorn.to_js(method.call)
18
+ else
19
+ return Function.wrap(method.unbind)
20
+ end
21
+ elsif object.respond_to?(:"#{name}=")
22
+ return nil
23
+ end
24
+ super
25
+ end
26
+
27
+ def set(object, name, value)
28
+ if object.respond_to?(set_name = :"#{name}=")
29
+ return object.send(set_name, Nashorn.to_rb(value))
30
+ end
31
+ super
32
+ end
33
+ alias_method :put, :set
34
+
35
+ end
36
+ end
37
+ end