diff --git a/cli/compilers/mod.rs b/cli/compilers/mod.rs index f773e2de6c..bc3bfade2b 100644 --- a/cli/compilers/mod.rs +++ b/cli/compilers/mod.rs @@ -6,14 +6,12 @@ use futures::Future; mod compiler_worker; mod js; mod ts; -mod wasm; pub use js::JsCompiler; pub use ts::runtime_compile; pub use ts::runtime_transpile; pub use ts::TargetLib; pub use ts::TsCompiler; -pub use wasm::WasmCompiler; pub type CompilationResultFuture = dyn Future; diff --git a/cli/compilers/ts.rs b/cli/compilers/ts.rs index db43139277..832d5e6df6 100644 --- a/cli/compilers/ts.rs +++ b/cli/compilers/ts.rs @@ -691,8 +691,6 @@ impl TsCompiler { } } -// TODO(bartlomieju): exactly same function is in `wasm.rs` - only difference -// it created WasmCompiler instead of TsCompiler - deduplicate async fn execute_in_thread( global_state: GlobalState, req: Buf, diff --git a/cli/compilers/wasm.rs b/cli/compilers/wasm.rs deleted file mode 100644 index ed56035843..0000000000 --- a/cli/compilers/wasm.rs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use super::compiler_worker::CompilerWorker; -use crate::compilers::CompiledModule; -use crate::file_fetcher::SourceFile; -use crate::global_state::GlobalState; -use crate::startup_data; -use crate::state::*; -use crate::tokio_util; -use crate::web_worker::WebWorkerHandle; -use crate::worker::WorkerEvent; -use deno_core::Buf; -use deno_core::ErrBox; -use deno_core::ModuleSpecifier; -use serde_derive::Deserialize; -use std::collections::HashMap; -use std::sync::atomic::Ordering; -use std::sync::{Arc, Mutex}; -use url::Url; - -// TODO(ry) The entire concept of spawning a thread, sending data to JS, -// compiling WASM there, and moving the data back into the calling thread is -// completelly wrong. V8 has native facilities for getting this information. -// We might be lacking bindings for this currently in rusty_v8 but ultimately -// this "compiler" should be calling into rusty_v8 directly, not spawning -// threads. - -// TODO(kevinkassimo): This is a hack to encode/decode data as base64 string. -// (Since Deno namespace might not be available, Deno.read can fail). -// Binary data is already available through source_file.source_code. -// If this is proven too wasteful in practice, refactor this. - -// Ref: https://webassembly.github.io/esm-integration/js-api/index.html#esm-integration -// https://github.com/nodejs/node/blob/35ec01097b2a397ad0a22aac536fe07514876e21/lib/internal/modules/esm/translators.js#L190-L210 - -// Dynamically construct JS wrapper with custom static imports and named exports. -// Boots up an internal worker to resolve imports/exports through query from V8. - -static WASM_WRAP: &str = include_str!("./wasm_wrap.js"); - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct WasmModuleInfo { - import_list: Vec, - export_list: Vec, -} - -#[derive(Default)] -pub struct WasmCompiler { - cache: Arc>>, -} - -impl WasmCompiler { - /// Create a new V8 worker with snapshot of WASM compiler and setup compiler's runtime. - fn setup_worker(global_state: GlobalState) -> CompilerWorker { - let entry_point = - ModuleSpecifier::resolve_url_or_path("./__$deno$wasm_compiler.ts") - .unwrap(); - let worker_state = - State::new(global_state.clone(), None, entry_point, DebugType::Internal) - .expect("Unable to create worker state"); - - // Count how many times we start the compiler worker. - global_state.compiler_starts.fetch_add(1, Ordering::SeqCst); - - let mut worker = CompilerWorker::new( - "WASM".to_string(), - startup_data::compiler_isolate_init(), - worker_state, - ); - worker.execute("bootstrap.wasmCompilerRuntime()").unwrap(); - worker - } - - pub async fn compile( - &self, - global_state: GlobalState, - source_file: &SourceFile, - ) -> Result { - let cache = self.cache.clone(); - let cache_ = self.cache.clone(); - let source_file = source_file.clone(); - - let maybe_cached = { cache.lock().unwrap().get(&source_file.url).cloned() }; - if let Some(m) = maybe_cached { - return Ok(m); - } - debug!(">>>>> wasm_compile START"); - let base64_data = base64::encode(&source_file.source_code); - let url = source_file.url.clone(); - let req_msg = serde_json::to_string(&base64_data) - .unwrap() - .into_boxed_str() - .into_boxed_bytes(); - let msg = execute_in_thread(global_state.clone(), req_msg).await?; - debug!("Received message from worker"); - let module_info: WasmModuleInfo = serde_json::from_slice(&msg).unwrap(); - debug!("WASM module info: {:#?}", &module_info); - let code = wrap_wasm_code( - &base64_data, - &module_info.import_list, - &module_info.export_list, - ); - debug!("Generated code: {}", &code); - let module = CompiledModule { - code, - name: url.to_string(), - }; - { - cache_.lock().unwrap().insert(url.clone(), module.clone()); - } - debug!("<<<<< wasm_compile END"); - Ok(module) - } -} - -async fn execute_in_thread( - global_state: GlobalState, - req: Buf, -) -> Result { - let (handle_sender, handle_receiver) = - std::sync::mpsc::sync_channel::>(1); - let builder = - std::thread::Builder::new().name("deno-wasm-compiler".to_string()); - let join_handle = builder.spawn(move || { - let worker = WasmCompiler::setup_worker(global_state); - handle_sender.send(Ok(worker.thread_safe_handle())).unwrap(); - drop(handle_sender); - tokio_util::run_basic(worker).expect("Panic in event loop"); - })?; - let handle = handle_receiver.recv().unwrap()?; - handle.post_message(req)?; - let event = handle.get_event().await.expect("Compiler didn't respond"); - let buf = match event { - WorkerEvent::Message(buf) => Ok(buf), - WorkerEvent::Error(error) => Err(error), - WorkerEvent::TerminalError(error) => Err(error), - }?; - // Shutdown worker and wait for thread to finish - handle.terminate(); - join_handle.join().unwrap(); - Ok(buf) -} - -fn build_single_import(index: usize, origin: &str) -> String { - let origin_json = serde_json::to_string(origin).unwrap(); - format!( - r#"import * as m{} from {}; -importObject[{}] = m{}; -"#, - index, &origin_json, &origin_json, index - ) -} - -fn build_imports(imports: &[String]) -> String { - let mut code = String::from(""); - for (index, origin) in imports.iter().enumerate() { - code.push_str(&build_single_import(index, origin)); - } - code -} - -fn build_single_export(name: &str) -> String { - format!("export const {} = instance.exports.{};\n", name, name) -} - -fn build_exports(exports: &[String]) -> String { - let mut code = String::from(""); - for e in exports { - code.push_str(&build_single_export(e)); - } - code -} - -fn wrap_wasm_code( - base64_data: &str, - imports: &[String], - exports: &[String], -) -> String { - let imports_code = build_imports(imports); - let exports_code = build_exports(exports); - String::from(WASM_WRAP) - .replace("//IMPORTS\n", &imports_code) - .replace("//EXPORTS\n", &exports_code) - .replace("BASE64_DATA", base64_data) -} diff --git a/cli/compilers/wasm_wrap.js b/cli/compilers/wasm_wrap.js deleted file mode 100644 index 98892b8e0e..0000000000 --- a/cli/compilers/wasm_wrap.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-nocheck -const importObject = Object.create(null); -//IMPORTS - -function base64ToUint8Array(data) { - const binString = window.atob(data); - const size = binString.length; - const bytes = new Uint8Array(size); - for (let i = 0; i < size; i++) { - bytes[i] = binString.charCodeAt(i); - } - return bytes; -} - -const buffer = base64ToUint8Array("BASE64_DATA"); -const compiled = await WebAssembly.compile(buffer); - -const instance = new WebAssembly.Instance(compiled, importObject); - -//EXPORTS diff --git a/cli/global_state.rs b/cli/global_state.rs index dbea5f827b..4602033649 100644 --- a/cli/global_state.rs +++ b/cli/global_state.rs @@ -3,7 +3,6 @@ use crate::compilers::CompiledModule; use crate::compilers::JsCompiler; use crate::compilers::TargetLib; use crate::compilers::TsCompiler; -use crate::compilers::WasmCompiler; use crate::deno_dir; use crate::file_fetcher::SourceFileFetcher; use crate::flags; @@ -36,7 +35,6 @@ pub struct GlobalStateInner { pub file_fetcher: SourceFileFetcher, pub js_compiler: JsCompiler, pub ts_compiler: TsCompiler, - pub wasm_compiler: WasmCompiler, pub lockfile: Option>, pub compiler_starts: AtomicUsize, compile_lock: AsyncMutex<()>, @@ -87,7 +85,6 @@ impl GlobalState { file_fetcher, ts_compiler, js_compiler: JsCompiler {}, - wasm_compiler: WasmCompiler::default(), lockfile, compiler_starts: AtomicUsize::new(0), compile_lock: AsyncMutex::new(()), @@ -116,12 +113,6 @@ impl GlobalState { let compile_lock = self.compile_lock.lock().await; let compiled_module = match out.media_type { - msg::MediaType::Json | msg::MediaType::Unknown => { - state1.js_compiler.compile(out).await - } - msg::MediaType::Wasm => { - state1.wasm_compiler.compile(state1.clone(), &out).await - } msg::MediaType::TypeScript | msg::MediaType::TSX | msg::MediaType::JSX => { @@ -152,6 +143,7 @@ impl GlobalState { state1.js_compiler.compile(out).await } } + _ => state1.js_compiler.compile(out).await, }?; drop(compile_lock); diff --git a/cli/js.rs b/cli/js.rs index 2985d2568a..2b499987f0 100644 --- a/cli/js.rs +++ b/cli/js.rs @@ -50,7 +50,7 @@ fn compiler_snapshot() { deno_core::js_check(isolate.execute( "", r#" - if (!(bootstrap.tsCompilerRuntime && bootstrap.wasmCompilerRuntime)) { + if (!(bootstrap.tsCompilerRuntime)) { throw Error("bad"); } console.log(`ts version: ${ts.version}`); diff --git a/cli/js/compiler.ts b/cli/js/compiler.ts index 0c1f8dcc97..146529edd1 100644 --- a/cli/js/compiler.ts +++ b/cli/js/compiler.ts @@ -4,10 +4,9 @@ // This module is the entry point for "compiler" isolate, ie. the one // that is created when Deno needs to compile TS/WASM to JS. // -// It provides a two functions that should be called by Rust: +// It provides a single functions that should be called by Rust: // - `bootstrapTsCompilerRuntime` -// - `bootstrapWasmCompilerRuntime` -// Either of these functions must be called when creating isolate +// This functions must be called when creating isolate // to properly setup runtime. // NOTE: this import has side effects! @@ -22,7 +21,6 @@ import { sendAsync, sendSync } from "./ops/dispatch_json.ts"; import { bootstrapWorkerRuntime } from "./runtime_worker.ts"; import { assert, log } from "./util.ts"; import * as util from "./util.ts"; -import { atob } from "./web/text_encoding.ts"; import { TextDecoder, TextEncoder } from "./web/text_encoding.ts"; import { core } from "./core.ts"; @@ -1123,16 +1121,6 @@ function commonPath(paths: string[], sep = "/"): string { return prefix.endsWith(sep) ? prefix : `${prefix}${sep}`; } -function base64ToUint8Array(data: string): Uint8Array { - const binString = atob(data); - const size = binString.length; - const bytes = new Uint8Array(size); - for (let i = 0; i < size; i++) { - bytes[i] = binString.charCodeAt(i); - } - return bytes; -} - let rootExports: string[] | undefined; function normalizeUrl(rootName: string): string { @@ -1585,43 +1573,11 @@ async function tsCompilerOnMessage({ // Currently Rust shuts down worker after single request } -async function wasmCompilerOnMessage({ - data: binary, -}: { - data: string; -}): Promise { - const buffer = base64ToUint8Array(binary); - // @ts-ignore - const compiled = await WebAssembly.compile(buffer); - - util.log(">>> WASM compile start"); - - const importList = Array.from( - // @ts-ignore - new Set(WebAssembly.Module.imports(compiled).map(({ module }) => module)) - ); - const exportList = Array.from( - // @ts-ignore - new Set(WebAssembly.Module.exports(compiled).map(({ name }) => name)) - ); - - globalThis.postMessage({ importList, exportList }); - - util.log("<<< WASM compile end"); - - // Currently Rust shuts down worker after single request -} - function bootstrapTsCompilerRuntime(): void { bootstrapWorkerRuntime("TS", false); globalThis.onmessage = tsCompilerOnMessage; } -function bootstrapWasmCompilerRuntime(): void { - bootstrapWorkerRuntime("WASM", false); - globalThis.onmessage = wasmCompilerOnMessage; -} - // Removes the `__proto__` for security reasons. This intentionally makes // Deno non compliant with ECMA-262 Annex B.2.2.1 // @@ -1632,7 +1588,6 @@ Object.defineProperties(globalThis, { bootstrap: { value: { ...globalThis.bootstrap, - wasmCompilerRuntime: bootstrapWasmCompilerRuntime, tsCompilerRuntime: bootstrapTsCompilerRuntime, }, configurable: true, diff --git a/cli/js/globals.ts b/cli/js/globals.ts index 89f6075a3b..5a04ec4434 100644 --- a/cli/js/globals.ts +++ b/cli/js/globals.ts @@ -147,7 +147,6 @@ declare global { workerRuntime: ((name: string) => Promise | void) | undefined; // Assigned to `self` global - compiler tsCompilerRuntime: (() => void) | undefined; - wasmCompilerRuntime: (() => void) | undefined; }; var onerror: diff --git a/cli/ops/compiler.rs b/cli/ops/compiler.rs index d93a0edf40..83b6d944c8 100644 --- a/cli/ops/compiler.rs +++ b/cli/ops/compiler.rs @@ -3,7 +3,6 @@ use super::dispatch_json::Deserialize; use super::dispatch_json::JsonOp; use super::dispatch_json::Value; use crate::futures::future::try_join_all; -use crate::msg; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; @@ -125,21 +124,7 @@ fn op_fetch_source_files( } _ => f, }; - // Special handling of WASM and JSON files: - // compile them into JS first! - // This allows TS to do correct export types as well as bundles. - let source_code = match file.media_type { - msg::MediaType::Wasm => { - global_state - .wasm_compiler - .compile(global_state.clone(), &file) - .await - .map_err(|e| OpError::other(e.to_string()))? - .code - } - _ => String::from_utf8(file.source_code) - .map_err(|_| OpError::invalid_utf8())?, - }; + let source_code = String::from_utf8(file.source_code).map_err(|_| OpError::invalid_utf8())?; Ok::<_, OpError>(json!({ "url": file.url.to_string(), "filename": file.filename.to_str().unwrap(), diff --git a/cli/tests/051_wasm_import.ts b/cli/tests/051_wasm_import.ts deleted file mode 100644 index 7000657c3b..0000000000 --- a/cli/tests/051_wasm_import.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { add, addImported, addRemote } from "./051_wasm_import/simple.wasm"; -import { state } from "./051_wasm_import/wasm-dep.js"; - -function assertEquals(actual: unknown, expected: unknown, msg?: string): void { - if (actual !== expected) { - throw new Error(msg); - } -} - -assertEquals(state, "WASM Start Executed", "Incorrect state"); - -assertEquals(add(10, 20), 30, "Incorrect add"); - -assertEquals(addImported(0), 42, "Incorrect addImported"); - -assertEquals(state, "WASM JS Function Executed", "Incorrect state"); - -assertEquals(addImported(1), 43, "Incorrect addImported"); - -assertEquals(addRemote(1), 2020, "Incorrect addRemote"); - -console.log("Passed"); diff --git a/cli/tests/051_wasm_import.ts.out b/cli/tests/051_wasm_import.ts.out deleted file mode 100644 index 863339fb8c..0000000000 --- a/cli/tests/051_wasm_import.ts.out +++ /dev/null @@ -1 +0,0 @@ -Passed diff --git a/cli/tests/051_wasm_import/remote.ts b/cli/tests/051_wasm_import/remote.ts deleted file mode 100644 index 761a5248e2..0000000000 --- a/cli/tests/051_wasm_import/remote.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function jsRemoteFn(): number { - return 2019; -} diff --git a/cli/tests/051_wasm_import/simple.wasm b/cli/tests/051_wasm_import/simple.wasm deleted file mode 100644 index 8e544fe305..0000000000 Binary files a/cli/tests/051_wasm_import/simple.wasm and /dev/null differ diff --git a/cli/tests/051_wasm_import/simple.wat b/cli/tests/051_wasm_import/simple.wat deleted file mode 100644 index 5e73db97b0..0000000000 --- a/cli/tests/051_wasm_import/simple.wat +++ /dev/null @@ -1,31 +0,0 @@ -;; From https://github.com/nodejs/node/blob/bbc254db5db672643aad89a436a4938412a5704e/test/fixtures/es-modules/simple.wat -;; MIT Licensed -;; $ wat2wasm simple.wat -o simple.wasm - -(module - (import "./wasm-dep.js" "jsFn" (func $jsFn (result i32))) - (import "./wasm-dep.js" "jsInitFn" (func $jsInitFn)) - (import "http://127.0.0.1:4545/cli/tests/051_wasm_import/remote.ts" "jsRemoteFn" (func $jsRemoteFn (result i32))) - (export "add" (func $add)) - (export "addImported" (func $addImported)) - (export "addRemote" (func $addRemote)) - (start $startFn) - (func $startFn - call $jsInitFn - ) - (func $add (param $a i32) (param $b i32) (result i32) - local.get $a - local.get $b - i32.add - ) - (func $addImported (param $a i32) (result i32) - local.get $a - call $jsFn - i32.add - ) - (func $addRemote (param $a i32) (result i32) - local.get $a - call $jsRemoteFn - i32.add - ) -) diff --git a/cli/tests/051_wasm_import/wasm-dep.js b/cli/tests/051_wasm_import/wasm-dep.js deleted file mode 100644 index 70b16348b8..0000000000 --- a/cli/tests/051_wasm_import/wasm-dep.js +++ /dev/null @@ -1,17 +0,0 @@ -function assertEquals(actual, expected, msg) { - if (actual !== expected) { - throw new Error(msg || ""); - } -} - -export function jsFn() { - state = "WASM JS Function Executed"; - return 42; -} - -export let state = "JS Function Executed"; - -export function jsInitFn() { - assertEquals(state, "JS Function Executed", "Incorrect state"); - state = "WASM Start Executed"; -} diff --git a/cli/tests/055_import_wasm_via_network.ts b/cli/tests/055_import_wasm_via_network.ts deleted file mode 100644 index 70d80365ed..0000000000 --- a/cli/tests/055_import_wasm_via_network.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as wasm from "./055_import_wasm_via_network.wasm"; -console.log(wasm); diff --git a/cli/tests/055_import_wasm_via_network.ts.out b/cli/tests/055_import_wasm_via_network.ts.out deleted file mode 100644 index c43c192fb4..0000000000 --- a/cli/tests/055_import_wasm_via_network.ts.out +++ /dev/null @@ -1,5 +0,0 @@ -Module { - add_one: [Function: 0], - memory: WebAssembly.Memory {}, - Symbol(Symbol.toStringTag): "Module" -} diff --git a/cli/tests/055_import_wasm_via_network.wasm b/cli/tests/055_import_wasm_via_network.wasm deleted file mode 100644 index fb6d3e471b..0000000000 Binary files a/cli/tests/055_import_wasm_via_network.wasm and /dev/null differ diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index b549dc6d09..bbd4376231 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -1143,12 +1143,6 @@ itest_ignore!(_049_info_flag_script_jsx { http_server: true, }); -itest!(_051_wasm_import { - args: "run --reload --allow-net --allow-read 051_wasm_import.ts", - output: "051_wasm_import.ts.out", - http_server: true, -}); - // TODO(ry) Re-enable flaky test https://github.com/denoland/deno/issues/4049 itest_ignore!(_052_no_remote_flag { args: @@ -1165,12 +1159,6 @@ itest!(_054_info_local_imports { exit_code: 0, }); -itest!(_055_import_wasm_via_network { - args: "run --reload http://127.0.0.1:4545/cli/tests/055_import_wasm_via_network.ts", - output: "055_import_wasm_via_network.ts.out", - http_server: true, -}); - itest!(_056_make_temp_file_write_perm { args: "run --allow-read --allow-write=./subdir/ 056_make_temp_file_write_perm.ts", diff --git a/docs/getting_started/wasm.md b/docs/getting_started/webassembly.md similarity index 75% rename from docs/getting_started/wasm.md rename to docs/getting_started/webassembly.md index f1c7e6fd29..b2dd6b95de 100644 --- a/docs/getting_started/wasm.md +++ b/docs/getting_started/webassembly.md @@ -17,15 +17,3 @@ const wasmInstance = new WebAssembly.Instance(wasmModule); console.log(wasmInstance.exports.main().toString()); ``` - -### ES Module style imports - -> This is an unstable feature. Learn more about -> [unstable features](../../runtime/unstable). - -WASM files can also be loaded using imports: - -```ts -import { fib } from "./fib.wasm"; -console.log(fib(20)); -```