0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -05:00

Rolling to V8 10.0.139.6 (#915)

Co-authored-by: Luca Casonato <hello@lcas.dev>
This commit is contained in:
github-actions[bot] 2022-03-09 14:41:46 +01:00 committed by GitHub
parent 482bf615e3
commit b91d363d2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 77 additions and 74 deletions

View file

@ -1,6 +1,6 @@
# Rusty V8 Binding # Rusty V8 Binding
V8 Version: 9.9.115.9 V8 Version: 10.0.139.6
[![ci](https://github.com/denoland/rusty_v8/workflows/ci/badge.svg?branch=main)](https://github.com/denoland/rusty_v8/actions) [![ci](https://github.com/denoland/rusty_v8/workflows/ci/badge.svg?branch=main)](https://github.com/denoland/rusty_v8/actions)
[![crates](https://img.shields.io/crates/v/v8.svg)](https://crates.io/crates/v8) [![crates](https://img.shields.io/crates/v/v8.svg)](https://crates.io/crates/v8)

View file

@ -66,5 +66,5 @@ fn main() {
unsafe { unsafe {
v8::V8::dispose(); v8::V8::dispose();
} }
v8::V8::shutdown_platform(); v8::V8::dispose_platform();
} }

View file

@ -22,7 +22,7 @@ extern "C" {
fn v8__V8__InitializePlatform(platform: *mut Platform); fn v8__V8__InitializePlatform(platform: *mut Platform);
fn v8__V8__Initialize(); fn v8__V8__Initialize();
fn v8__V8__Dispose() -> bool; fn v8__V8__Dispose() -> bool;
fn v8__V8__ShutdownPlatform(); fn v8__V8__DisposePlatform();
} }
/// EntropySource is used as a callback function when v8 needs a source /// EntropySource is used as a callback function when v8 needs a source
@ -234,13 +234,16 @@ pub unsafe fn dispose() -> bool {
} }
/// Clears all references to the v8::Platform. This should be invoked after /// Clears all references to the v8::Platform. This should be invoked after
/// V8 was disposed. /// V8 was disposed. If it is called if V8 is not disposed, it will panic.
pub fn shutdown_platform() { pub fn dispose_platform() {
let mut global_state_guard = GLOBAL_STATE.lock().unwrap(); let mut global_state_guard = GLOBAL_STATE.lock().unwrap();
// First shutdown platform, then drop platform // First check that the global state is disposed. If it is we dispose the
unsafe { v8__V8__ShutdownPlatform() }; // platform. We then drop the platform.
*global_state_guard = match *global_state_guard { *global_state_guard = match *global_state_guard {
Disposed(_) => PlatformShutdown, Disposed(_) => {
unsafe { v8__V8__DisposePlatform() };
PlatformShutdown
}
_ => panic!("Invalid global state"), _ => panic!("Invalid global state"),
}; };
} }

View file

@ -98,24 +98,22 @@ enum InternalSlots {
(isolate->GetNumberOfDataSlots() - 1 - slot) (isolate->GetNumberOfDataSlots() - 1 - slot)
// This is an extern C calling convention compatible version of // This is an extern C calling convention compatible version of
// v8::HostImportModuleDynamicallyWithImportAssertionsCallback // v8::HostImportModuleDynamicallyCallback
typedef v8::Promise* ( typedef v8::Promise* (*v8__HostImportModuleDynamicallyCallback)(
*v8__HostImportModuleDynamicallyWithImportAssertionsCallback)( v8::Local<v8::Context> context, v8::Local<v8::Data> host_defined_options,
v8::Local<v8::Context> context, v8::Local<v8::ScriptOrModule> referrer, v8::Local<v8::Value> resource_name, v8::Local<v8::String> specifier,
v8::Local<v8::String> specifier,
v8::Local<v8::FixedArray> import_assertions); v8::Local<v8::FixedArray> import_assertions);
v8::MaybeLocal<v8::Promise> v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallback(
HostImportModuleDynamicallyWithImportAssertionsCallback( v8::Local<v8::Context> context, v8::Local<v8::Data> host_defined_options,
v8::Local<v8::Context> context, v8::Local<v8::ScriptOrModule> referrer, v8::Local<v8::Value> resource_name, v8::Local<v8::String> specifier,
v8::Local<v8::String> specifier,
v8::Local<v8::FixedArray> import_assertions) { v8::Local<v8::FixedArray> import_assertions) {
auto* isolate = context->GetIsolate(); auto* isolate = context->GetIsolate();
void* d = isolate->GetData(SLOT_INTERNAL(isolate, kSlotDynamicImport)); void* d = isolate->GetData(SLOT_INTERNAL(isolate, kSlotDynamicImport));
auto* callback = reinterpret_cast< auto* callback = reinterpret_cast<v8__HostImportModuleDynamicallyCallback>(d);
v8__HostImportModuleDynamicallyWithImportAssertionsCallback>(d);
assert(callback != nullptr); assert(callback != nullptr);
auto* promise_ptr = callback(context, referrer, specifier, import_assertions); auto* promise_ptr = callback(context, host_defined_options, resource_name,
specifier, import_assertions);
if (promise_ptr == nullptr) { if (promise_ptr == nullptr) {
return v8::MaybeLocal<v8::Promise>(); return v8::MaybeLocal<v8::Promise>();
} else { } else {
@ -150,7 +148,7 @@ void v8__V8__Initialize() { v8::V8::Initialize(); }
bool v8__V8__Dispose() { return v8::V8::Dispose(); } bool v8__V8__Dispose() { return v8::V8::Dispose(); }
void v8__V8__ShutdownPlatform() { v8::V8::ShutdownPlatform(); } void v8__V8__DisposePlatform() { v8::V8::DisposePlatform(); }
v8::Isolate* v8__Isolate__New(const v8::Isolate::CreateParams& params) { v8::Isolate* v8__Isolate__New(const v8::Isolate::CreateParams& params) {
return v8::Isolate::New(params); return v8::Isolate::New(params);
@ -256,12 +254,11 @@ void v8__Isolate__SetHostInitializeImportMetaObjectCallback(
} }
void v8__Isolate__SetHostImportModuleDynamicallyCallback( void v8__Isolate__SetHostImportModuleDynamicallyCallback(
v8::Isolate* isolate, v8::Isolate* isolate, v8__HostImportModuleDynamicallyCallback callback) {
v8__HostImportModuleDynamicallyWithImportAssertionsCallback callback) {
isolate->SetData(SLOT_INTERNAL(isolate, kSlotDynamicImport), isolate->SetData(SLOT_INTERNAL(isolate, kSlotDynamicImport),
reinterpret_cast<void*>(callback)); reinterpret_cast<void*>(callback));
isolate->SetHostImportModuleDynamicallyCallback( isolate->SetHostImportModuleDynamicallyCallback(
HostImportModuleDynamicallyWithImportAssertionsCallback); HostImportModuleDynamicallyCallback);
} }
bool v8__Isolate__AddMessageListener(v8::Isolate* isolate, bool v8__Isolate__AddMessageListener(v8::Isolate* isolate,
@ -411,18 +408,18 @@ const v8::Script* v8__ScriptCompiler__Compile(
return maybe_local_to_ptr(maybe_local); return maybe_local_to_ptr(maybe_local);
} }
const v8::Function* v8__ScriptCompiler__CompileFunctionInContext( const v8::Function* v8__ScriptCompiler__CompileFunction(
const v8::Context* context, v8::ScriptCompiler::Source* source, const v8::Context* context, v8::ScriptCompiler::Source* source,
size_t arguments_count, const v8::String** arguments, size_t arguments_count, const v8::String** arguments,
size_t context_extensions_count, const v8::Object** context_extensions, size_t context_extensions_count, const v8::Object** context_extensions,
v8::ScriptCompiler::CompileOptions options, v8::ScriptCompiler::CompileOptions options,
v8::ScriptCompiler::NoCacheReason no_cache_reason) { v8::ScriptCompiler::NoCacheReason no_cache_reason) {
return maybe_local_to_ptr(v8::ScriptCompiler::CompileFunctionInContext( return maybe_local_to_ptr(v8::ScriptCompiler::CompileFunction(
ptr_to_local(context), source, arguments_count, ptr_to_local(context), source, arguments_count,
reinterpret_cast<v8::Local<v8::String>*>(arguments), reinterpret_cast<v8::Local<v8::String>*>(arguments),
context_extensions_count, context_extensions_count,
reinterpret_cast<v8::Local<v8::Object>*>(context_extensions), options, reinterpret_cast<v8::Local<v8::Object>*>(context_extensions), options,
no_cache_reason, nullptr)); no_cache_reason));
} }
const v8::UnboundScript* v8__ScriptCompiler__CompileUnboundScript( const v8::UnboundScript* v8__ScriptCompiler__CompileUnboundScript(
@ -687,7 +684,8 @@ const v8::Boolean* v8__Value__ToBoolean(const v8::Value& self,
void v8__Value__InstanceOf(const v8::Value& self, const v8::Context& context, void v8__Value__InstanceOf(const v8::Value& self, const v8::Context& context,
const v8::Object& object, v8::Maybe<bool>* out) { const v8::Object& object, v8::Maybe<bool>* out) {
v8::Value* self_non_const = const_cast<v8::Value*>(&self); v8::Value* self_non_const = const_cast<v8::Value*>(&self);
*out = self_non_const->InstanceOf(ptr_to_local(&context), ptr_to_local(&object)); *out =
self_non_const->InstanceOf(ptr_to_local(&context), ptr_to_local(&object));
} }
void v8__Value__NumberValue(const v8::Value& self, const v8::Context& context, void v8__Value__NumberValue(const v8::Value& self, const v8::Context& context,
@ -1048,9 +1046,12 @@ void v8__ObjectTemplate__SetAccessorWithSetter(
} }
void v8__ObjectTemplate__SetAccessorProperty(const v8::ObjectTemplate& self, void v8__ObjectTemplate__SetAccessorProperty(const v8::ObjectTemplate& self,
const v8::Name& key, const v8::Name& key,
v8::FunctionTemplate& getter, v8::FunctionTemplate& setter, v8::PropertyAttribute attr) { v8::FunctionTemplate& getter,
ptr_to_local(&self)->SetAccessorProperty(ptr_to_local(&key), ptr_to_local(&getter), ptr_to_local(&setter), attr); v8::FunctionTemplate& setter,
v8::PropertyAttribute attr) {
ptr_to_local(&self)->SetAccessorProperty(
ptr_to_local(&key), ptr_to_local(&getter), ptr_to_local(&setter), attr);
} }
const v8::Object* v8__Object__New(v8::Isolate* isolate) { const v8::Object* v8__Object__New(v8::Isolate* isolate) {
@ -1174,10 +1175,11 @@ MaybeBool v8__Object__HasIndex(const v8::Object& self,
ptr_to_local(&self)->Has(ptr_to_local(&context), index)); ptr_to_local(&self)->Has(ptr_to_local(&context), index));
} }
MaybeBool v8__Object__HasOwnProperty(const v8::Object& self, const v8::Context& context, MaybeBool v8__Object__HasOwnProperty(const v8::Object& self,
const v8::Name& key) { const v8::Context& context,
return maybe_to_maybe_bool( const v8::Name& key) {
ptr_to_local(&self)->HasOwnProperty(ptr_to_local(&context), ptr_to_local(&key))); return maybe_to_maybe_bool(ptr_to_local(&self)->HasOwnProperty(
ptr_to_local(&context), ptr_to_local(&key)));
} }
MaybeBool v8__Object__Delete(const v8::Object& self, const v8::Context& context, MaybeBool v8__Object__Delete(const v8::Object& self, const v8::Context& context,
@ -1894,7 +1896,8 @@ v8::ScriptCompiler::CachedData* v8__UnboundModuleScript__CreateCodeCache(
ptr_to_local(&unbound_module_script)); ptr_to_local(&unbound_module_script));
} }
v8::ScriptCompiler::CachedData* v8__Function__CreateCodeCache(const v8::Function& self) { v8::ScriptCompiler::CachedData* v8__Function__CreateCodeCache(
const v8::Function& self) {
return v8::ScriptCompiler::CreateCodeCacheForFunction(ptr_to_local(&self)); return v8::ScriptCompiler::CreateCodeCacheForFunction(ptr_to_local(&self));
} }
@ -1920,9 +1923,9 @@ const v8::Value* v8__ScriptOrModule__GetResourceName(
return local_to_ptr(ptr_to_local(&self)->GetResourceName()); return local_to_ptr(ptr_to_local(&self)->GetResourceName());
} }
const v8::PrimitiveArray* v8__ScriptOrModule__GetHostDefinedOptions( const v8::Data* v8__ScriptOrModule__HostDefinedOptions(
const v8::ScriptOrModule& self) { const v8::ScriptOrModule& self) {
return local_to_ptr(ptr_to_local(&self)->GetHostDefinedOptions()); return local_to_ptr(ptr_to_local(&self)->HostDefinedOptions());
} }
const v8::SharedArrayBuffer* v8__SharedArrayBuffer__New__with_byte_length( const v8::SharedArrayBuffer* v8__SharedArrayBuffer__New__with_byte_length(

View file

@ -172,11 +172,6 @@ impl<T> Global<T> {
pub fn open<'a>(&'a self, scope: &mut Isolate) -> &'a T { pub fn open<'a>(&'a self, scope: &mut Isolate) -> &'a T {
Handle::open(self, scope) Handle::open(self, scope)
} }
#[deprecated = "use Global::open() instead"]
pub fn get<'a>(&'a self, scope: &mut Isolate) -> &'a T {
Handle::open(self, scope)
}
} }
impl<T> Clone for Global<T> { impl<T> Clone for Global<T> {

View file

@ -15,6 +15,7 @@ use crate::wasm::WasmStreaming;
use crate::Array; use crate::Array;
use crate::CallbackScope; use crate::CallbackScope;
use crate::Context; use crate::Context;
use crate::Data;
use crate::FixedArray; use crate::FixedArray;
use crate::Function; use crate::Function;
use crate::HandleScope; use crate::HandleScope;
@ -23,7 +24,6 @@ use crate::Message;
use crate::Module; use crate::Module;
use crate::Object; use crate::Object;
use crate::Promise; use crate::Promise;
use crate::ScriptOrModule;
use crate::String; use crate::String;
use crate::Value; use crate::Value;
@ -96,7 +96,7 @@ pub type PromiseRejectCallback = extern "C" fn(PromiseRejectMessage);
pub type HostInitializeImportMetaObjectCallback = pub type HostInitializeImportMetaObjectCallback =
extern "C" fn(Local<Context>, Local<Module>, Local<Object>); extern "C" fn(Local<Context>, Local<Module>, Local<Object>);
/// HostImportModuleDynamicallyWithImportAssertionsCallback is called when we require the /// HostImportModuleDynamicallyCallback is called when we require the
/// embedder to load a module. This is used as part of the dynamic /// embedder to load a module. This is used as part of the dynamic
/// import syntax. /// import syntax.
/// ///
@ -114,13 +114,13 @@ pub type HostInitializeImportMetaObjectCallback =
/// this promise with the exception. If the promise creation itself /// this promise with the exception. If the promise creation itself
/// fails (e.g. due to stack overflow), the embedder must propagate /// fails (e.g. due to stack overflow), the embedder must propagate
/// that exception by returning an empty MaybeLocal. /// that exception by returning an empty MaybeLocal.
pub type HostImportModuleDynamicallyWithImportAssertionsCallback = pub type HostImportModuleDynamicallyCallback = extern "C" fn(
extern "C" fn( Local<Context>,
Local<Context>, Local<Data>,
Local<ScriptOrModule>, Local<Value>,
Local<String>, Local<String>,
Local<FixedArray>, Local<FixedArray>,
) -> *mut Promise; ) -> *mut Promise;
pub type InterruptCallback = pub type InterruptCallback =
extern "C" fn(isolate: &mut Isolate, data: *mut c_void); extern "C" fn(isolate: &mut Isolate, data: *mut c_void);
@ -213,7 +213,7 @@ extern "C" {
); );
fn v8__Isolate__SetHostImportModuleDynamicallyCallback( fn v8__Isolate__SetHostImportModuleDynamicallyCallback(
isolate: *mut Isolate, isolate: *mut Isolate,
callback: HostImportModuleDynamicallyWithImportAssertionsCallback, callback: HostImportModuleDynamicallyCallback,
); );
fn v8__Isolate__RequestInterrupt( fn v8__Isolate__RequestInterrupt(
isolate: *const Isolate, isolate: *const Isolate,
@ -581,7 +581,7 @@ impl Isolate {
/// import() language feature to load modules. /// import() language feature to load modules.
pub fn set_host_import_module_dynamically_callback( pub fn set_host_import_module_dynamically_callback(
&mut self, &mut self,
callback: HostImportModuleDynamicallyWithImportAssertionsCallback, callback: HostImportModuleDynamicallyCallback,
) { ) {
unsafe { unsafe {
v8__Isolate__SetHostImportModuleDynamicallyCallback(self, callback) v8__Isolate__SetHostImportModuleDynamicallyCallback(self, callback)

View file

@ -91,7 +91,7 @@ pub use handle::Global;
pub use handle::Handle; pub use handle::Handle;
pub use handle::Local; pub use handle::Local;
pub use isolate::HeapStatistics; pub use isolate::HeapStatistics;
pub use isolate::HostImportModuleDynamicallyWithImportAssertionsCallback; pub use isolate::HostImportModuleDynamicallyCallback;
pub use isolate::HostInitializeImportMetaObjectCallback; pub use isolate::HostInitializeImportMetaObjectCallback;
pub use isolate::Isolate; pub use isolate::Isolate;
pub use isolate::IsolateHandle; pub use isolate::IsolateHandle;

View file

@ -38,7 +38,7 @@ extern "C" {
options: CompileOptions, options: CompileOptions,
no_cache_reason: NoCacheReason, no_cache_reason: NoCacheReason,
) -> *const Script; ) -> *const Script;
fn v8__ScriptCompiler__CompileFunctionInContext( fn v8__ScriptCompiler__CompileFunction(
context: *const Context, context: *const Context,
source: *mut Source, source: *mut Source,
arguments_count: usize, arguments_count: usize,
@ -255,7 +255,7 @@ pub fn compile<'s>(
} }
} }
pub fn compile_function_in_context<'s>( pub fn compile_function<'s>(
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
mut source: Source, mut source: Source,
arguments: &[Local<String>], arguments: &[Local<String>],
@ -267,7 +267,7 @@ pub fn compile_function_in_context<'s>(
let context_extensions = Local::slice_into_raw(context_extensions); let context_extensions = Local::slice_into_raw(context_extensions);
unsafe { unsafe {
scope.cast_local(|sd| { scope.cast_local(|sd| {
v8__ScriptCompiler__CompileFunctionInContext( v8__ScriptCompiler__CompileFunction(
&*sd.get_current_context(), &*sd.get_current_context(),
&mut source, &mut source,
arguments.len(), arguments.len(),

View file

@ -1,6 +1,6 @@
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
use crate::Data;
use crate::Local; use crate::Local;
use crate::PrimitiveArray;
use crate::ScriptOrModule; use crate::ScriptOrModule;
use crate::Value; use crate::Value;
@ -9,9 +9,9 @@ extern "C" {
this: *const ScriptOrModule, this: *const ScriptOrModule,
) -> *const Value; ) -> *const Value;
fn v8__ScriptOrModule__GetHostDefinedOptions( fn v8__ScriptOrModule__HostDefinedOptions(
this: *const ScriptOrModule, this: *const ScriptOrModule,
) -> *const PrimitiveArray; ) -> *const Data;
} }
impl ScriptOrModule { impl ScriptOrModule {
@ -29,12 +29,12 @@ impl ScriptOrModule {
/// The options that were passed by the embedder as HostDefinedOptions to the /// The options that were passed by the embedder as HostDefinedOptions to the
/// ScriptOrigin. /// ScriptOrigin.
pub fn get_host_defined_options(&self) -> Local<PrimitiveArray> { pub fn host_defined_options(&self) -> Local<Data> {
// Note: the C++ `v8::ScriptOrModule::GetHostDefinedOptions()` does not // Note: the C++ `v8::ScriptOrModule::HostDefinedOptions()` does not
// actually return a local handle, but rather a handle whose lifetime is // actually return a local handle, but rather a handle whose lifetime is
// bound to the related `ScriptOrModule` object. // bound to the related `ScriptOrModule` object.
unsafe { unsafe {
let ptr = v8__ScriptOrModule__GetHostDefinedOptions(self); let ptr = v8__ScriptOrModule__HostDefinedOptions(self);
Local::from_raw(ptr).unwrap() Local::from_raw(ptr).unwrap()
} }
} }

View file

@ -2644,7 +2644,8 @@ fn import_assertions() {
extern "C" fn dynamic_import_cb( extern "C" fn dynamic_import_cb(
context: v8::Local<v8::Context>, context: v8::Local<v8::Context>,
_referrer: v8::Local<v8::ScriptOrModule>, _host_defined_options: v8::Local<v8::Data>,
_resource_name: v8::Local<v8::Value>,
_specifier: v8::Local<v8::String>, _specifier: v8::Local<v8::String>,
import_assertions: v8::Local<v8::FixedArray>, import_assertions: v8::Local<v8::FixedArray>,
) -> *mut v8::Promise { ) -> *mut v8::Promise {
@ -3224,7 +3225,8 @@ fn dynamic_import() {
extern "C" fn dynamic_import_cb( extern "C" fn dynamic_import_cb(
context: v8::Local<v8::Context>, context: v8::Local<v8::Context>,
_referrer: v8::Local<v8::ScriptOrModule>, _host_defined_options: v8::Local<v8::Data>,
_resource_name: v8::Local<v8::Value>,
specifier: v8::Local<v8::String>, specifier: v8::Local<v8::String>,
_import_assertions: v8::Local<v8::FixedArray>, _import_assertions: v8::Local<v8::FixedArray>,
) -> *mut v8::Promise { ) -> *mut v8::Promise {
@ -5607,7 +5609,7 @@ fn function_code_cache() {
None, None,
); );
let word = v8::String::new(scope, "word").unwrap(); let word = v8::String::new(scope, "word").unwrap();
let function = v8::script_compiler::compile_function_in_context( let function = v8::script_compiler::compile_function(
scope, scope,
source, source,
&[word], &[word],
@ -5630,7 +5632,7 @@ fn function_code_cache() {
code_cache, code_cache,
); );
let word = v8::String::new(scope, "word").unwrap(); let word = v8::String::new(scope, "word").unwrap();
let function = v8::script_compiler::compile_function_in_context( let function = v8::script_compiler::compile_function(
scope, scope,
source, source,
&[word], &[word],
@ -5712,7 +5714,7 @@ fn code_cache_script() {
} }
#[test] #[test]
fn compile_function_in_context() { fn compile_function() {
let _setup_guard = setup(); let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default()); let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate); let scope = &mut v8::HandleScope::new(isolate);
@ -5729,7 +5731,7 @@ fn compile_function_in_context() {
let source = v8::String::new(scope, "return x * y").unwrap(); let source = v8::String::new(scope, "return x * y").unwrap();
let source = v8::script_compiler::Source::new(source, None); let source = v8::script_compiler::Source::new(source, None);
let function = v8::script_compiler::compile_function_in_context( let function = v8::script_compiler::compile_function(
scope, scope,
source, source,
&[argument], &[argument],

View file

@ -39,7 +39,7 @@ fn set_entropy_source() {
unsafe { unsafe {
v8::V8::dispose(); v8::V8::dispose();
} }
v8::V8::shutdown_platform(); v8::V8::dispose_platform();
// All runs should have produced the same value. // All runs should have produced the same value.
assert_eq!(results.len(), N); assert_eq!(results.len(), N);

View file

@ -28,5 +28,5 @@ fn concurrent_isolate_creation_and_disposal() {
} }
unsafe { v8::V8::dispose() }; unsafe { v8::V8::dispose() };
v8::V8::shutdown_platform(); v8::V8::dispose_platform();
} }

View file

@ -18,5 +18,5 @@ fn single_threaded_default_platform() {
} }
unsafe { v8::V8::dispose() }; unsafe { v8::V8::dispose() };
v8::V8::shutdown_platform(); v8::V8::dispose_platform();
} }

2
v8

@ -1 +1 @@
Subproject commit 54421808b7ceeed65cb1c376dcfcacb4a0ed2c0f Subproject commit 12395308dcfabf28b339e2948eb34fb63954025a