@wasm-oj/server 0.2.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.
- package/LICENSE +21 -0
- package/README.md +6 -0
- package/THIRD_PARTY_NOTICES.md +302 -0
- package/crates/runtime-core/Cargo.lock +5099 -0
- package/crates/runtime-core/Cargo.toml +66 -0
- package/crates/runtime-core/README.md +47 -0
- package/crates/runtime-core/src/bin/wasm-oj-compiler.rs +418 -0
- package/crates/runtime-core/src/bin/wasm-oj-runner.rs +294 -0
- package/crates/runtime-core/src/capabilities.rs +118 -0
- package/crates/runtime-core/src/compiler.rs +658 -0
- package/crates/runtime-core/src/contract.rs +5 -0
- package/crates/runtime-core/src/deterministic.rs +1051 -0
- package/crates/runtime-core/src/error.rs +58 -0
- package/crates/runtime-core/src/filesystem.rs +547 -0
- package/crates/runtime-core/src/filesystem_quota.rs +167 -0
- package/crates/runtime-core/src/go_compiler_session.rs +297 -0
- package/crates/runtime-core/src/interactive.rs +1019 -0
- package/crates/runtime-core/src/judge_package.rs +1539 -0
- package/crates/runtime-core/src/lib.rs +98 -0
- package/crates/runtime-core/src/memory.rs +84 -0
- package/crates/runtime-core/src/meter.rs +549 -0
- package/crates/runtime-core/src/module_imports.rs +149 -0
- package/crates/runtime-core/src/module_policy.rs +714 -0
- package/crates/runtime-core/src/output.rs +204 -0
- package/crates/runtime-core/src/run/mod.rs +208 -0
- package/crates/runtime-core/src/run/native.rs +260 -0
- package/crates/runtime-core/src/run/web.rs +229 -0
- package/crates/runtime-core/src/run/web_runtime.rs +109 -0
- package/crates/runtime-core/src/types.rs +268 -0
- package/crates/runtime-core/src/web.rs +83 -0
- package/dist/chunks/go-toolchain-Dbt-lp2L.js +426 -0
- package/dist/chunks/java-toolchain-DajoRCHu.js +44 -0
- package/dist/chunks/python-toolchain-Dx834o2A.js +4 -0
- package/dist/chunks/rust-toolchain-CJ3sMxPE.js +252 -0
- package/dist/chunks/toolchains-C6KuA1yM.js +224 -0
- package/dist/go-stage.mjs +193 -0
- package/dist/index.d.ts +221 -0
- package/dist/index.js +4393 -0
- package/dist/java-stage.mjs +111 -0
- package/dist/python-stage.mjs +90 -0
- package/dist/rustc-stage.mjs +301 -0
- package/dist/server-build-stage.mjs +2564 -0
- package/dist/server-runner-stage.mjs +155 -0
- package/licenses/fflate-MIT.txt +21 -0
- package/licenses/runtime-core-dependencies.html +6253 -0
- package/licenses/runtime-core-dependencies.json +3041 -0
- package/licenses/wasmer-sdk-MIT.txt +21 -0
- package/licenses/wasmer-sdk-dependencies.html +6901 -0
- package/licenses/wasmer-sdk-dependencies.json +3013 -0
- package/package.json +70 -0
- package/rust-toolchain.toml +5 -0
- package/testdata/wojjdg02-v2-text.hex +1 -0
- package/vendor/shared-buffer/Cargo.toml +22 -0
- package/vendor/shared-buffer/LICENSE_APACHE.md +176 -0
- package/vendor/shared-buffer/LICENSE_MIT.md +25 -0
- package/vendor/shared-buffer/README.md +34 -0
- package/vendor/shared-buffer/src/lib.rs +58 -0
- package/vendor/shared-buffer/src/mmap.rs +250 -0
- package/vendor/shared-buffer/src/owned.rs +389 -0
- package/vendor/virtual-fs/Cargo.toml +181 -0
- package/vendor/virtual-fs/LICENSE +25 -0
- package/vendor/virtual-fs/src/arc_box_file.rs +142 -0
- package/vendor/virtual-fs/src/arc_file.rs +182 -0
- package/vendor/virtual-fs/src/arc_fs.rs +68 -0
- package/vendor/virtual-fs/src/buffer_file.rs +103 -0
- package/vendor/virtual-fs/src/builder.rs +232 -0
- package/vendor/virtual-fs/src/combine_file.rs +101 -0
- package/vendor/virtual-fs/src/cow_file.rs +345 -0
- package/vendor/virtual-fs/src/dual_write_file.rs +113 -0
- package/vendor/virtual-fs/src/empty_fs.rs +81 -0
- package/vendor/virtual-fs/src/filesystems.rs +108 -0
- package/vendor/virtual-fs/src/host_fs.rs +1390 -0
- package/vendor/virtual-fs/src/lib.rs +782 -0
- package/vendor/virtual-fs/src/limiter.rs +252 -0
- package/vendor/virtual-fs/src/mem_fs/file.rs +1799 -0
- package/vendor/virtual-fs/src/mem_fs/file_opener.rs +941 -0
- package/vendor/virtual-fs/src/mem_fs/filesystem.rs +2134 -0
- package/vendor/virtual-fs/src/mem_fs/mod.rs +245 -0
- package/vendor/virtual-fs/src/mem_fs/offloaded_file.rs +474 -0
- package/vendor/virtual-fs/src/mem_fs/stdio.rs +318 -0
- package/vendor/virtual-fs/src/mount_fs.rs +2225 -0
- package/vendor/virtual-fs/src/null_file.rs +87 -0
- package/vendor/virtual-fs/src/ops.rs +364 -0
- package/vendor/virtual-fs/src/overlay_fs.rs +2216 -0
- package/vendor/virtual-fs/src/passthru_fs.rs +119 -0
- package/vendor/virtual-fs/src/pipe.rs +603 -0
- package/vendor/virtual-fs/src/random_file.rs +88 -0
- package/vendor/virtual-fs/src/special_file.rs +108 -0
- package/vendor/virtual-fs/src/static_file.rs +133 -0
- package/vendor/virtual-fs/src/static_fs.rs +460 -0
- package/vendor/virtual-fs/src/tmp_fs.rs +95 -0
- package/vendor/virtual-fs/src/trace_fs.rs +258 -0
- package/vendor/virtual-fs/src/webc_volume_fs.rs +829 -0
- package/vendor/virtual-fs/src/zero_file.rs +90 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { _ as GO_STANDARD_LIBRARY_SHA256, c as GO_COMPILER_SHA256, d as GO_LINKER_SHA256, f as GO_PACKAGE_ASSET_PATH, g as GO_STANDARD_LIBRARY_ASSET_PATH, h as GO_PACKAGE_SHA256, l as GO_COMPRESSED_PACKAGE_SHA256, m as GO_PACKAGE_MANIFEST_SHA256, p as GO_PACKAGE_MANIFEST_ASSET_PATH, u as GO_COMPRESSED_STANDARD_LIBRARY_SHA256, v as GO_VERSION } from "./toolchains-C6KuA1yM.js";
|
|
2
|
+
import { WASM_OJ_SCHEMAS } from "@wasm-oj/contracts";
|
|
3
|
+
//#region src/compiler/dependency-input.ts
|
|
4
|
+
var ECOSYSTEM_BY_LANGUAGE = Object.freeze({
|
|
5
|
+
c: "cpp",
|
|
6
|
+
cpp: "cpp",
|
|
7
|
+
rust: "cargo",
|
|
8
|
+
python: "pypi",
|
|
9
|
+
javascript: "npm",
|
|
10
|
+
typescript: "npm",
|
|
11
|
+
go: "go"
|
|
12
|
+
});
|
|
13
|
+
function assertProjectDependencyEcosystem(project) {
|
|
14
|
+
if (!project.dependencies) return;
|
|
15
|
+
const expected = ECOSYSTEM_BY_LANGUAGE[project.config.language];
|
|
16
|
+
if (!expected) throw new Error(`Compiler '${project.config.language}' does not declare a dependency ecosystem.`);
|
|
17
|
+
const mismatch = project.dependencies.packages.find((item) => item.package.ecosystem !== expected);
|
|
18
|
+
if (mismatch) throw new Error(`${project.config.language} projects accept only '${expected}' dependencies; '${mismatch.package.id}' is '${mismatch.package.ecosystem}'.`);
|
|
19
|
+
}
|
|
20
|
+
function projectDependencyPackages(project, ecosystem) {
|
|
21
|
+
assertProjectDependencyEcosystem(project);
|
|
22
|
+
return project.dependencies?.packages.filter((item) => item.package.ecosystem === ecosystem) ?? [];
|
|
23
|
+
}
|
|
24
|
+
function pythonDependencyFiles(project) {
|
|
25
|
+
const sourceFiles = [];
|
|
26
|
+
const artifactFiles = {};
|
|
27
|
+
for (const item of projectDependencyPackages(project, "pypi")) for (const [path, bytes] of Object.entries(item.files)) {
|
|
28
|
+
const installedPath = `site-packages/${path}`;
|
|
29
|
+
artifactFiles[installedPath] = bytes.slice();
|
|
30
|
+
if (path.endsWith(".py")) sourceFiles.push({
|
|
31
|
+
path: installedPath,
|
|
32
|
+
language: "python",
|
|
33
|
+
content: decodeDependencyText(bytes, item.package.id, path)
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
sourceFiles,
|
|
38
|
+
artifactFiles
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function npmDependencyFiles(project) {
|
|
42
|
+
const files = {};
|
|
43
|
+
const names = /* @__PURE__ */ new Set();
|
|
44
|
+
const untyped = [];
|
|
45
|
+
for (const item of projectDependencyPackages(project, "npm")) {
|
|
46
|
+
if (names.has(item.package.name)) throw new Error(`npm dependency '${item.package.name}' resolves to multiple versions in a flat runtime graph.`);
|
|
47
|
+
names.add(item.package.name);
|
|
48
|
+
const manifestBytes = item.files["package.json"];
|
|
49
|
+
if (!manifestBytes) throw new Error(`npm dependency '${item.package.id}' omits package.json.`);
|
|
50
|
+
const manifestText = decodeDependencyText(manifestBytes, item.package.id, "package.json");
|
|
51
|
+
if (JSON.parse(manifestText).type === "module") throw new Error(`npm dependency '${item.package.id}' uses unsupported ESM package semantics.`);
|
|
52
|
+
if (!Object.keys(item.files).some((path) => path.endsWith(".d.ts"))) untyped.push(item.package.name);
|
|
53
|
+
for (const [path, bytes] of Object.entries(item.files)) {
|
|
54
|
+
const installedPath = `node_modules/${item.package.name}/${path}`;
|
|
55
|
+
files[installedPath] = isNpmTextPath(path) ? decodeDependencyText(bytes, item.package.id, path) : bytes.slice();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (untyped.length > 0) files[".wasm-oj/npm-untyped-modules.d.ts"] = untyped.sort().flatMap((name) => [`declare module ${JSON.stringify(name)} { const value: any; export = value; }`, `declare module ${JSON.stringify(`${name}/*`)} { const value: any; export = value; }`]).join("\n");
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
function cppDependencyInput(project) {
|
|
62
|
+
const files = /* @__PURE__ */ new Map();
|
|
63
|
+
const includeDirectories = [];
|
|
64
|
+
const sources = [];
|
|
65
|
+
for (const [index, item] of projectDependencyPackages(project, "cpp").entries()) {
|
|
66
|
+
const root = `.wasm-oj/dependencies/cpp/${String(index).padStart(4, "0")}`;
|
|
67
|
+
includeDirectories.push(`/project/${root}`);
|
|
68
|
+
if (Object.keys(item.files).some((path) => path.startsWith("include/"))) includeDirectories.push(`/project/${root}/include`);
|
|
69
|
+
for (const [path, bytes] of Object.entries(item.files)) {
|
|
70
|
+
if (!isCppCompilerPath(path)) continue;
|
|
71
|
+
decodeDependencyText(bytes, item.package.id, path);
|
|
72
|
+
const installedPath = `${root}/${path}`;
|
|
73
|
+
files.set(installedPath, bytes.slice());
|
|
74
|
+
if (isCppSourcePath(path)) {
|
|
75
|
+
if (project.config.language === "c" && !path.endsWith(".c")) throw new Error(`C dependency '${item.package.id}' contains C++ source '${path}'.`);
|
|
76
|
+
sources.push(installedPath);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
files,
|
|
82
|
+
includeDirectories: Object.freeze(includeDirectories),
|
|
83
|
+
sources: Object.freeze(sources)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function rustDependencyInput(project) {
|
|
87
|
+
const packages = projectDependencyPackages(project, "cargo");
|
|
88
|
+
const packageById = new Map(packages.map((item) => [item.package.id, item]));
|
|
89
|
+
const ordered = topologicalPackages(packages);
|
|
90
|
+
const descriptorById = /* @__PURE__ */ new Map();
|
|
91
|
+
const files = [];
|
|
92
|
+
for (const [index, item] of ordered.entries()) {
|
|
93
|
+
const prefix = `.wasm-oj/dependencies/cargo/${String(index).padStart(4, "0")}`;
|
|
94
|
+
const manifestBytes = item.files["Cargo.toml"];
|
|
95
|
+
const manifest = decodeDependencyText(manifestBytes, item.package.id, "Cargo.toml");
|
|
96
|
+
if (/\bpackage\s*=\s*"/m.test(dependencySections(manifest))) throw new Error(`Cargo dependency '${item.package.id}' uses unsupported renamed dependencies.`);
|
|
97
|
+
const libSection = tomlSection(manifest, "lib");
|
|
98
|
+
const crateName = rustIdentifier(tomlString(libSection, "name") ?? item.package.name, item.package.id);
|
|
99
|
+
const rootRelative = tomlString(libSection, "path") ?? "src/lib.rs";
|
|
100
|
+
if (!item.files[rootRelative]) throw new Error(`Cargo dependency '${item.package.id}' omits '${rootRelative}'.`);
|
|
101
|
+
const edition = tomlString(tomlSection(manifest, "package"), "edition") ?? "2015";
|
|
102
|
+
if (!/^(?:2015|2018|2021|2024)$/.test(edition)) throw new Error(`Cargo dependency '${item.package.id}' has unsupported Rust edition '${edition}'.`);
|
|
103
|
+
const outputPath = `/work/build/deps/lib${String(index).padStart(4, "0")}_${crateName}.rlib`;
|
|
104
|
+
descriptorById.set(item.package.id, {
|
|
105
|
+
id: item.package.id,
|
|
106
|
+
crateName,
|
|
107
|
+
root: `${prefix}/${rootRelative}`,
|
|
108
|
+
edition,
|
|
109
|
+
outputPath,
|
|
110
|
+
features: Object.freeze([...item.package.features ?? []])
|
|
111
|
+
});
|
|
112
|
+
for (const [path, bytes] of Object.entries(item.files)) {
|
|
113
|
+
if (!isCargoCompilerText(path)) continue;
|
|
114
|
+
files.push({
|
|
115
|
+
path: `${prefix}/${path}`,
|
|
116
|
+
language: "rust",
|
|
117
|
+
content: decodeDependencyText(bytes, item.package.id, path)
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const crates = ordered.map((item) => {
|
|
122
|
+
const descriptor = descriptorById.get(item.package.id);
|
|
123
|
+
return Object.freeze({
|
|
124
|
+
...descriptor,
|
|
125
|
+
externs: Object.freeze(item.package.dependencies.map((id) => {
|
|
126
|
+
const dependency = descriptorById.get(id);
|
|
127
|
+
if (!dependency) throw new Error(`Cargo dependency '${item.package.id}' refers to unavailable '${id}'.`);
|
|
128
|
+
return Object.freeze({
|
|
129
|
+
crateName: dependency.crateName,
|
|
130
|
+
path: dependency.outputPath
|
|
131
|
+
});
|
|
132
|
+
}))
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
const roots = project.dependencies?.lock.roots.map((id) => {
|
|
136
|
+
if (!packageById.has(id)) throw new Error(`Cargo root '${id}' is unavailable.`);
|
|
137
|
+
const descriptor = descriptorById.get(id);
|
|
138
|
+
return Object.freeze({
|
|
139
|
+
crateName: descriptor.crateName,
|
|
140
|
+
path: descriptor.outputPath
|
|
141
|
+
});
|
|
142
|
+
}) ?? [];
|
|
143
|
+
return {
|
|
144
|
+
files,
|
|
145
|
+
crates: Object.freeze(crates),
|
|
146
|
+
roots: Object.freeze(roots)
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function goDependencyInput(project) {
|
|
150
|
+
const files = [];
|
|
151
|
+
const packages = [];
|
|
152
|
+
for (const [moduleIndex, item] of projectDependencyPackages(project, "go").entries()) {
|
|
153
|
+
const moduleRoot = `.wasm-oj/dependencies/go/${String(moduleIndex).padStart(4, "0")}`;
|
|
154
|
+
const directories = /* @__PURE__ */ new Map();
|
|
155
|
+
for (const [path, bytes] of Object.entries(item.files)) {
|
|
156
|
+
if (!path.endsWith(".go") || path.endsWith("_test.go") || path.split("/").includes("vendor")) continue;
|
|
157
|
+
const content = decodeDependencyText(bytes, item.package.id, path);
|
|
158
|
+
if (/^\s*\/\/(?:go:build|\s*\+build)\b/m.test(content)) throw new Error(`Go dependency '${item.package.id}' uses unsupported build constraints in '${path}'.`);
|
|
159
|
+
if (/import\s+(?:[._A-Za-z][A-Za-z0-9_]*\s+)?["`]C["`]/.test(content)) throw new Error(`Go dependency '${item.package.id}' uses unsupported cgo in '${path}'.`);
|
|
160
|
+
const directory = path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
|
|
161
|
+
const group = directories.get(directory) ?? [];
|
|
162
|
+
group.push({
|
|
163
|
+
path,
|
|
164
|
+
content
|
|
165
|
+
});
|
|
166
|
+
directories.set(directory, group);
|
|
167
|
+
files.push({
|
|
168
|
+
path: `${moduleRoot}/${path}`,
|
|
169
|
+
language: "go",
|
|
170
|
+
content
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
for (const [directory, sourceFiles] of [...directories].sort(([left], [right]) => left.localeCompare(right))) {
|
|
174
|
+
const packageNames = new Set(sourceFiles.map((file) => goPackageName(file.content, item.package.id, file.path)));
|
|
175
|
+
if (packageNames.size !== 1) throw new Error(`Go dependency '${item.package.id}' directory '${directory || "."}' contains multiple packages.`);
|
|
176
|
+
if ([...packageNames][0] === "main") continue;
|
|
177
|
+
const importPath = directory ? `${item.package.name}/${directory}` : item.package.name;
|
|
178
|
+
const index = packages.length;
|
|
179
|
+
packages.push(Object.freeze({
|
|
180
|
+
id: `${item.package.id}:${directory || "."}`,
|
|
181
|
+
importPath,
|
|
182
|
+
sourcePaths: Object.freeze(sourceFiles.map((file) => `${moduleRoot}/${file.path}`).sort()),
|
|
183
|
+
imports: Object.freeze([...new Set(sourceFiles.flatMap((file) => goImports(file.content)))].sort()),
|
|
184
|
+
archivePath: `/work/build/deps/${String(index).padStart(4, "0")}.a`
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
files,
|
|
190
|
+
packages: Object.freeze(packages)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function decodeDependencyText(bytes, id, path) {
|
|
194
|
+
try {
|
|
195
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
throw new Error(`Dependency '${id}' compiler file '${path}' is not valid UTF-8.`, { cause: error });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function isNpmTextPath(path) {
|
|
201
|
+
return /(?:^|\/)(?:package\.json)$/.test(path) || /\.(?:js|cjs|d\.ts|json)$/i.test(path);
|
|
202
|
+
}
|
|
203
|
+
function isCppCompilerPath(path) {
|
|
204
|
+
return /\.(?:h|hh|hpp|hxx|inc|c|cc|cpp|cxx)$/i.test(path);
|
|
205
|
+
}
|
|
206
|
+
function isCppSourcePath(path) {
|
|
207
|
+
return /\.(?:c|cc|cpp|cxx)$/i.test(path);
|
|
208
|
+
}
|
|
209
|
+
function topologicalPackages(packages) {
|
|
210
|
+
const byId = new Map(packages.map((item) => [item.package.id, item]));
|
|
211
|
+
const state = /* @__PURE__ */ new Map();
|
|
212
|
+
const ordered = [];
|
|
213
|
+
const visit = (id) => {
|
|
214
|
+
const current = state.get(id);
|
|
215
|
+
if (current === "visited") return;
|
|
216
|
+
if (current === "visiting") throw new Error(`Dependency graph contains a cycle at '${id}'.`);
|
|
217
|
+
const item = byId.get(id);
|
|
218
|
+
if (!item) throw new Error(`Dependency graph refers to unavailable package '${id}'.`);
|
|
219
|
+
state.set(id, "visiting");
|
|
220
|
+
for (const dependency of item.package.dependencies) visit(dependency);
|
|
221
|
+
state.set(id, "visited");
|
|
222
|
+
ordered.push(item);
|
|
223
|
+
};
|
|
224
|
+
for (const item of packages) visit(item.package.id);
|
|
225
|
+
return ordered;
|
|
226
|
+
}
|
|
227
|
+
function tomlSection(manifest, name) {
|
|
228
|
+
return manifest.match(new RegExp(`(?:^|\\n)\\[${name.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&")}\\]\\s*\\n([\\s\\S]*?)(?=\\n\\[|$)`))?.[1] ?? "";
|
|
229
|
+
}
|
|
230
|
+
function tomlString(section, key) {
|
|
231
|
+
return section.match(new RegExp(`^\\s*${key}\\s*=\\s*"([^"]+)"\\s*(?:#.*)?$`, "m"))?.[1];
|
|
232
|
+
}
|
|
233
|
+
function dependencySections(manifest) {
|
|
234
|
+
return manifest.split(/\n(?=\[)/).filter((section) => /\bdependencies\]/.test(section.split("\n", 1)[0])).join("\n");
|
|
235
|
+
}
|
|
236
|
+
function rustIdentifier(name, id) {
|
|
237
|
+
const normalized = name.replaceAll("-", "_");
|
|
238
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(normalized)) throw new Error(`Cargo dependency '${id}' has unsupported crate name '${name}'.`);
|
|
239
|
+
return normalized;
|
|
240
|
+
}
|
|
241
|
+
function isCargoCompilerText(path) {
|
|
242
|
+
return path.endsWith(".rs") || path.endsWith(".md") || path.endsWith(".txt") || path === "Cargo.toml";
|
|
243
|
+
}
|
|
244
|
+
function goPackageName(source, id, path) {
|
|
245
|
+
const match = source.match(/^\s*package\s+([A-Za-z_][A-Za-z0-9_]*)\b/m);
|
|
246
|
+
if (!match) throw new Error(`Go dependency '${id}' source '${path}' has no package declaration.`);
|
|
247
|
+
return match[1];
|
|
248
|
+
}
|
|
249
|
+
function goImports(source) {
|
|
250
|
+
const imports = [];
|
|
251
|
+
const blockPattern = /\bimport\s*\(([\s\S]*?)\)/g;
|
|
252
|
+
for (const block of source.matchAll(blockPattern)) for (const match of block[1].matchAll(/(?:^|\n)\s*(?:[._A-Za-z][A-Za-z0-9_]*\s+)?["`]([^"`]+)["`]/g)) imports.push(match[1]);
|
|
253
|
+
const withoutBlocks = source.replace(blockPattern, "");
|
|
254
|
+
for (const match of withoutBlocks.matchAll(/\bimport\s+(?:[._A-Za-z][A-Za-z0-9_]*\s+)?["`]([^"`]+)["`]/g)) imports.push(match[1]);
|
|
255
|
+
return imports;
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/compiler/go-toolchain.ts
|
|
259
|
+
var GO_LANGUAGE_VERSION = `go${GO_VERSION.split(".").slice(0, 2).join(".")}`;
|
|
260
|
+
var GO_COMPILE_TIMEOUT_MS = 18e4;
|
|
261
|
+
var GO_ARCHIVE_PATH = "/work/build/main.a";
|
|
262
|
+
var GO_OUTPUT_PATH = "/work/build/app.wasm";
|
|
263
|
+
var GO_TOOLCHAIN = Object.freeze({
|
|
264
|
+
version: GO_VERSION,
|
|
265
|
+
target: "wasip1/wasm",
|
|
266
|
+
packageAsset: GO_PACKAGE_ASSET_PATH,
|
|
267
|
+
packageCompressedSha256: GO_COMPRESSED_PACKAGE_SHA256,
|
|
268
|
+
packageSha256: GO_PACKAGE_SHA256,
|
|
269
|
+
manifestAsset: GO_PACKAGE_MANIFEST_ASSET_PATH,
|
|
270
|
+
manifestSha256: GO_PACKAGE_MANIFEST_SHA256,
|
|
271
|
+
standardLibraryAsset: GO_STANDARD_LIBRARY_ASSET_PATH,
|
|
272
|
+
standardLibraryCompressedSha256: GO_COMPRESSED_STANDARD_LIBRARY_SHA256,
|
|
273
|
+
standardLibrarySha256: GO_STANDARD_LIBRARY_SHA256,
|
|
274
|
+
compilerSha256: GO_COMPILER_SHA256,
|
|
275
|
+
linkerSha256: GO_LINKER_SHA256
|
|
276
|
+
});
|
|
277
|
+
function decodeGoToolchainManifest(bytes) {
|
|
278
|
+
const manifest = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
279
|
+
const compiler = asRecord(manifest.compiler, "compiler");
|
|
280
|
+
const linker = asRecord(manifest.linker, "linker");
|
|
281
|
+
const output = asRecord(manifest.output, "output");
|
|
282
|
+
const standardLibrary = asRecord(manifest.standardLibrary, "standardLibrary");
|
|
283
|
+
if (manifest.schema !== WASM_OJ_SCHEMAS.goToolchain || manifest.version !== GO_TOOLCHAIN.version || manifest.target !== GO_TOOLCHAIN.target || compiler.command !== "go-compile" || compiler.sha256 !== GO_TOOLCHAIN.compilerSha256 || linker.command !== "go-link" || linker.sha256 !== GO_TOOLCHAIN.linkerSha256 || JSON.stringify(manifest.deterministicReplacements) !== JSON.stringify([
|
|
284
|
+
"wasi_snapshot_preview1.random_get",
|
|
285
|
+
"wasi_snapshot_preview1.clock_time_get",
|
|
286
|
+
"wasi_snapshot_preview1.sock_accept",
|
|
287
|
+
"wasi_snapshot_preview1.sock_shutdown"
|
|
288
|
+
]) || manifest.filesystemMount !== null || output.sha256 !== GO_TOOLCHAIN.packageSha256 || output.compressedSha256 !== GO_TOOLCHAIN.packageCompressedSha256 || standardLibrary.sha256 !== GO_TOOLCHAIN.standardLibrarySha256 || standardLibrary.compressedSha256 !== GO_TOOLCHAIN.standardLibraryCompressedSha256 || standardLibrary.format !== "WOJGO002") throw new Error("Pinned Go toolchain manifest does not match the compiler contract.");
|
|
289
|
+
if (!Array.isArray(manifest.packages) || manifest.packages.length < 200) throw new Error("Pinned Go toolchain manifest has an incomplete standard library.");
|
|
290
|
+
let previous = "";
|
|
291
|
+
const packages = manifest.packages.map((value) => {
|
|
292
|
+
const item = asRecord(value, "packages[]");
|
|
293
|
+
if (typeof item.importPath !== "string" || item.importPath <= previous || typeof item.archivePath !== "string" || item.archivePath !== `/go/pkg/${item.importPath}.a` || typeof item.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)) throw new Error("Pinned Go toolchain manifest contains a non-canonical package entry.");
|
|
294
|
+
previous = item.importPath;
|
|
295
|
+
return Object.freeze({
|
|
296
|
+
importPath: item.importPath,
|
|
297
|
+
archivePath: item.archivePath,
|
|
298
|
+
sha256: item.sha256
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
return Object.freeze({ packages: Object.freeze(packages) });
|
|
302
|
+
}
|
|
303
|
+
function validateGoStandardLibrary(bytes, packages) {
|
|
304
|
+
goStandardLibraryLayout(bytes, packages);
|
|
305
|
+
}
|
|
306
|
+
function goStandardLibraryLayout(bytes, packages) {
|
|
307
|
+
if (bytes.byteLength < 12 || new TextDecoder().decode(bytes.subarray(0, 8)) !== "WOJGO002") throw new Error("Pinned Go standard library has an invalid format header.");
|
|
308
|
+
const dataOffset = 12 + new DataView(bytes.buffer, bytes.byteOffset + 8, 4).getUint32(0, true);
|
|
309
|
+
if (dataOffset > bytes.byteLength) throw new Error("Pinned Go standard-library index exceeds its archive.");
|
|
310
|
+
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(12, dataOffset)));
|
|
311
|
+
if (!Array.isArray(parsed) || parsed.length !== packages.length) throw new Error("Pinned Go standard-library index does not match the manifest.");
|
|
312
|
+
const entries = [];
|
|
313
|
+
let expectedOffset = 0;
|
|
314
|
+
for (let index = 0; index < packages.length; index += 1) {
|
|
315
|
+
const entry = asRecord(parsed[index], "standardLibrary[]");
|
|
316
|
+
const declared = packages[index];
|
|
317
|
+
if (entry.importPath !== declared.importPath || entry.archivePath !== declared.archivePath || entry.sha256 !== declared.sha256 || !Number.isSafeInteger(entry.offset) || entry.offset !== expectedOffset || !Number.isSafeInteger(entry.length) || entry.length <= 8 || dataOffset + entry.offset + entry.length > bytes.byteLength) throw new Error("Pinned Go standard-library index contains a non-canonical archive entry.");
|
|
318
|
+
entries.push(entry);
|
|
319
|
+
expectedOffset += entry.length;
|
|
320
|
+
}
|
|
321
|
+
if (dataOffset + expectedOffset !== bytes.byteLength) throw new Error("Pinned Go standard library contains trailing or missing archive bytes.");
|
|
322
|
+
return {
|
|
323
|
+
dataOffset,
|
|
324
|
+
entries: Object.freeze(entries)
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function goImportConfig(packages, includeMain) {
|
|
328
|
+
const lines = packages.map((item) => `packagefile ${item.importPath}=${item.archivePath}`);
|
|
329
|
+
if (includeMain) lines.push(`packagefile command-line-arguments=${GO_ARCHIVE_PATH}`);
|
|
330
|
+
return `${lines.join("\n")}\n`;
|
|
331
|
+
}
|
|
332
|
+
function reachableGoDependencies(projectFiles, dependencies, standardLibrary) {
|
|
333
|
+
const byImport = new Map(dependencies.map((item) => [item.importPath, item]));
|
|
334
|
+
const standard = new Set(standardLibrary.map((item) => item.importPath));
|
|
335
|
+
const state = /* @__PURE__ */ new Map();
|
|
336
|
+
const ordered = [];
|
|
337
|
+
const visitImport = (importPath, importer) => {
|
|
338
|
+
if (standard.has(importPath)) return;
|
|
339
|
+
const dependency = byImport.get(importPath);
|
|
340
|
+
if (!dependency) throw new Error(`Go package '${importer}' imports unlocked package '${importPath}'.`);
|
|
341
|
+
const current = state.get(importPath);
|
|
342
|
+
if (current === "visited") return;
|
|
343
|
+
if (current === "visiting") throw new Error(`Go dependency import cycle contains '${importPath}'.`);
|
|
344
|
+
state.set(importPath, "visiting");
|
|
345
|
+
for (const nested of dependency.imports) visitImport(nested, importPath);
|
|
346
|
+
state.set(importPath, "visited");
|
|
347
|
+
ordered.push(dependency);
|
|
348
|
+
};
|
|
349
|
+
for (const source of projectFiles.filter((file) => file.path.endsWith(".go"))) for (const importPath of goImports(source.content)) visitImport(importPath, "main");
|
|
350
|
+
return ordered;
|
|
351
|
+
}
|
|
352
|
+
function goCompileDependencyArguments(dependency, optimization) {
|
|
353
|
+
return [
|
|
354
|
+
"-o",
|
|
355
|
+
dependency.archivePath,
|
|
356
|
+
"-p",
|
|
357
|
+
dependency.importPath,
|
|
358
|
+
"-lang",
|
|
359
|
+
GO_LANGUAGE_VERSION,
|
|
360
|
+
"-complete",
|
|
361
|
+
`-buildid=wasm_oj_dependency_${dependency.importPath}`,
|
|
362
|
+
"-c=1",
|
|
363
|
+
"-dwarf=false",
|
|
364
|
+
"-trimpath",
|
|
365
|
+
"/work=.",
|
|
366
|
+
"-importcfg",
|
|
367
|
+
"/work/importcfg",
|
|
368
|
+
"-pack",
|
|
369
|
+
...optimization === "debug" ? ["-N", "-l"] : [],
|
|
370
|
+
...dependency.sourcePaths.map((path) => `/work/${path}`)
|
|
371
|
+
];
|
|
372
|
+
}
|
|
373
|
+
function goCompileArguments(files, optimization) {
|
|
374
|
+
const sources = files.filter((file) => file.path.endsWith(".go")).map((file) => `/work/${file.path}`).sort();
|
|
375
|
+
if (sources.length === 0) throw new Error("A Go project must contain at least one .go source file.");
|
|
376
|
+
return [
|
|
377
|
+
"-o",
|
|
378
|
+
GO_ARCHIVE_PATH,
|
|
379
|
+
"-p",
|
|
380
|
+
"main",
|
|
381
|
+
"-lang",
|
|
382
|
+
GO_LANGUAGE_VERSION,
|
|
383
|
+
"-complete",
|
|
384
|
+
"-buildid=wasm_oj_submission",
|
|
385
|
+
"-c=1",
|
|
386
|
+
"-dwarf=false",
|
|
387
|
+
"-trimpath",
|
|
388
|
+
"/work=.",
|
|
389
|
+
"-importcfg",
|
|
390
|
+
"/work/importcfg",
|
|
391
|
+
"-pack",
|
|
392
|
+
...optimization === "debug" ? ["-N", "-l"] : [],
|
|
393
|
+
...sources
|
|
394
|
+
];
|
|
395
|
+
}
|
|
396
|
+
function goLinkArguments(optimization) {
|
|
397
|
+
return [
|
|
398
|
+
"-o",
|
|
399
|
+
GO_OUTPUT_PATH,
|
|
400
|
+
"-importcfg",
|
|
401
|
+
"/work/importcfg.link",
|
|
402
|
+
"-buildmode=exe",
|
|
403
|
+
"-buildid=",
|
|
404
|
+
...optimization === "release" ? ["-s", "-w"] : [],
|
|
405
|
+
GO_ARCHIVE_PATH
|
|
406
|
+
];
|
|
407
|
+
}
|
|
408
|
+
function deterministicGoCompilerEnvironment() {
|
|
409
|
+
return {
|
|
410
|
+
GOOS: "wasip1",
|
|
411
|
+
GOARCH: "wasm",
|
|
412
|
+
GOROOT: "/go",
|
|
413
|
+
GOENV: "off",
|
|
414
|
+
GOTOOLCHAIN: "local",
|
|
415
|
+
PWD: "/work",
|
|
416
|
+
SOURCE_DATE_EPOCH: "946684800",
|
|
417
|
+
TZ: "UTC",
|
|
418
|
+
LC_ALL: "C"
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function asRecord(value, label) {
|
|
422
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`Pinned Go toolchain manifest '${label}' field must be an object.`);
|
|
423
|
+
return value;
|
|
424
|
+
}
|
|
425
|
+
//#endregion
|
|
426
|
+
export { pythonDependencyFiles as _, decodeGoToolchainManifest as a, goCompileDependencyArguments as c, reachableGoDependencies as d, validateGoStandardLibrary as f, npmDependencyFiles as g, goDependencyInput as h, GO_TOOLCHAIN as i, goImportConfig as l, cppDependencyInput as m, GO_COMPILE_TIMEOUT_MS as n, deterministicGoCompilerEnvironment as o, assertProjectDependencyEcosystem as p, GO_OUTPUT_PATH as r, goCompileArguments as s, GO_ARCHIVE_PATH as t, goLinkArguments as u, rustDependencyInput as v };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { C as JAVA_COMPILE_CLASSLIB_ASSET_PATH, D as JAVA_VERSION, E as JAVA_RUNTIME_CLASSLIB_SHA256, S as JAVA_COMPILER_PACKAGE_SHA256, T as JAVA_RUNTIME_CLASSLIB_ASSET_PATH, b as JAVA_COMPILER_COMPRESSED_PACKAGE_SHA256, w as JAVA_COMPILE_CLASSLIB_SHA256, x as JAVA_COMPILER_PACKAGE, y as JAVA_COMPILER_ASSET_PATH } from "./toolchains-C6KuA1yM.js";
|
|
2
|
+
//#region src/compiler/java-toolchain.ts
|
|
3
|
+
var JAVA_COMPILE_TIMEOUT_MS = 18e4;
|
|
4
|
+
Object.freeze({
|
|
5
|
+
version: JAVA_VERSION,
|
|
6
|
+
package: JAVA_COMPILER_PACKAGE,
|
|
7
|
+
compilerAsset: JAVA_COMPILER_ASSET_PATH,
|
|
8
|
+
compilerCompressedSha256: JAVA_COMPILER_COMPRESSED_PACKAGE_SHA256,
|
|
9
|
+
compilerPackageSha256: JAVA_COMPILER_PACKAGE_SHA256,
|
|
10
|
+
compileClasslibAsset: JAVA_COMPILE_CLASSLIB_ASSET_PATH,
|
|
11
|
+
compileClasslibSha256: JAVA_COMPILE_CLASSLIB_SHA256,
|
|
12
|
+
runtimeClasslibAsset: JAVA_RUNTIME_CLASSLIB_ASSET_PATH,
|
|
13
|
+
runtimeClasslibSha256: JAVA_RUNTIME_CLASSLIB_SHA256
|
|
14
|
+
});
|
|
15
|
+
function javaMainClass(entry, source) {
|
|
16
|
+
const className = entry.split("/").at(-1)?.replace(/\.java$/u, "") ?? "";
|
|
17
|
+
if (!/^[A-Za-z_$][\w$]*$/u.test(className)) throw new Error(`Java entry '${entry}' must name a valid .java class file.`);
|
|
18
|
+
const packageName = source.match(/^\s*package\s+([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*;/m)?.[1];
|
|
19
|
+
return packageName ? `${packageName}.${className}` : className;
|
|
20
|
+
}
|
|
21
|
+
function parseJavaDiagnostics(output, fallbackFile) {
|
|
22
|
+
const diagnostics = [];
|
|
23
|
+
const pattern = /^(.*?\.java):(\d+)(?::(\d+))?:\s*(?:(error|warning):\s*)?(.+)$/gim;
|
|
24
|
+
let match;
|
|
25
|
+
while ((match = pattern.exec(output)) !== null) diagnostics.push({
|
|
26
|
+
severity: match[4]?.toLowerCase() === "warning" ? "warning" : "error",
|
|
27
|
+
message: match[5],
|
|
28
|
+
file: match[1].replace(/^\/?(?:project|workspace)\//u, ""),
|
|
29
|
+
line: Number(match[2]),
|
|
30
|
+
column: Number(match[3] ?? 1),
|
|
31
|
+
source: "java"
|
|
32
|
+
});
|
|
33
|
+
if (diagnostics.length === 0 && /(?:error|exception|failed)/iu.test(output)) diagnostics.push({
|
|
34
|
+
severity: "error",
|
|
35
|
+
message: output.trim().split(/\r?\n/u).filter(Boolean).at(-1) ?? "Java compilation failed.",
|
|
36
|
+
file: fallbackFile,
|
|
37
|
+
line: 1,
|
|
38
|
+
column: 1,
|
|
39
|
+
source: "java"
|
|
40
|
+
});
|
|
41
|
+
return diagnostics;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { javaMainClass as n, parseJavaDiagnostics as r, JAVA_COMPILE_TIMEOUT_MS as t };
|