From f34fcd16ea4d504c8a87c0873c65598d70bb1d07 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Tue, 9 May 2023 12:37:13 +0200 Subject: [PATCH] fix(core): let V8 drive extension ESM loads (#18997) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This now allows circular imports across extensions. Instead of load + eval of all ESM files in declaration order, all files are only loaded. Eval is done recursively by V8, only evaluating files that are listed in `Extension::esm_entry_point` fields. --------- Co-authored-by: Bartek IwaƄczuk --- cli/build.rs | 4 +- cli/js/99_main.js | 3 + core/modules.rs | 24 +- core/runtime.rs | 108 ++++++--- ext/crypto/00_crypto.js | 502 ++++++++++++++++++++++++++++++++++++++ ext/crypto/01_webidl.js | 516 ---------------------------------------- ext/crypto/lib.rs | 2 +- ext/web/09_file.js | 28 +++ ext/web/11_blob_url.js | 45 ---- ext/web/lib.rs | 1 - runtime/build.rs | 12 +- 11 files changed, 640 insertions(+), 605 deletions(-) create mode 100644 cli/js/99_main.js delete mode 100644 ext/crypto/01_webidl.js delete mode 100644 ext/web/11_blob_url.js diff --git a/cli/build.rs b/cli/build.rs index 8e6b670e29..94b49dfe02 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -309,9 +309,11 @@ mod ts { // deps = [runtime] deno_core::extension!( cli, + esm_entry_point = "ext:cli/99_main.js", esm = [ dir "js", - "40_testing.js" + "40_testing.js", + "99_main.js" ], customizer = |ext: &mut deno_core::ExtensionBuilder| { ext.esm(vec![ExtensionFileSource { diff --git a/cli/js/99_main.js b/cli/js/99_main.js new file mode 100644 index 0000000000..dc9d74fb06 --- /dev/null +++ b/cli/js/99_main.js @@ -0,0 +1,3 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +import "ext:cli/40_testing.js"; +import "ext:cli/runtime/js/99_main.js"; diff --git a/core/modules.rs b/core/modules.rs index 9352301ba8..d1e871ba90 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -1093,6 +1093,28 @@ impl ModuleMap { output } + pub(crate) fn assert_all_modules_evaluated( + &self, + scope: &mut v8::HandleScope, + ) { + let mut not_evaluated = vec![]; + + for (i, handle) in self.handles.iter().enumerate() { + let module = v8::Local::new(scope, handle); + if !matches!(module.get_status(), v8::ModuleStatus::Evaluated) { + not_evaluated.push(self.info[i].name.as_str().to_string()); + } + } + + if !not_evaluated.is_empty() { + let mut msg = "Following modules were not evaluated; make sure they are imported from other code:\n".to_string(); + for m in not_evaluated { + msg.push_str(&format!(" - {}\n", m)); + } + panic!("{}", msg); + } + } + pub fn serialize_for_snapshotting( &self, scope: &mut v8::HandleScope, @@ -1366,7 +1388,7 @@ impl ModuleMap { /// Get module id, following all aliases in case of module specifier /// that had been redirected. - fn get_id( + pub(crate) fn get_id( &self, name: impl AsRef, asserted_module_type: AssertedModuleType, diff --git a/core/runtime.rs b/core/runtime.rs index 3c2e6f3e11..b56ef5d659 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -8,6 +8,7 @@ use crate::extensions::OpDecl; use crate::extensions::OpEventLoopFn; use crate::inspector::JsRuntimeInspector; use crate::module_specifier::ModuleSpecifier; +use crate::modules::AssertedModuleType; use crate::modules::ExtModuleLoaderCb; use crate::modules::ModuleCode; use crate::modules::ModuleError; @@ -23,7 +24,6 @@ use crate::snapshot_util; use crate::source_map::SourceMapCache; use crate::source_map::SourceMapGetter; use crate::Extension; -use crate::ExtensionFileSource; use crate::NoopModuleLoader; use crate::OpMiddlewareFn; use crate::OpResult; @@ -687,46 +687,49 @@ impl JsRuntime { module_map } - /// Initializes JS of provided Extensions in the given realm + /// Initializes JS of provided Extensions in the given realm. fn init_extension_js(&mut self, realm: &JsRealm) -> Result<(), Error> { - fn load_and_evaluate_module( - runtime: &mut JsRuntime, - file_source: &ExtensionFileSource, - ) -> Result<(), Error> { - futures::executor::block_on(async { - let id = runtime - .load_side_module( - &ModuleSpecifier::parse(file_source.specifier)?, - None, - ) - .await?; - let receiver = runtime.mod_evaluate(id); - runtime.run_event_loop(false).await?; - receiver.await? - }) - .with_context(|| format!("Couldn't execute '{}'", file_source.specifier)) - } + // Initalization of JS happens in phases: + // 1. Iterate through all extensions: + // a. Execute all extension "script" JS files + // b. Load all extension "module" JS files (but do not execute them yet) + // 2. Iterate through all extensions: + // a. If an extension has a `esm_entry_point`, execute it. + + let mut esm_entrypoints = vec![]; // Take extensions to avoid double-borrow let extensions = std::mem::take(&mut self.extensions); - for ext in extensions.borrow().iter() { - { - if let Some(esm_files) = ext.get_esm_sources() { - if let Some(entry_point) = ext.get_esm_entry_point() { - let file_source = esm_files - .iter() - .find(|file| file.specifier == entry_point) - .unwrap(); - load_and_evaluate_module(self, file_source)?; - } else { - for file_source in esm_files { - load_and_evaluate_module(self, file_source)?; - } + + futures::executor::block_on(async { + let num_of_extensions = extensions.borrow().len(); + for i in 0..num_of_extensions { + let (maybe_esm_files, maybe_esm_entry_point) = { + let exts = extensions.borrow(); + ( + exts[i].get_esm_sources().map(|e| e.to_owned()), + exts[i].get_esm_entry_point(), + ) + }; + + if let Some(esm_files) = maybe_esm_files { + for file_source in esm_files { + self + .load_side_module( + &ModuleSpecifier::parse(file_source.specifier)?, + None, + ) + .await?; } } - } - { + if let Some(entry_point) = maybe_esm_entry_point { + esm_entrypoints.push(entry_point); + } + + let exts = extensions.borrow(); + let ext = &exts[i]; + if let Some(js_files) = ext.get_js_sources() { for file_source in js_files { realm.execute_script( @@ -736,14 +739,41 @@ impl JsRuntime { )?; } } + + if ext.is_core { + self.init_cbs(realm); + } } - // TODO(bartlomieju): this not great that we need to have this conditional - // here, but I haven't found a better way to do it yet. - if ext.is_core { - self.init_cbs(realm); + for specifier in esm_entrypoints { + let mod_id = { + let module_map = self.module_map.as_ref().unwrap(); + + module_map + .borrow() + .get_id(specifier, AssertedModuleType::JavaScriptOrWasm) + .unwrap_or_else(|| { + panic!("{} not present in the module map", specifier) + }) + }; + let receiver = self.mod_evaluate(mod_id); + self.run_event_loop(false).await?; + receiver + .await? + .with_context(|| format!("Couldn't execute '{specifier}'"))?; } - } + + #[cfg(debug_assertions)] + { + let module_map_rc = self.module_map.clone().unwrap(); + let mut scope = realm.handle_scope(self.v8_isolate()); + let module_map = module_map_rc.borrow(); + module_map.assert_all_modules_evaluated(&mut scope); + } + + Ok::<_, anyhow::Error>(()) + })?; + // Restore extensions self.extensions = extensions; diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 5253c5784c..19e669acd0 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -4734,4 +4734,506 @@ webidl.configurePrototype(Crypto); const CryptoPrototype = Crypto.prototype; const crypto = webidl.createBranded(Crypto); + +webidl.converters.AlgorithmIdentifier = (V, prefix, context, opts) => { + // Union for (object or DOMString) + if (webidl.type(V) == "Object") { + return webidl.converters.object(V, prefix, context, opts); + } + return webidl.converters.DOMString(V, prefix, context, opts); +}; + +webidl.converters["BufferSource or JsonWebKey"] = ( + V, + prefix, + context, + opts, +) => { + // Union for (BufferSource or JsonWebKey) + if ( + ArrayBufferIsView(V) || + ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V) + ) { + return webidl.converters.BufferSource(V, prefix, context, opts); + } + return webidl.converters.JsonWebKey(V, prefix, context, opts); +}; + +webidl.converters.KeyType = webidl.createEnumConverter("KeyType", [ + "public", + "private", + "secret", +]); + +webidl.converters.KeyFormat = webidl.createEnumConverter("KeyFormat", [ + "raw", + "pkcs8", + "spki", + "jwk", +]); + +webidl.converters.KeyUsage = webidl.createEnumConverter("KeyUsage", [ + "encrypt", + "decrypt", + "sign", + "verify", + "deriveKey", + "deriveBits", + "wrapKey", + "unwrapKey", +]); + +webidl.converters["sequence"] = webidl.createSequenceConverter( + webidl.converters.KeyUsage, +); + +webidl.converters.HashAlgorithmIdentifier = + webidl.converters.AlgorithmIdentifier; + +/** @type {webidl.Dictionary} */ +const dictAlgorithm = [{ + key: "name", + converter: webidl.converters.DOMString, + required: true, +}]; + +webidl.converters.Algorithm = webidl + .createDictionaryConverter("Algorithm", dictAlgorithm); + +webidl.converters.BigInteger = webidl.converters.Uint8Array; + +/** @type {webidl.Dictionary} */ +const dictRsaKeyGenParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "modulusLength", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + required: true, + }, + { + key: "publicExponent", + converter: webidl.converters.BigInteger, + required: true, + }, +]; + +webidl.converters.RsaKeyGenParams = webidl + .createDictionaryConverter("RsaKeyGenParams", dictRsaKeyGenParams); + +const dictRsaHashedKeyGenParams = [ + ...new SafeArrayIterator(dictRsaKeyGenParams), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, +]; + +webidl.converters.RsaHashedKeyGenParams = webidl.createDictionaryConverter( + "RsaHashedKeyGenParams", + dictRsaHashedKeyGenParams, +); + +const dictRsaHashedImportParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, +]; + +webidl.converters.RsaHashedImportParams = webidl.createDictionaryConverter( + "RsaHashedImportParams", + dictRsaHashedImportParams, +); + +webidl.converters.NamedCurve = webidl.converters.DOMString; + +const dictEcKeyImportParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "namedCurve", + converter: webidl.converters.NamedCurve, + required: true, + }, +]; + +webidl.converters.EcKeyImportParams = webidl.createDictionaryConverter( + "EcKeyImportParams", + dictEcKeyImportParams, +); + +const dictEcKeyGenParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "namedCurve", + converter: webidl.converters.NamedCurve, + required: true, + }, +]; + +webidl.converters.EcKeyGenParams = webidl + .createDictionaryConverter("EcKeyGenParams", dictEcKeyGenParams); + +const dictAesKeyGenParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "length", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned short"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + required: true, + }, +]; + +webidl.converters.AesKeyGenParams = webidl + .createDictionaryConverter("AesKeyGenParams", dictAesKeyGenParams); + +const dictHmacKeyGenParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, + { + key: "length", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + }, +]; + +webidl.converters.HmacKeyGenParams = webidl + .createDictionaryConverter("HmacKeyGenParams", dictHmacKeyGenParams); + +const dictRsaPssParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "saltLength", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + required: true, + }, +]; + +webidl.converters.RsaPssParams = webidl + .createDictionaryConverter("RsaPssParams", dictRsaPssParams); + +const dictRsaOaepParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "label", + converter: webidl.converters["BufferSource"], + }, +]; + +webidl.converters.RsaOaepParams = webidl + .createDictionaryConverter("RsaOaepParams", dictRsaOaepParams); + +const dictEcdsaParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, +]; + +webidl.converters["EcdsaParams"] = webidl + .createDictionaryConverter("EcdsaParams", dictEcdsaParams); + +const dictHmacImportParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, + { + key: "length", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + }, +]; + +webidl.converters.HmacImportParams = webidl + .createDictionaryConverter("HmacImportParams", dictHmacImportParams); + +const dictRsaOtherPrimesInfo = [ + { + key: "r", + converter: webidl.converters["DOMString"], + }, + { + key: "d", + converter: webidl.converters["DOMString"], + }, + { + key: "t", + converter: webidl.converters["DOMString"], + }, +]; + +webidl.converters.RsaOtherPrimesInfo = webidl.createDictionaryConverter( + "RsaOtherPrimesInfo", + dictRsaOtherPrimesInfo, +); +webidl.converters["sequence"] = webidl + .createSequenceConverter( + webidl.converters.RsaOtherPrimesInfo, + ); + +const dictJsonWebKey = [ + // Sections 4.2 and 4.3 of RFC7517. + // https://datatracker.ietf.org/doc/html/rfc7517#section-4 + { + key: "kty", + converter: webidl.converters["DOMString"], + }, + { + key: "use", + converter: webidl.converters["DOMString"], + }, + { + key: "key_ops", + converter: webidl.converters["sequence"], + }, + { + key: "alg", + converter: webidl.converters["DOMString"], + }, + // JSON Web Key Parameters Registration + { + key: "ext", + converter: webidl.converters["boolean"], + }, + // Section 6 of RFC7518 JSON Web Algorithms + // https://datatracker.ietf.org/doc/html/rfc7518#section-6 + { + key: "crv", + converter: webidl.converters["DOMString"], + }, + { + key: "x", + converter: webidl.converters["DOMString"], + }, + { + key: "y", + converter: webidl.converters["DOMString"], + }, + { + key: "d", + converter: webidl.converters["DOMString"], + }, + { + key: "n", + converter: webidl.converters["DOMString"], + }, + { + key: "e", + converter: webidl.converters["DOMString"], + }, + { + key: "p", + converter: webidl.converters["DOMString"], + }, + { + key: "q", + converter: webidl.converters["DOMString"], + }, + { + key: "dp", + converter: webidl.converters["DOMString"], + }, + { + key: "dq", + converter: webidl.converters["DOMString"], + }, + { + key: "qi", + converter: webidl.converters["DOMString"], + }, + { + key: "oth", + converter: webidl.converters["sequence"], + }, + { + key: "k", + converter: webidl.converters["DOMString"], + }, +]; + +webidl.converters.JsonWebKey = webidl.createDictionaryConverter( + "JsonWebKey", + dictJsonWebKey, +); + +const dictHkdfParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, + { + key: "salt", + converter: webidl.converters["BufferSource"], + required: true, + }, + { + key: "info", + converter: webidl.converters["BufferSource"], + required: true, + }, +]; + +webidl.converters.HkdfParams = webidl + .createDictionaryConverter("HkdfParams", dictHkdfParams); + +const dictPbkdf2Params = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "hash", + converter: webidl.converters.HashAlgorithmIdentifier, + required: true, + }, + { + key: "iterations", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + required: true, + }, + { + key: "salt", + converter: webidl.converters["BufferSource"], + required: true, + }, +]; + +webidl.converters.Pbkdf2Params = webidl + .createDictionaryConverter("Pbkdf2Params", dictPbkdf2Params); + +const dictAesDerivedKeyParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "length", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + required: true, + }, +]; + +const dictAesCbcParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "iv", + converter: webidl.converters["BufferSource"], + required: true, + }, +]; + +const dictAesGcmParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "iv", + converter: webidl.converters["BufferSource"], + required: true, + }, + { + key: "tagLength", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned long"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + }, + { + key: "additionalData", + converter: webidl.converters["BufferSource"], + }, +]; + +const dictAesCtrParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "counter", + converter: webidl.converters["BufferSource"], + required: true, + }, + { + key: "length", + converter: (V, prefix, context, opts) => + webidl.converters["unsigned short"](V, prefix, context, { + ...opts, + enforceRange: true, + }), + required: true, + }, +]; + +webidl.converters.AesDerivedKeyParams = webidl + .createDictionaryConverter("AesDerivedKeyParams", dictAesDerivedKeyParams); + +webidl.converters.AesCbcParams = webidl + .createDictionaryConverter("AesCbcParams", dictAesCbcParams); + +webidl.converters.AesGcmParams = webidl + .createDictionaryConverter("AesGcmParams", dictAesGcmParams); + +webidl.converters.AesCtrParams = webidl + .createDictionaryConverter("AesCtrParams", dictAesCtrParams); + +webidl.converters.CryptoKey = webidl.createInterfaceConverter( + "CryptoKey", + CryptoKey.prototype, +); + +const dictCryptoKeyPair = [ + { + key: "publicKey", + converter: webidl.converters.CryptoKey, + }, + { + key: "privateKey", + converter: webidl.converters.CryptoKey, + }, +]; + +webidl.converters.CryptoKeyPair = webidl + .createDictionaryConverter("CryptoKeyPair", dictCryptoKeyPair); + +const dictEcdhKeyDeriveParams = [ + ...new SafeArrayIterator(dictAlgorithm), + { + key: "public", + converter: webidl.converters.CryptoKey, + required: true, + }, +]; + +webidl.converters.EcdhKeyDeriveParams = webidl + .createDictionaryConverter("EcdhKeyDeriveParams", dictEcdhKeyDeriveParams); + export { Crypto, crypto, CryptoKey, SubtleCrypto }; diff --git a/ext/crypto/01_webidl.js b/ext/crypto/01_webidl.js deleted file mode 100644 index cd0655b3b8..0000000000 --- a/ext/crypto/01_webidl.js +++ /dev/null @@ -1,516 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -// @ts-check -/// -/// - -const primordials = globalThis.__bootstrap.primordials; -import * as webidl from "ext:deno_webidl/00_webidl.js"; -import { CryptoKey } from "ext:deno_crypto/00_crypto.js"; -const { - ArrayBufferIsView, - ArrayBufferPrototype, - ObjectPrototypeIsPrototypeOf, - SafeArrayIterator, -} = primordials; - -webidl.converters.AlgorithmIdentifier = (V, prefix, context, opts) => { - // Union for (object or DOMString) - if (webidl.type(V) == "Object") { - return webidl.converters.object(V, prefix, context, opts); - } - return webidl.converters.DOMString(V, prefix, context, opts); -}; - -webidl.converters["BufferSource or JsonWebKey"] = ( - V, - prefix, - context, - opts, -) => { - // Union for (BufferSource or JsonWebKey) - if ( - ArrayBufferIsView(V) || - ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V) - ) { - return webidl.converters.BufferSource(V, prefix, context, opts); - } - return webidl.converters.JsonWebKey(V, prefix, context, opts); -}; - -webidl.converters.KeyType = webidl.createEnumConverter("KeyType", [ - "public", - "private", - "secret", -]); - -webidl.converters.KeyFormat = webidl.createEnumConverter("KeyFormat", [ - "raw", - "pkcs8", - "spki", - "jwk", -]); - -webidl.converters.KeyUsage = webidl.createEnumConverter("KeyUsage", [ - "encrypt", - "decrypt", - "sign", - "verify", - "deriveKey", - "deriveBits", - "wrapKey", - "unwrapKey", -]); - -webidl.converters["sequence"] = webidl.createSequenceConverter( - webidl.converters.KeyUsage, -); - -webidl.converters.HashAlgorithmIdentifier = - webidl.converters.AlgorithmIdentifier; - -/** @type {webidl.Dictionary} */ -const dictAlgorithm = [{ - key: "name", - converter: webidl.converters.DOMString, - required: true, -}]; - -webidl.converters.Algorithm = webidl - .createDictionaryConverter("Algorithm", dictAlgorithm); - -webidl.converters.BigInteger = webidl.converters.Uint8Array; - -/** @type {webidl.Dictionary} */ -const dictRsaKeyGenParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "modulusLength", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - required: true, - }, - { - key: "publicExponent", - converter: webidl.converters.BigInteger, - required: true, - }, -]; - -webidl.converters.RsaKeyGenParams = webidl - .createDictionaryConverter("RsaKeyGenParams", dictRsaKeyGenParams); - -const dictRsaHashedKeyGenParams = [ - ...new SafeArrayIterator(dictRsaKeyGenParams), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, -]; - -webidl.converters.RsaHashedKeyGenParams = webidl.createDictionaryConverter( - "RsaHashedKeyGenParams", - dictRsaHashedKeyGenParams, -); - -const dictRsaHashedImportParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, -]; - -webidl.converters.RsaHashedImportParams = webidl.createDictionaryConverter( - "RsaHashedImportParams", - dictRsaHashedImportParams, -); - -webidl.converters.NamedCurve = webidl.converters.DOMString; - -const dictEcKeyImportParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "namedCurve", - converter: webidl.converters.NamedCurve, - required: true, - }, -]; - -webidl.converters.EcKeyImportParams = webidl.createDictionaryConverter( - "EcKeyImportParams", - dictEcKeyImportParams, -); - -const dictEcKeyGenParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "namedCurve", - converter: webidl.converters.NamedCurve, - required: true, - }, -]; - -webidl.converters.EcKeyGenParams = webidl - .createDictionaryConverter("EcKeyGenParams", dictEcKeyGenParams); - -const dictAesKeyGenParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "length", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned short"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - required: true, - }, -]; - -webidl.converters.AesKeyGenParams = webidl - .createDictionaryConverter("AesKeyGenParams", dictAesKeyGenParams); - -const dictHmacKeyGenParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, - { - key: "length", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - }, -]; - -webidl.converters.HmacKeyGenParams = webidl - .createDictionaryConverter("HmacKeyGenParams", dictHmacKeyGenParams); - -const dictRsaPssParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "saltLength", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - required: true, - }, -]; - -webidl.converters.RsaPssParams = webidl - .createDictionaryConverter("RsaPssParams", dictRsaPssParams); - -const dictRsaOaepParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "label", - converter: webidl.converters["BufferSource"], - }, -]; - -webidl.converters.RsaOaepParams = webidl - .createDictionaryConverter("RsaOaepParams", dictRsaOaepParams); - -const dictEcdsaParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, -]; - -webidl.converters["EcdsaParams"] = webidl - .createDictionaryConverter("EcdsaParams", dictEcdsaParams); - -const dictHmacImportParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, - { - key: "length", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - }, -]; - -webidl.converters.HmacImportParams = webidl - .createDictionaryConverter("HmacImportParams", dictHmacImportParams); - -const dictRsaOtherPrimesInfo = [ - { - key: "r", - converter: webidl.converters["DOMString"], - }, - { - key: "d", - converter: webidl.converters["DOMString"], - }, - { - key: "t", - converter: webidl.converters["DOMString"], - }, -]; - -webidl.converters.RsaOtherPrimesInfo = webidl.createDictionaryConverter( - "RsaOtherPrimesInfo", - dictRsaOtherPrimesInfo, -); -webidl.converters["sequence"] = webidl - .createSequenceConverter( - webidl.converters.RsaOtherPrimesInfo, - ); - -const dictJsonWebKey = [ - // Sections 4.2 and 4.3 of RFC7517. - // https://datatracker.ietf.org/doc/html/rfc7517#section-4 - { - key: "kty", - converter: webidl.converters["DOMString"], - }, - { - key: "use", - converter: webidl.converters["DOMString"], - }, - { - key: "key_ops", - converter: webidl.converters["sequence"], - }, - { - key: "alg", - converter: webidl.converters["DOMString"], - }, - // JSON Web Key Parameters Registration - { - key: "ext", - converter: webidl.converters["boolean"], - }, - // Section 6 of RFC7518 JSON Web Algorithms - // https://datatracker.ietf.org/doc/html/rfc7518#section-6 - { - key: "crv", - converter: webidl.converters["DOMString"], - }, - { - key: "x", - converter: webidl.converters["DOMString"], - }, - { - key: "y", - converter: webidl.converters["DOMString"], - }, - { - key: "d", - converter: webidl.converters["DOMString"], - }, - { - key: "n", - converter: webidl.converters["DOMString"], - }, - { - key: "e", - converter: webidl.converters["DOMString"], - }, - { - key: "p", - converter: webidl.converters["DOMString"], - }, - { - key: "q", - converter: webidl.converters["DOMString"], - }, - { - key: "dp", - converter: webidl.converters["DOMString"], - }, - { - key: "dq", - converter: webidl.converters["DOMString"], - }, - { - key: "qi", - converter: webidl.converters["DOMString"], - }, - { - key: "oth", - converter: webidl.converters["sequence"], - }, - { - key: "k", - converter: webidl.converters["DOMString"], - }, -]; - -webidl.converters.JsonWebKey = webidl.createDictionaryConverter( - "JsonWebKey", - dictJsonWebKey, -); - -const dictHkdfParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, - { - key: "salt", - converter: webidl.converters["BufferSource"], - required: true, - }, - { - key: "info", - converter: webidl.converters["BufferSource"], - required: true, - }, -]; - -webidl.converters.HkdfParams = webidl - .createDictionaryConverter("HkdfParams", dictHkdfParams); - -const dictPbkdf2Params = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "hash", - converter: webidl.converters.HashAlgorithmIdentifier, - required: true, - }, - { - key: "iterations", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - required: true, - }, - { - key: "salt", - converter: webidl.converters["BufferSource"], - required: true, - }, -]; - -webidl.converters.Pbkdf2Params = webidl - .createDictionaryConverter("Pbkdf2Params", dictPbkdf2Params); - -const dictAesDerivedKeyParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "length", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - required: true, - }, -]; - -const dictAesCbcParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "iv", - converter: webidl.converters["BufferSource"], - required: true, - }, -]; - -const dictAesGcmParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "iv", - converter: webidl.converters["BufferSource"], - required: true, - }, - { - key: "tagLength", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned long"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - }, - { - key: "additionalData", - converter: webidl.converters["BufferSource"], - }, -]; - -const dictAesCtrParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "counter", - converter: webidl.converters["BufferSource"], - required: true, - }, - { - key: "length", - converter: (V, prefix, context, opts) => - webidl.converters["unsigned short"](V, prefix, context, { - ...opts, - enforceRange: true, - }), - required: true, - }, -]; - -webidl.converters.AesDerivedKeyParams = webidl - .createDictionaryConverter("AesDerivedKeyParams", dictAesDerivedKeyParams); - -webidl.converters.AesCbcParams = webidl - .createDictionaryConverter("AesCbcParams", dictAesCbcParams); - -webidl.converters.AesGcmParams = webidl - .createDictionaryConverter("AesGcmParams", dictAesGcmParams); - -webidl.converters.AesCtrParams = webidl - .createDictionaryConverter("AesCtrParams", dictAesCtrParams); - -webidl.converters.CryptoKey = webidl.createInterfaceConverter( - "CryptoKey", - CryptoKey.prototype, -); - -const dictCryptoKeyPair = [ - { - key: "publicKey", - converter: webidl.converters.CryptoKey, - }, - { - key: "privateKey", - converter: webidl.converters.CryptoKey, - }, -]; - -webidl.converters.CryptoKeyPair = webidl - .createDictionaryConverter("CryptoKeyPair", dictCryptoKeyPair); - -const dictEcdhKeyDeriveParams = [ - ...new SafeArrayIterator(dictAlgorithm), - { - key: "public", - converter: webidl.converters.CryptoKey, - required: true, - }, -]; - -webidl.converters.EcdhKeyDeriveParams = webidl - .createDictionaryConverter("EcdhKeyDeriveParams", dictEcdhKeyDeriveParams); diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs index 695cc3abdf..f481f97f6b 100644 --- a/ext/crypto/lib.rs +++ b/ext/crypto/lib.rs @@ -103,7 +103,7 @@ deno_core::extension!(deno_crypto, x25519::op_crypto_export_spki_x25519, x25519::op_crypto_export_pkcs8_x25519, ], - esm = [ "00_crypto.js", "01_webidl.js" ], + esm = [ "00_crypto.js" ], options = { maybe_seed: Option, }, diff --git a/ext/web/09_file.js b/ext/web/09_file.js index a81176b385..d65a512f93 100644 --- a/ext/web/09_file.js +++ b/ext/web/09_file.js @@ -14,6 +14,7 @@ const core = globalThis.Deno.core; const ops = core.ops; import * as webidl from "ext:deno_webidl/00_webidl.js"; import { ReadableStream } from "ext:deno_web/06_streams.js"; +import { URL } from "ext:deno_url/00_url.js"; const primordials = globalThis.__bootstrap.primordials; const { ArrayBufferPrototype, @@ -653,6 +654,33 @@ function blobFromObjectUrl(url) { return blob; } +/** + * @param {Blob} blob + * @returns {string} + */ +function createObjectURL(blob) { + const prefix = "Failed to execute 'createObjectURL' on 'URL'"; + webidl.requiredArguments(arguments.length, 1, prefix); + blob = webidl.converters["Blob"](blob, prefix, "Argument 1"); + + return ops.op_blob_create_object_url(blob.type, getParts(blob)); +} + +/** + * @param {string} url + * @returns {void} + */ +function revokeObjectURL(url) { + const prefix = "Failed to execute 'revokeObjectURL' on 'URL'"; + webidl.requiredArguments(arguments.length, 1, prefix); + url = webidl.converters["DOMString"](url, prefix, "Argument 1"); + + ops.op_blob_revoke_object_url(url); +} + +URL.createObjectURL = createObjectURL; +URL.revokeObjectURL = revokeObjectURL; + export { Blob, blobFromObjectUrl, diff --git a/ext/web/11_blob_url.js b/ext/web/11_blob_url.js deleted file mode 100644 index 3ac240d90a..0000000000 --- a/ext/web/11_blob_url.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -// @ts-check -/// -/// -/// -/// -/// -/// -/// -/// -/// - -const core = globalThis.Deno.core; -const ops = core.ops; -import * as webidl from "ext:deno_webidl/00_webidl.js"; -import { getParts } from "ext:deno_web/09_file.js"; -import { URL } from "ext:deno_url/00_url.js"; - -/** - * @param {Blob} blob - * @returns {string} - */ -function createObjectURL(blob) { - const prefix = "Failed to execute 'createObjectURL' on 'URL'"; - webidl.requiredArguments(arguments.length, 1, prefix); - blob = webidl.converters["Blob"](blob, prefix, "Argument 1"); - - return ops.op_blob_create_object_url(blob.type, getParts(blob)); -} - -/** - * @param {string} url - * @returns {void} - */ -function revokeObjectURL(url) { - const prefix = "Failed to execute 'revokeObjectURL' on 'URL'"; - webidl.requiredArguments(arguments.length, 1, prefix); - url = webidl.converters["DOMString"](url, prefix, "Argument 1"); - - ops.op_blob_revoke_object_url(url); -} - -URL.createObjectURL = createObjectURL; -URL.revokeObjectURL = revokeObjectURL; diff --git a/ext/web/lib.rs b/ext/web/lib.rs index b0dc0d56d5..3f4468f1f1 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -103,7 +103,6 @@ deno_core::extension!(deno_web, "08_text_encoding.js", "09_file.js", "10_filereader.js", - "11_blob_url.js", "12_location.js", "13_message_port.js", "14_compression.js", diff --git a/runtime/build.rs b/runtime/build.rs index 4f49ba6816..18aaf7a7f0 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -267,6 +267,17 @@ mod startup_snapshot { include_str!("js/99_main.js"), ), }]); + ext.esm_entry_point("ext:runtime_main/js/99_main.js"); + } + ); + + #[cfg(feature = "snapshot_from_snapshot")] + deno_core::extension!( + runtime_main, + deps = [runtime], + customizer = |ext: &mut deno_core::ExtensionBuilder| { + eprintln!("I am here!!!"); + ext.esm_entry_point("ext:runtime/90_deno_ns.js"); } ); @@ -315,7 +326,6 @@ mod startup_snapshot { // FIXME(bartlomieju): these extensions are specified last, because they // depend on `runtime`, even though it should be other way around deno_node::deno_node::init_ops_and_esm::(None, fs), - #[cfg(not(feature = "snapshot_from_snapshot"))] runtime_main::init_ops_and_esm(), ];