jsg 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 656528ab1a482268d018a12df7b3cd5fda4d74f08368926f7fb665a4f5f3621f
4
- data.tar.gz: a63fec4f4c89edc7e116aa878781aa9235bcdf17967f12508ccea62ab5bcef19
3
+ metadata.gz: c5bbe669419df7b6181dacae7851ccf5a27b97abdf6e6a4a2a48c73e10d87632
4
+ data.tar.gz: c838fccba5ca6a8316d0718b097312b3760f31b94f9112eeee1bf1e7053c142f
5
5
  SHA512:
6
- metadata.gz: e231cea6d1794b20a9bffc034ac38020968288177af7c49f973b7901deb4a02cf4c86fa7ec8655e5ac7c078293c9b986d9cb8fdfd712d199ed349b80ca74ef80
7
- data.tar.gz: cfc908766616ad9b18026b20369caf5d01e79e7d2bde8463d8af9f619a3c1b86c5d686476b007759c15fa9dfc4dfa74e0ee375dac929bff53e9fd123e0c472ed
6
+ metadata.gz: 448f59e03a1e7a38c89f0ff99e5ff32ddda31fd3009bef7d712929ce93c4b7804aba3d137df8c4aff25f051f47a4bec023ad211a907da1ed06c2de4baa53c850
7
+ data.tar.gz: 5bfbcff342b82afd36fd558eb8a63052f8b2699e98f5d65eebdb5c5c2cb0dd67dbab2c9505fd28227ed6d2716e32070dce6aded230627ec8bbc37e0786d9fe82
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2026-11-05
4
+
5
+ - New opt-in `require "jsg/global"`: unknown methods on the `JS` module are forwarded to `JS.global`, so `JS.document.title`, `JS.alert("Hi")` and `JS.myValue = 1` work. Names the `JS` module already answers keep their meaning (`JS.global`, `JS.eval`, and Ruby's own module methods such as `JS.name`). It loads `jsg` too. `require "jsg"` alone does not change the `JS` module.
6
+ - The ruby.wasm tests run every test file in a fresh VM, so a file that only requires `jsg/global` is tested on its own.
7
+
3
8
  ## [0.2.1] - 2026-09-29
4
9
 
5
10
  - First release published from GitHub Actions with RubyGems trusted publishing (`.github/workflows/release.yml`, triggered by `v*` tags).
data/README.md CHANGED
@@ -97,6 +97,29 @@ el.tap { |e| ... } # like Kernel#tap (JS::Object is a BasicObject since js 2.10)
97
97
  value == true # comparing with true, false and nil works (JavaScript's == rules)
98
98
  ```
99
99
 
100
+ ### `JS.document` instead of `JS.global.document` (opt-in)
101
+
102
+ `require "jsg/global"` forwards unknown methods on the `JS` module to `JS.global`. It loads `jsg` as well, so this one line is enough:
103
+
104
+ ```ruby
105
+ require "jsg/global"
106
+
107
+ JS.document.title # JS.global.document.title
108
+ JS.alert("Hello") # JS.global.alert("Hello")
109
+ JS.localStorage.getItem("k")
110
+ JS.myValue = 1 # sets window.myValue
111
+ JS.hidden? # JavaScript truthiness, like the ? methods above
112
+ ```
113
+
114
+ It is not part of `require "jsg"` because it changes the `JS` module itself, which the js gem and other libraries use too. Load it when you want the shorter syntax in your own app.
115
+
116
+ Only names that `JS` does not already answer are forwarded. These keep their Ruby meaning, so use `JS.global` for a browser global of the same name:
117
+
118
+ - methods of the js gem: `JS.global`, `JS.eval`, `JS.try_convert`, `JS.is_a?`, ...
119
+ - methods every Ruby module has: `JS.name` (returns `"JS"`, not `window.name`), `JS.hash`, `JS.inspect`, `JS.class`, `JS.method`, `JS.display`, `JS.freeze`, ...
120
+
121
+ Private `Kernel` methods such as `open`, `print` or `format` are forwarded, because calling them with an explicit receiver (`JS.open(...)`) ends up in `method_missing`. A name that the global object does not have raises `NoMethodError` as before. `JSG.xxx` forwards to `JS`, so after `require "jsg/global"` it reaches the globals too.
122
+
100
123
  ## Development
101
124
 
102
125
  ```bash
@@ -107,8 +130,8 @@ bundle exec rake # rspec, the ruby.wasm tests and rubocop
107
130
  To release a new version, update `lib/jsg/version.rb` and `CHANGELOG.md`, commit, and push a matching tag:
108
131
 
109
132
  ```bash
110
- git tag v0.2.1
111
- git push origin v0.2.1
133
+ git tag v0.3.0
134
+ git push origin v0.3.0
112
135
  ```
113
136
 
114
137
  The `Release` workflow runs the tests and publishes the gem to RubyGems.org with trusted publishing, so no API key is stored in GitHub.
data/lib/jsg/global.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jsg"
4
+
5
+ module JSG
6
+ # Opt-in shortcut: forwards unknown methods on the JS module to JS.global,
7
+ # so browser globals can be used without writing JS.global every time.
8
+ #
9
+ # require "jsg/global"
10
+ #
11
+ # JS.document.title # JS.global.document.title
12
+ # JS.alert("Hello") # JS.global.alert("Hello")
13
+ # JS.localStorage.getItem("k")
14
+ # JS.myValue = 1 # sets window.myValue
15
+ #
16
+ # It is a separate file because it changes the JS module itself, which the
17
+ # js gem and other libraries also use. `require "jsg"` alone does not load it.
18
+ #
19
+ # Only names that JS does not already answer are forwarded. These keep their
20
+ # Ruby meaning, so use JS.global for the browser global of the same name:
21
+ #
22
+ # - methods of the js gem: JS.global, JS.eval, JS.try_convert, JS.is_a?, ...
23
+ # - methods every Ruby module has: JS.name (returns "JS", not window.name),
24
+ # JS.hash, JS.inspect, JS.class, JS.method, JS.display, JS.freeze, ...
25
+ #
26
+ # Private Kernel methods such as open, print or format are forwarded, because
27
+ # calling them with an explicit receiver (JS.open) ends up in method_missing.
28
+ # A name the global object does not have raises NoMethodError as usual.
29
+ module Global
30
+ # Sends +name+ with its arguments and block to JS.global if the global
31
+ # object responds to it (property read, setter, method call or predicate,
32
+ # as handled by the jsg patch); otherwise raises NoMethodError via super.
33
+ def method_missing(name, ...)
34
+ return super unless global.respond_to?(name)
35
+
36
+ global.__send__(name, ...)
37
+ end
38
+
39
+ # Makes JS.respond_to?(name) true for the names method_missing forwards.
40
+ def respond_to_missing?(name, include_private = false)
41
+ global.respond_to?(name) || super
42
+ end
43
+ end
44
+ end
45
+
46
+ JS.extend(JSG::Global)
data/lib/jsg/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSG
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
data/sig/jsg.rbs CHANGED
@@ -1,4 +1,9 @@
1
1
  module JSG
2
2
  VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
3
+
4
+ # require "jsg/global": forwards unknown methods on the JS module to JS.global
5
+ module Global
6
+ def method_missing: (Symbol name, *untyped args) ?{ (*untyped) -> untyped } -> untyped
7
+ def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
8
+ end
4
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andi
@@ -53,6 +53,7 @@ files:
53
53
  - exe/jsg
54
54
  - lib/jsg.rb
55
55
  - lib/jsg/cli.rb
56
+ - lib/jsg/global.rb
56
57
  - lib/jsg/version.rb
57
58
  - sig/jsg.rbs
58
59
  - template/Gemfile