From ec54f28bfd21ffe86b3e4323df363db60e0def27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sun, 14 Feb 2021 19:49:37 +0100 Subject: [PATCH] feat: Add ModuleRequest (#623) --- src/binding.cc | 16 ++++++++++++++++ src/data.rs | 12 ++++++++++++ src/module.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_api.rs | 13 ++++++++++++- 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/binding.cc b/src/binding.cc index 02d22501..2c10b612 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -2048,6 +2048,10 @@ const v8::String* v8__Module__GetModuleRequest(const v8::Module& self, int i) { return local_to_ptr(self.GetModuleRequest(i)); } +const v8::FixedArray* v8__Module__GetModuleRequests(const v8::Module& self) { + return local_to_ptr(self.GetModuleRequests()); +} + void v8__Module__GetModuleRequestLocation(const v8::Module& self, int i, v8::Location* out) { *out = self.GetModuleRequestLocation(i); @@ -2110,6 +2114,18 @@ MaybeBool v8__Module__SetSyntheticModuleExport(const v8::Module& self, isolate, ptr_to_local(export_name), ptr_to_local(export_value))); } +const v8::String* v8__ModuleRequest__GetSpecifier(const v8::ModuleRequest& self) { + return local_to_ptr(self.GetSpecifier()); +} + +int v8__ModuleRequest__GetSourceOffset(const v8::ModuleRequest& self) { + return self.GetSourceOffset(); +} + +const v8::FixedArray* v8__ModuleRequest__GetImportAssertions(const v8::ModuleRequest& self) { + return local_to_ptr(self.GetImportAssertions()); +} + struct WasmStreamingSharedPtr { std::shared_ptr inner; }; diff --git a/src/data.rs b/src/data.rs index c1f85c75..7006a6c5 100644 --- a/src/data.rs +++ b/src/data.rs @@ -202,6 +202,7 @@ impl_from! { AccessorSignature for Data } impl_from! { Context for Data } impl_from! { Message for Data } impl_from! { Module for Data } +impl_from! { ModuleRequest for Data } impl_from! { PrimitiveArray for Data } impl_from! { Private for Data } impl_from! { Script for Data } @@ -367,6 +368,17 @@ impl_hash! { for FixedArray } impl_partial_eq! { Data for FixedArray use identity } impl_partial_eq! { FixedArray for FixedArray use identity } +#[repr(C)] +#[derive(Debug)] +pub struct ModuleRequest(Opaque); + +impl_deref! { Data for ModuleRequest } +impl_from! { Data for ModuleRequest } +impl_eq! { for ModuleRequest } +impl_hash! { for ModuleRequest } +impl_partial_eq! { Data for ModuleRequest use identity } +impl_partial_eq! { ModuleRequest for ModuleRequest use identity } + /// An array to hold Primitive values. This is used by the embedder to /// pass host defined options to the ScriptOptions during compilation. /// diff --git a/src/module.rs b/src/module.rs index 8440d45b..d1430c91 100644 --- a/src/module.rs +++ b/src/module.rs @@ -16,6 +16,7 @@ use crate::HandleScope; use crate::Isolate; use crate::Local; use crate::Module; +use crate::ModuleRequest; use crate::String; use crate::Value; @@ -138,6 +139,7 @@ extern "C" { fn v8__Module__GetModuleRequestsLength(this: *const Module) -> int; fn v8__Module__GetModuleRequest(this: *const Module, i: int) -> *const String; + fn v8__Module__GetModuleRequests(this: *const Module) -> *const FixedArray; fn v8__Module__GetModuleRequestLocation( this: *const Module, i: int, @@ -172,6 +174,13 @@ extern "C" { ) -> MaybeBool; fn v8__Location__GetLineNumber(this: *const Location) -> int; fn v8__Location__GetColumnNumber(this: *const Location) -> int; + fn v8__ModuleRequest__GetSpecifier( + this: *const ModuleRequest, + ) -> *const String; + fn v8__ModuleRequest__GetSourceOffset(this: *const ModuleRequest) -> int; + fn v8__ModuleRequest__GetImportAssertions( + this: *const ModuleRequest, + ) -> *const FixedArray; } /// A location in JavaScript source. @@ -236,6 +245,11 @@ impl Module { .unwrap() } + /// Returns the ModuleRequests for this module. + pub fn get_module_requests(&self) -> Local { + unsafe { Local::from_raw(v8__Module__GetModuleRequests(self)) }.unwrap() + } + /// Returns the source location (line number and column number) of the ith /// module specifier's first occurrence in this module. pub fn get_module_request_location(&self, i: usize) -> Location { @@ -387,3 +401,33 @@ impl Hash for Module { state.write_i32(self.get_identity_hash()); } } + +impl ModuleRequest { + /// Returns the module specifier for this ModuleRequest. + pub fn get_specifier(&self) -> Local { + unsafe { Local::from_raw(v8__ModuleRequest__GetSpecifier(self)) }.unwrap() + } + + /// Returns the source code offset of this module request. + /// Use Module::SourceOffsetToLocation to convert this to line/column numbers. + pub fn get_source_offset(&self) -> int { + unsafe { v8__ModuleRequest__GetSourceOffset(self) } + } + + /// Contains the import assertions for this request in the form: + /// [key1, value1, source_offset1, key2, value2, source_offset2, ...]. + /// The keys and values are of type v8::String, and the source offsets are of + /// type Int32. Use Module::SourceOffsetToLocation to convert the source + /// offsets to Locations with line/column numbers. + /// + /// All assertions present in the module request will be supplied in this + /// list, regardless of whether they are supported by the host. Per + /// https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions, + /// hosts are expected to ignore assertions that they do not support (as + /// opposed to, for example, triggering an error if an unsupported assertion is + /// present). + pub fn get_import_assertions(&self) -> Local { + unsafe { Local::from_raw(v8__ModuleRequest__GetImportAssertions(self)) } + .unwrap() + } +} diff --git a/tests/test_api.rs b/tests/test_api.rs index 9d6aa0c8..97b91e4c 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1952,7 +1952,18 @@ fn module_instantiation_failures1() { let module = v8::script_compiler::compile_module(scope, source).unwrap(); assert_eq!(v8::ModuleStatus::Uninstantiated, module.get_status()); - assert_eq!(2, module.get_module_requests_length()); + let module_requests = module.get_module_requests(); + assert_eq!(2, module_requests.length()); + let mr1 = v8::Local::::try_from( + module_requests.get(scope, 0).unwrap(), + ) + .unwrap(); + assert_eq!(0, mr1.get_import_assertions().length()); + let mr2 = v8::Local::::try_from( + module_requests.get(scope, 1).unwrap(), + ) + .unwrap(); + assert_eq!(0, mr2.get_import_assertions().length()); assert!(module.script_id().is_some()); assert_eq!(