wasm_rails 0.1.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 +7 -0
- data/MIT-LICENSE +22 -0
- data/README.md +157 -0
- data/lib/generators/wasm_rails/install/install_generator.rb +109 -0
- data/lib/generators/wasm_rails/install/templates/boot.js +31 -0
- data/lib/generators/wasm_rails/install/templates/build_app_bundle.mjs +201 -0
- data/lib/generators/wasm_rails/install/templates/esbuild_wasm.mjs +58 -0
- data/lib/generators/wasm_rails/install/templates/serve_wasm.mjs +86 -0
- data/lib/generators/wasm_rails/install/templates/service_worker.js +413 -0
- data/lib/generators/wasm_rails/install/templates/wasm_shell.html +97 -0
- data/lib/generators/wasm_rails/install/templates/wasm_sqlite3_adapter.rb +160 -0
- data/lib/wasm_rails/railtie.rb +23 -0
- data/lib/wasm_rails/version.rb +3 -0
- data/lib/wasm_rails.rb +8 -0
- data/wasm_stubs/io/console/size.rb +8 -0
- data/wasm_stubs/io/wait.rb +6 -0
- data/wasm_stubs/loofah.rb +39 -0
- data/wasm_stubs/nokogiri.rb +67 -0
- data/wasm_stubs/openssl.rb +122 -0
- data/wasm_stubs/rails-html-sanitizer.rb +89 -0
- data/wasm_stubs/resolv.rb +19 -0
- data/wasm_stubs/socket.rb +47 -0
- data/wasm_stubs/sqlite3.rb +102 -0
- data/wasm_stubs/thread.rb +10 -0
- metadata +81 -0
data/lib/wasm_rails.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# WASM stub — io/console/size is a C extension not available in ruby+stdlib.wasm.
|
|
2
|
+
# Returns a fixed terminal size since WASM has no real console.
|
|
3
|
+
|
|
4
|
+
class IO
|
|
5
|
+
def self.console_size = [24, 80]
|
|
6
|
+
def self.default_console_size = [24, 80]
|
|
7
|
+
def winsize = [24, 80]
|
|
8
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# WASM stub — Loofah depends on Nokogiri which is not available in WASM.
|
|
2
|
+
# Provides minimal interface for rails-html-sanitizer to load.
|
|
3
|
+
|
|
4
|
+
require "nokogiri"
|
|
5
|
+
|
|
6
|
+
module Loofah
|
|
7
|
+
VERSION = "2.25.1"
|
|
8
|
+
|
|
9
|
+
def self.document(html, *) = Nokogiri::HTML::Document.new(html.to_s)
|
|
10
|
+
def self.fragment(html, *) = Nokogiri::HTML::DocumentFragment.new(html.to_s)
|
|
11
|
+
def self.scrub_document(html, scrubber) = document(html)
|
|
12
|
+
def self.scrub_fragment(html, scrubber) = fragment(html)
|
|
13
|
+
|
|
14
|
+
class Scrubber
|
|
15
|
+
STOP = :stop
|
|
16
|
+
CONTINUE = nil
|
|
17
|
+
attr_accessor :direction
|
|
18
|
+
def initialize(**opts); @direction = opts[:direction] || :bottom_up; end
|
|
19
|
+
def scrub(node) = nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class StripScrubber < Scrubber; end
|
|
23
|
+
class WhitelistScrubber < Scrubber; end
|
|
24
|
+
class SafeListScrubber < Scrubber; end
|
|
25
|
+
|
|
26
|
+
module HTML5
|
|
27
|
+
def self.parse(html, *) = Nokogiri::HTML::Document.new(html.to_s)
|
|
28
|
+
def self.fragment(html, *) = Nokogiri::HTML::DocumentFragment.new(html.to_s)
|
|
29
|
+
|
|
30
|
+
class Document < Nokogiri::HTML::Document; end
|
|
31
|
+
class DocumentFragment < Nokogiri::HTML::DocumentFragment; end
|
|
32
|
+
class SafeDocument < Document; end
|
|
33
|
+
class SafeDocumentFragment < DocumentFragment; end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module XssFoliate
|
|
37
|
+
def self.included(base); end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# WASM stub — Nokogiri is a C extension not available in ruby+stdlib.wasm.
|
|
2
|
+
# Provides minimal classes so loofah and rails-html-sanitizer can load.
|
|
3
|
+
|
|
4
|
+
module Nokogiri
|
|
5
|
+
VERSION = "1.18.0"
|
|
6
|
+
LIBXML_VERSION = "2.9.14"
|
|
7
|
+
|
|
8
|
+
module HTML
|
|
9
|
+
def self.parse(html, url = nil, encoding = nil, options = 0)
|
|
10
|
+
Document.new(html.to_s)
|
|
11
|
+
end
|
|
12
|
+
def self.fragment(html, encoding = nil, options = 0)
|
|
13
|
+
DocumentFragment.new(html.to_s)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Document
|
|
17
|
+
def initialize(html = ""); @html = html.to_s; end
|
|
18
|
+
def to_s = @html
|
|
19
|
+
def text = @html.gsub(/<[^>]+>/, "")
|
|
20
|
+
def inner_html = @html
|
|
21
|
+
def css(*) = NodeSet.new
|
|
22
|
+
def xpath(*) = NodeSet.new
|
|
23
|
+
def search(*) = NodeSet.new
|
|
24
|
+
def at_css(*) = nil
|
|
25
|
+
def at_xpath(*) = nil
|
|
26
|
+
def encoding = "UTF-8"
|
|
27
|
+
def errors = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class DocumentFragment < Document; end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
HTML4 = HTML
|
|
34
|
+
|
|
35
|
+
module XML
|
|
36
|
+
Node = HTML::Document
|
|
37
|
+
|
|
38
|
+
class Document < HTML::Document; end
|
|
39
|
+
class DocumentFragment < HTML::DocumentFragment; end
|
|
40
|
+
|
|
41
|
+
class NodeSet
|
|
42
|
+
include Enumerable
|
|
43
|
+
def initialize(items = []) = @items = items
|
|
44
|
+
def each(&b) = @items.each(&b)
|
|
45
|
+
def to_s = @items.map(&:to_s).join
|
|
46
|
+
def text = @items.map { |n| n.respond_to?(:text) ? n.text : n.to_s }.join
|
|
47
|
+
def size = @items.size
|
|
48
|
+
def empty? = @items.empty?
|
|
49
|
+
def [](i) = @items[i]
|
|
50
|
+
def first = @items.first
|
|
51
|
+
def css(*) = NodeSet.new
|
|
52
|
+
def xpath(*) = NodeSet.new
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
module SAX
|
|
56
|
+
class Document; end
|
|
57
|
+
class Parser
|
|
58
|
+
def initialize(doc = nil); end
|
|
59
|
+
def parse(data); end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module CSS
|
|
65
|
+
def self.xpath_for(*) = ""
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# WASM stub — OpenSSL C extension is not included in ruby+stdlib.wasm.
|
|
2
|
+
# Provides the minimal interface ActiveSupport needs for MessageEncryptor,
|
|
3
|
+
# MessageVerifier, and EncryptedConfiguration at load time.
|
|
4
|
+
# Real encryption is not used in WASM (no server secrets, local-only data).
|
|
5
|
+
|
|
6
|
+
module OpenSSL
|
|
7
|
+
VERSION = "3.0.0"
|
|
8
|
+
OPENSSL_VERSION = "OpenSSL 3.0.0 (wasm stub)"
|
|
9
|
+
|
|
10
|
+
# Must be a class (not module) so that SHA256 < OpenSSL::Digest returns true.
|
|
11
|
+
# ActiveSupport::KeyGenerator checks this with klass < OpenSSL::Digest.
|
|
12
|
+
class Digest
|
|
13
|
+
def self.hexdigest(data)
|
|
14
|
+
require "digest"
|
|
15
|
+
::Digest::SHA256.hexdigest(data.to_s)
|
|
16
|
+
end
|
|
17
|
+
def self.digest(data) = [self.hexdigest(data)].pack("H*")
|
|
18
|
+
def hexdigest(data) = self.class.hexdigest(data)
|
|
19
|
+
def digest(data) = self.class.digest(data)
|
|
20
|
+
def initialize(*); end
|
|
21
|
+
def update(*); self; end
|
|
22
|
+
def reset; self; end
|
|
23
|
+
def finish = ""
|
|
24
|
+
|
|
25
|
+
class SHA1 < Digest
|
|
26
|
+
def self.hexdigest(data)
|
|
27
|
+
require "digest"; ::Digest::SHA1.hexdigest(data.to_s)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class SHA256 < Digest
|
|
32
|
+
def self.hexdigest(data)
|
|
33
|
+
require "digest"; ::Digest::SHA256.hexdigest(data.to_s)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class SHA384 < Digest
|
|
38
|
+
def self.hexdigest(data)
|
|
39
|
+
require "digest"; ::Digest::SHA384.hexdigest(data.to_s)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class SHA512 < Digest
|
|
44
|
+
def self.hexdigest(data)
|
|
45
|
+
require "digest"; ::Digest::SHA512.hexdigest(data.to_s)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Real OpenSSL::Cipher is a class (not a module), so .new works directly.
|
|
51
|
+
class Cipher
|
|
52
|
+
CipherError = Class.new(StandardError)
|
|
53
|
+
|
|
54
|
+
def initialize(algo); @algo = algo.to_s; end
|
|
55
|
+
def authenticated?; @algo.upcase.include?("GCM") || @algo.upcase.include?("CCM"); end
|
|
56
|
+
def encrypt; self; end
|
|
57
|
+
def decrypt; self; end
|
|
58
|
+
def key=(k); end
|
|
59
|
+
def iv=(v); end
|
|
60
|
+
def iv_len = 12
|
|
61
|
+
def key_len = 32
|
|
62
|
+
def padding=(v); end
|
|
63
|
+
def auth_data=(d); end
|
|
64
|
+
def auth_tag(len = 16) = ("\x00" * (len || 16))
|
|
65
|
+
def auth_tag=(t); end
|
|
66
|
+
def update(data) = data
|
|
67
|
+
def final = ""
|
|
68
|
+
def random_key = ("\x00" * 32)
|
|
69
|
+
def random_iv = ("\x00" * 12)
|
|
70
|
+
def block_size = 16
|
|
71
|
+
|
|
72
|
+
class AES < Cipher; end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
module HMAC
|
|
76
|
+
def self.digest(digest, key, data) = ""
|
|
77
|
+
def self.hexdigest(digest, key, data) = ("00" * 32)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
module PKCS5
|
|
81
|
+
def self.pbkdf2_hmac(secret, salt, iterations, length, digest)
|
|
82
|
+
require "digest"
|
|
83
|
+
base = ::Digest::SHA256.digest("#{secret}:#{salt}:#{iterations}")
|
|
84
|
+
(base * ((length / 32) + 2))[0, length]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
module KDF
|
|
89
|
+
def self.hkdf(secret, salt:, info:, length:, hash:) = ("\x00" * length)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
module Random
|
|
93
|
+
def self.random_bytes(n = 16) = SecureRandom.random_bytes(n)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module PKey
|
|
97
|
+
class PKey; end
|
|
98
|
+
class RSA < PKey
|
|
99
|
+
def initialize(*); end
|
|
100
|
+
def public_key = self
|
|
101
|
+
def private? = false
|
|
102
|
+
def sign(*) = ""
|
|
103
|
+
def verify(*) = false
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
module SSL
|
|
108
|
+
VERIFY_NONE = 0
|
|
109
|
+
VERIFY_PEER = 1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
class BN
|
|
113
|
+
def initialize(n = 0, base = 10); @n = n.to_i; end
|
|
114
|
+
def to_i = @n
|
|
115
|
+
def to_s(base = 10) = @n.to_s(base)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class X509
|
|
119
|
+
class Certificate; end
|
|
120
|
+
class Store; end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# WASM stub — rails-html-sanitizer depends on loofah+nokogiri.
|
|
2
|
+
# In WASM, all data is user-local, so sanitizers pass through without modification.
|
|
3
|
+
# Defines both Rails::Html (legacy) and Rails::HTML4/HTML5 (rails-html-sanitizer 1.6+).
|
|
4
|
+
|
|
5
|
+
require "loofah"
|
|
6
|
+
|
|
7
|
+
module Rails
|
|
8
|
+
# Base sanitizer shared by all namespaces
|
|
9
|
+
module HtmlSanitizerBase
|
|
10
|
+
class Sanitizer
|
|
11
|
+
def sanitize(html, options = {}) = html.to_s
|
|
12
|
+
def self.full_sanitizer = FullSanitizer.new
|
|
13
|
+
def self.link_sanitizer = LinkSanitizer.new
|
|
14
|
+
def self.safe_list_sanitizer = SafeListSanitizer.new
|
|
15
|
+
def self.white_list_sanitizer = safe_list_sanitizer
|
|
16
|
+
def self.best_supported_vendor = Rails::HTML4
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class FullSanitizer < Sanitizer
|
|
20
|
+
def sanitize(html, options = {})
|
|
21
|
+
return "" if html.nil?
|
|
22
|
+
html.to_s.gsub(/<[^>]+>/, "")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class LinkSanitizer < Sanitizer; end
|
|
27
|
+
class SafeListSanitizer < Sanitizer; end
|
|
28
|
+
WhiteListSanitizer = SafeListSanitizer
|
|
29
|
+
|
|
30
|
+
module Scrubbers
|
|
31
|
+
class Strip < ::Loofah::Scrubber; end
|
|
32
|
+
class SafeList < ::Loofah::Scrubber; end
|
|
33
|
+
WhiteList = SafeList
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Legacy namespace (rails-html-sanitizer < 1.6)
|
|
38
|
+
module Html
|
|
39
|
+
include HtmlSanitizerBase
|
|
40
|
+
Sanitizer = HtmlSanitizerBase::Sanitizer
|
|
41
|
+
FullSanitizer = HtmlSanitizerBase::FullSanitizer
|
|
42
|
+
LinkSanitizer = HtmlSanitizerBase::LinkSanitizer
|
|
43
|
+
SafeListSanitizer = HtmlSanitizerBase::SafeListSanitizer
|
|
44
|
+
WhiteListSanitizer = SafeListSanitizer
|
|
45
|
+
Scrubbers = HtmlSanitizerBase::Scrubbers
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Rails::HTML is the top-level namespace referenced by railties load_defaults
|
|
49
|
+
module HTML
|
|
50
|
+
Sanitizer = HtmlSanitizerBase::Sanitizer
|
|
51
|
+
FullSanitizer = HtmlSanitizerBase::FullSanitizer
|
|
52
|
+
LinkSanitizer = HtmlSanitizerBase::LinkSanitizer
|
|
53
|
+
SafeListSanitizer = HtmlSanitizerBase::SafeListSanitizer
|
|
54
|
+
WhiteListSanitizer = SafeListSanitizer
|
|
55
|
+
Scrubbers = HtmlSanitizerBase::Scrubbers
|
|
56
|
+
|
|
57
|
+
def self.best_supported_vendor = Rails::HTML4
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# New namespaces (rails-html-sanitizer 1.6+ / Rails 8)
|
|
61
|
+
# ActionView::SanitizeHelper defaults to Rails::HTML4
|
|
62
|
+
module HTML4
|
|
63
|
+
Sanitizer = HtmlSanitizerBase::Sanitizer
|
|
64
|
+
FullSanitizer = HtmlSanitizerBase::FullSanitizer
|
|
65
|
+
LinkSanitizer = HtmlSanitizerBase::LinkSanitizer
|
|
66
|
+
SafeListSanitizer = HtmlSanitizerBase::SafeListSanitizer
|
|
67
|
+
WhiteListSanitizer = SafeListSanitizer
|
|
68
|
+
Scrubbers = HtmlSanitizerBase::Scrubbers
|
|
69
|
+
|
|
70
|
+
def self.full_sanitizer = FullSanitizer.new
|
|
71
|
+
def self.link_sanitizer = LinkSanitizer.new
|
|
72
|
+
def self.safe_list_sanitizer = SafeListSanitizer.new
|
|
73
|
+
def self.best_supported_vendor = self
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
module HTML5
|
|
77
|
+
Sanitizer = HtmlSanitizerBase::Sanitizer
|
|
78
|
+
FullSanitizer = HtmlSanitizerBase::FullSanitizer
|
|
79
|
+
LinkSanitizer = HtmlSanitizerBase::LinkSanitizer
|
|
80
|
+
SafeListSanitizer = HtmlSanitizerBase::SafeListSanitizer
|
|
81
|
+
WhiteListSanitizer = SafeListSanitizer
|
|
82
|
+
Scrubbers = HtmlSanitizerBase::Scrubbers
|
|
83
|
+
|
|
84
|
+
def self.full_sanitizer = FullSanitizer.new
|
|
85
|
+
def self.link_sanitizer = LinkSanitizer.new
|
|
86
|
+
def self.safe_list_sanitizer = SafeListSanitizer.new
|
|
87
|
+
def self.best_supported_vendor = self
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# WASM stub — DNS resolution not available in browser WASM.
|
|
2
|
+
module Resolv
|
|
3
|
+
def self.getaddress(name) = "127.0.0.1"
|
|
4
|
+
def self.getaddresses(name) = ["127.0.0.1"]
|
|
5
|
+
def self.getname(addr) = "localhost"
|
|
6
|
+
def self.getnames(addr) = ["localhost"]
|
|
7
|
+
|
|
8
|
+
class DNS; end
|
|
9
|
+
class IPv4
|
|
10
|
+
def self.create(addr) = new(addr)
|
|
11
|
+
def initialize(addr); @addr = addr; end
|
|
12
|
+
def to_s = @addr
|
|
13
|
+
end
|
|
14
|
+
class IPv6
|
|
15
|
+
def self.create(addr) = new(addr)
|
|
16
|
+
def initialize(addr); @addr = addr; end
|
|
17
|
+
def to_s = @addr
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# WASM stub — socket C extension is not available in ruby+stdlib.wasm.
|
|
2
|
+
# Provides the constants and classes that ipaddr, activesupport, and railties need.
|
|
3
|
+
|
|
4
|
+
class BasicSocket; end
|
|
5
|
+
|
|
6
|
+
class Socket < BasicSocket
|
|
7
|
+
AF_UNSPEC = 0
|
|
8
|
+
AF_UNIX = 1
|
|
9
|
+
AF_INET = 2
|
|
10
|
+
AF_INET6 = 10
|
|
11
|
+
AF_LOCAL = 1
|
|
12
|
+
SOCK_STREAM = 1
|
|
13
|
+
SOCK_DGRAM = 2
|
|
14
|
+
SOCK_RAW = 3
|
|
15
|
+
IPPROTO_IP = 0
|
|
16
|
+
IPPROTO_TCP = 6
|
|
17
|
+
IPPROTO_UDP = 17
|
|
18
|
+
IPPROTO_IPV6 = 41
|
|
19
|
+
IPPORT_RESERVED = 1024
|
|
20
|
+
|
|
21
|
+
def self.gethostname = "localhost"
|
|
22
|
+
def self.getaddrinfo(*) = []
|
|
23
|
+
def self.gethostbyname(*) = nil
|
|
24
|
+
def self.gethostbyaddr(*) = nil
|
|
25
|
+
def self.ip_address_list = []
|
|
26
|
+
def self.pack_sockaddr_in(port, host) = ""
|
|
27
|
+
def self.unpack_sockaddr_in(addr) = [0, "127.0.0.1"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class Addrinfo
|
|
31
|
+
attr_reader :afamily, :pfamily, :socktype, :protocol
|
|
32
|
+
def initialize(*); end
|
|
33
|
+
def self.getaddrinfo(*) = []
|
|
34
|
+
def self.tcp(host, port) = new
|
|
35
|
+
def self.udp(host, port) = new
|
|
36
|
+
def ip? = false
|
|
37
|
+
def ip_address = "127.0.0.1"
|
|
38
|
+
def ip_port = 0
|
|
39
|
+
def ipv4? = false
|
|
40
|
+
def ipv6? = false
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class TCPSocket < BasicSocket; def initialize(*); end; end
|
|
44
|
+
class TCPServer < BasicSocket; def initialize(*); end; end
|
|
45
|
+
class UDPSocket < BasicSocket; def initialize(*); end; end
|
|
46
|
+
class UNIXSocket < BasicSocket; def initialize(*); end; end
|
|
47
|
+
class UNIXServer < BasicSocket; def initialize(*); end; end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# WASM stub for the sqlite3 C extension.
|
|
2
|
+
# Loaded via /stubs (prepended to $LOAD_PATH) before any gem path, so
|
|
3
|
+
# `require 'sqlite3'` resolves here instead of trying to load the native .so.
|
|
4
|
+
# Provides enough constants and classes for sqlite3_adapter.rb to load;
|
|
5
|
+
# the actual DB operations are handled by WasmSqlite3Adapter::ExternalInterface.
|
|
6
|
+
|
|
7
|
+
module SQLite3
|
|
8
|
+
VERSION = '2.5.0'
|
|
9
|
+
|
|
10
|
+
module ForkSafety
|
|
11
|
+
def self.suppress_warnings!; end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Exception < StandardError; end
|
|
15
|
+
class BusyException < Exception; end
|
|
16
|
+
class FullException < Exception; end
|
|
17
|
+
class IOException < Exception; end
|
|
18
|
+
class AccessDeniedException < Exception; end
|
|
19
|
+
class ProtocolException < Exception; end
|
|
20
|
+
class RangeException < Exception; end
|
|
21
|
+
class NotADatabaseException < Exception; end
|
|
22
|
+
class MisuseException < Exception; end
|
|
23
|
+
class CantOpenException < Exception; end
|
|
24
|
+
class NotFoundException < Exception; end
|
|
25
|
+
class CorruptException < Exception; end
|
|
26
|
+
class ConstraintException < Exception; end
|
|
27
|
+
|
|
28
|
+
module Constants
|
|
29
|
+
module TextRep
|
|
30
|
+
UTF8 = 1
|
|
31
|
+
UTF16LE = 2
|
|
32
|
+
UTF16BE = 3
|
|
33
|
+
UTF16 = 4
|
|
34
|
+
ANY = 5
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
module ColumnType
|
|
38
|
+
INTEGER = 1
|
|
39
|
+
FLOAT = 2
|
|
40
|
+
TEXT = 3
|
|
41
|
+
BLOB = 4
|
|
42
|
+
NULL = 5
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module Open
|
|
46
|
+
READONLY = 0x00000001
|
|
47
|
+
READWRITE = 0x00000002
|
|
48
|
+
CREATE = 0x00000004
|
|
49
|
+
NOMUTEX = 0x00008000
|
|
50
|
+
FULLMUTEX = 0x00010000
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
module Pragmas; end
|
|
55
|
+
|
|
56
|
+
class Statement
|
|
57
|
+
attr_reader :remainder
|
|
58
|
+
|
|
59
|
+
def initialize(db, sql); end
|
|
60
|
+
def close; end
|
|
61
|
+
def step; nil; end
|
|
62
|
+
def columns; []; end
|
|
63
|
+
def types; []; end
|
|
64
|
+
def reset!; end
|
|
65
|
+
def bind_params(*); end
|
|
66
|
+
def execute(*); []; end
|
|
67
|
+
def done?; true; end
|
|
68
|
+
def must_be_open!; end
|
|
69
|
+
def column_count; 0; end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class Database
|
|
73
|
+
def self.quote(s) = s.gsub("'", "''")
|
|
74
|
+
|
|
75
|
+
def initialize(file = '', options = {}); end
|
|
76
|
+
def close; end
|
|
77
|
+
def closed?; false; end
|
|
78
|
+
def execute(sql, *binds); []; end
|
|
79
|
+
def execute2(sql, *binds); []; end
|
|
80
|
+
def query(sql, *binds); []; end
|
|
81
|
+
def prepare(sql); Statement.new(self, sql); end
|
|
82
|
+
def transaction(mode = :deferred); yield self if block_given?; end
|
|
83
|
+
def commit; end
|
|
84
|
+
def rollback; end
|
|
85
|
+
def changes; 0; end
|
|
86
|
+
def last_insert_row_id; 0; end
|
|
87
|
+
def errmsg; ''; end
|
|
88
|
+
def errcode; 0; end
|
|
89
|
+
def complete?(sql); true; end
|
|
90
|
+
def busy_handler_timeout=(v); end
|
|
91
|
+
def busy_timeout=(v); end
|
|
92
|
+
def busy_timeout(ms); end
|
|
93
|
+
def extended_result_codes=(v); end
|
|
94
|
+
def results_as_hash=(v); end
|
|
95
|
+
def type_translation=(v); end
|
|
96
|
+
def encoding; 'UTF-8'; end
|
|
97
|
+
def authorizer=(v); end
|
|
98
|
+
def trace(&block); end
|
|
99
|
+
|
|
100
|
+
include Pragmas
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# WASM is single-threaded — map Thread to Fiber so gems that spawn threads
|
|
2
|
+
# don't raise. The fiber runs synchronously when .value or .join is called.
|
|
3
|
+
class Thread
|
|
4
|
+
def self.new(...)
|
|
5
|
+
f = Fiber.new(...)
|
|
6
|
+
def f.value = resume
|
|
7
|
+
def f.join = value
|
|
8
|
+
f
|
|
9
|
+
end
|
|
10
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: wasm_rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Emerson Argueta
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: railties
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '7.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '7.1'
|
|
27
|
+
description: Infrastructure gem for building WASM-first Rails apps. Provides a Service
|
|
28
|
+
Worker that boots Ruby+Rails inside the browser, SQLite persistence via OPFS, build
|
|
29
|
+
tooling, and C extension stubs.
|
|
30
|
+
email:
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- MIT-LICENSE
|
|
36
|
+
- README.md
|
|
37
|
+
- lib/generators/wasm_rails/install/install_generator.rb
|
|
38
|
+
- lib/generators/wasm_rails/install/templates/boot.js
|
|
39
|
+
- lib/generators/wasm_rails/install/templates/build_app_bundle.mjs
|
|
40
|
+
- lib/generators/wasm_rails/install/templates/esbuild_wasm.mjs
|
|
41
|
+
- lib/generators/wasm_rails/install/templates/serve_wasm.mjs
|
|
42
|
+
- lib/generators/wasm_rails/install/templates/service_worker.js
|
|
43
|
+
- lib/generators/wasm_rails/install/templates/wasm_shell.html
|
|
44
|
+
- lib/generators/wasm_rails/install/templates/wasm_sqlite3_adapter.rb
|
|
45
|
+
- lib/wasm_rails.rb
|
|
46
|
+
- lib/wasm_rails/railtie.rb
|
|
47
|
+
- lib/wasm_rails/version.rb
|
|
48
|
+
- wasm_stubs/io/console/size.rb
|
|
49
|
+
- wasm_stubs/io/wait.rb
|
|
50
|
+
- wasm_stubs/loofah.rb
|
|
51
|
+
- wasm_stubs/nokogiri.rb
|
|
52
|
+
- wasm_stubs/openssl.rb
|
|
53
|
+
- wasm_stubs/rails-html-sanitizer.rb
|
|
54
|
+
- wasm_stubs/resolv.rb
|
|
55
|
+
- wasm_stubs/socket.rb
|
|
56
|
+
- wasm_stubs/sqlite3.rb
|
|
57
|
+
- wasm_stubs/thread.rb
|
|
58
|
+
homepage: https://github.com/emerson-argueta/wasm-rails
|
|
59
|
+
licenses:
|
|
60
|
+
- MIT
|
|
61
|
+
metadata: {}
|
|
62
|
+
post_install_message:
|
|
63
|
+
rdoc_options: []
|
|
64
|
+
require_paths:
|
|
65
|
+
- lib
|
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '3.3'
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
requirements: []
|
|
77
|
+
rubygems_version: 3.5.9
|
|
78
|
+
signing_key:
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: Run Rails apps in the browser via WebAssembly
|
|
81
|
+
test_files: []
|