Dumping exceptions in live editor
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Tái cấu trúc
- Độ rõ ràng
- Cần làm rõ
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- javascript, ruby
Hướng nghiên cứu
Bắt đầu bằng cách lần theo các phương thức vòng đời trong đoạn mã React::NativeLibrary và Hyperloop::Component::Mixin đã dán, đặc biệt là các đường dẫn callback được bọc trong rescue Exception. Tái hiện sự cố sập live editor khi thêm before_mount hoặc một phương thức vòng đời khác, sau đó xác minh rằng exception bên dưới được xử lý mà không cần các bản vá rescue tạm thời của #barrie và trang vẫn có thể sử dụng được.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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
- Ngôn ngữ chính
- CSS
- Star
- 5
- Fork
- 11
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của hyperstack-org/website
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
hyperstack-org/website#102 ·
-
www redirect is broken Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 39/100
hyperstack-org/website#62 ·
-
Error an search Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 35/100
hyperstack-org/website#40 ·
-
Lockable Records Đang mởrequested-topic
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 20/100
hyperstack-org/website#39 · 13 bình luận ·
-
login and authentication example Đang mởrequested-topic
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 10/100
hyperstack-org/website#38 ·
Tất cả issue của hyperstack-org/website
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
pastelsky/bundlephobia#1122 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
speaches-ai/speaches#678 ·
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 95/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
jellyfin/jellyfin-web#8540 ·