Dumping exceptions in live editor
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 25/100
- issue の種類
- リファクタリング
- 明瞭さ
- 説明が足りない
- 活発さ
- 停滞
- 技術スタック
- javascript, ruby
調査の方向性
まず、貼り付けられた React::NativeLibrary と Hyperloop::Component::Mixin のコードでライフサイクルメソッドを追跡します。特に、rescue Exception でラップされているコールバックの経路を確認してください。before_mount または別のライフサイクルメソッドを追加したときにライブエディターがクラッシュすることを再現し、その後、一時的な #barrie rescue パッチなしで基礎となる例外が処理され、ページが引き続き使用可能であることを確認してください。
索引モデルが issue の本文から書いたものです。
説明
The live editor can crash the whole page if the user adds one of the lifecycle methods (before_mount, etc). The only fix so far is the patch below which catches and dumps an exception. Each change has comment #barrie
We need to find a better solution and this needs to be removed before the rename.
module React
find_and_render_component
class NativeLibrary
class << self
def imports(native_name)
@native_prefix = "#{native_name}."
self
end
def rename(rename_list)
# rename_list is a hash in the form: native_name => ruby_name, native_name => ruby_name
rename_list.each do |js_name, ruby_name|
native_name = lookup_native_name(js_name)
if lookup_native_name(js_name)
create_component_wrapper(self, native_name, ruby_name) ||
create_library_wrapper(self, native_name, ruby_name)
else
raise "class #{name} < React::NativeLibrary could not import #{js_name}. "\
"Native value #{scope_native_name(js_name)} is undefined."
end
end
end
def import_const_from_native(klass, const_name, create_library)
begin
native_name = lookup_native_name(const_name) ||
lookup_native_name(const_name[0].downcase + const_name[1..-1])
native_name && (
create_component_wrapper(klass, native_name, const_name) || (
create_library &&
create_library_wrapper(klass, native_name, const_name)))
rescue Exception
# barrie
end
end
def const_missing(const_name)
import_const_from_native(self, const_name, true) || super
end
def method_missing(method, *args, &block)
component_class = const_get(method) if const_defined?(method, false)
component_class ||= import_const_from_native(self, method, false)
raise 'could not import a react component named: '\
"#{scope_native_name method}" unless component_class
React::RenderingContext.render(component_class, *args, &block)
end
private
def lookup_native_name(js_name)
native_name = scope_native_name(js_name)
`eval(#{native_name}) !== undefined && native_name`
# rubocop:disable Lint/RescueException # that is what eval raises in Opal >= 0.10.
rescue Exception
nil
# rubocop:enable Lint/RescueException
end
def scope_native_name(js_name)
"#{@native_prefix}#{js_name}"
end
def create_component_wrapper(klass, native_name, ruby_name)
if React::API.native_react_component?(native_name)
new_klass = klass.const_set ruby_name, Class.new
new_klass.class_eval do
include Hyperloop::Component::Mixin
imports native_name
end
new_klass
end
end
def create_library_wrapper(klass, native_name, ruby_name)
klass.const_set ruby_name, Class.new(React::NativeLibrary).imports(native_name)
end
end
end
end
module Hyperloop
class Component
class << self
def mounted_components
@mounted_components ||= Set.new
end
def force_update!
components = mounted_components.to_a
components.each do |comp|
next unless mounted_components.include? comp
comp.force_update!
end
end
end
module Mixin
def self.included(base)
base.include(Hyperloop::Store::Mixin)
base.include(React::Component::API)
base.include(React::Callbacks)
base.include(React::Component::Tags)
base.include(React::Component::DslInstanceMethods)
base.include(React::Component::ShouldComponentUpdate)
base.class_eval do
class_attribute :initial_state
define_callback :before_mount
define_callback :after_mount
define_callback :before_receive_props
define_callback :before_update
define_callback :after_update
define_callback :before_unmount
define_callback(:after_error) { React::API.add_after_error_hook(base) }
end
base.extend(React::Component::ClassMethods)
end
def self.deprecation_warning(message)
React::Component.deprecation_warning(name, message)
end
def deprecation_warning(message)
React::Component.deprecation_warning(self.class.name, message)
end
def initialize(native_element)
@native = native_element
init_store
end
def emit(event_name, *args)
if React::Event::BUILT_IN_EVENTS.include?(built_in_event_name = "on#{event_name.to_s.event_camelize}")
params[built_in_event_name].call(*args)
else
params["on_#{event_name}"].call(*args)
end
end
def component_will_mount
begin
React::IsomorphicHelpers.load_context(true) if React::IsomorphicHelpers.on_opal_client?
React::State.set_state_context_to(self) do
Hyperloop::Component.mounted_components << self
run_callback(:before_mount)
end
rescue Exception
# barrie
end
end
def component_did_mount
begin
React::State.set_state_context_to(self) do
run_callback(:after_mount)
React::State.update_states_to_observe
end
rescue Exception
# barrie
end
end
def component_will_receive_props(next_props)
# need to rethink how this works in opal-react, or if its actually that useful within the react.rb environment
# for now we are just using it to clear processed_params
begin
React::State.set_state_context_to(self) { run_callback(:before_receive_props, next_props) }
@_receiving_props = true
rescue Exception
# barrie
end
end
def component_will_update(next_props, next_state)
begin
React::State.set_state_context_to(self) { run_callback(:before_update, next_props, next_state) }
params._reset_all_others_cache if @_receiving_props
@_receiving_props = false
rescue Exception
# barrie
end
end
def component_did_update(prev_props, prev_state)
begin
React::State.set_state_context_to(self) do
run_callback(:after_update, prev_props, prev_state)
React::State.update_states_to_observe
end
rescue Exception
# barrie
end
end
def component_will_unmount
begin
React::State.set_state_context_to(self) do
run_callback(:before_unmount)
React::State.remove
Hyperloop::Component.mounted_components.delete self
end
rescue Exception
# barrie
end
end
def component_did_catch(error, info)
React::State.set_state_context_to(self) do
run_callback(:after_error, error, info)
end
end
attr_reader :waiting_on_resources
def update_react_js_state(object, name, value)
if object
name = "#{object.class}.#{name}" unless object == self
# Date.now() has only millisecond precision, if several notifications of
# observer happen within a millisecond, updates may get lost.
# to mitigate this the Math.random() appends some random number
# this way notifactions will happen as expected by the rest of hyperloop
set_state(
'***_state_updated_at-***' => `Date.now() + Math.random()`,
name => value
)
else
set_state name => value
end
end
def set_state_synchronously?
@native.JS[:__opalInstanceSyncSetState]
end
def render
raise 'no render defined'
end unless method_defined?(:render)
def _render_wrapper
React::State.set_state_context_to(self, true) do
element = React::RenderingContext.render(nil) { render || '' }
@waiting_on_resources =
element.waiting_on_resources if element.respond_to? :waiting_on_resources
element
end
end
def watch(value, &on_change)
Observable.new(value, on_change)
end
def define_state(*args, &block)
React::State.initialize_states(self, self.class.define_state(*args, &block))
end
end
end
end
- 主要言語
- CSS
- スター
- 5
- フォーク
- 11
- PR マージ指標
- 30日以内にマージされた PR はありません
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
hyperstack-org/website のほかの issue
-
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
hyperstack-org/website#102 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 39/100
hyperstack-org/website#62 ·
-
Error an search オープン
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
hyperstack-org/website#40 ·
-
Lockable Records オープンrequested-topic
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
hyperstack-org/website#39 · コメント 13 件 ·
-
requested-topic
難易度 5/5 1週間以上 初心者へのやさしさ 10/100
hyperstack-org/website#38 ·
hyperstack-org/website の issue をすべて見る
似ている issue
-
Browser (wasm) relay client cannot connect to relays whose URL has a trailing-dot FQDN hostname オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
n0-computer/iroh#4550 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
nightscout/nocturne#1425 ·
-
ui/ux
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
docToolchain/docToolchain#1705 ·