jrubyfx-fxmlloader 0.2-java → 0.3-java
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.
- data/README +15 -3
- data/Rakefile +1 -1
- data/lib/FXMLLoader-j8.jar +0 -0
- data/lib/fxmlloader/elts.rb +68 -59
- data/lib/fxmlloader/fxml_jit_info.rb +158 -0
- data/lib/fxmlloader/j8_expression_value.rb +148 -101
- data/lib/fxmlloader/real_elts.rb +195 -184
- data/lib/fxmlloader/rorba.rb +3 -29
- data/lib/fxmlloader/rrba.rb +161 -399
- data/lib/fxmlloader/value_elts.rb +13 -23
- data/lib/jrubyfx-fxmlloader.rb +240 -124
- metadata +6 -5
data/README
CHANGED
@@ -1,5 +1,17 @@
|
|
1
|
-
|
1
|
+
# JRubyFX-FxmlLoader
|
2
2
|
|
3
|
-
|
3
|
+
JRubyFX-FxmlLoader is the JIT-enabled FXML parser for the JRubyFX project based
|
4
|
+
on the official OpenJDK 8 FXML parser. FxmlLoader strives to be a nearly drop-in
|
5
|
+
replacement FxmlLoader, only differing in JRuby compatibility.
|
4
6
|
|
5
|
-
|
7
|
+
At this point,
|
8
|
+
most code is directly copied from OpenJDK and converted to ruby via regexes and
|
9
|
+
as such is far from idiomatic ruby. The JIT compiler is also a work in progress.
|
10
|
+
|
11
|
+
If you would like to help clean up the code please do but be careful about breaking
|
12
|
+
FXML. Any 100% standard Java FXML document should work *identically* when run as a JRuby FXML document and
|
13
|
+
vice-versa with the exception of JRuby support (like ruby classes & controllers).
|
14
|
+
|
15
|
+
Use with JRubyFX!
|
16
|
+
|
17
|
+
rake gem to build. Note that half of this project is java and must be compiled.
|
data/Rakefile
CHANGED
data/lib/FXMLLoader-j8.jar
CHANGED
Binary file
|
data/lib/fxmlloader/elts.rb
CHANGED
@@ -49,16 +49,19 @@ class Element
|
|
49
49
|
collection = false;
|
50
50
|
end
|
51
51
|
end
|
52
|
-
dputs callz + "Is it a collection? #{collection.inspect} <= #{@value.java_class}"
|
53
52
|
return collection;
|
54
53
|
end
|
55
54
|
|
56
|
-
def add(element)
|
57
|
-
dputs callz + "about to add #{element} to #{value.to_java}"
|
55
|
+
def add(element, prop_name=nil, rputs_elt=nil)
|
58
56
|
# If value is a list, add element to it; otherwise, get the value
|
59
57
|
# of the default property, which is assumed to be a list and add
|
60
58
|
# to that (coerce to the appropriate type)
|
61
59
|
if (@value.kind_of?(Enumerable) || @value.java_kind_of?(java.util.List))
|
60
|
+
if prop_name == nil
|
61
|
+
rputs value, "add(#{rget(element)||element.inspect})"
|
62
|
+
else
|
63
|
+
rputs @parent.value, "get#{prop_name[0].upcase}#{prop_name[1..-1]}.add(#{rputs_elt || rget(element)||element.inspect})"
|
64
|
+
end
|
62
65
|
value.to_java
|
63
66
|
else
|
64
67
|
type = value.java_class
|
@@ -69,10 +72,11 @@ class Element
|
|
69
72
|
list = getProperties[defaultPropertyName]
|
70
73
|
|
71
74
|
# Coerce the element to the list item type
|
72
|
-
if (!Map.java_class.assignable_from?(type))
|
75
|
+
if (!java.util.Map.java_class.assignable_from?(type))
|
73
76
|
listType = @valueAdapter.getGenericType(defaultPropertyName);
|
74
77
|
element = RubyWrapperBeanAdapter.coerce(element, RubyWrapperBeanAdapter.getListItemType(listType));
|
75
78
|
end
|
79
|
+
rputs @value, "get#{defaultPropertyName[0].upcase}#{defaultPropertyName[1..-1]}.add(#{rget(element)||element.inspect})"
|
76
80
|
list = list.to_java if list.class == Java::JavaObject
|
77
81
|
list
|
78
82
|
end.add(element)
|
@@ -94,38 +98,17 @@ class Element
|
|
94
98
|
end
|
95
99
|
|
96
100
|
def updateValue(value)
|
97
|
-
dputs callz + "Updating value from #{@value} to #{value.class}"
|
98
101
|
@value = value;
|
99
102
|
@valueAdapter = nil;
|
100
103
|
end
|
101
104
|
|
102
105
|
def isTyped()
|
103
|
-
|
104
|
-
dp @value.class
|
105
|
-
dp @value
|
106
|
-
q = !(@value.java_kind_of? Java::java.util.Map or @value.is_a? Hash );
|
107
|
-
dputs callz + "type result: #{q.inspect}"
|
108
|
-
q
|
106
|
+
!(@value.java_kind_of? Java::java.util.Map or @value.is_a? Hash )
|
109
107
|
end
|
110
108
|
|
111
109
|
def getValueAdapter()
|
112
110
|
if (@valueAdapter == nil)
|
113
|
-
|
114
|
-
dprint callz
|
115
|
-
dprint @value
|
116
|
-
dputs @value.class
|
117
|
-
dputs caller
|
118
|
-
if @value.class.to_s == "Java::JavafxFxml::ObjectBuilder"
|
119
|
-
dputs caller
|
120
|
-
end
|
121
|
-
if @value.is_a? java.lang.Object
|
122
|
-
dputs callz + "trying to call wrapper"
|
123
|
-
@valueAdapter = RubyWrapperBeanAdapter.new(@value);
|
124
|
-
else
|
125
|
-
dputs callz + "trying to call ruby object wrapper"
|
126
|
-
@valueAdapter = RubyObjectWrapperBeanAdapter.new(@value)
|
127
|
-
end
|
128
|
-
dputs callz + "got"
|
111
|
+
@valueAdapter = RubyWrapperBeanAdapter.for(@value)
|
129
112
|
end
|
130
113
|
return @valueAdapter;
|
131
114
|
end
|
@@ -172,7 +155,6 @@ class Element
|
|
172
155
|
if (@loadListener != nil)
|
173
156
|
@loadListener.readEventHandlerAttribute(localName, value);
|
174
157
|
end
|
175
|
-
dputs callz + "found eventHandler prefix #{prefix}, #{localName}, #{value}"
|
176
158
|
eventHandlerAttributes <<(Attribute.new(localName, nil, value));
|
177
159
|
else
|
178
160
|
i = localName.rindex('.');
|
@@ -183,15 +165,12 @@ class Element
|
|
183
165
|
@loadListener.readPropertyAttribute(localName, nil, value);
|
184
166
|
end
|
185
167
|
|
186
|
-
dputs callz + "found property attrib #{prefix}, #{localName}, #{value}"
|
187
168
|
instancePropertyAttributes << (Attribute.new(localName, nil, value));
|
188
169
|
else
|
189
170
|
# The attribute represents a static property
|
190
171
|
name = localName[(i + 1)..-1];
|
191
172
|
sourceType = parentLoader.getType(localName[0, i]);
|
192
173
|
|
193
|
-
dputs callz + "found static property #{prefix}, #{localName}, #{value}"
|
194
|
-
dputs callz + "and its #{sourceType}, #{staticLoad}"
|
195
174
|
if (sourceType != nil)
|
196
175
|
if (@loadListener != nil)
|
197
176
|
@loadListener.readPropertyAttribute(name, sourceType, value);
|
@@ -217,7 +196,6 @@ class Element
|
|
217
196
|
def processPropertyAttribute(attribute)
|
218
197
|
value = attribute.value;
|
219
198
|
if (isBindingExpression(value))
|
220
|
-
dputs callz + "is a binding !"
|
221
199
|
# Resolve the expression
|
222
200
|
|
223
201
|
if (attribute.sourceType != nil)
|
@@ -235,38 +213,28 @@ class Element
|
|
235
213
|
end
|
236
214
|
|
237
215
|
value = value[2..-2] # TODO: BINDING_EXPRESSION_PREFIX == ${
|
238
|
-
|
216
|
+
#value.length() - 1];
|
239
217
|
# TODO: this only works for 7, not 8
|
240
|
-
dputs "getting expression value of '#{value}' with #{parentLoader.namespace}"
|
241
218
|
expression = Expression.valueOf(value);
|
242
|
-
dputs callz + "got the expression as '#{expression}'"
|
243
|
-
dp expression
|
244
219
|
# Create the binding
|
245
220
|
targetAdapter = RubyWrapperBeanAdapter.new(@value);
|
246
|
-
dputs callz + "target adapter is #{targetAdapter} from #{value}"
|
247
221
|
propertyModel = targetAdapter.getPropertyModel(attribute.name).to_java
|
248
222
|
type = targetAdapter.getType(attribute.name);
|
249
|
-
dputs callz + "prop model is #{propertyModel.inspect} and type is #{type.inspect}"
|
250
223
|
if (propertyModel.is_a? Property)
|
251
|
-
|
224
|
+
rputs @value, "#{attribute.name}Property.bind(RRExpressionValue.new(__local_namespace, Java::org.jruby.jfx8.Expression.valueOf(#{value.inspect}), Java::#{type.name.gsub(/[\$\.]/, "::")}.java_class))"
|
252
225
|
#expression.value_property.addListener(JRExpressionTargetMapping.new(expression, getProperties(), Expression.split(value)));
|
253
226
|
( propertyModel).bind(RRExpressionValue.new(parentLoader.namespace, expression, type));
|
254
|
-
dputs callz + "bound!"
|
255
227
|
end
|
256
228
|
elsif (isBidirectionalBindingExpression(value))
|
257
229
|
raise UnsupportedOperationException.new("This feature is not currently enabled.");
|
258
230
|
else
|
259
|
-
dputs callz + "processing 3 for #{attribute.sourceType}, #{attribute.name}, #{value}"
|
260
231
|
processValue3(attribute.sourceType, attribute.name, value);
|
261
232
|
end
|
262
233
|
end
|
263
234
|
|
264
235
|
def isBindingExpression(aValue)
|
265
|
-
dputs callz + "checking if '#{aValue}' is a binding prefix..."
|
266
236
|
# TODO: BINDING_EXPRESSION_PREFIX == ${
|
267
|
-
|
268
|
-
dputs callz + "it is? #{q.inspect}"
|
269
|
-
q
|
237
|
+
aValue.start_with?("${") && aValue.end_with?(FXL::BINDING_EXPRESSION_SUFFIX);
|
270
238
|
end
|
271
239
|
|
272
240
|
def isBidirectionalBindingExpression(aValue)
|
@@ -279,7 +247,6 @@ class Element
|
|
279
247
|
processed = false;
|
280
248
|
#process list or array first
|
281
249
|
if (sourceType == nil && isTyped())
|
282
|
-
dputs callz + "getting value adptr"
|
283
250
|
lvalueAdapter = getValueAdapter();
|
284
251
|
type = lvalueAdapter.getType(propertyName);
|
285
252
|
|
@@ -288,9 +255,8 @@ class Element
|
|
288
255
|
dp sourceType, propertyName, aValue
|
289
256
|
dp lvalueAdapter
|
290
257
|
dp caller
|
291
|
-
raise
|
258
|
+
raise("Property \"" + propertyName + "\" does not exist" + " or is read-only.");
|
292
259
|
end
|
293
|
-
dputs "checking assignable"
|
294
260
|
if (List.java_class.assignable_from?(type) && lvalueAdapter.read_only?(propertyName))
|
295
261
|
populateListFromString(lvalueAdapter, propertyName, aValue);
|
296
262
|
processed = true;
|
@@ -299,11 +265,8 @@ class Element
|
|
299
265
|
processed = true;
|
300
266
|
end
|
301
267
|
end
|
302
|
-
dputs callz + "276"
|
303
268
|
if (!processed)
|
304
|
-
dputs callz + "Must appky it"
|
305
269
|
applyProperty(propertyName, sourceType, resolvePrefixedValue(aValue));
|
306
|
-
dputs callz + "280"
|
307
270
|
processed = true;
|
308
271
|
end
|
309
272
|
return processed;
|
@@ -336,7 +299,11 @@ class Element
|
|
336
299
|
return aValue;
|
337
300
|
else
|
338
301
|
begin
|
339
|
-
|
302
|
+
if $JRUBYFX_AOT_COMPILING
|
303
|
+
return RelativeFXMLString.new(aValue, URL.new(parentLoader.location, aValue).to_s)
|
304
|
+
else
|
305
|
+
return (aValue[0] == '/') ? classLoader.getResource(aValue[1..-1]).to_s : URL.new(parentLoader.location, aValue).to_s
|
306
|
+
end
|
340
307
|
rescue MalformedURLException => e
|
341
308
|
dp e
|
342
309
|
dputs "#{parentLoader.location} + /+ #{aValue}"
|
@@ -375,10 +342,8 @@ class Element
|
|
375
342
|
# The attribute value is nil
|
376
343
|
return nil;
|
377
344
|
end
|
378
|
-
dputs callz + "Getting expression '#{aValue}'"
|
379
345
|
# remove all nils, them add one in at the end so [0] returns nil if empty
|
380
346
|
q = (KeyPath.parse(aValue).map{|i|parentLoader.namespace[i]} - [nil] + [nil])[0]
|
381
|
-
dputs callz + "Parsed Expression! #{q};;;;#{q.inspect}"
|
382
347
|
return q
|
383
348
|
end
|
384
349
|
return aValue;
|
@@ -482,7 +447,6 @@ class Element
|
|
482
447
|
if (attrValue.length() == 0)
|
483
448
|
raise LoadException.new("Missing expression reference.");
|
484
449
|
end
|
485
|
-
dputs callz + "exprValue!' #{attrValue}'"
|
486
450
|
expression = Expression.get(@namespace, KeyPath.parse(attrValue));
|
487
451
|
if (expression.is_a? EventHandler)
|
488
452
|
eventHandler = expression;
|
@@ -490,12 +454,12 @@ class Element
|
|
490
454
|
|
491
455
|
end
|
492
456
|
if (eventHandler == nil)
|
493
|
-
if (attrValue.length() == 0 ||
|
457
|
+
if (attrValue.length() == 0 || parentLoader.scriptEngine == nil)
|
494
458
|
raise LoadException.new("Error resolving " + attribute.name + "='" + attribute.value +
|
495
459
|
"', either the event handler is not in the Namespace or there is an error in the script.");
|
496
460
|
end
|
497
461
|
|
498
|
-
eventHandler = ScriptEventHandler.new(attrValue,
|
462
|
+
eventHandler = ScriptEventHandler.new(attrValue, parentLoader.scriptEngine);
|
499
463
|
end
|
500
464
|
# Add the handler
|
501
465
|
if (eventHandler != nil)
|
@@ -546,6 +510,7 @@ end
|
|
546
510
|
|
547
511
|
class EventHandlerWrapper
|
548
512
|
include EventHandler
|
513
|
+
attr_reader :funcName
|
549
514
|
def initialize(ctrl, funcName)
|
550
515
|
@ctrl = ctrl
|
551
516
|
@funcName = funcName
|
@@ -558,7 +523,51 @@ class EventHandlerWrapper
|
|
558
523
|
@ctrl.send(@funcName, eventArgs)
|
559
524
|
end
|
560
525
|
else
|
561
|
-
|
526
|
+
puts "Warning: method #{@funcName} was not found on controller #{@ctrl}"
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
class ScriptEventHandler
|
532
|
+
include EventHandler
|
533
|
+
attr_reader :script, :scriptEngine
|
534
|
+
def initialize(script, scriptEngine)
|
535
|
+
@script = script;
|
536
|
+
@scriptEngine = scriptEngine;
|
537
|
+
end
|
538
|
+
|
539
|
+
def handle(event)
|
540
|
+
# Don't pollute the page namespace with values defined in the script
|
541
|
+
engineBindings = @scriptEngine.getBindings(ScriptContext::ENGINE_SCOPE);
|
542
|
+
localBindings = @scriptEngine.createBindings();
|
543
|
+
localBindings.put(FXL::EVENT_KEY, event);
|
544
|
+
@scriptEngine.setBindings(localBindings, ScriptContext::ENGINE_SCOPE);
|
545
|
+
|
546
|
+
# Execute the script
|
547
|
+
begin
|
548
|
+
@scriptEngine.eval(@script);
|
549
|
+
rescue ScriptException => exception
|
550
|
+
raise exception
|
562
551
|
end
|
552
|
+
|
553
|
+
# Restore the original bindings
|
554
|
+
@scriptEngine.setBindings(engineBindings, ScriptContext::ENGINE_SCOPE);
|
563
555
|
end
|
564
|
-
end
|
556
|
+
end
|
557
|
+
|
558
|
+
class RelativeFXMLString < String
|
559
|
+
alias :super_inspect :inspect
|
560
|
+
def initialize(str, rel)
|
561
|
+
super(rel)
|
562
|
+
@rel = str
|
563
|
+
end
|
564
|
+
def inspect
|
565
|
+
"java.net.URL.new(__local_namespace['location'], #{@rel.inspect}).to_s"
|
566
|
+
end
|
567
|
+
def to_s
|
568
|
+
super
|
569
|
+
end
|
570
|
+
def class()
|
571
|
+
String
|
572
|
+
end
|
573
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# * Copyright (c) 2013 Patrick Plenefisch
|
2
|
+
# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
3
|
+
# *
|
4
|
+
# * This code is free software; you can redistribute it and/or modify it
|
5
|
+
# * under the terms of the GNU General Public License version 2 only, as
|
6
|
+
# * published by the Free Software Foundation. Oracle designates this
|
7
|
+
# * particular file as subject to the "Classpath" exception as provided
|
8
|
+
# * by Oracle in the LICENSE file that accompanied this code.
|
9
|
+
# *
|
10
|
+
# * This code is distributed in the hope that it will be useful, but WITHOUT
|
11
|
+
# * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
12
|
+
# * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
13
|
+
# * version 2 for more details (a copy is included in the LICENSE file that
|
14
|
+
# * accompanied this code).
|
15
|
+
# *
|
16
|
+
# * You should have received a copy of the GNU General Public License version
|
17
|
+
# * 2 along with this work; if not, write to the Free Software Foundation,
|
18
|
+
# * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
19
|
+
# *
|
20
|
+
|
21
|
+
require 'digest/sha1'
|
22
|
+
require 'fileutils'
|
23
|
+
|
24
|
+
def javafx
|
25
|
+
Java::javafx
|
26
|
+
end
|
27
|
+
|
28
|
+
Infinity = 1.0/0.0
|
29
|
+
|
30
|
+
class FxmlJitInfo
|
31
|
+
include JRubyFX
|
32
|
+
def self.hash(file)
|
33
|
+
Digest::SHA1.hexdigest(File.read file)
|
34
|
+
end
|
35
|
+
def self.load_aot(file, cache, validate = true)
|
36
|
+
if validate
|
37
|
+
hash = hash(file)
|
38
|
+
f_hash = File.open(cache, "r", &:readline).strip
|
39
|
+
return false if "# #{hash} encoding: utf-8" != f_hash
|
40
|
+
end
|
41
|
+
hash = Digest::SHA1.hexdigest(File.basename file)
|
42
|
+
require cache
|
43
|
+
JRubyFX::GeneratedAssets.const_get("AOT#{hash}").new rescue nil
|
44
|
+
end
|
45
|
+
# TODO: store jit settings in here instead of $RB_* variables
|
46
|
+
attr_accessor :file_name, :raw_code, :jit_settings
|
47
|
+
def initialize(file_name, jit_settings=1, outfile=nil, cache_dir=nil,validate = true, opts = nil)
|
48
|
+
@file_name = file_name
|
49
|
+
@no_write = (opts && opts[:no_write]) || false
|
50
|
+
if @file_name.start_with? "file:"
|
51
|
+
@file_name = @file_name.gsub(/^file\:/, '')
|
52
|
+
elsif @file_name.start_with? "jar:"
|
53
|
+
@no_write = true
|
54
|
+
elsif @file_name.start_with? "compoundjar:"
|
55
|
+
@no_write = true
|
56
|
+
end
|
57
|
+
@jit_settings = jit_settings
|
58
|
+
@run_count = 0
|
59
|
+
@opts = opts
|
60
|
+
@outfile = if @outfile
|
61
|
+
outfile
|
62
|
+
else
|
63
|
+
cache_dir = cache_dir || File.join(File.dirname(@file_name), ".jrubyfx_cache")
|
64
|
+
FileUtils.mkpath(cache_dir) unless File.directory?(cache_dir) or @no_write
|
65
|
+
@f_hash = Digest::SHA1.hexdigest(File.basename @file_name)
|
66
|
+
File.join(cache_dir, "#{@f_hash}.rb")
|
67
|
+
end
|
68
|
+
if File.exist?(@outfile) && !(opts && opts[:force])
|
69
|
+
@compiled = self.class.load_aot(@file_name, @outfile, validate)
|
70
|
+
if @compiled
|
71
|
+
dputs "got #{file_name} from cache"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
def hash
|
76
|
+
FxmlJitInfo.hash(@file_name)
|
77
|
+
end
|
78
|
+
def should_jit?
|
79
|
+
return false if @jit_settings == :no_jit || compiled?
|
80
|
+
return true if (@run_count += 1) >= @jit_settings
|
81
|
+
end
|
82
|
+
def compiled?
|
83
|
+
!!@compiled
|
84
|
+
end
|
85
|
+
def decompile
|
86
|
+
@compiled = nil
|
87
|
+
end
|
88
|
+
def __build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
|
89
|
+
@compiled.__build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
|
90
|
+
end
|
91
|
+
def compile(code=@raw_code)
|
92
|
+
@raw_code = code
|
93
|
+
# TODO: begin rescue end
|
94
|
+
full_code = <<METHOD_DEF
|
95
|
+
def __build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
|
96
|
+
__local_fx_id_setter = lambda do |name, __i|
|
97
|
+
__local_namespace[name] = __i
|
98
|
+
__local_fxml_controller.instance_variable_set(("@\#{name}").to_sym, __i)
|
99
|
+
end
|
100
|
+
#{code}
|
101
|
+
end
|
102
|
+
METHOD_DEF
|
103
|
+
;#)
|
104
|
+
unless @no_write
|
105
|
+
begin
|
106
|
+
jit_aot_cache(full_code)
|
107
|
+
rescue
|
108
|
+
p $!
|
109
|
+
jit_no_cache(full_code)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
jit_no_cache(full_code)
|
113
|
+
end
|
114
|
+
if @opts && @opts[:compiled_hook]
|
115
|
+
@opts[:compiled_hook].call(@outfile)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
def jit_no_cache(full_code)
|
121
|
+
dputs "JIT only, no aot for #{@file_name}"
|
122
|
+
self.instance_eval full_code
|
123
|
+
@compiled = true
|
124
|
+
end
|
125
|
+
|
126
|
+
def jit_aot_cache(full_code)
|
127
|
+
File.open(@outfile, "w") do |f|
|
128
|
+
hash = hash()
|
129
|
+
f << <<AOT
|
130
|
+
# #{hash} encoding: utf-8
|
131
|
+
# @@ 1
|
132
|
+
|
133
|
+
########################### DO NOT MODIFY THIS FILE ###########################
|
134
|
+
# This file was automatically generated by JRubyFX-fxmlloader on #
|
135
|
+
# #{Time.now} for #{@file_name}
|
136
|
+
########################### DO NOT MODIFY THIS FILE ###########################
|
137
|
+
|
138
|
+
module JRubyFX
|
139
|
+
module GeneratedAssets
|
140
|
+
class AOT#{@f_hash}
|
141
|
+
include JRubyFX
|
142
|
+
#{full_code}
|
143
|
+
def hash
|
144
|
+
#{hash.inspect}
|
145
|
+
end
|
146
|
+
def compiled?
|
147
|
+
true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
AOT
|
153
|
+
end
|
154
|
+
puts "saved #{@outfile} to cache"
|
155
|
+
require @outfile
|
156
|
+
@compiled = JRubyFX::GeneratedAssets.const_get("AOT#{@f_hash}").new rescue nil
|
157
|
+
end
|
158
|
+
end
|