js 0.0.1 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/js/bindgen/.clang-format +2 -0
- data/ext/js/bindgen/rb-js-abi-host.c +342 -0
- data/ext/js/bindgen/rb-js-abi-host.h +82 -0
- data/ext/js/bindgen/rb-js-abi-host.wit +47 -0
- data/ext/js/depend +10 -0
- data/ext/js/extconf.rb +3 -0
- data/ext/js/js-core.c +577 -0
- data/ext/witapi/bindgen/.clang-format +2 -0
- data/ext/witapi/bindgen/rb-abi-guest.c +222 -0
- data/ext/witapi/bindgen/rb-abi-guest.h +77 -0
- data/ext/witapi/bindgen/rb-abi-guest.wit +25 -0
- data/ext/witapi/depend +11 -0
- data/ext/witapi/extconf.rb +3 -0
- data/ext/witapi/witapi-core.c +325 -0
- data/js.gemspec +26 -16
- data/lib/js/array.rb +9 -0
- data/lib/js/hash.rb +8 -0
- data/lib/js/nil_class.rb +6 -0
- data/lib/js/require_remote/evaluator.rb +15 -0
- data/lib/js/require_remote/url_resolver.rb +45 -0
- data/lib/js/require_remote.rb +85 -0
- data/lib/js/version.rb +2 -2
- data/lib/js.rb +238 -3
- metadata +39 -22
- data/.gitignore +0 -17
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/README.md +0 -35
- data/Rakefile +0 -1
data/js.gemspec
CHANGED
@@ -1,19 +1,29 @@
|
|
1
|
-
#
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'js/version'
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
6
|
-
|
7
|
-
gem.name = "js"
|
8
|
-
gem.version = Js::VERSION
|
9
|
-
gem.authors = ["Charles Lowell"]
|
10
|
-
gem.email = ["cowboyd@thefrontside.net"]
|
11
|
-
gem.description = %q{embed a JavaScript interpreter}
|
12
|
-
gem.summary = %q{use JavaScript objects from Ruby and embed Ruby objects into JavaScript}
|
13
|
-
gem.homepage = ""
|
3
|
+
require_relative "lib/js/version"
|
14
4
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "js"
|
7
|
+
spec.version = JS::VERSION
|
8
|
+
spec.authors = ["Yuta Saito"]
|
9
|
+
spec.email = ["kateinoigakukun@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{JavaScript bindings for ruby.wasm}
|
12
|
+
spec.description = %q{JavaScript bindings for ruby.wasm. This gem provides a way to use JavaScript functionalities from Ruby through WebAssembly.}
|
13
|
+
spec.homepage = "https://github.com/ruby/ruby.wasm"
|
14
|
+
|
15
|
+
spec.metadata = {
|
16
|
+
"source_code_uri" => "https://github.com/ruby/ruby.wasm/tree/main/packages/gems/js",
|
17
|
+
}
|
18
|
+
|
19
|
+
spec.license = "MIT"
|
20
|
+
|
21
|
+
spec.files = Dir.chdir(__dir__) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
(File.expand_path(f) == __FILE__) ||
|
24
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
spec.extensions = ["ext/js/extconf.rb", "ext/witapi/extconf.rb"]
|
19
29
|
end
|
data/lib/js/array.rb
ADDED
data/lib/js/hash.rb
ADDED
data/lib/js/nil_class.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module JS
|
2
|
+
class RequireRemote
|
3
|
+
# Execute the body of the response and record the URL.
|
4
|
+
class Evaluator
|
5
|
+
def evaluate(code, filename, final_url)
|
6
|
+
Kernel.eval(code, ::Object::TOPLEVEL_BINDING, filename)
|
7
|
+
$LOADED_FEATURES << final_url
|
8
|
+
end
|
9
|
+
|
10
|
+
def evaluated?(url)
|
11
|
+
$LOADED_FEATURES.include?(url)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module JS
|
2
|
+
class RequireRemote
|
3
|
+
ScriptLocation = Data.define(:url, :filename)
|
4
|
+
|
5
|
+
# When require_relative is called within a running Ruby script,
|
6
|
+
# the URL is resolved from a relative file path based on the URL of the running Ruby script.
|
7
|
+
# It uses a stack to store URLs of running Ruby Script.
|
8
|
+
# Push the URL onto the stack before executing the new script.
|
9
|
+
# Then pop it when the script has finished executing.
|
10
|
+
class URLResolver
|
11
|
+
def initialize(base_url)
|
12
|
+
@url_stack = [base_url]
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_location(relative_feature)
|
16
|
+
filename = filename_from(relative_feature)
|
17
|
+
url = resolve(filename)
|
18
|
+
ScriptLocation.new(url, filename)
|
19
|
+
end
|
20
|
+
|
21
|
+
def push(url)
|
22
|
+
@url_stack.push url
|
23
|
+
end
|
24
|
+
|
25
|
+
def pop()
|
26
|
+
@url_stack.pop
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def filename_from(relative_feature)
|
32
|
+
if relative_feature.end_with?(".rb")
|
33
|
+
relative_feature
|
34
|
+
else
|
35
|
+
"#{relative_feature}.rb"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return a URL object of JavaScript.
|
40
|
+
def resolve(relative_filepath)
|
41
|
+
JS.global[:URL].new relative_filepath, @url_stack.last
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "singleton"
|
2
|
+
require "js"
|
3
|
+
require_relative "./require_remote/url_resolver"
|
4
|
+
require_relative "./require_remote/evaluator"
|
5
|
+
|
6
|
+
module JS
|
7
|
+
# This class is used to load remote Ruby scripts.
|
8
|
+
#
|
9
|
+
# == Example
|
10
|
+
#
|
11
|
+
# require 'js/require_remote'
|
12
|
+
# JS::RequireRemote.instance.load("foo")
|
13
|
+
#
|
14
|
+
# This class is intended to be used to replace Kernel#require_relative.
|
15
|
+
#
|
16
|
+
# == Example
|
17
|
+
#
|
18
|
+
# require 'js/require_remote'
|
19
|
+
# module Kernel
|
20
|
+
# def require_relative(path) = JS::RequireRemote.instance.load(path)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# If you want to load the bundled gem
|
24
|
+
#
|
25
|
+
# == Example
|
26
|
+
#
|
27
|
+
# require 'js/require_remote'
|
28
|
+
# module Kernel
|
29
|
+
# alias original_require_relative require_relative
|
30
|
+
#
|
31
|
+
# def require_relative(path)
|
32
|
+
# caller_path = caller_locations(1, 1).first.absolute_path || ''
|
33
|
+
# dir = File.dirname(caller_path)
|
34
|
+
# file = File.absolute_path(path, dir)
|
35
|
+
#
|
36
|
+
# original_require_relative(file)
|
37
|
+
# rescue LoadError
|
38
|
+
# JS::RequireRemote.instance.load(path)
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
class RequireRemote
|
43
|
+
include Singleton
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
base_url = JS.global[:URL].new(JS.global[:location][:href])
|
47
|
+
@resolver = URLResolver.new(base_url)
|
48
|
+
@evaluator = Evaluator.new
|
49
|
+
end
|
50
|
+
|
51
|
+
# Load the given feature from remote.
|
52
|
+
def load(relative_feature)
|
53
|
+
location = @resolver.get_location(relative_feature)
|
54
|
+
|
55
|
+
# Do not load the same URL twice.
|
56
|
+
return false if @evaluator.evaluated?(location.url[:href].to_s)
|
57
|
+
|
58
|
+
response = JS.global.fetch(location.url).await
|
59
|
+
unless response[:status].to_i == 200
|
60
|
+
raise LoadError.new "cannot load such url -- #{response[:status]} #{location.url}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# The fetch API may have responded to a redirect response
|
64
|
+
# and fetched the script from a different URL than the original URL.
|
65
|
+
# Retrieve the final URL again from the response object.
|
66
|
+
final_url = response[:url].to_s
|
67
|
+
|
68
|
+
# Do not evaluate the same URL twice.
|
69
|
+
return false if @evaluator.evaluated?(final_url)
|
70
|
+
|
71
|
+
code = response.text().await.to_s
|
72
|
+
|
73
|
+
evaluate(code, location.filename, final_url)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def evaluate(code, filename, final_url)
|
79
|
+
@resolver.push(final_url)
|
80
|
+
@evaluator.evaluate(code, filename, final_url)
|
81
|
+
@resolver.pop
|
82
|
+
true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/js/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module
|
2
|
-
VERSION = "
|
1
|
+
module JS
|
2
|
+
VERSION = "2.5.0"
|
3
3
|
end
|
data/lib/js.rb
CHANGED
@@ -1,5 +1,240 @@
|
|
1
|
-
require "js
|
1
|
+
require "js.so"
|
2
|
+
require_relative "js/hash.rb"
|
3
|
+
require_relative "js/array.rb"
|
4
|
+
require_relative "js/nil_class.rb"
|
2
5
|
|
3
|
-
module
|
4
|
-
|
6
|
+
# The JS module provides a way to interact with JavaScript from Ruby.
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# require 'js'
|
11
|
+
# JS.eval("return 1 + 2") # => 3
|
12
|
+
# JS.global[:document].write("Hello, world!")
|
13
|
+
# div = JS.global[:document].createElement("div")
|
14
|
+
# div[:innerText] = "click me"
|
15
|
+
# body = JS.global[:document][:body]
|
16
|
+
# if body[:classList].contains?("main")
|
17
|
+
# body.appendChild(div)
|
18
|
+
# end
|
19
|
+
# div.addEventListener("click") do |event|
|
20
|
+
# puts event # => # [object MouseEvent]
|
21
|
+
# puts event[:detail] # => 1
|
22
|
+
# div[:innerText] = "clicked!"
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# If you are using `ruby.wasm` without `stdlib` you will not have `addEventListener`
|
26
|
+
# and other specialized functions defined. You can still acomplish many
|
27
|
+
# of the same things using `call` instead.
|
28
|
+
#
|
29
|
+
# == Example
|
30
|
+
#
|
31
|
+
# require 'js'
|
32
|
+
# JS.eval("return 1 + 2") # => 3
|
33
|
+
# JS.global[:document].call(:write, "Hello, world!")
|
34
|
+
# div = JS.global[:document].call(:createElement, "div")
|
35
|
+
# div[:innerText] = "click me"
|
36
|
+
# if body[:classList].call(:contains, "main") == JS::True
|
37
|
+
# body.appendChild(div)
|
38
|
+
# end
|
39
|
+
# div.call(:addEventListener, "click") do |event|
|
40
|
+
# puts event # => # [object MouseEvent]
|
41
|
+
# puts event[:detail] # => 1
|
42
|
+
# div[:innerText] = "clicked!"
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
module JS
|
46
|
+
Undefined = JS.eval("return undefined")
|
47
|
+
Null = JS.eval("return null")
|
48
|
+
|
49
|
+
# A boolean value in JavaScript is always a JS::Object instance from Ruby's point of view.
|
50
|
+
# If we use the boolean value returned by a JavaScript function as the condition for an if expression in Ruby,
|
51
|
+
# the if expression will always be true.
|
52
|
+
#
|
53
|
+
# == Bad Example
|
54
|
+
#
|
55
|
+
# searchParams = JS.global[:URLSearchParams].new(JS.global[:location][:search])
|
56
|
+
# if searchParams.has('phrase')
|
57
|
+
# # Always pass through here.
|
58
|
+
# ...
|
59
|
+
# else
|
60
|
+
# ...
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# Therefore, the JS::True constant is used to determine if the JavaScript function return value is true or false.
|
64
|
+
#
|
65
|
+
# == Good Example
|
66
|
+
#
|
67
|
+
# if searchParams.has('phrase') == JS::True
|
68
|
+
# ...
|
69
|
+
# end
|
70
|
+
True = JS.eval("return true;")
|
71
|
+
False = JS.eval("return false;")
|
72
|
+
|
73
|
+
class PromiseScheduler
|
74
|
+
def initialize(loop)
|
75
|
+
@loop = loop
|
76
|
+
end
|
77
|
+
|
78
|
+
def await(promise)
|
79
|
+
current = Fiber.current
|
80
|
+
promise.call(
|
81
|
+
:then,
|
82
|
+
->(value) { current.transfer(value, :success) },
|
83
|
+
->(value) { current.transfer(value, :failure) }
|
84
|
+
)
|
85
|
+
if @loop == current
|
86
|
+
raise (
|
87
|
+
"JS::Object#await can be called only from RubyVM#evalAsync or RbValue#callAsync JS API\n" +
|
88
|
+
"If you are using browser.script.iife.js, please ensure that you specify `data-eval=\"async\"` in your script tag\n" +
|
89
|
+
"e.g. <script type=\"text/ruby\" data-eval=\"async\">puts :hello</script>\n" +
|
90
|
+
"Or <script type=\"text/ruby\" data-eval=\"async\" src=\"path/to/script.rb\"></script>"
|
91
|
+
)
|
92
|
+
end
|
93
|
+
value, status = @loop.transfer
|
94
|
+
raise JS::Error.new(value) if status == :failure
|
95
|
+
value
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
@promise_scheduler = PromiseScheduler.new Fiber.current
|
100
|
+
|
101
|
+
def self.promise_scheduler
|
102
|
+
@promise_scheduler
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def self.__eval_async_rb(rb_code, future)
|
108
|
+
self.__async(future) do
|
109
|
+
JS::Object.wrap(Kernel.eval(rb_code.to_s, TOPLEVEL_BINDING, "eval_async"))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.__call_async_method(recv, method_name, future, *args)
|
114
|
+
self.__async(future) { recv.send(method_name.to_s, *args) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.__async(future, &block)
|
118
|
+
Fiber
|
119
|
+
.new do
|
120
|
+
future.resolve block.call
|
121
|
+
rescue => e
|
122
|
+
future.reject JS::Object.wrap(e)
|
123
|
+
end
|
124
|
+
.transfer
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class JS::Object
|
129
|
+
# Create a JavaScript object with the new method
|
130
|
+
#
|
131
|
+
# The below examples show typical usage in Ruby
|
132
|
+
#
|
133
|
+
# JS.global[:Object].new
|
134
|
+
# JS.global[:Number].new(1.23)
|
135
|
+
# JS.global[:String].new("string")
|
136
|
+
# JS.global[:Array].new(1, 2, 3)
|
137
|
+
# JS.global[:Date].new(2020, 1, 1)
|
138
|
+
# JS.global[:Error].new("error message")
|
139
|
+
# JS.global[:URLSearchParams].new(JS.global[:location][:search])
|
140
|
+
#
|
141
|
+
def new(*args)
|
142
|
+
JS.global[:Reflect].construct(self, args.to_js)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Converts +self+ to an Array:
|
146
|
+
#
|
147
|
+
# JS.eval("return [1, 2, 3]").to_a.map(&:to_i) # => [1, 2, 3]
|
148
|
+
# JS.global[:document].querySelectorAll("p").to_a # => [[object HTMLParagraphElement], ...
|
149
|
+
def to_a
|
150
|
+
as_array = JS.global[:Array].from(self)
|
151
|
+
Array.new(as_array[:length].to_i) { as_array[_1] }
|
152
|
+
end
|
153
|
+
|
154
|
+
# Provide a shorthand form for JS::Object#call
|
155
|
+
#
|
156
|
+
# This method basically calls the JavaScript method with the same
|
157
|
+
# name as the Ruby method name as is using JS::Object#call.
|
158
|
+
#
|
159
|
+
# Exceptions are the following cases:
|
160
|
+
# * If the method name ends with a question mark (?), the question mark is removed
|
161
|
+
# and the method is called as a predicate method. The return value is converted to
|
162
|
+
# a Ruby boolean value automatically.
|
163
|
+
#
|
164
|
+
# This shorthand is unavailable for the following cases and you need to use
|
165
|
+
# JS::Object#call instead:
|
166
|
+
# * If the method name is invalid as a Ruby method name (e.g. contains a hyphen, reserved word, etc.)
|
167
|
+
# * If the method name is already defined as a Ruby method under JS::Object
|
168
|
+
# * If the JavaScript method name ends with a question mark (?)
|
169
|
+
def method_missing(sym, *args, &block)
|
170
|
+
sym_str = sym.to_s
|
171
|
+
if sym_str.end_with?("?")
|
172
|
+
# When a JS method is called with a ? suffix, it is treated as a predicate method,
|
173
|
+
# and the return value is converted to a Ruby boolean value automatically.
|
174
|
+
self.call(sym_str[0..-2].to_sym, *args, &block) == JS::True
|
175
|
+
elsif self[sym].typeof == "function"
|
176
|
+
self.call(sym, *args, &block)
|
177
|
+
else
|
178
|
+
super
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Check if a JavaScript method exists
|
183
|
+
#
|
184
|
+
# See JS::Object#method_missing for details.
|
185
|
+
def respond_to_missing?(sym, include_private)
|
186
|
+
return true if super
|
187
|
+
sym_str = sym.to_s
|
188
|
+
sym = sym_str[0..-2].to_sym if sym_str.end_with?("?")
|
189
|
+
self[sym].typeof == "function"
|
190
|
+
end
|
191
|
+
|
192
|
+
# Await a JavaScript Promise like `await` in JavaScript.
|
193
|
+
# This method looks like a synchronous method, but it actually runs asynchronously using fibers.
|
194
|
+
# In other words, the next line to the `await` call at Ruby source will be executed after the
|
195
|
+
# promise will be resolved. However, it does not block JavaScript event loop, so the next line
|
196
|
+
# to the RubyVM.evalAsync` (in the case when no `await` operator before the call expression)
|
197
|
+
# at JavaScript source will be executed without waiting for the promise.
|
198
|
+
#
|
199
|
+
# The below example shows how the execution order goes. It goes in the order of "step N"
|
200
|
+
#
|
201
|
+
# # In JavaScript
|
202
|
+
# const response = vm.evalAsync(`
|
203
|
+
# puts "step 1"
|
204
|
+
# JS.global.fetch("https://example.com").await
|
205
|
+
# puts "step 3"
|
206
|
+
# `) // => Promise
|
207
|
+
# console.log("step 2")
|
208
|
+
# await response
|
209
|
+
# console.log("step 4")
|
210
|
+
#
|
211
|
+
# The below examples show typical usage in Ruby
|
212
|
+
#
|
213
|
+
# JS.eval("return new Promise((ok) => setTimeout(() => ok(42), 1000))").await # => 42 (after 1 second)
|
214
|
+
# JS.global.fetch("https://example.com").await # => [object Response]
|
215
|
+
# JS.eval("return 42").await # => 42
|
216
|
+
# JS.eval("return new Promise((ok, err) => err(new Error())").await # => raises JS::Error
|
217
|
+
def await
|
218
|
+
# Promise.resolve wrap a value or flattens promise-like object and its thenable chain
|
219
|
+
promise = JS.global[:Promise].resolve(self)
|
220
|
+
JS.promise_scheduler.await(promise)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# A wrapper class for JavaScript Error to allow the Error to be thrown in Ruby.
|
225
|
+
class JS::Error
|
226
|
+
def initialize(exception)
|
227
|
+
@exception = exception
|
228
|
+
super
|
229
|
+
end
|
230
|
+
|
231
|
+
def message
|
232
|
+
stack = @exception[:stack]
|
233
|
+
if stack.typeof == "string"
|
234
|
+
# Error.stack contains the error message also
|
235
|
+
stack.to_s
|
236
|
+
else
|
237
|
+
@exception.to_s
|
238
|
+
end
|
239
|
+
end
|
5
240
|
end
|
metadata
CHANGED
@@ -1,53 +1,70 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: js
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
-
|
7
|
+
- Yuta Saito
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2024-01-28 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
13
|
+
description: JavaScript bindings for ruby.wasm. This gem provides a way to use JavaScript
|
14
|
+
functionalities from Ruby through WebAssembly.
|
15
15
|
email:
|
16
|
-
-
|
16
|
+
- kateinoigakukun@gmail.com
|
17
17
|
executables: []
|
18
|
-
extensions:
|
18
|
+
extensions:
|
19
|
+
- ext/js/extconf.rb
|
20
|
+
- ext/witapi/extconf.rb
|
19
21
|
extra_rdoc_files: []
|
20
22
|
files:
|
21
|
-
-
|
22
|
-
-
|
23
|
-
-
|
24
|
-
-
|
25
|
-
-
|
23
|
+
- ext/js/bindgen/.clang-format
|
24
|
+
- ext/js/bindgen/rb-js-abi-host.c
|
25
|
+
- ext/js/bindgen/rb-js-abi-host.h
|
26
|
+
- ext/js/bindgen/rb-js-abi-host.wit
|
27
|
+
- ext/js/depend
|
28
|
+
- ext/js/extconf.rb
|
29
|
+
- ext/js/js-core.c
|
30
|
+
- ext/witapi/bindgen/.clang-format
|
31
|
+
- ext/witapi/bindgen/rb-abi-guest.c
|
32
|
+
- ext/witapi/bindgen/rb-abi-guest.h
|
33
|
+
- ext/witapi/bindgen/rb-abi-guest.wit
|
34
|
+
- ext/witapi/depend
|
35
|
+
- ext/witapi/extconf.rb
|
36
|
+
- ext/witapi/witapi-core.c
|
26
37
|
- js.gemspec
|
27
38
|
- lib/js.rb
|
39
|
+
- lib/js/array.rb
|
40
|
+
- lib/js/hash.rb
|
41
|
+
- lib/js/nil_class.rb
|
42
|
+
- lib/js/require_remote.rb
|
43
|
+
- lib/js/require_remote/evaluator.rb
|
44
|
+
- lib/js/require_remote/url_resolver.rb
|
28
45
|
- lib/js/version.rb
|
29
|
-
homepage:
|
30
|
-
licenses:
|
46
|
+
homepage: https://github.com/ruby/ruby.wasm
|
47
|
+
licenses:
|
48
|
+
- MIT
|
49
|
+
metadata:
|
50
|
+
source_code_uri: https://github.com/ruby/ruby.wasm/tree/main/packages/gems/js
|
31
51
|
post_install_message:
|
32
52
|
rdoc_options: []
|
33
53
|
require_paths:
|
34
54
|
- lib
|
35
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
-
none: false
|
37
56
|
requirements:
|
38
|
-
- -
|
57
|
+
- - ">="
|
39
58
|
- !ruby/object:Gem::Version
|
40
59
|
version: '0'
|
41
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
61
|
requirements:
|
44
|
-
- -
|
62
|
+
- - ">="
|
45
63
|
- !ruby/object:Gem::Version
|
46
64
|
version: '0'
|
47
65
|
requirements: []
|
48
|
-
|
49
|
-
rubygems_version: 1.8.24
|
66
|
+
rubygems_version: 3.5.3
|
50
67
|
signing_key:
|
51
|
-
specification_version:
|
52
|
-
summary:
|
68
|
+
specification_version: 4
|
69
|
+
summary: JavaScript bindings for ruby.wasm
|
53
70
|
test_files: []
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2012 Charles Lowell
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# js.rb - Embed JavasScript into Ruby
|
2
|
-
|
3
|
-
js.rb harnesses the power of JavaScript inside your Ruby application
|
4
|
-
|
5
|
-
## Synopsis
|
6
|
-
|
7
|
-
evaluate some simple JavaScript
|
8
|
-
|
9
|
-
cxt = JS::Context.new
|
10
|
-
cxt.eval('7 * 6') #=> 42
|
11
|
-
|
12
|
-
embed values into the scope of your context
|
13
|
-
|
14
|
-
cxt['foo'] = "bar"
|
15
|
-
cxt.eval('foo') # => "bar"
|
16
|
-
|
17
|
-
embed Ruby code into your scope and call it from JavaScript
|
18
|
-
|
19
|
-
cxt["say"] = lambda {|this, word, times| word * times}
|
20
|
-
cxt.eval("say('Hello', 3)") #=> HelloHelloHello
|
21
|
-
|
22
|
-
## Installation
|
23
|
-
|
24
|
-
Add this line to your application's Gemfile:
|
25
|
-
|
26
|
-
gem 'js'
|
27
|
-
|
28
|
-
And then execute:
|
29
|
-
|
30
|
-
$ bundle
|
31
|
-
|
32
|
-
Or install it yourself as:
|
33
|
-
|
34
|
-
$ gem install js
|
35
|
-
|
data/Rakefile
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|