This repository was archived by the owner on Oct 19, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
Rewriting in JS
Mitch VanDuyn edited this page Aug 3, 2017
·
6 revisions
What would happen if the entire hyperloop internal code base was rewritten in JS and used JS classes and objects, instead of in opal-ruby.
Here is an experiment:
Take the following code (from hyper-model)
module React
class State
ALWAYS_UPDATE_STATE_AFTER_RENDER = Hyperloop.on_client? # if on server then we don't wait to update the state
@rendering_level = 0
class << self
attr_reader :current_observer
def observers_by_name
@observers_by_name ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = [] } }
end
def has_observers?(object, name)
!observers_by_name[object][name].empty?
end
def bulk_update
saved_bulk_update_flag = @bulk_update_flag
@bulk_update_flag = true
yield
ensure
@bulk_update_flag = saved_bulk_update_flag
end
def set_state2(object, name, value, updates, exclusions = nil)
# set object's name state to value, tell all observers it has changed.
# Observers must implement update_react_js_state
object_needs_notification = object.respond_to? :update_react_js_state
observers_by_name[object][name].dup.each do |observer|
next if exclusions && exclusions.include?(observer)
updates[observer] += [object, name, value]
object_needs_notification = false if object == observer
end
updates[object] += [nil, name, value] if object_needs_notification
end
def initialize_states(object, initial_values) # initialize objects' name/value pairs
states[object].merge!(initial_values || {})
end
def get_state(object, name, current_observer = @current_observer)
# get current value of name for object, remember that the current object depends on this state,
# current observer can be overriden with last param
if current_observer && !new_observers[current_observer][object].include?(name)
new_observers[current_observer][object] << name
end
if @delayed_updates && @delayed_updates[object][name]
@delayed_updates[object][name][1] << current_observer
end
states[object][name]
end
# lots of other methods ... follow
end
end
end
Here is the same functionality written in JS:
React.State = function () {
var ALWAYS_UPDATE_STATE_AFTER_RENDER = Opal.Hyperloop['$on_client?']();
var rendering_level = 0;
var _current_observer;
var by_name = {};
var bulk_update_flag = false;
var set_observer = function (observer, k1, k2, value) {
if (!observer[k1]) { observer[k1] = {} }
observer[k1][k2] = value
};
var get_observer = function (observer, k1, k2) {
if (!observer[k1]) { return null }
observer[k1][k2]
};
var set_state2 = function (object, name, value, updates, exclusions) {
var object_needs_notification = object['respond_to?']('update_react_js_state')
for (observer in get_observers(by_name, object, name).slice(0)) {
if (!exclusions || !exclusions.includes(object)) {
updates[observer].push([object, name, value])
if (object == observer) { object_needs_notification = false }
}
}
if (!object_needs_notification) { updates[object].push += [null, name, value] }
}
return {
current_observer: function () { return _current_observer; }
has_observers: function (object, name) {
var r = get_observers(by_name, object, name)
return r && r.length > 0)
}
bulk_update: function (fn) {
var saved_bulk_update_flag = bulk_update_flag
bulk_update_flag = true
try {
fn();
}
finally {
bulk_update_flag = saved_bulk_update_flag
}
}
var myPrivateVar = "I can be accessed only from within YAHOO.myProject.myModule.";
//"private" method:
var myPrivateMethod = function () {
YAHOO.log("I can be accessed only from within YAHOO.myProject.myModule");
}
return {
myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty.",
myPublicMethod: function () {
YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");
//Within myProject, I can access "private" vars and methods:
YAHOO.log(myPrivateVar);
YAHOO.log(myPrivateMethod());
//The native scope of myPublicMethod is myProject; we can
//access public members using "this":
YAHOO.log(this.myPublicProperty);
}
};
}();