-
-
Save chancancode/0087d86c935db02453ae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require_relative 'javascript' | |
| puts "This is totally Ruby" | |
| javascript { | |
| console.log("OMG JavaScript"); | |
| var a = 1; | |
| console.log(a); | |
| a = a + 1; | |
| console.log(a); | |
| var b = function(x) { | |
| console.log(x + 1); | |
| }; | |
| b(3); | |
| function c(x) { | |
| console.log(x + 2); | |
| } | |
| c(4); | |
| function inspectArguments() { | |
| console.log("I was called with " + String(arguments.length) + " arguments"); | |
| } | |
| inspectArguments(1, 2, 3, 4, 5); | |
| puts "Just kidding, it is Ruby in here too..." | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| % ruby test.rb | |
| This is totally Ruby | |
| OMG JavaScript | |
| 1 | |
| 2 | |
| 4 | |
| 6 | |
| I was called with 5 arguments | |
| Just kidding, it is Ruby in here too... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'binding_of_caller' | |
| def supress_warnings | |
| verbose, $VERBOSE = $VERBOSE, nil | |
| yield | |
| ensure | |
| $VERBOSE = verbose | |
| end | |
| module JavaScript | |
| # Make it an `Object` instead of `BasicObject` so that we can bind | |
| # any instance methods from `Object` and call them here | |
| class Scope < ::Object; end | |
| supress_warnings do | |
| Scope.instance_methods(true).each { |meth| Scope.send(:undef_method, meth) } | |
| end | |
| class Scope | |
| def initialize(locals = {}) | |
| @locals = locals | |
| end | |
| def var(*); end | |
| def function(*args, &block) | |
| if args.length == 1 && Function === args[0] | |
| @locals[args[0].name] = args[0] | |
| else | |
| Function.new(nil, args, block) | |
| end | |
| end | |
| def console | |
| @console ||= Console.new | |
| end | |
| def self.eval(&block) | |
| new.__eval__(&block) | |
| end | |
| def __eval__(&block) | |
| Object.new.method(:instance_eval).unbind.bind(self).call(&block) | |
| end | |
| def method_missing(name, *args, &block) | |
| caller_binding = binding.of_caller(1) | |
| result = nil | |
| if caller_binding.local_variable_defined?(name) | |
| result = caller_binding.local_variable_get(name) | |
| elsif @locals.key?(name) | |
| result = @locals[name] | |
| end | |
| if result && Function === result | |
| result.call(*args) | |
| elsif result | |
| result | |
| elsif args.empty? && block.nil? | |
| Identifier.new(name) | |
| else | |
| Function.new(name, args, block) | |
| end | |
| end | |
| end | |
| class Identifier < Struct.new(:name); end | |
| class Function < Struct.new(:name, :arg_names, :block) | |
| def call(*arg_values) | |
| locals = Hash[ arg_names.map(&:name).zip(arg_values) ] | |
| locals[:arguments] = arg_values | |
| Scope.new(locals).__eval__(&block) | |
| end | |
| end | |
| class Console | |
| def log(*args) | |
| puts(*args) | |
| end | |
| end | |
| end | |
| module Kernel | |
| def javascript(&block) | |
| JavaScript::Scope.eval(&block) | |
| end | |
| end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Moved to https://github.com/vanruby/javascript