hyper-component 1.0.alpha1.5 → 1.0.alpha1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5eb3f7c53a31ed9f6708f9fd1251f3ed52f7d54e5894145abaaf4ac4e5ac7fce
4
- data.tar.gz: b95ea7df69882114a1a55f772911ba2b609221bde04df9e629e1278c0e71ea73
3
+ metadata.gz: 280f2800045d849e7cc7eb6e517673861a9a0dd15ea96a204bc246f7c35fdf96
4
+ data.tar.gz: 5f15dcac1988d4aa3443db720bb253e4b0f1cf36fa59884fafdf8d73ade1bbb5
5
5
  SHA512:
6
- metadata.gz: b7022103f15e46d7251addacac7ca755bb2cc2e7d52ae9ec8ebcd9fbb24ada6db90e77d3d689ad20a058a60e84192f00ea88f5d99065c2b86420187f2a0a2057
7
- data.tar.gz: 44d0acecd8dc27123a35d0db8fa32f9cbdbe6715c523661a618114ad157891dfec8ebc226b6eff70e3a2a562271e3144d477e16f9110a8a274058edd1fb188cf
6
+ metadata.gz: d56717e2ef07a3b4e94e3dbe933a1710167bf8a6a9318f2667e986d055d14af3f2a86daa426ef20bdd394352398dbdd6877615daf4b7a1454e7bea40d9014c04
7
+ data.tar.gz: 5d7920af6aa4843c8141c41b44ca7120d46be0be7a752336a7d48fb2cfc5aad76c985b2b5b3586391c4baed240b9c3d3655c59db3db07a6bdf0890c07e784614
data/Gemfile CHANGED
@@ -4,5 +4,10 @@ gem 'hyper-spec', path: '../hyper-spec'
4
4
  gem 'hyperstack-config', path: '../hyperstack-config'
5
5
  gem 'hyper-store', path: '../hyper-store'
6
6
  gem 'hyper-state', path: '../hyper-state'
7
+ unless ENV['OPAL_VERSION']&.match("0.11")
8
+ gem 'opal-browser', git: 'https://github.com/opal/opal-browser'
9
+ end
10
+ gem 'hyper-trace', path: '../hyper-trace'
11
+
7
12
  #gem 'puma', '~> 3.11.0' # As of adding, version 3.12.0 isn't working so we are locking
8
13
  gemspec
@@ -23,30 +23,27 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_dependency 'hyper-state', Hyperstack::Component::VERSION
25
25
  spec.add_dependency 'hyperstack-config', Hyperstack::Component::VERSION
26
- spec.add_dependency 'libv8', '~> 6.7.0'
27
- spec.add_dependency 'mini_racer', '~> 0.2.4'
28
- spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
29
26
  spec.add_dependency 'opal-activesupport', '~> 0.3.1'
30
27
  spec.add_dependency 'react-rails', '>= 2.4.0', '< 2.5.0'
31
28
 
32
- spec.add_development_dependency 'bundler', ['>= 1.17.3', '< 2.1']
29
+ spec.add_development_dependency 'bundler'
33
30
  spec.add_development_dependency 'chromedriver-helper'
34
31
  spec.add_development_dependency 'hyper-spec', Hyperstack::Component::VERSION
35
32
  spec.add_development_dependency 'jquery-rails'
36
33
  spec.add_development_dependency 'listen'
37
34
  spec.add_development_dependency 'mime-types'
35
+ spec.add_development_dependency 'mini_racer'
38
36
  spec.add_development_dependency 'nokogiri'
39
37
  spec.add_development_dependency 'opal-jquery'
40
- spec.add_development_dependency 'opal-rails', '~> 0.9.4'
41
- spec.add_development_dependency 'opal-rspec'
42
- spec.add_development_dependency 'pry'
38
+ spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
43
39
  spec.add_development_dependency 'pry-rescue'
40
+ spec.add_development_dependency 'pry-stack_explorer'
44
41
  spec.add_development_dependency 'puma'
45
- spec.add_development_dependency 'rails', '>= 4.0.0'
42
+ spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
46
43
  spec.add_development_dependency 'rails-controller-testing'
47
44
  spec.add_development_dependency 'rake'
48
45
  spec.add_development_dependency 'rspec-rails'
49
46
  spec.add_development_dependency 'rubocop', '~> 0.51.0'
50
- spec.add_development_dependency 'sqlite3', '~> 1.3.6' # see https://github.com/rails/rails/issues/35153
47
+ spec.add_development_dependency 'sqlite3', '~> 1.4.2'
51
48
  spec.add_development_dependency 'timecop', '~> 0.8.1'
52
49
  end
@@ -1,9 +1,9 @@
1
1
  require 'hyperstack/internal/component'
2
2
 
3
- Hyperstack.import 'hyper-state'
4
3
  Hyperstack.js_import 'react/react-source-browser', client_only: true, defines: %w[ReactDOM React]
5
4
  Hyperstack.js_import 'react/react-source-server', server_only: true, defines: 'React'
6
5
  Hyperstack.import 'browser/delay', client_only: true
6
+ Hyperstack.import 'browser/interval', client_only: true
7
7
  Hyperstack.js_import 'react_ujs', defines: 'ReactRailsUJS'
8
8
  Hyperstack.import 'hyper-component' # TODO: confirm this does not break anything. Added while converting hyperloop->hyperstack
9
9
  Hyperstack.import 'hyperstack/component/auto-import' # TODO: confirm we can cancel the import
@@ -38,6 +38,7 @@ if RUBY_ENGINE == 'opal'
38
38
  require 'hyperstack/component/version'
39
39
  else
40
40
  require 'opal'
41
+ require 'hyper-state'
41
42
  require 'opal-activesupport'
42
43
  require 'hyperstack/component/version'
43
44
  require 'hyperstack/internal/component/rails'
@@ -1,7 +1,6 @@
1
1
  require 'hyperstack/ext/component/string'
2
2
  require 'hyperstack/ext/component/hash'
3
3
  require 'active_support/core_ext/class/attribute'
4
- require 'hyperstack/internal/auto_unmount'
5
4
  require 'hyperstack/internal/component/rendering_context'
6
5
  require 'hyperstack/internal/component'
7
6
  require 'hyperstack/internal/component/instance_methods'
@@ -19,15 +18,40 @@ module Hyperstack
19
18
  base.include(Hyperstack::Internal::Component::ShouldComponentUpdate)
20
19
  base.class_eval do
21
20
  class_attribute :initial_state
22
- define_callback :before_mount
21
+
22
+ method_args_deprecation_check = lambda do |name, sself, proc, *args|
23
+ if proc.arity.zero?
24
+ args = []
25
+ else
26
+ deprecation_warning "In the future #{name} callbacks will not receive any parameters."
27
+ end
28
+ sself.instance_exec(*args, &proc)
29
+ args
30
+ end
31
+
32
+ define_callback :before_mount, before_call_hook: method_args_deprecation_check
23
33
  define_callback :after_mount
24
- define_callback :before_new_params
25
- define_callback :before_update
34
+ define_callback(
35
+ :before_new_params,
36
+ after_define_hook: lambda do |klass|
37
+ klass.deprecation_warning "`before_new_params` has been deprecated. The base "\
38
+ "method componentWillReceiveProps is deprecated in React without replacement"
39
+ end
40
+ )
41
+ define_callback(:before_update, before_call_hook: method_args_deprecation_check)
26
42
  define_callback :after_update
27
- define_callback :__hyperstack_component_after_render_hook
28
- define_callback :__hyperstack_component_rescue_hook
29
- #define_callback :before_unmount defined already by Async module
30
- define_callback(:after_error) { Hyperstack::Internal::Component::ReactWrapper.add_after_error_hook(base) }
43
+ define_callback(
44
+ :__hyperstack_component_after_render_hook,
45
+ before_call_hook: ->(_, sself, proc, *args) { [*sself.instance_exec(*args, &proc)] }
46
+ )
47
+ define_callback(
48
+ :__hyperstack_component_rescue_hook,
49
+ before_call_hook: ->(_, sself, proc, *args) { sself.instance_exec(*args, &proc) }
50
+ )
51
+ define_callback(
52
+ :after_error,
53
+ after_define_hook: ->(klass) { Hyperstack::Internal::Component::ReactWrapper.add_after_error_hook(klass) }
54
+ )
31
55
  end
32
56
  base.extend(Hyperstack::Internal::Component::ClassMethods)
33
57
  unless `Opal.__hyperstack_component_original_defn`
@@ -165,13 +189,25 @@ module Hyperstack
165
189
  end
166
190
 
167
191
  def __hyperstack_component_run_post_render_hooks(element)
168
- run_callback(:__hyperstack_component_after_render_hook, element) { |*args| args }.first
192
+ run_callback(:__hyperstack_component_after_render_hook, element).first
169
193
  end
170
194
 
195
+ def _run_before_render_callbacks
196
+ # eventually add before_update if @__component_mounted
197
+ # but that will not perfectly match the current React behavior.
198
+ # However that behavior is deprecated, and so once we have
199
+ # given a chance for the code to be updated we can switch this over
200
+ # and switch the deprecation notice to an error.
201
+ component_will_mount unless @__component_mounted
202
+ @__component_mounted = true
203
+ end
204
+
205
+
171
206
  def _render_wrapper
207
+ _run_before_render_callbacks
172
208
  observing(rendering: true) do
173
209
  element = Hyperstack::Internal::Component::RenderingContext.render(nil) do
174
- render || ''
210
+ render || ""
175
211
  end
176
212
  @__hyperstack_component_waiting_on_resources =
177
213
  element.waiting_on_resources if element.respond_to? :waiting_on_resources
@@ -22,7 +22,7 @@ module Hyperstack
22
22
  %x{
23
23
  React.Children.forEach(#{@children}, function(context){
24
24
  #{
25
- element = Element.new(`context`)
25
+ element = Element.new(`context`, :wrap_child)
26
26
  block.call(element)
27
27
  collection << element
28
28
  }
@@ -15,33 +15,73 @@ module Hyperstack
15
15
  # by using method missing
16
16
  #
17
17
  class Element
18
- include Native
19
18
 
20
- alias_native :element_type, :type
21
- alias_native :props, :props
19
+ # $$typeof: Symbol(react.element)
20
+ # key: null
21
+ # props: {}
22
+ # ref: null
23
+ # type: "div"
24
+ # _ _owner: null
22
25
 
23
- attr_reader :type
26
+ attr_reader :type
27
+
28
+ attr_reader :element_type # change this so name does not conflict - change to element type
24
29
  attr_reader :properties
25
30
  attr_reader :block
31
+ attr_reader :to_n
26
32
 
27
33
  attr_accessor :waiting_on_resources
28
34
 
29
- def initialize(native_element, type = nil, properties = {}, block = nil)
30
- @type = type
35
+ def set_native_attributes(native_element)
36
+ @key = `native_element.key`
37
+ @props = `native_element.props`
38
+ @ref = `native_element.ref`
39
+ @type = `native_element.type`
40
+ @_owner = `native_element._owner`
41
+ @_props_as_hash = Hash.new(@props)
42
+ end
43
+
44
+ def props
45
+ @_props_as_hash
46
+ end
47
+
48
+ def convert_string(native_element, element_type, props, block)
49
+ return native_element unless `native_element['$is_a?']`
50
+ return native_element unless native_element.is_a? String
51
+ raise "Internal Error Element.new called with string, but non-nil props or block" if !props.empty? || block
52
+
53
+ if element_type == :wrap_child
54
+ `React.createElement(React.Fragment, null, [native_element])`
55
+ else
56
+ `React.createElement(native_element, null)`
57
+ end
58
+ end
59
+
60
+ def initialize(native_element, element_type = nil, properties = {}, block = nil)
61
+
62
+ native_element = convert_string(native_element, element_type, properties, block)
63
+ @element_type = element_type unless element_type == :wrap_child
31
64
  @properties = (`typeof #{properties} === 'undefined'` ? nil : properties) || {}
32
65
  @block = block
33
- @native = native_element
66
+ `#{self}.$$typeof = native_element.$$typeof`
67
+ @to_n = self
68
+ set_native_attributes(native_element)
69
+ rescue Exception
70
+ end
71
+
72
+ def children
73
+ `#{@props}.children`
34
74
  end
35
75
 
36
76
  def _update_ref(x)
37
- @ref = x
77
+ @_ref = x
38
78
  @_child_element._update_ref(x) if @_child_element
39
79
  end
40
80
 
41
- def ref
42
- return @ref if @ref
43
- raise("The instance of #{self.type} has not been mounted yet") if properties[:ref]
44
- raise("Attempt to get a ref on #{self.type} which is a static component.")
81
+ def ref # this will not conflict with React's on ref attribute okay because its $ref!!!
82
+ return @_ref if @_ref
83
+ raise("The instance of #{self.element_type} has not been mounted yet") if properties[:ref]
84
+ raise("Attempt to get a ref on #{self.element_type} which is a static component.")
45
85
  end
46
86
 
47
87
  def dom_node
@@ -57,7 +97,7 @@ module Hyperstack
57
97
  merge_event_prop!(event_name, &block)
58
98
  any_found = true
59
99
  end
60
- @native = `React.cloneElement(#{@native}, #{@properties.shallow_to_n})` if any_found
100
+ set_native_attributes(`React.cloneElement(#{self}, #{@properties.shallow_to_n})`) if any_found
61
101
  self
62
102
  end
63
103
 
@@ -69,10 +109,10 @@ module Hyperstack
69
109
  if props.empty?
70
110
  Hyperstack::Internal::Component::RenderingContext.render(self)
71
111
  else
72
- props = Hyperstack::Internal::Component::ReactWrapper.convert_props(@type, @properties, *props)
112
+ props = Hyperstack::Internal::Component::ReactWrapper.convert_props(element_type, @properties, *props)
73
113
  @_child_element = Hyperstack::Internal::Component::RenderingContext.render(
74
- Element.new(`React.cloneElement(#{@native}, #{props.shallow_to_n})`,
75
- type, props, block)
114
+ Element.new(`React.cloneElement(#{self}, #{props.shallow_to_n})`,
115
+ element_type, props, block)
76
116
  )
77
117
  end
78
118
  end
@@ -80,11 +120,12 @@ module Hyperstack
80
120
  # Delete (remove) element from rendering context, the element may later be added back in
81
121
  # using the render method.
82
122
 
83
- def delete
123
+ def ~
84
124
  Hyperstack::Internal::Component::RenderingContext.delete(self)
85
125
  end
86
126
  # Deprecated version of delete method
87
- alias as_node delete
127
+ alias as_node ~
128
+ alias delete ~
88
129
 
89
130
  private
90
131
 
@@ -109,7 +150,7 @@ module Hyperstack
109
150
  merge_built_in_event_prop! name, &block
110
151
  elsif event_name == :enter
111
152
  merge_built_in_event_prop!('onKeyDown') { |evt| yield(evt) if evt.key_code == 13 }
112
- elsif @type.instance_variable_get('@native_import')
153
+ elsif element_type.instance_variable_get('@native_import')
113
154
  merge_component_event_prop! name, &block
114
155
  else
115
156
  merge_component_event_prop! "on_#{event_name}", &block
@@ -1,7 +1,7 @@
1
1
  module Hyperstack
2
2
  module Component
3
3
  class Event
4
- include Native
4
+ include Native::Wrapper
5
5
  alias_native :bubbles, :bubbles
6
6
  alias_native :cancelable, :cancelable
7
7
  alias_native :current_target, :currentTarget
@@ -18,16 +18,22 @@ module Hyperstack
18
18
  def self.load_context(unique_id = nil, name = nil)
19
19
  # can be called on the client to force re-initialization for testing purposes
20
20
  if !unique_id || !@context || @context.unique_id != unique_id
21
- if on_opal_server?
22
- `console.history = []` rescue nil
23
- message = "************************ React Prerendering Context Initialized #{name} ***********************"
24
- else
25
- message = "************************ React Browser Context Initialized ****************************"
26
- end
21
+ message =
22
+ if on_opal_server?
23
+ `console.history = []` rescue nil
24
+ "************************ React Prerendering Context Initialized #{name} ***********************"
25
+ else
26
+ '************************ React Browser Context Initialized ****************************'
27
+ end
28
+
27
29
  log(message)
30
+
28
31
  @context = Context.new(unique_id)
29
32
  end
30
- @context
33
+
34
+ # True is returned here because this method is evaluated by MiniRacer,
35
+ # and can cause TypeError: Converting circular structure to JSON to raise
36
+ true
31
37
  end
32
38
  end
33
39
 
@@ -139,7 +145,6 @@ module Hyperstack
139
145
 
140
146
  def send_to_opal(method_name, *args)
141
147
  return unless @ctx
142
- args = [1] if args.length == 0
143
148
  Hyperstack::Internal::Component::Rails::ComponentLoader.new(@ctx).load!
144
149
  method_args = args.collect do |arg|
145
150
  quarg = "#{arg}".tr('"', "'")
@@ -1,5 +1,5 @@
1
1
  module Hyperstack
2
2
  module Component
3
- VERSION = '1.0.alpha1.5' # '1.0.alpha1.5'
3
+ VERSION = '1.0.alpha1.6' # '1.0.alpha1.5'
4
4
  end
5
5
  end
@@ -16,7 +16,7 @@ module Hyperstack
16
16
  if Hyperstack::Component::IsomorphicHelpers.on_opal_client?
17
17
  %x{
18
18
  function onError(event) {
19
- if (event.message.startsWith('Uncaught NotQuiet: ')) event.preventDefault();
19
+ if (event.message.match(/^Uncaught NotQuiet: /)) event.preventDefault();
20
20
  }
21
21
 
22
22
  window.addEventListener('error', onError);
@@ -50,7 +50,7 @@ module Hyperstack
50
50
  def render(container = nil, params = {}, &block)
51
51
  Tags.included(self)
52
52
  if container
53
- container = container.type if container.is_a? Hyperstack::Component::Element
53
+ container = container.element_type if container.is_a? Hyperstack::Component::Element
54
54
  define_method(:__hyperstack_component_render) do
55
55
  __hyperstack_component_select_wrappers do
56
56
  RenderingContext.render(container, params) do
@@ -28,7 +28,7 @@ module Hyperstack
28
28
  self,
29
29
  Hyperstack::Internal::Component::RenderingContext.build do
30
30
  Hyperstack::Internal::Component::RenderingContext.render(
31
- type, @properties, args, class: haml_class_name(class_name), &new_block
31
+ element_type, @properties, args, class: haml_class_name(class_name), &new_block
32
32
  )
33
33
  end
34
34
  )
@@ -43,6 +43,9 @@ module Hyperstack
43
43
  end
44
44
 
45
45
  def footers
46
+ return if @hyperstack_footers_rendered
47
+
48
+ @hyperstack_footers_rendered = true
46
49
  Hyperstack::Component::IsomorphicHelpers.prerender_footers(controller)
47
50
  end
48
51
  end
@@ -13,7 +13,11 @@ module Hyperstack
13
13
 
14
14
  class ContextualRenderer < React::ServerRendering::BundleRenderer
15
15
  def initialize(options = {})
16
- super(options)
16
+ unless v8_runtime?
17
+ raise "Hyperstack prerendering only works with MiniRacer. Add 'mini_racer' to your Gemfile"
18
+ end
19
+
20
+ super({ files: ['hyperstack-prerender-loader.js'] }.merge(options))
17
21
  ComponentLoader.new(v8_context).load
18
22
  end
19
23
 
@@ -9,7 +9,9 @@ module Hyperstack
9
9
  module ServerRendering
10
10
  class HyperTestAssetContainer
11
11
  def find_asset(logical_path)
12
- ::Rails.cache.read(logical_path)
12
+ # we skip the container if it raises an error so we
13
+ # don't care if we are running under hyperspec or not
14
+ HyperSpec::Internal::Controller.cache_read(logical_path)
13
15
  end
14
16
  end
15
17
 
@@ -24,7 +26,7 @@ module Hyperstack
24
26
  if React::ServerRendering::WebpackerManifestContainer.compatible?
25
27
  @ass_containers << React::ServerRendering::WebpackerManifestContainer.new
26
28
  end
27
- @ass_containers << HyperTestAssetContainer.new if ::Rails.env.test?
29
+ @ass_containers << HyperTestAssetContainer.new
28
30
  end
29
31
 
30
32
  def find_asset(logical_path)
@@ -19,7 +19,7 @@ module Hyperstack
19
19
  @@component_classes = {}
20
20
 
21
21
  def self.stateless?(ncc)
22
- `typeof #{ncc} === 'function' && !(#{ncc}.prototype && #{ncc}.prototype.isReactComponent)`
22
+ `typeof #{ncc} === 'symbol' || (typeof #{ncc} === 'function' && !(#{ncc}.prototype && #{ncc}.prototype.isReactComponent))`
23
23
  end
24
24
 
25
25
  def self.import_native_component(opal_class, native_class)
@@ -30,6 +30,7 @@ module Hyperstack
30
30
  def self.eval_native_react_component(name)
31
31
  component = `eval(name)`
32
32
  raise "#{name} is not defined" if `#{component} === undefined`
33
+
33
34
  component = `component.default` if `component.__esModule`
34
35
  is_component_class = `#{component}.prototype !== undefined` &&
35
36
  (`!!#{component}.prototype.isReactComponent` ||
@@ -43,9 +44,11 @@ module Hyperstack
43
44
 
44
45
  def self.native_react_component?(name = nil)
45
46
  return false unless name
47
+
46
48
  eval_native_react_component(name)
47
49
  true
48
- rescue
50
+ # Exception to be compatible with all versions of opal
51
+ rescue Exception # rubocop:disable Lint/RescueException
49
52
  false
50
53
  end
51
54
 
@@ -64,93 +67,81 @@ module Hyperstack
64
67
  end
65
68
 
66
69
  def self.create_native_react_class(type)
70
+ raise "createReactClass is undefined. Add the 'react-create-class' npm module, and import it as 'createReactClass'" if `typeof(createReactClass)=='undefined'`
67
71
  raise "Provided class should define `render` method" if !(type.method_defined? :render)
68
- render_fn = (type.method_defined? :_render_wrapper) ? :_render_wrapper : :render
72
+ old_school = !type.method_defined?(:_render_wrapper)
73
+ render_fn = old_school ? :render : :_render_wrapper
69
74
  # this was hashing type.to_s, not sure why but .to_s does not work as it Foo::Bar::View.to_s just returns "View"
70
-
71
75
  @@component_classes[type] ||= begin
72
76
  comp = %x{
73
- class extends React.Component {
74
- constructor(props) {
75
- super(props);
77
+ createReactClass({
78
+ getInitialState: function() {
76
79
  this.mixins = #{type.respond_to?(:native_mixins) ? type.native_mixins : `[]`};
77
80
  this.statics = #{type.respond_to?(:static_call_backs) ? type.static_call_backs.to_n : `{}`};
78
- this.state = {};
79
81
  this.__opalInstanceInitializedState = false;
80
82
  this.__opalInstanceSyncSetState = true;
81
83
  this.__opalInstance = #{type.new(`this`)};
82
84
  this.__opalInstanceInitializedState = true;
83
85
  this.__opalInstanceSyncSetState = false;
84
86
  this.__name = #{type.name};
85
- }
86
- static get displayName() {
87
- if (typeof this.__name != "undefined") {
88
- return this.__name;
89
- } else {
90
- return #{type.name};
91
- }
92
- }
93
- static set displayName(name) {
94
- this.__name = name;
95
- }
96
- static get defaultProps() {
87
+ return {}
88
+ },
89
+ displayName: #{type.name},
90
+ getDefaultProps: function() {
97
91
  return #{type.respond_to?(:default_props) ? type.default_props.to_n : `{}`};
98
- }
99
- static get propTypes() {
100
- return #{type.respond_to?(:prop_types) ? type.prop_types.to_n : `{}`};
101
- }
102
- componentWillMount() {
92
+ },
93
+ propTypes: #{type.respond_to?(:prop_types) ? type.prop_types.to_n : `{}`},
94
+ componentWillMount: old_school && function() {
103
95
  if (#{type.method_defined? :component_will_mount}) {
104
96
  this.__opalInstanceSyncSetState = true;
105
97
  this.__opalInstance.$component_will_mount();
106
98
  this.__opalInstanceSyncSetState = false;
107
99
  }
108
- }
109
- componentDidMount() {
100
+ },
101
+ componentDidMount: function() {
110
102
  this.__opalInstance.__hyperstack_component_is_mounted = true
111
103
  if (#{type.method_defined? :component_did_mount}) {
112
104
  this.__opalInstanceSyncSetState = false;
113
105
  this.__opalInstance.$component_did_mount();
114
106
  }
115
- }
116
- componentWillReceiveProps(next_props) {
107
+ },
108
+ UNSAFE_componentWillReceiveProps: function(next_props) {
117
109
  if (#{type.method_defined? :component_will_receive_props}) {
118
110
  this.__opalInstanceSyncSetState = true;
119
111
  this.__opalInstance.$component_will_receive_props(Opal.Hash.$new(next_props));
120
112
  this.__opalInstanceSyncSetState = false;
121
113
  }
122
- }
123
- shouldComponentUpdate(next_props, next_state) {
114
+ },
115
+ shouldComponentUpdate: function(next_props, next_state) {
124
116
  if (#{type.method_defined? :should_component_update?}) {
125
117
  this.__opalInstanceSyncSetState = false;
126
118
  return this.__opalInstance["$should_component_update?"](Opal.Hash.$new(next_props), Opal.Hash.$new(next_state));
127
119
  } else { return true; }
128
- }
129
- componentWillUpdate(next_props, next_state) {
120
+ },
121
+ UNSAFE_componentWillUpdate: function(next_props, next_state) {
130
122
  if (#{type.method_defined? :component_will_update}) {
131
123
  this.__opalInstanceSyncSetState = false;
132
124
  this.__opalInstance.$component_will_update(Opal.Hash.$new(next_props), Opal.Hash.$new(next_state));
133
125
  }
134
- }
135
- componentDidUpdate(prev_props, prev_state) {
126
+ },
127
+ componentDidUpdate: function(prev_props, prev_state) {
136
128
  if (#{type.method_defined? :component_did_update}) {
137
129
  this.__opalInstanceSyncSetState = false;
138
130
  this.__opalInstance.$component_did_update(Opal.Hash.$new(prev_props), Opal.Hash.$new(prev_state));
139
131
  }
140
- }
141
- componentWillUnmount() {
132
+ },
133
+ componentWillUnmount: function() {
142
134
  if (#{type.method_defined? :component_will_unmount}) {
143
135
  this.__opalInstanceSyncSetState = false;
144
136
  this.__opalInstance.$component_will_unmount();
145
137
  }
146
138
  this.__opalInstance.__hyperstack_component_is_mounted = false;
147
- }
148
-
149
- render() {
139
+ },
140
+ render: function() {
150
141
  this.__opalInstanceSyncSetState = false;
151
142
  return this.__opalInstance.$send(render_fn).$to_n();
152
143
  }
153
- }
144
+ })
154
145
  }
155
146
  # check to see if there is an after_error callback. If there is add a
156
147
  # componentDidCatch handler. Because legacy behavior is to allow any object
@@ -19,27 +19,41 @@ module Hyperstack
19
19
  raise NotQuiet.new("#{component} is waiting on resources")
20
20
  end
21
21
 
22
+ def render_string(string)
23
+ @buffer ||= []
24
+ @buffer << string
25
+ end
26
+
22
27
  def render(name, *args, &block)
23
28
  was_outer_most = !@not_outer_most
24
29
  @not_outer_most = true
25
30
  remove_nodes_from_args(args)
26
- @buffer ||= [] unless @buffer
31
+ @buffer ||= [] #unless @buffer
27
32
  if block
28
33
  element = build do
29
34
  saved_waiting_on_resources = nil #waiting_on_resources what was the purpose of this its used below to or in with the current elements waiting_for_resources
30
35
  self.waiting_on_resources = nil
31
- run_child_block(name.nil?, &block)
36
+ run_child_block(&block)
32
37
  if name
33
38
  buffer = @buffer.dup
34
39
  ReactWrapper.create_element(name, *args) { buffer }.tap do |element|
35
40
  element.waiting_on_resources = saved_waiting_on_resources || !!buffer.detect { |e| e.waiting_on_resources if e.respond_to?(:waiting_on_resources) }
36
41
  element.waiting_on_resources ||= waiting_on_resources if buffer.last.is_a?(String)
37
42
  end
38
- elsif @buffer.last.is_a? Hyperstack::Component::Element
39
- @buffer.last.tap { |element| element.waiting_on_resources ||= saved_waiting_on_resources }
40
43
  else
41
- buffer_s = @buffer.last.to_s
42
- RenderingContext.render(:span) { buffer_s }.tap { |element| element.waiting_on_resources = saved_waiting_on_resources }
44
+ buffer = @buffer.collect do |item|
45
+ if item.is_a? Hyperstack::Component::Element
46
+ item.waiting_on_resources ||= saved_waiting_on_resources
47
+ item
48
+ else
49
+ RenderingContext.render(:span) { item.to_s }.tap { |element| element.waiting_on_resources = saved_waiting_on_resources }
50
+ end
51
+ end
52
+ if buffer.length > 1
53
+ buffer
54
+ else
55
+ buffer.first
56
+ end
43
57
  end
44
58
  end
45
59
  elsif name.is_a? Hyperstack::Component::Element
@@ -65,6 +79,7 @@ module Hyperstack
65
79
 
66
80
  def delete(element)
67
81
  @buffer.delete(element)
82
+ @last_deleted = element
68
83
  element
69
84
  end
70
85
  alias as_node delete
@@ -86,55 +101,74 @@ module Hyperstack
86
101
  end if args[0] && args[0].is_a?(Hash)
87
102
  end
88
103
 
89
- # run_child_block gathers the element(s) generated by a child block.
104
+ # run_child_block yields to the child rendering block which will put any
105
+ # elements to be rendered into the current rendering buffer.
106
+ #
90
107
  # for example when rendering this div: div { "hello".span; "goodby".span }
91
108
  # two child Elements will be generated.
92
109
  #
93
- # the final value of the block should either be
94
- # 1 an object that responds to :acts_as_string?
95
- # 2 a string,
96
- # 3 an element that is NOT yet pushed on the rendering buffer
97
- # 4 or the last element pushed on the buffer
110
+ # However the block itself will return a value, which in some cases should
111
+ # also added to the buffer:
112
+ #
113
+ # If the final value of the block is a
98
114
  #
99
- # in case 1 we render a span
100
- # in case 2 we automatically push the string onto the buffer
101
- # in case 3 we also push the Element onto the buffer IF the buffer is empty
102
- # case 4 requires no special processing
115
+ # a hyper model dummy value that is being loaded, then wrap it in a span and add it to the buffer
116
+ # a string (or if the buffer is empty any value), then add it to the buffer
117
+ # an Element, then add it on the buffer unless it has been just deleted
118
+ # #
119
+ # Note that the reason we don't always allow Strings to be automatically pushed is
120
+ # to avoid confusing results in situations like this:
121
+ # DIV { collection.each { |item| SPAN { item } } }
122
+ # If we accepted any object to be rendered this would generate:
123
+ # DIV { SPAN { collection[0] } SPAN { collection[n] } collection.to_s }
124
+ # which is probably not the desired output. If it was you would just append to_s
125
+ # to the end of the expression, to force it to be added to the output buffer.
103
126
  #
104
- # Once we have taken care of these special cases we do a check IF we are in an
105
- # outer rendering scope. In this case react only allows us to generate 1 Element
106
- # so we insure that is the case, and also check to make sure that element in the buffer
107
- # is the element returned
127
+ # However if the buffer is empty then it makes sense to automatically apply the `.to_s`
128
+ # to the value, and push it on the buffer, unless it is a falsy value or an array
108
129
 
109
- def run_child_block(is_outer_scope)
130
+ def run_child_block
110
131
  result = yield
111
- if result.respond_to?(:acts_as_string?) && result.acts_as_string?
112
- # hyper-mesh DummyValues respond to acts_as_string, and must
132
+ check_for_component_return(result)
133
+ if dummy_value?(result)
134
+ # hyper-mesh DummyValues must
113
135
  # be converted to spans INSIDE the parent, otherwise the waiting_on_resources
114
136
  # flag will get set in the wrong context
115
137
  RenderingContext.render(:span) { result.to_s }
116
- elsif result.is_a?(String) || (result.is_a?(Hyperstack::Component::Element) && @buffer.empty?)
117
- @buffer << result
138
+ elsif result.is_a?(Hyperstack::Component::Element)
139
+ @buffer << result if @buffer.empty? unless @last_deleted == result
140
+ elsif pushable_string?(result)
141
+ @buffer << result.to_s
118
142
  end
119
- raise_render_error(result) if is_outer_scope && @buffer != [result]
143
+ @last_deleted = nil
120
144
  end
121
145
 
122
- # heurestically raise a meaningful error based on the situation
123
-
124
- def raise_render_error(result)
125
- improper_render 'A different element was returned than was generated within the DSL.',
126
- 'Possibly improper use of Element#delete.' if @buffer.count == 1
127
- improper_render "Instead #{@buffer.count} elements were generated.",
128
- 'Do you want to wrap your elements in a div?' if @buffer.count > 1
129
- improper_render "Instead the component #{result} was returned.",
130
- "Did you mean #{result}()?" if result.try :hyper_component?
131
- improper_render "Instead the #{result.class} #{result} was returned.",
132
- 'You may need to convert this to a string.'
146
+ def check_for_component_return(result)
147
+ # check for a common error of saying (for example) DIV (without parens)
148
+ # which returns the DIV component class instead of a rendered DIV
149
+ return unless result.try :hyper_component?
150
+
151
+ Hyperstack::Component::IsomorphicHelpers.log(
152
+ "a component's render method returned the component class #{result}, did you mean to say #{result}()",
153
+ :warning
154
+ )
155
+ end
156
+
157
+ def dummy_value?(result)
158
+ result.respond_to?(:loading?) && result.loading?
159
+ end
160
+
161
+ def pushable_string?(result)
162
+ # if the buffer is not empty we will only push on strings, and ignore anything else
163
+ return result.is_a?(String) unless @buffer.empty?
164
+
165
+ # if the buffer IS empty then we can push on anything except we avoid nil, false and arrays
166
+ # as these are almost never what you want to render, and if you do there are mechanisms
167
+ # to render them explicitly
168
+ result && result.respond_to?(:to_n) && !result.is_a?(Array)
133
169
  end
134
170
 
135
171
  def improper_render(message, solution)
136
- raise "a component's render method must generate and return exactly 1 element or a string.\n"\
137
- " #{message} #{solution}"
138
172
  end
139
173
  end
140
174
  end
@@ -143,7 +177,7 @@ module Hyperstack
143
177
  end
144
178
 
145
179
  class Object
146
- [:span, :td, :th].each do |tag|
180
+ %i[span td th].each do |tag|
147
181
  define_method(tag) do |*args, &block|
148
182
  args.unshift(tag)
149
183
  # legacy hyperloop allowed tags to be lower case as well so if self is a component
@@ -155,24 +189,26 @@ class Object
155
189
  # in the component.
156
190
  # If we fully deprecate lowercase tags, then this next line can go...
157
191
  return send(*args, &block) if respond_to?(:hyper_component?) && hyper_component?
192
+
158
193
  Hyperstack::Internal::Component::RenderingContext.render(*args) { to_s }
159
194
  end
160
195
  end
161
196
 
162
-
163
197
  def para(*args, &block)
164
198
  args.unshift(:p)
165
199
  # see above comment
166
200
  return send(*args, &block) if respond_to?(:hyper_component?) && hyper_component?
201
+
167
202
  Hyperstack::Internal::Component::RenderingContext.render(*args) { to_s }
168
203
  end
169
204
 
170
205
  def br
171
206
  # see above comment
172
207
  return send(:br) if respond_to?(:hyper_component?) && hyper_component?
173
- Hyperstack::Internal::Component::RenderingContext.render(:span) do
174
- Hyperstack::Internal::Component::RenderingContext.render(to_s)
175
- Hyperstack::Internal::Component::RenderingContext.render(:br)
208
+
209
+ Hyperstack::Internal::Component::RenderingContext.render(Hyperstack::Internal::Component::Tags::FRAGMENT) do
210
+ Hyperstack::Internal::Component::RenderingContext.render(Hyperstack::Internal::Component::Tags::FRAGMENT) { to_s }
211
+ Hyperstack::Internal::Component::RenderingContext.render(Hyperstack::Internal::Component::Tags::BR)
176
212
  end
177
213
  end
178
214
 
@@ -27,7 +27,7 @@ module Hyperstack
27
27
 
28
28
  after_error do |error, info|
29
29
  args = RescueWrapper.after_error_args || [error, info]
30
- found, * = @Child.run_callback(:__hyperstack_component_rescue_hook, found, *args) { |a| a }
30
+ found, * = @Child.run_callback(:__hyperstack_component_rescue_hook, found, *args)
31
31
  unless found
32
32
  RescueWrapper.after_error_args = args
33
33
  raise error
@@ -32,6 +32,14 @@ module Hyperstack
32
32
  const_set tag.upcase, tag
33
33
  end
34
34
 
35
+ const_set "FRAGMENT", (
36
+ Class.new do
37
+ include Hyperstack::Component
38
+ render {}
39
+ Hyperstack::Internal::Component::ReactWrapper.import_native_component(self, `React.Fragment`)
40
+ end
41
+ )
42
+
35
43
  # this is used for haml style (i.e. DIV.foo.bar) class tags which is deprecated
36
44
  def self.html_tag_class_for(tag)
37
45
  downcased_tag = tag.downcase
@@ -85,6 +93,7 @@ module Hyperstack
85
93
 
86
94
  def lookup_const(name)
87
95
  return nil unless name =~ /^[A-Z]/
96
+ return Hyperstack::Internal::Component::Tags::FRAGMENT if name == "FRAGMENT"
88
97
  scopes = self.class.name.to_s.split('::').inject([Object]) do |nesting, next_const|
89
98
  nesting + [nesting.last.const_get(next_const)]
90
99
  end.reverse
@@ -11,7 +11,7 @@ if RUBY_ENGINE == 'opal'
11
11
  else
12
12
  require "hyperstack/internal/component"
13
13
  require "react/rails/asset_variant"
14
- variant = Hyperstack.env.production? ? 'production' : 'development'
15
- react_directory = React::Rails::AssetVariant.new({environment: variant}).react_directory
14
+ variant = Hyperstack.env.production? ? :production : :development
15
+ react_directory = React::Rails::AssetVariant.new({ variant: variant }).react_directory
16
16
  Opal.append_path react_directory.untaint
17
17
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyper-component
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.alpha1.5
4
+ version: 1.0.alpha1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Chang
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2019-06-19 00:00:00.000000000 Z
15
+ date: 2021-03-29 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: hyper-state
@@ -20,76 +20,28 @@ dependencies:
20
20
  requirements:
21
21
  - - '='
22
22
  - !ruby/object:Gem::Version
23
- version: 1.0.alpha1.5
23
+ version: 1.0.alpha1.6
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
28
  - - '='
29
29
  - !ruby/object:Gem::Version
30
- version: 1.0.alpha1.5
30
+ version: 1.0.alpha1.6
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: hyperstack-config
33
33
  requirement: !ruby/object:Gem::Requirement
34
34
  requirements:
35
35
  - - '='
36
36
  - !ruby/object:Gem::Version
37
- version: 1.0.alpha1.5
37
+ version: 1.0.alpha1.6
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - '='
43
43
  - !ruby/object:Gem::Version
44
- version: 1.0.alpha1.5
45
- - !ruby/object:Gem::Dependency
46
- name: libv8
47
- requirement: !ruby/object:Gem::Requirement
48
- requirements:
49
- - - "~>"
50
- - !ruby/object:Gem::Version
51
- version: 6.7.0
52
- type: :runtime
53
- prerelease: false
54
- version_requirements: !ruby/object:Gem::Requirement
55
- requirements:
56
- - - "~>"
57
- - !ruby/object:Gem::Version
58
- version: 6.7.0
59
- - !ruby/object:Gem::Dependency
60
- name: mini_racer
61
- requirement: !ruby/object:Gem::Requirement
62
- requirements:
63
- - - "~>"
64
- - !ruby/object:Gem::Version
65
- version: 0.2.4
66
- type: :runtime
67
- prerelease: false
68
- version_requirements: !ruby/object:Gem::Requirement
69
- requirements:
70
- - - "~>"
71
- - !ruby/object:Gem::Version
72
- version: 0.2.4
73
- - !ruby/object:Gem::Dependency
74
- name: opal
75
- requirement: !ruby/object:Gem::Requirement
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: 0.11.0
80
- - - "<"
81
- - !ruby/object:Gem::Version
82
- version: 0.12.0
83
- type: :runtime
84
- prerelease: false
85
- version_requirements: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: 0.11.0
90
- - - "<"
91
- - !ruby/object:Gem::Version
92
- version: 0.12.0
44
+ version: 1.0.alpha1.6
93
45
  - !ruby/object:Gem::Dependency
94
46
  name: opal-activesupport
95
47
  requirement: !ruby/object:Gem::Requirement
@@ -130,20 +82,14 @@ dependencies:
130
82
  requirements:
131
83
  - - ">="
132
84
  - !ruby/object:Gem::Version
133
- version: 1.17.3
134
- - - "<"
135
- - !ruby/object:Gem::Version
136
- version: '2.1'
85
+ version: '0'
137
86
  type: :development
138
87
  prerelease: false
139
88
  version_requirements: !ruby/object:Gem::Requirement
140
89
  requirements:
141
90
  - - ">="
142
91
  - !ruby/object:Gem::Version
143
- version: 1.17.3
144
- - - "<"
145
- - !ruby/object:Gem::Version
146
- version: '2.1'
92
+ version: '0'
147
93
  - !ruby/object:Gem::Dependency
148
94
  name: chromedriver-helper
149
95
  requirement: !ruby/object:Gem::Requirement
@@ -164,14 +110,14 @@ dependencies:
164
110
  requirements:
165
111
  - - '='
166
112
  - !ruby/object:Gem::Version
167
- version: 1.0.alpha1.5
113
+ version: 1.0.alpha1.6
168
114
  type: :development
169
115
  prerelease: false
170
116
  version_requirements: !ruby/object:Gem::Requirement
171
117
  requirements:
172
118
  - - '='
173
119
  - !ruby/object:Gem::Version
174
- version: 1.0.alpha1.5
120
+ version: 1.0.alpha1.6
175
121
  - !ruby/object:Gem::Dependency
176
122
  name: jquery-rails
177
123
  requirement: !ruby/object:Gem::Requirement
@@ -215,7 +161,7 @@ dependencies:
215
161
  - !ruby/object:Gem::Version
216
162
  version: '0'
217
163
  - !ruby/object:Gem::Dependency
218
- name: nokogiri
164
+ name: mini_racer
219
165
  requirement: !ruby/object:Gem::Requirement
220
166
  requirements:
221
167
  - - ">="
@@ -229,7 +175,7 @@ dependencies:
229
175
  - !ruby/object:Gem::Version
230
176
  version: '0'
231
177
  - !ruby/object:Gem::Dependency
232
- name: opal-jquery
178
+ name: nokogiri
233
179
  requirement: !ruby/object:Gem::Requirement
234
180
  requirements:
235
181
  - - ">="
@@ -243,35 +189,41 @@ dependencies:
243
189
  - !ruby/object:Gem::Version
244
190
  version: '0'
245
191
  - !ruby/object:Gem::Dependency
246
- name: opal-rails
192
+ name: opal-jquery
247
193
  requirement: !ruby/object:Gem::Requirement
248
194
  requirements:
249
- - - "~>"
195
+ - - ">="
250
196
  - !ruby/object:Gem::Version
251
- version: 0.9.4
197
+ version: '0'
252
198
  type: :development
253
199
  prerelease: false
254
200
  version_requirements: !ruby/object:Gem::Requirement
255
201
  requirements:
256
- - - "~>"
202
+ - - ">="
257
203
  - !ruby/object:Gem::Version
258
- version: 0.9.4
204
+ version: '0'
259
205
  - !ruby/object:Gem::Dependency
260
- name: opal-rspec
206
+ name: opal-rails
261
207
  requirement: !ruby/object:Gem::Requirement
262
208
  requirements:
263
209
  - - ">="
264
210
  - !ruby/object:Gem::Version
265
- version: '0'
211
+ version: 0.9.4
212
+ - - "<"
213
+ - !ruby/object:Gem::Version
214
+ version: '2.0'
266
215
  type: :development
267
216
  prerelease: false
268
217
  version_requirements: !ruby/object:Gem::Requirement
269
218
  requirements:
270
219
  - - ">="
271
220
  - !ruby/object:Gem::Version
272
- version: '0'
221
+ version: 0.9.4
222
+ - - "<"
223
+ - !ruby/object:Gem::Version
224
+ version: '2.0'
273
225
  - !ruby/object:Gem::Dependency
274
- name: pry
226
+ name: pry-rescue
275
227
  requirement: !ruby/object:Gem::Requirement
276
228
  requirements:
277
229
  - - ">="
@@ -285,7 +237,7 @@ dependencies:
285
237
  - !ruby/object:Gem::Version
286
238
  version: '0'
287
239
  - !ruby/object:Gem::Dependency
288
- name: pry-rescue
240
+ name: pry-stack_explorer
289
241
  requirement: !ruby/object:Gem::Requirement
290
242
  requirements:
291
243
  - - ">="
@@ -318,14 +270,20 @@ dependencies:
318
270
  requirements:
319
271
  - - ">="
320
272
  - !ruby/object:Gem::Version
321
- version: 4.0.0
273
+ version: 5.0.0
274
+ - - "<"
275
+ - !ruby/object:Gem::Version
276
+ version: '7.0'
322
277
  type: :development
323
278
  prerelease: false
324
279
  version_requirements: !ruby/object:Gem::Requirement
325
280
  requirements:
326
281
  - - ">="
327
282
  - !ruby/object:Gem::Version
328
- version: 4.0.0
283
+ version: 5.0.0
284
+ - - "<"
285
+ - !ruby/object:Gem::Version
286
+ version: '7.0'
329
287
  - !ruby/object:Gem::Dependency
330
288
  name: rails-controller-testing
331
289
  requirement: !ruby/object:Gem::Requirement
@@ -388,14 +346,14 @@ dependencies:
388
346
  requirements:
389
347
  - - "~>"
390
348
  - !ruby/object:Gem::Version
391
- version: 1.3.6
349
+ version: 1.4.2
392
350
  type: :development
393
351
  prerelease: false
394
352
  version_requirements: !ruby/object:Gem::Requirement
395
353
  requirements:
396
354
  - - "~>"
397
355
  - !ruby/object:Gem::Version
398
- version: 1.3.6
356
+ version: 1.4.2
399
357
  - !ruby/object:Gem::Dependency
400
358
  name: timecop
401
359
  requirement: !ruby/object:Gem::Requirement
@@ -493,7 +451,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
493
451
  - !ruby/object:Gem::Version
494
452
  version: 1.3.1
495
453
  requirements: []
496
- rubygems_version: 3.0.4
454
+ rubygems_version: 3.0.8
497
455
  signing_key:
498
456
  specification_version: 4
499
457
  summary: Opal Ruby wrapper of React.js library.