ruby_wasm 2.5.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +8 -0
  3. data/CONTRIBUTING.md +124 -0
  4. data/Cargo.lock +2452 -0
  5. data/Cargo.toml +7 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +21 -0
  8. data/NOTICE +1293 -0
  9. data/README.md +161 -0
  10. data/Rakefile +164 -0
  11. data/Steepfile +24 -0
  12. data/benchmarks/vm_deep_call.rb +55 -0
  13. data/builders/wasm32-unknown-emscripten/Dockerfile +43 -0
  14. data/builders/wasm32-unknown-emscripten/entrypoint.sh +7 -0
  15. data/builders/wasm32-unknown-wasi/Dockerfile +47 -0
  16. data/builders/wasm32-unknown-wasi/entrypoint.sh +7 -0
  17. data/docs/api.md +2 -0
  18. data/docs/cheat_sheet.md +195 -0
  19. data/docs/faq.md +25 -0
  20. data/exe/rbwasm +7 -0
  21. data/ext/.gitignore +2 -0
  22. data/ext/README.md +11 -0
  23. data/ext/extinit.c.erb +32 -0
  24. data/ext/ruby_wasm/Cargo.toml +17 -0
  25. data/ext/ruby_wasm/extconf.rb +6 -0
  26. data/ext/ruby_wasm/src/lib.rs +69 -0
  27. data/lib/ruby_wasm/build/build_params.rb +3 -0
  28. data/lib/ruby_wasm/build/downloader.rb +18 -0
  29. data/lib/ruby_wasm/build/executor.rb +187 -0
  30. data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
  31. data/lib/ruby_wasm/build/product/crossruby.rb +326 -0
  32. data/lib/ruby_wasm/build/product/libyaml.rb +68 -0
  33. data/lib/ruby_wasm/build/product/openssl.rb +88 -0
  34. data/lib/ruby_wasm/build/product/product.rb +39 -0
  35. data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
  36. data/lib/ruby_wasm/build/product/wasi_vfs.rb +83 -0
  37. data/lib/ruby_wasm/build/product/zlib.rb +68 -0
  38. data/lib/ruby_wasm/build/product.rb +8 -0
  39. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
  40. data/lib/ruby_wasm/build/toolchain.rb +193 -0
  41. data/lib/ruby_wasm/build.rb +88 -0
  42. data/lib/ruby_wasm/cli.rb +195 -0
  43. data/lib/ruby_wasm/packager/core.rb +156 -0
  44. data/lib/ruby_wasm/packager/file_system.rb +157 -0
  45. data/lib/ruby_wasm/packager.rb +159 -0
  46. data/lib/ruby_wasm/rake_task.rb +58 -0
  47. data/lib/ruby_wasm/util.rb +15 -0
  48. data/lib/ruby_wasm/version.rb +3 -0
  49. data/lib/ruby_wasm.rb +33 -0
  50. data/package-lock.json +9500 -0
  51. data/package.json +12 -0
  52. data/ruby_wasm.gemspec +32 -0
  53. data/sig/open_uri.rbs +4 -0
  54. data/sig/ruby_wasm/build.rbs +322 -0
  55. data/sig/ruby_wasm/cli.rbs +24 -0
  56. data/sig/ruby_wasm/ext.rbs +11 -0
  57. data/sig/ruby_wasm/packager.rbs +91 -0
  58. data/sig/ruby_wasm/util.rbs +5 -0
  59. data/tasks/check.rake +37 -0
  60. data/tasks/ci.rake +152 -0
  61. data/tasks/doc.rake +24 -0
  62. data/tasks/format.rake +34 -0
  63. data/tasks/gem.rake +19 -0
  64. data/tasks/packaging.rake +148 -0
  65. data/tasks/version.rake +38 -0
  66. data/tools/clang-format-diff.sh +18 -0
  67. data/tools/exe/rbminify +12 -0
  68. data/tools/lib/syntax_tree/minify_ruby.rb +63 -0
  69. metadata +115 -0
data/tasks/doc.rake ADDED
@@ -0,0 +1,24 @@
1
+ require "rdoc/task"
2
+ require "ruby_wasm/version"
3
+
4
+ RDoc::Task.new do |doc|
5
+ doc.main = "README.md"
6
+ doc.title = "ruby.wasm Documentation"
7
+ doc.rdoc_files = FileList.new %w[*.md ext/**/*.c ext/**/*.rb]
8
+ end
9
+
10
+ namespace :doc do
11
+ desc "Update docs/api/javascript.md"
12
+ task :api_js do
13
+ sh "npx",
14
+ "documentation",
15
+ "readme",
16
+ "--readme-file",
17
+ "./packages/npm-packages/ruby-wasm-wasi/README.md",
18
+ "--section",
19
+ "API",
20
+ "--markdown-toc",
21
+ "false",
22
+ "./packages/npm-packages/ruby-wasm-wasi/dist/esm/index.js"
23
+ end
24
+ end
data/tasks/format.rake ADDED
@@ -0,0 +1,34 @@
1
+ namespace :format do
2
+ begin
3
+ require "syntax_tree/rake_tasks"
4
+ SyntaxTree::Rake::WriteTask.new(
5
+ :ruby,
6
+ Rake::FileList[
7
+ "Rakefile",
8
+ "lib/**/*.rb",
9
+ "ext/**/*.rb",
10
+ "tasks/**/*.rake",
11
+ "packages/**/*.rb"
12
+ ]
13
+ )
14
+ rescue LoadError
15
+ end
16
+
17
+ task :js do
18
+ sh "npm run format", chdir: "packages/npm-packages/ruby-wasm-wasi"
19
+ end
20
+
21
+ task :c do
22
+ sh "find ./ext -iname *.h -o -iname *.c | xargs clang-format -i"
23
+ end
24
+ end
25
+
26
+ task :format do
27
+ if Rake::Task.task_defined?("format:ruby")
28
+ Rake::Task["format:ruby"].invoke
29
+ else
30
+ puts "\e[33mSyntaxTree not installed, skipping format:ruby\e[0m"
31
+ end
32
+ Rake::Task["format:js"].invoke
33
+ Rake::Task["format:c"].invoke
34
+ end
data/tasks/gem.rake ADDED
@@ -0,0 +1,19 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ begin
11
+ require "rb_sys/extensiontask"
12
+
13
+ RbSys::ExtensionTask.new("ruby_wasm") { |ext| ext.lib_dir = "lib/ruby_wasm" }
14
+ rescue LoadError => e
15
+ task :compile do
16
+ $stderr.puts "Skipping compilation of ruby_wasm extension: #{e.message}"
17
+ exit 1
18
+ end
19
+ end
@@ -0,0 +1,148 @@
1
+ wasi_vfs = RubyWasm::WasiVfsProduct.new(File.join(Dir.pwd, "build"))
2
+ wasi_sdk = TOOLCHAINS["wasi-sdk"]
3
+ tools = {
4
+ "WASI_VFS_CLI" => wasi_vfs.cli_bin_path,
5
+ "WASMOPT" => wasi_sdk.wasm_opt
6
+ }
7
+
8
+ def npm_pkg_build_command(pkg)
9
+ [
10
+ "bundle",
11
+ "exec",
12
+ "rbwasm",
13
+ "build",
14
+ "--ruby-version",
15
+ pkg[:ruby_version],
16
+ "--target",
17
+ pkg[:target],
18
+ "--build-profile",
19
+ "full"
20
+ ]
21
+ end
22
+
23
+ def npm_pkg_rubies_cache_key(pkg)
24
+ build_command = npm_pkg_build_command(pkg)
25
+ require "open3"
26
+ cmd = build_command + ["--print-ruby-cache-key"]
27
+ stdout, status = Open3.capture2(*cmd)
28
+ unless status.success?
29
+ raise "Command failed with status (#{status.exitstatus}): #{cmd.join ""}"
30
+ end
31
+ require "json"
32
+ JSON.parse(stdout)["hexdigest"]
33
+ end
34
+
35
+ namespace :npm do
36
+ NPM_PACKAGES.each do |pkg|
37
+ base_dir = Dir.pwd
38
+ pkg_dir = "#{Dir.pwd}/packages/npm-packages/#{pkg[:name]}"
39
+
40
+ namespace pkg[:name] do
41
+ build_command = npm_pkg_build_command(pkg)
42
+
43
+ desc "Build ruby for npm package #{pkg[:name]}"
44
+ task "ruby" do
45
+ env = {
46
+ # Share ./build and ./rubies in the same workspace
47
+ "RUBY_WASM_ROOT" => base_dir
48
+ }
49
+ if gemfile_path = pkg[:gemfile]
50
+ env["BUNDLE_GEMFILE"] = File.join(base_dir, gemfile_path)
51
+ else
52
+ # Explicitly disable rubygems integration since Bundler finds
53
+ # Gemfile in the repo root directory.
54
+ build_command.push "--disable-gems"
55
+ end
56
+ dist_dir = File.join(pkg_dir, "dist")
57
+ mkdir_p dist_dir
58
+ if pkg[:target] == "wasm32-unknown-wasi"
59
+ sh env,
60
+ *build_command,
61
+ "--no-stdlib",
62
+ "-o",
63
+ File.join(dist_dir, "ruby.wasm")
64
+ sh env,
65
+ *build_command,
66
+ "-o",
67
+ File.join(dist_dir, "ruby.debug+stdlib.wasm")
68
+ sh wasi_sdk.wasm_opt,
69
+ "--strip-debug",
70
+ File.join(dist_dir, "ruby.wasm"),
71
+ "-o",
72
+ File.join(dist_dir, "ruby.wasm")
73
+ sh wasi_sdk.wasm_opt,
74
+ "--strip-debug",
75
+ File.join(dist_dir, "ruby.debug+stdlib.wasm"),
76
+ "-o",
77
+ File.join(dist_dir, "ruby+stdlib.wasm")
78
+ elsif pkg[:target] == "wasm32-unknown-emscripten"
79
+ sh env, *build_command, "-o", "/dev/null"
80
+ end
81
+ end
82
+
83
+ desc "Build npm package #{pkg[:name]}"
84
+ task "build" => ["ruby"] do
85
+ sh tools, "npm run build", chdir: pkg_dir
86
+ end
87
+
88
+ desc "Check npm package #{pkg[:name]}"
89
+ task "check" do
90
+ sh "npm test", chdir: pkg_dir
91
+ end
92
+ end
93
+
94
+ desc "Make tarball for npm package #{pkg[:name]}"
95
+ task pkg[:name] do
96
+ wasi_vfs.install_cli
97
+ wasi_sdk.install_binaryen
98
+ Rake::Task["npm:#{pkg[:name]}:build"].invoke
99
+ sh "npm pack", chdir: pkg_dir
100
+ end
101
+ end
102
+
103
+ desc "Configure for pre-release"
104
+ task :configure_prerelease, [:prerel] do |t, args|
105
+ require "json"
106
+ prerel = args[:prerel]
107
+ new_pkgs = {}
108
+ NPM_PACKAGES.each do |pkg|
109
+ pkg_dir = "#{Dir.pwd}/packages/npm-packages/#{pkg[:name]}"
110
+ pkg_json = "#{pkg_dir}/package.json"
111
+ package = JSON.parse(File.read(pkg_json))
112
+
113
+ version = package["version"] + "-#{prerel}"
114
+ new_pkgs[package["name"]] = version
115
+ sh *["npm", "pkg", "set", "version=#{version}"], chdir: pkg_dir
116
+ end
117
+
118
+ NPM_PACKAGES.each do |pkg|
119
+ pkg_dir = "#{Dir.pwd}/packages/npm-packages/#{pkg[:name]}"
120
+ pkg_json = "#{pkg_dir}/package.json"
121
+ package = JSON.parse(File.read(pkg_json))
122
+ (package["dependencies"] || []).each do |dep, _|
123
+ next unless new_pkgs[dep]
124
+ sh *["npm", "pkg", "set", "dependencies.#{dep}=#{new_pkgs[dep]}"],
125
+ chdir: pkg_dir
126
+ end
127
+ end
128
+ end
129
+
130
+ desc "Build all npm packages"
131
+ multitask all: NPM_PACKAGES.map { |pkg| pkg[:name] }
132
+ end
133
+
134
+ namespace :standalone do
135
+ STANDALONE_PACKAGES.each do |pkg|
136
+ pkg_dir = "#{Dir.pwd}/packages/standalone/#{pkg[:name]}"
137
+
138
+ desc "Build standalone package #{pkg[:name]}"
139
+ task "#{pkg[:name]}" => ["build:#{pkg[:build]}"] do
140
+ wasi_vfs.install_cli
141
+ wasi_sdk.install_binaryen
142
+ base_dir = Dir.pwd
143
+ sh tools,
144
+ "./build-package.sh #{base_dir}/rubies/ruby-#{pkg[:build]}",
145
+ chdir: pkg_dir
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,38 @@
1
+ def bump_version_npm_package(package, version)
2
+ require "json"
3
+ pkg_dir = "#{Dir.pwd}/packages/npm-packages/#{package}"
4
+ pkg_json = "#{pkg_dir}/package.json"
5
+ package = JSON.parse(File.read(pkg_json))
6
+ old_version = package["version"]
7
+ pkg_name = package["name"]
8
+ package["version"] = version
9
+ File.write(pkg_json, JSON.pretty_generate(package) + "\n")
10
+
11
+ # Update package-lock.json
12
+ # Update README.md and other docs
13
+ `git grep -l #{pkg_name}@#{old_version}`.split.each do |file|
14
+ content = File.read(file)
15
+ next_nightly = Date.today.strftime("%Y-%m-%d")
16
+ content.gsub!(
17
+ /#{pkg_name}@#{old_version}-\d{4}-\d{2}-\d{2}-a/,
18
+ "#{pkg_name}@#{version}-#{next_nightly}-a"
19
+ )
20
+ content.gsub!(/#{pkg_name}@#{old_version}/, "#{pkg_name}@#{version}")
21
+ File.write(file, content)
22
+ end
23
+ end
24
+
25
+ def bump_version_rb(version_rb, version)
26
+ version_rb_content = File.read(version_rb)
27
+ version_rb_content.gsub!(/VERSION = ".+"/, "VERSION = \"#{version}\"")
28
+ File.write(version_rb, version_rb_content)
29
+ end
30
+
31
+ task :bump_version, %i[version] do |t, args|
32
+ version = args[:version] or raise "version is required"
33
+ bump_version_rb("lib/ruby_wasm/version.rb", version)
34
+ bump_version_rb("packages/gems/js/lib/js/version.rb", version)
35
+ NPM_PACKAGES.each { |pkg| bump_version_npm_package(pkg[:name], version) }
36
+ # Update ./package-lock.json
37
+ sh "npm install"
38
+ end
@@ -0,0 +1,18 @@
1
+ #!/bin/bash
2
+
3
+ set -eo pipefail
4
+
5
+ if [ -n "$1" ]; then
6
+ BASE_BRANCH="$1"
7
+ elif [ -n "$GITHUB_EVENT_BEFORE" ] && [ "push" = "$GITHUB_EVENT_NAME" ]; then
8
+ BASE_BRANCH="$GITHUB_EVENT_BEFORE"
9
+ elif [ -n "$GITHUB_BASE_REF" ]; then
10
+ BASE_BRANCH="origin/$GITHUB_BASE_REF"
11
+ else
12
+ BASE_BRANCH="@{upstream}"
13
+ fi
14
+
15
+ MERGE_BASE=$(git merge-base $BASE_BRANCH HEAD)
16
+
17
+ git diff -U0 --no-color $MERGE_BASE -- '*.c' '*.h' | clang-format-diff -i -p1
18
+ exit $?
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
4
+
5
+ require "syntax_tree"
6
+ require "syntax_tree/cli"
7
+ require "syntax_tree/minify_ruby"
8
+
9
+ # Override the default formatter with our own.
10
+ SyntaxTree.register_handler(".rb", SyntaxTree::MinifyRuby)
11
+
12
+ exit(SyntaxTree::CLI.run(ARGV))
@@ -0,0 +1,63 @@
1
+ require "syntax_tree"
2
+
3
+ module SyntaxTree
4
+ module MinifyRuby
5
+
6
+ # This is a required API for syntax tree which just delegates to SyntaxTree.parse.
7
+ def self.parse(source)
8
+ ::SyntaxTree.parse(source)
9
+ end
10
+
11
+ # This is the main entrypoint for the formatter. It parses the source,
12
+ # builds a formatter, then prints the result.
13
+ def self.format(source, _maxwidth = nil)
14
+ formatter = Formatter.new(source)
15
+ program = parse(source)
16
+ CommentStrippingVisitor.new.visit(program)
17
+ program.format(formatter)
18
+
19
+ formatter.flush
20
+ formatter.output.join
21
+ end
22
+
23
+ # This is a required API for syntax tree which just delegates to SyntaxTree.read.
24
+ def self.read(filepath)
25
+ ::SyntaxTree.read(filepath)
26
+ end
27
+
28
+ class CommentStrippingVisitor < SyntaxTree::Visitor
29
+ def visit(node)
30
+ if node and node.comments.any?
31
+ node.comments.clear
32
+ end
33
+ super(node)
34
+ end
35
+
36
+ def visit_statements(node)
37
+ node.body.delete_if { _1.is_a?(SyntaxTree::Comment) }
38
+ super(node)
39
+ end
40
+ end
41
+
42
+ class Formatter < SyntaxTree::Formatter
43
+ def initialize(source)
44
+ super(source, [], Float::INFINITY) do |n|
45
+ # This block, called `genspace`, is used to generate indentation for `n` depth.
46
+ ""
47
+ end
48
+ end
49
+
50
+ def breakable(
51
+ separator = " ",
52
+ _width = separator.length,
53
+ indent: nil,
54
+ force: nil
55
+ )
56
+ # Don't break when already broken
57
+ return if target.last.is_a?(PrettierPrint::BreakParent)
58
+ return if not force and separator == ""
59
+ super(separator, _width, indent: indent, force: force)
60
+ end
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_wasm
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.5.0.pre.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuta Saito
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-01-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby to WebAssembly toolkit. This gem takes Ruby code and Gemfile, and
14
+ packages them with Ruby runtime into a WebAssembly binary.
15
+ email:
16
+ - kateinoigakukun@gmail.com
17
+ executables:
18
+ - rbwasm
19
+ extensions:
20
+ - ext/ruby_wasm/Cargo.toml
21
+ extra_rdoc_files: []
22
+ files:
23
+ - ".clang-format"
24
+ - CONTRIBUTING.md
25
+ - Cargo.lock
26
+ - Cargo.toml
27
+ - Gemfile
28
+ - LICENSE
29
+ - NOTICE
30
+ - README.md
31
+ - Rakefile
32
+ - Steepfile
33
+ - benchmarks/vm_deep_call.rb
34
+ - builders/wasm32-unknown-emscripten/Dockerfile
35
+ - builders/wasm32-unknown-emscripten/entrypoint.sh
36
+ - builders/wasm32-unknown-wasi/Dockerfile
37
+ - builders/wasm32-unknown-wasi/entrypoint.sh
38
+ - docs/api.md
39
+ - docs/cheat_sheet.md
40
+ - docs/faq.md
41
+ - exe/rbwasm
42
+ - ext/.gitignore
43
+ - ext/README.md
44
+ - ext/extinit.c.erb
45
+ - ext/ruby_wasm/Cargo.toml
46
+ - ext/ruby_wasm/extconf.rb
47
+ - ext/ruby_wasm/src/lib.rs
48
+ - lib/ruby_wasm.rb
49
+ - lib/ruby_wasm/build.rb
50
+ - lib/ruby_wasm/build/build_params.rb
51
+ - lib/ruby_wasm/build/downloader.rb
52
+ - lib/ruby_wasm/build/executor.rb
53
+ - lib/ruby_wasm/build/product.rb
54
+ - lib/ruby_wasm/build/product/baseruby.rb
55
+ - lib/ruby_wasm/build/product/crossruby.rb
56
+ - lib/ruby_wasm/build/product/libyaml.rb
57
+ - lib/ruby_wasm/build/product/openssl.rb
58
+ - lib/ruby_wasm/build/product/product.rb
59
+ - lib/ruby_wasm/build/product/ruby_source.rb
60
+ - lib/ruby_wasm/build/product/wasi_vfs.rb
61
+ - lib/ruby_wasm/build/product/zlib.rb
62
+ - lib/ruby_wasm/build/toolchain.rb
63
+ - lib/ruby_wasm/build/toolchain/wit_bindgen.rb
64
+ - lib/ruby_wasm/cli.rb
65
+ - lib/ruby_wasm/packager.rb
66
+ - lib/ruby_wasm/packager/core.rb
67
+ - lib/ruby_wasm/packager/file_system.rb
68
+ - lib/ruby_wasm/rake_task.rb
69
+ - lib/ruby_wasm/util.rb
70
+ - lib/ruby_wasm/version.rb
71
+ - package-lock.json
72
+ - package.json
73
+ - ruby_wasm.gemspec
74
+ - sig/open_uri.rbs
75
+ - sig/ruby_wasm/build.rbs
76
+ - sig/ruby_wasm/cli.rbs
77
+ - sig/ruby_wasm/ext.rbs
78
+ - sig/ruby_wasm/packager.rbs
79
+ - sig/ruby_wasm/util.rbs
80
+ - tasks/check.rake
81
+ - tasks/ci.rake
82
+ - tasks/doc.rake
83
+ - tasks/format.rake
84
+ - tasks/gem.rake
85
+ - tasks/packaging.rake
86
+ - tasks/version.rake
87
+ - tools/clang-format-diff.sh
88
+ - tools/exe/rbminify
89
+ - tools/lib/syntax_tree/minify_ruby.rb
90
+ homepage: https://github.com/ruby/ruby.wasm
91
+ licenses:
92
+ - MIT
93
+ metadata:
94
+ homepage_uri: https://github.com/ruby/ruby.wasm
95
+ source_code_uri: https://github.com/ruby/ruby.wasm
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 2.6.0
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.5.3
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Ruby to WebAssembly toolkit
115
+ test_files: []