dienashorner 0.1.1

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.
@@ -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