isomorfeus-preact 10.5.0
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 +7 -0
- data/README.md +62 -0
- data/lib/browser/delegate_native.rb +70 -0
- data/lib/browser/element.rb +176 -0
- data/lib/browser/element/canvas.rb +17 -0
- data/lib/browser/element/media.rb +78 -0
- data/lib/browser/event.rb +92 -0
- data/lib/browser/event_target.rb +39 -0
- data/lib/browser/file_list.rb +125 -0
- data/lib/browser/iterable.rb +15 -0
- data/lib/isomorfeus-preact.rb +109 -0
- data/lib/isomorfeus/preact/config.rb +189 -0
- data/lib/isomorfeus/preact/memcached_component_cache.rb +19 -0
- data/lib/isomorfeus/preact/redis_component_cache.rb +19 -0
- data/lib/isomorfeus/preact/thread_local_component_cache.rb +17 -0
- data/lib/isomorfeus/preact_view_helper.rb +188 -0
- data/lib/isomorfeus/props/validate_hash_proxy.rb +186 -0
- data/lib/isomorfeus/props/validator.rb +159 -0
- data/lib/isomorfeus/top_level.rb +101 -0
- data/lib/isomorfeus/top_level_ssr.rb +27 -0
- data/lib/isomorfeus_preact/lucid_app/api.rb +22 -0
- data/lib/isomorfeus_preact/lucid_app/base.rb +7 -0
- data/lib/isomorfeus_preact/lucid_app/mixin.rb +16 -0
- data/lib/isomorfeus_preact/lucid_app/native_component_constructor.rb +91 -0
- data/lib/isomorfeus_preact/lucid_component/api.rb +68 -0
- data/lib/isomorfeus_preact/lucid_component/app_store_proxy.rb +37 -0
- data/lib/isomorfeus_preact/lucid_component/base.rb +7 -0
- data/lib/isomorfeus_preact/lucid_component/class_store_proxy.rb +44 -0
- data/lib/isomorfeus_preact/lucid_component/initializer.rb +14 -0
- data/lib/isomorfeus_preact/lucid_component/instance_store_proxy.rb +44 -0
- data/lib/isomorfeus_preact/lucid_component/mixin.rb +15 -0
- data/lib/isomorfeus_preact/lucid_component/native_component_constructor.rb +84 -0
- data/lib/isomorfeus_preact/lucid_component/styles_api.rb +31 -0
- data/lib/isomorfeus_preact/lucid_component/styles_wrapper.rb +40 -0
- data/lib/isomorfeus_preact/lucid_func/base.rb +7 -0
- data/lib/isomorfeus_preact/lucid_func/initializer.rb +11 -0
- data/lib/isomorfeus_preact/lucid_func/mixin.rb +12 -0
- data/lib/isomorfeus_preact/lucid_func/native_component_constructor.rb +55 -0
- data/lib/isomorfeus_preact/preact/function_component/api.rb +123 -0
- data/lib/isomorfeus_preact/preact/function_component/base.rb +9 -0
- data/lib/isomorfeus_preact/preact/function_component/initializer.rb +10 -0
- data/lib/isomorfeus_preact/preact/function_component/mixin.rb +12 -0
- data/lib/isomorfeus_preact/preact/function_component/native_component_constructor.rb +48 -0
- data/lib/lucid_app/context.rb +24 -0
- data/lib/lucid_prop_declaration/mixin.rb +126 -0
- data/lib/preact.rb +309 -0
- data/lib/preact/component/api.rb +124 -0
- data/lib/preact/component/base.rb +9 -0
- data/lib/preact/component/callbacks.rb +102 -0
- data/lib/preact/component/elements.rb +64 -0
- data/lib/preact/component/initializer.rb +11 -0
- data/lib/preact/component/mixin.rb +15 -0
- data/lib/preact/component/native_component_constructor.rb +65 -0
- data/lib/preact/component/params.rb +18 -0
- data/lib/preact/component/props.rb +55 -0
- data/lib/preact/component/resolution.rb +97 -0
- data/lib/preact/component/state.rb +58 -0
- data/lib/preact/context_wrapper.rb +46 -0
- data/lib/preact/native_constant_wrapper.rb +29 -0
- data/lib/preact/options.rb +98 -0
- data/lib/preact/ref.rb +17 -0
- data/lib/preact/version.rb +3 -0
- metadata +301 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
class InstanceStoreProxy
|
3
|
+
def initialize(component_instance)
|
4
|
+
@native = component_instance.to_n
|
5
|
+
@component_instance = component_instance
|
6
|
+
@component_object_id = component_instance.object_id.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
method_missing(key)
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
method_missing(key, value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing(key, *args, &block)
|
18
|
+
if `args.length > 0`
|
19
|
+
# set instance state, simply a dispatch
|
20
|
+
|
21
|
+
action = { type: 'INSTANCE_STATE', object_id: @component_object_id, name: (`key.endsWith('=')` ? key.chop : key), value: args[0] }
|
22
|
+
Isomorfeus.store.collect_and_defer_dispatch(action)
|
23
|
+
|
24
|
+
else
|
25
|
+
# get instance state
|
26
|
+
if @native.JS[:props].JS[:iso_store]
|
27
|
+
if @native.JS[:props].JS[:iso_store].JS[:instance_state] &&
|
28
|
+
@native.JS[:props].JS[:iso_store].JS[:instance_state].JS[@component_object_id] &&
|
29
|
+
@native.JS[:props].JS[:iso_store].JS[:instance_state].JS[@component_object_id].JS.hasOwnProperty(key)
|
30
|
+
# check if we have a component local state value
|
31
|
+
return @native.JS[:props].JS[:iso_store].JS[:instance_state].JS[@component_object_id].JS[key]
|
32
|
+
end
|
33
|
+
else
|
34
|
+
a_state = Isomorfeus.store.get_state
|
35
|
+
if a_state.key?(:instance_state) && a_state[:instance_state].key?(key)
|
36
|
+
return a_state[:instance_state][key]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
# otherwise return nil
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.include(::Native::Wrapper)
|
5
|
+
base.extend(::LucidComponent::NativeComponentConstructor)
|
6
|
+
base.include(::Preact::Component::Elements)
|
7
|
+
base.extend(::LucidPropDeclaration::Mixin)
|
8
|
+
base.include(::Preact::Component::Api)
|
9
|
+
base.include(::Preact::Component::Callbacks)
|
10
|
+
base.include(::LucidComponent::Api)
|
11
|
+
base.include(::LucidComponent::StylesApi)
|
12
|
+
base.include(::LucidComponent::Initializer)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module NativeComponentConstructor
|
3
|
+
# for should_component_update we apply ruby semantics for comparing props
|
4
|
+
# to do so, we convert the props to ruby hashes and then compare
|
5
|
+
# this makes sure, that for example rubys Nil object gets handled properly
|
6
|
+
def self.extended(base)
|
7
|
+
component_name = base.to_s
|
8
|
+
wrapper_name = component_name + 'Wrapper'
|
9
|
+
%x{
|
10
|
+
base.css_styles = null;
|
11
|
+
base.preload_block = null;
|
12
|
+
base.while_loading_block = null;
|
13
|
+
|
14
|
+
base.preact_component = function(props) {
|
15
|
+
let value = Opal.global.PreactHooks.useContext(Opal.global.LucidApplicationContext);
|
16
|
+
return Opal.global.Preact.createElement(base.lucid_preact_component, Object.assign({}, props, value));
|
17
|
+
};
|
18
|
+
base.preact_component.displayName = #{wrapper_name};
|
19
|
+
|
20
|
+
base.lucid_preact_component = class extends Opal.global.Preact.Component {
|
21
|
+
constructor(props) {
|
22
|
+
super(props);
|
23
|
+
const oper = Opal.Preact;
|
24
|
+
if (base.$default_state_defined()) {
|
25
|
+
this.state = base.$state().$to_n();
|
26
|
+
} else {
|
27
|
+
this.state = {};
|
28
|
+
};
|
29
|
+
this.__ruby_instance = base.$new(this);
|
30
|
+
var defined_refs = base.$defined_refs();
|
31
|
+
for (var ref in defined_refs) {
|
32
|
+
if (defined_refs[ref] != null) {
|
33
|
+
this[ref] = function(element) {
|
34
|
+
element = oper.native_element_or_component_to_ruby(element);
|
35
|
+
#{`this.__ruby_instance`.instance_exec(`element`, &`defined_refs[ref]`)}
|
36
|
+
}
|
37
|
+
this[ref] = this[ref].bind(this);
|
38
|
+
} else {
|
39
|
+
this[ref] = Opal.global.Preact.createRef();
|
40
|
+
}
|
41
|
+
}
|
42
|
+
if (base.preload_block) {
|
43
|
+
oper.active_redux_components.push(this);
|
44
|
+
this.state.preloaded = this.__ruby_instance.$execute_preload_block();
|
45
|
+
oper.active_redux_components.pop();
|
46
|
+
}
|
47
|
+
}
|
48
|
+
static get displayName() {
|
49
|
+
return #{component_name};
|
50
|
+
}
|
51
|
+
render(props, state) {
|
52
|
+
const oper = Opal.Preact;
|
53
|
+
oper.render_buffer.push([]);
|
54
|
+
// console.log("lucid component pushed", oper.render_buffer, oper.render_buffer.toString());
|
55
|
+
oper.active_components.push(this);
|
56
|
+
oper.active_redux_components.push(this);
|
57
|
+
let block_result;
|
58
|
+
if (base.while_loading_block && !state.preloaded) { block_result = #{`this.__ruby_instance`.instance_exec(&`base.while_loading_block`)}; }
|
59
|
+
else { block_result = #{`this.__ruby_instance`.instance_exec(&`base.render_block`)}; }
|
60
|
+
if (block_result && block_result !== nil) { oper.render_block_result(block_result); }
|
61
|
+
oper.active_redux_components.pop();
|
62
|
+
oper.active_components.pop();
|
63
|
+
// console.log("lucid component popping", oper.render_buffer, oper.render_buffer.toString());
|
64
|
+
let result = oper.render_buffer.pop();
|
65
|
+
return (result.length === 1) ? result[0] : result;
|
66
|
+
}
|
67
|
+
data_access() {
|
68
|
+
return this.props.iso_store;
|
69
|
+
}
|
70
|
+
shouldComponentUpdate(next_props, next_state) {
|
71
|
+
if (!Opal.Preact.props_are_equal(this.props, next_props)) { return true; }
|
72
|
+
if (Opal.Preact.state_is_not_equal(this.state, next_state)) { return true; }
|
73
|
+
return false;
|
74
|
+
}
|
75
|
+
validateProp(props, propName, componentName) {
|
76
|
+
try { base.$validate_prop(propName, props[propName]) }
|
77
|
+
catch (e) { return new Error(componentName + " Error: prop validation failed: " + e.message); }
|
78
|
+
return null;
|
79
|
+
}
|
80
|
+
};
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module StylesApi
|
3
|
+
def self.included(base)
|
4
|
+
base.instance_exec do
|
5
|
+
def styles(styles_hash = nil, &block)
|
6
|
+
component_name = self.to_s
|
7
|
+
styles_hash = block.call if block_given?
|
8
|
+
if styles_hash
|
9
|
+
%x{
|
10
|
+
if (typeof styles_hash.$is_wrapped_style !== 'undefined') {
|
11
|
+
base.css_styles = styles_hash;
|
12
|
+
} else {
|
13
|
+
let css;
|
14
|
+
if (typeof styles_hash.$to_n === 'function') { css = styles_hash.$to_n(); }
|
15
|
+
else { css = styles_hash; }
|
16
|
+
let nano_styles = Opal.global.NanoCSSInstance.sheet(css, component_name.replace(/:/g, '_'));
|
17
|
+
base.css_styles = #{::LucidComponent::StylesWrapper.new(`nano_styles`)};
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
`base.css_styles`
|
22
|
+
end
|
23
|
+
alias_method :styles=, :styles
|
24
|
+
end
|
25
|
+
|
26
|
+
def styles
|
27
|
+
`self.$class().css_styles`
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
class StylesWrapper
|
3
|
+
include ::Native::Wrapper
|
4
|
+
|
5
|
+
def is_wrapped_style
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def fade_in
|
10
|
+
'fadeIn'
|
11
|
+
end
|
12
|
+
|
13
|
+
def fade_out
|
14
|
+
'fadeOut'
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](prop)
|
18
|
+
method_missing(prop)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(prop, *args, &block)
|
22
|
+
%x{
|
23
|
+
let value;
|
24
|
+
value = #@native[prop];
|
25
|
+
if (value) { return value; }
|
26
|
+
else {
|
27
|
+
console.warn("Style/Theme key '" + prop + "' returning nil!");
|
28
|
+
return #{nil};
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_h
|
34
|
+
%x{
|
35
|
+
if (#@props_prop) { return Opal.Hash.$new(#@native.props[#@props_prop]); }
|
36
|
+
else { return Opal.Hash.$new(#@native); }
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module LucidFunc
|
2
|
+
module Initializer
|
3
|
+
def initialize
|
4
|
+
self.JS[:native_props] = `{ props: null }`
|
5
|
+
@native_props = `Opal.Preact.Component.Props.$new(#{self})`
|
6
|
+
@app_store = LucidComponent::AppStoreProxy.new(self)
|
7
|
+
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self, self)
|
8
|
+
@store = LucidComponent::InstanceStoreProxy.new(self)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module LucidFunc
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.include(::LucidFunc::Initializer)
|
5
|
+
base.include(::Preact::FunctionComponent::Api)
|
6
|
+
base.extend(::LucidFunc::NativeComponentConstructor)
|
7
|
+
base.include(::Preact::Component::Elements)
|
8
|
+
base.include(::LucidComponent::Api)
|
9
|
+
base.include(::LucidComponent::StylesApi)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module LucidFunc
|
2
|
+
module NativeComponentConstructor
|
3
|
+
def self.extended(base)
|
4
|
+
component_name = base.to_s
|
5
|
+
%x{
|
6
|
+
base.css_styles = null;
|
7
|
+
base.instance_init = function(initial) {
|
8
|
+
let ruby_state = { instance: #{base.new(`{}`)} };
|
9
|
+
ruby_state.instance.__ruby_instance = ruby_state.instance;
|
10
|
+
ruby_state.instance.data_access = function() { return this.props.iso_store; }
|
11
|
+
ruby_state.instance.data_access.bind(ruby_state.instance);
|
12
|
+
return ruby_state;
|
13
|
+
}
|
14
|
+
base.instance_reducer = function(state, action) { return state; }
|
15
|
+
base.preact_component = function(props) {
|
16
|
+
const og = Opal.global;
|
17
|
+
const oper = Opal.Preact;
|
18
|
+
oper.render_buffer.push([]);
|
19
|
+
// console.log("function pushed", oper.render_buffer, oper.render_buffer.toString());
|
20
|
+
// Lucid functionality
|
21
|
+
let context = og.PreactHooks.useContext(og.LucidApplicationContext);
|
22
|
+
// prepare Ruby instance
|
23
|
+
const [__ruby_state, __ruby_dispatch] = og.PreactHooks.useReducer(base.instance_reducer, null, base.instance_init);
|
24
|
+
const __ruby_instance = __ruby_state.instance;
|
25
|
+
__ruby_instance.props = Object.assign({}, props, context);
|
26
|
+
oper.active_components.push(__ruby_instance);
|
27
|
+
oper.active_redux_components.push(__ruby_instance);
|
28
|
+
let block_result = #{`__ruby_instance`.instance_exec(&`base.render_block`)};
|
29
|
+
if (block_result && block_result !== nil) { oper.render_block_result(block_result); }
|
30
|
+
oper.active_redux_components.pop();
|
31
|
+
oper.active_components.pop();
|
32
|
+
// console.log("function popping", oper.render_buffer, oper.render_buffer.toString());
|
33
|
+
let result = oper.render_buffer.pop();
|
34
|
+
return (result.length === 1) ? result[0] : result;
|
35
|
+
};
|
36
|
+
base.preact_component.displayName = #{component_name};
|
37
|
+
}
|
38
|
+
|
39
|
+
base_module = base.to_s.deconstantize
|
40
|
+
if base_module != ''
|
41
|
+
base_module.constantize.define_singleton_method(base.to_s.demodulize) do |*args, &block|
|
42
|
+
`Opal.Preact.internal_prepare_args_and_render(#{base}.preact_component, args, block)`
|
43
|
+
end
|
44
|
+
else
|
45
|
+
Object.define_method(base.to_s) do |*args, &block|
|
46
|
+
`Opal.Preact.internal_prepare_args_and_render(#{base}.preact_component, args, block)`
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def render(&block)
|
51
|
+
`base.render_block = #{block}`
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Preact
|
2
|
+
module FunctionComponent
|
3
|
+
module Api
|
4
|
+
def props
|
5
|
+
@native_props
|
6
|
+
end
|
7
|
+
|
8
|
+
def use_callback(*deps, &block)
|
9
|
+
`Opal.global.PreactHooks.useCallback(function() { #{block.call} }, deps)`
|
10
|
+
end
|
11
|
+
|
12
|
+
def use_context(context)
|
13
|
+
native_context = `(typeof context.$is_wrapped_context !== 'undefined')` ? context.to_n : context
|
14
|
+
`Opal.global.PreactHooks.useContext(native_context)`
|
15
|
+
end
|
16
|
+
|
17
|
+
def use_debug_value(value, formatter)
|
18
|
+
formatter = `null` unless formatter
|
19
|
+
`Opal.global.PreactHooks.useDebugValue(value, formatter)`
|
20
|
+
end
|
21
|
+
|
22
|
+
def use_effect(*args, &block)
|
23
|
+
`Opal.global.PreactHooks.useEffect(function() { #{block.call} }, args)`
|
24
|
+
end
|
25
|
+
|
26
|
+
def use_error_boundary(&block)
|
27
|
+
error = nil
|
28
|
+
reset_error = nil
|
29
|
+
%x{
|
30
|
+
let _error;
|
31
|
+
let _reset_error;
|
32
|
+
if (block) {
|
33
|
+
[_error, reset_error] = Opal.global.PreactHooks.useErrorBoundary(function() { #{block.call(Error(_error))} });
|
34
|
+
} else {
|
35
|
+
[_error, reset_error] = Opal.global.PreactHooks.useErrorBoundary();
|
36
|
+
}
|
37
|
+
error = #{Error(e)};
|
38
|
+
}
|
39
|
+
[error, reset_error]
|
40
|
+
end
|
41
|
+
|
42
|
+
def use_imperative_handle(ruby_ref, *args, &block)
|
43
|
+
ref = ruby_ref.to_n
|
44
|
+
args = `null` if args.empty?
|
45
|
+
`Opal.global.PreactHooks.useImperativeHandle(ref, function() { #{block.call} }, args)`
|
46
|
+
end
|
47
|
+
|
48
|
+
def use_layout_effect(&block)
|
49
|
+
`Opal.global.PreactHooks.useLayoutEffect(function() { #{block.call} })`
|
50
|
+
end
|
51
|
+
|
52
|
+
def use_memo(*deps, &block)
|
53
|
+
`Opal.global.PreactHooks.useMemo(function() { #{block.call} }, deps)`
|
54
|
+
end
|
55
|
+
|
56
|
+
def use_reducer(inital_state, &block)
|
57
|
+
state = nil
|
58
|
+
dispatcher = nil
|
59
|
+
%x{
|
60
|
+
[state, dispatcher] = Opal.global.PreactHooks.useReducer(function(state, action) {
|
61
|
+
#{block.call(state, action)}
|
62
|
+
}, initial_state);
|
63
|
+
}
|
64
|
+
[state, proc { |arg| `dispatcher(arg)` }]
|
65
|
+
end
|
66
|
+
|
67
|
+
def use_ref(native_ref)
|
68
|
+
Preact::Ref.new(`Opal.global.PreactHooks.useRef(native_ref)`)
|
69
|
+
end
|
70
|
+
|
71
|
+
def use_state(initial_value)
|
72
|
+
initial = nil
|
73
|
+
setter = nil
|
74
|
+
`[initial, setter] = Opal.global.PreactHooks.useState(initial_value);`
|
75
|
+
[initial, proc { |arg| `setter(arg)` }]
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_preact_element(arg, &block)
|
79
|
+
if block_given?
|
80
|
+
# execute block, fetch last element from buffer
|
81
|
+
%x{
|
82
|
+
let last_buffer_length = Opal.Preact.render_buffer[Opal.Preact.render_buffer.length - 1].length;
|
83
|
+
let last_buffer_element = Opal.Preact.render_buffer[Opal.Preact.render_buffer.length - 1][last_buffer_length - 1];
|
84
|
+
block.$call();
|
85
|
+
// console.log("get_preact_element popping", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString())
|
86
|
+
let new_element = Opal.Preact.render_buffer[Opal.Preact.render_buffer.length - 1].pop();
|
87
|
+
if (last_buffer_element === new_element) { #{Isomorfeus.raise_error(message: "Block did not create any Preact element!")} }
|
88
|
+
return new_element;
|
89
|
+
}
|
90
|
+
else
|
91
|
+
# element was rendered before being passed as arg
|
92
|
+
# fetch last element from buffer
|
93
|
+
# `console.log("get_preact_element popping", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString())`
|
94
|
+
`Opal.Preact.render_buffer[Opal.Preact.render_buffer.length - 1].pop()`
|
95
|
+
end
|
96
|
+
end
|
97
|
+
alias gpe get_preact_element
|
98
|
+
|
99
|
+
def render_preact_element(el)
|
100
|
+
# push el to buffer
|
101
|
+
`Opal.Preact.render_buffer[Opal.Preact.render_buffer.length - 1].push(el)`
|
102
|
+
# `console.log("render_preact_element pushed", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString())`
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
alias rpe render_preact_element
|
106
|
+
|
107
|
+
def method_ref(method_symbol, *args)
|
108
|
+
method_key = "#{method_symbol}#{args}"
|
109
|
+
%x{
|
110
|
+
if (#{self}.method_refs && #{self}.method_refs[#{method_key}]) { return #{self}.method_refs[#{method_key}]; }
|
111
|
+
if (!#{self}.method_refs) { #{self}.method_refs = {}; }
|
112
|
+
#{self}.method_refs[#{method_key}] = { m: #{method(method_symbol)}, a: args };
|
113
|
+
return #{self}.method_refs[#{method_key}];
|
114
|
+
}
|
115
|
+
end
|
116
|
+
alias m_ref method_ref
|
117
|
+
|
118
|
+
def to_n
|
119
|
+
self
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|