From 6a394cc30e0e224893da80c987ccf11f6ee751a8 Mon Sep 17 00:00:00 2001 From: Joe Cheng Date: Tue, 26 Jun 2012 21:56:13 -0700 Subject: [PATCH] Remove Ruby implementation... *sniff* --- Gemfile | 5 -- Gemfile.lock | 18 ------ hash.rb | 19 ------ lib/react.rb | 172 -------------------------------------------------- lib/shiny.rb | 156 --------------------------------------------- react-test.rb | 23 ------- run.sh | 5 -- 7 files changed, 398 deletions(-) delete mode 100644 Gemfile delete mode 100644 Gemfile.lock delete mode 100644 hash.rb delete mode 100644 lib/react.rb delete mode 100644 lib/shiny.rb delete mode 100644 react-test.rb delete mode 100755 run.sh diff --git a/Gemfile b/Gemfile deleted file mode 100644 index deccee473..000000000 --- a/Gemfile +++ /dev/null @@ -1,5 +0,0 @@ -source 'https://rubygems.org' - -gem 'em-websocket' -gem 'eventmachine_httpserver' -gem 'json' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index f41ad4b9e..000000000 --- a/Gemfile.lock +++ /dev/null @@ -1,18 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.2.8) - em-websocket (0.3.6) - addressable (>= 2.1.1) - eventmachine (>= 0.12.9) - eventmachine (0.12.10) - eventmachine_httpserver (0.2.1) - json (1.7.3) - -PLATFORMS - ruby - -DEPENDENCIES - em-websocket - eventmachine_httpserver - json diff --git a/hash.rb b/hash.rb deleted file mode 100644 index 364bc0c49..000000000 --- a/hash.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'shiny' -require 'digest/sha1' -require 'digest/md5' - -shinyapp = ShinyApp.new - -input1 = React::ObservableValue.new { - shinyapp.session.get('input1') + (shinyapp.session.get('addnewline') ? "\n" : '') -} - -shinyapp.define_output('md5_hash') do - Digest::MD5.hexdigest(input1.value) -end - -shinyapp.define_output('sha1_hash') do - Digest::SHA1.hexdigest(input1.value) -end - -shinyapp.run diff --git a/lib/react.rb b/lib/react.rb deleted file mode 100644 index e49de011f..000000000 --- a/lib/react.rb +++ /dev/null @@ -1,172 +0,0 @@ -module React - - class Context - - private - - @@next_id = 0 - @@current_context = nil - @@pending_invalidate = [] - - public - - def self.current! - return current || raise("No current context") - end - - def self.current - @@current_context - end - - attr_reader :id - - def initialize - # The ID can used to identify/sort/dedupe contexts - @id = @@next_id += 1 - - # Indicates whether this context is invalidated, i.e. its - # callbacks have been called or are about to be called - @invalidated = false - - # List of callbacks to be called after invalidation - @callbacks = [] - end - - # Run a block with this context as the current context. The - # original current context will be restored after the block - # is executed. - def run - old_ctx = @@current_context - @@current_context = self - begin - return yield - ensure - @@current_context = old_ctx - end - end - - def invalidate - return if @invalidated - - @invalidated = true - @@pending_invalidate << self - end - - # Register a callback to be called after this context is - # invalidated (or immediately if it's already invalidated). - # The callback takes one argument, the context. - def on_invalidate(&callback) - if @invalidated - callback.call(self) - else - @callbacks << callback - end - end - - def execute_callbacks - @callbacks.each {|callback| callback.call(self)} - end - - # Execute all callbacks on invalidated contexts. Will do this - # repeatedly if the callbacks themselves cause more invalidations. - def self.flush - while !@@pending_invalidate.empty? - contexts = @@pending_invalidate - @@pending_invalidate = [] - - contexts.each {|context| context.execute_callbacks} - end - end - end - - class Session - def initialize - # Key is variable name, value is variable value - @values = Hash.new - # Key is variable name, value is { Context IDs => Contexts } - @dependencies = Hash.new - end - - def get(name) - cur_ctx = React::Context.current! - @dependencies[name] = @dependencies[name] || Hash.new - if !@dependencies[name].has_key?(cur_ctx.id) - @dependencies[name][cur_ctx.id] = cur_ctx - cur_ctx.on_invalidate do - @dependencies[name].delete(cur_ctx.id) - end - end - - return @values[name] - end - - def set(name, value) - if @values.has_key?(name) && @values[name] == value - return - end - - @values[name] = value - if @dependencies[name] - @dependencies[name].each_value {|ctx| ctx.invalidate} - end - end - end - - # Stores (and caches) a single dependent value in a context - class ObservableValue - def initialize(&valueProc) - @valueProc = valueProc - - @dependencies = Hash.new - @initialized = false - end - - def value - if !@initialized - @initialized = true - update_value - end - - cur_ctx = React::Context.current! - @dependencies[cur_ctx.id] = cur_ctx - cur_ctx.on_invalidate do - @dependencies.delete cur_ctx.id - end - @value - end - - private - def update_value - old_value = @value - - ctx = Context.new - ctx.on_invalidate do - update_value - end - ctx.run do - @value = @valueProc.call - end - - if old_value != @value - @dependencies.each_value {|dep_ctx| dep_ctx.invalidate} - end - end - end - - # Runs the given proc whenever its dependencies change - class Observer - def initialize(&proc) - @proc = proc - run - end - - def run - ctx = React::Context.new - ctx.on_invalidate do - run - end - ctx.run &@proc - end - end - -end \ No newline at end of file diff --git a/lib/shiny.rb b/lib/shiny.rb deleted file mode 100644 index d12bf1bfb..000000000 --- a/lib/shiny.rb +++ /dev/null @@ -1,156 +0,0 @@ -require 'eventmachine' -require 'evma_httpserver' -require 'em-websocket' -require 'pathname' -require 'json' -require 'react' - - -class WebServer < EM::Connection - include EM::HttpServer - - def post_init - super - no_environment_strings - - @basepath = File.join(Dir.pwd, 'www') - end - - def resolve_path(path) - # It's not a valid path if it doesn't start with / - return nil if path !~ /^\// - - abspath = File.join(@basepath, "./#{path}") - # Resolves '..', etc. - abspath = Pathname.new(abspath).cleanpath.to_s - - return false if abspath[0...(@basepath.size + 1)] != @basepath + '/' - return false if !File.exist?(abspath) - - return abspath - end - - def process_http_request - # the http request details are available via the following instance variables: - # @http_protocol - # @http_request_method - # @http_cookie - # @http_if_none_match - # @http_content_type - # @http_path_info - # @http_request_uri - # @http_query_string - # @http_post_content - # @http_headers - - response = EM::DelegatedHttpResponse.new(self) - - path = @http_path_info - path = '/index.html' if path == '/' - - resolved_path = resolve_path(path) - - if !resolved_path - response.status = 404 - response.content_type 'text/html' - response.content = '

404 Not Found

' - else - response.status = 200 - response.content_type case resolved_path - when /\.html?$/ - 'text/html' - when /\.js$/ - 'text/javascript' - when /\.css$/ - 'text/css' - when /\.png$/ - 'image/png' - when /\.jpg$/ - 'image/jpeg' - when /\.gif$/ - 'image/gif' - end - response.content = File.read(resolved_path) - end - response.send_response - end -end - -def run_shiny_app(shinyapp) - EventMachine.run do - EventMachine.start_server '0.0.0.0', 8100, WebServer - puts "Listening on port 8100" - - EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 8101) do |ws| - shinyapp.websocket = ws - ws.onclose { exit(0) } - ws.onmessage do |msg| - begin - puts "RECV: #{msg}" - - msg_obj = JSON.parse(msg) - case msg_obj['method'] - when 'init' - msg_obj['data'].each do |k, v| - shinyapp.session.set(k, v) - end - React::Context.flush - shinyapp.instantiate_outputs - when 'update' - msg_obj['data'].each do |k, v| - shinyapp.session.set(k, v) - end - end - - React::Context.flush - shinyapp.flush_output - rescue Exception => e - puts "ERROR: #{e}" - puts e.backtrace.collect {|x| "\t#{x}"} - raise - end - end - end - end -end - -class ShinyApp - attr_reader :session - - def initialize - @session = React::Session.new - @outputs = {} - @invalidated_output_values = Hash.new - end - - def websocket=(value) - @websocket = value - end - - def define_output(name, &proc) - @outputs[name] = proc - end - - def instantiate_outputs - @outputs.keys.each do |name| - proc = @outputs.delete(name) - React::Observer.new do - value = proc.call - @invalidated_output_values[name] = value - end - end - end - - def flush_output - return if @invalidated_output_values.empty? - - data = @invalidated_output_values - @invalidated_output_values = Hash.new - puts "SEND: #{JSON.generate(data)}" - @websocket.send(JSON.generate(data)) - end - - def run - run_shiny_app self - end -end diff --git a/react-test.rb b/react-test.rb deleted file mode 100644 index 810c5df7c..000000000 --- a/react-test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'react' - -include React - -def print_observable_value(obsVal) - Observer.new { puts obsVal.value } -end - -sess = Session.new -sess.set('user', '') - -user = ObservableValue.new { sess.get('user') } -user_caps = ObservableValue.new { user.value.upcase } - -# This will print the value not just once, but every -# time the value changes -print_observable_value(user_caps) - -sess.set('user', 'jcheng') -Context.flush # pay no attention to the man behind the curtain -sess.set('user', 'jjallaire') -sess.set('user', 'jwpaulson') -Context.flush diff --git a/run.sh b/run.sh deleted file mode 100755 index 85164a328..000000000 --- a/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -SCRIPT=${1:-hash.rb} - -bundle exec ruby -Ilib "$SCRIPT" \ No newline at end of file