From 50c835d98c1318a5a5bc3a6bca3012f19a36975c Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Sat, 22 Feb 2025 09:39:46 +0800 Subject: [PATCH 001/266] [WebNN] Fix missing parameter (#23778) Missing first parameter when invoking `jsepEnsureTensor`. --- onnxruntime/core/providers/webnn/webnn_execution_provider.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index df95b653bd863..39e6520e3912b 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -293,7 +293,8 @@ class WebNNMemcpy : public OpKernel { shape.call("push", SafeInt(dim).Ref()); } - jsepEnsureTensor(reinterpret_cast(Y->MutableDataRaw()), + jsepEnsureTensor(emscripten::val::undefined(), + reinterpret_cast(Y->MutableDataRaw()), Y->GetElementType(), shape, false) .await(); From 9799c3fbd26fd5dd5cc161abc2a84bd21ba91a30 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Sat, 22 Feb 2025 23:51:05 +0800 Subject: [PATCH 002/266] [webgpu] Enable FlashAttention for GQA (#23761) ### Description ### Motivation and Context --- .../webgpu/bert/flash_attention.cc | 180 ++++++++++-------- .../contrib_ops/webgpu/bert/flash_attention.h | 14 +- .../webgpu/bert/group_query_attention.cc | 6 + 3 files changed, 116 insertions(+), 84 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index b51c2fbe27e1d..57ae8a7e5ba74 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -26,73 +26,85 @@ Status CopyKVCacheProgram::GenerateShaderCode(ShaderHelper& shader) const { // H - head size or hidden dimension for each qkv head. // KV cache is stored as BN(total_sequence_length)H // Attention bias is in BN(total_sequence_length) - shader.AddInput("key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); - shader.AddInput("value", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& key = shader.AddInput("key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias | ShaderUsage::UseIndicesTypeAlias); + shader.AddInput("value", ShaderUsage::UseUniform); + const auto& present_key = shader.AddOutput("present_key", ShaderUsage::UseUniform); + const auto& present_value = shader.AddOutput("present_value", ShaderUsage::UseUniform); + const auto& valid_present_shape = shader.AddIndices("valid_present_shape"); + + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.valid_present_size") + << " let output_indices = " << valid_present_shape.OffsetToIndices("global_idx") << ";\n" + << " let head_size_id = output_indices[3];\n" + " let sequence_id = output_indices[2];\n" + " let num_head_id = output_indices[1];\n" + " let batch = output_indices[0];\n" + << " let present_offset = " << (past_present_share_buffer_ ? present_key.IndicesToOffset("output_indices") : "global_idx") << ";\n"; if (has_past_) { - shader.AddInput("past_key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); - shader.AddInput("past_value", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); - } - shader.AddOutput("present_key", ShaderUsage::UseUniform); - shader.AddOutput("present_value", ShaderUsage::UseUniform); - - shader.MainFunctionBody() << "let headIdx = workgroup_id.z;\n" - << "let kIdx = workgroup_id.x;\n" - << "let presentKeyOffset = headIdx * num_workgroups.x * uniforms.vectorized_head_size + (kIdx)*uniforms.vectorized_head_size;\n"; - if (has_past_) { - shader.MainFunctionBody() << "if (kIdx < uniforms.past_sequence_length) {\n" - << " let pastKeyOffset = headIdx * uniforms.past_sequence_length * uniforms.vectorized_head_size + (kIdx)*uniforms.vectorized_head_size;\n" - << " for (var w: u32 = 0u; w < uniforms.vectorized_head_size; w ++) {\n" - << " present_key[presentKeyOffset+w] = past_key[pastKeyOffset+w];\n" - << " present_value[presentKeyOffset+w] = past_value[pastKeyOffset+w];\n" - << " }\n" - << "}\n" - << "else if (kIdx >= uniforms.past_sequence_length) {\n"; + shader.MainFunctionBody() << "let past_sequence_length = uniforms.past_sequence_length;\n"; + if (past_present_share_buffer_) { + shader.MainFunctionBody() << "if (sequence_id >= past_sequence_length) {\n" + << " let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id - past_sequence_length, head_size_id)" : "key_indices_t(batch, sequence_id - past_sequence_length, num_head_id, head_size_id)") << ";\n" + << " " << present_key.SetByOffset("present_offset", "key[offset]") << ";\n" + << " " << present_value.SetByOffset("present_offset", "value[offset]") << ";\n" + << "}"; + } else { + const auto& past_key = shader.AddInput("past_key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias | ShaderUsage::UseIndicesTypeAlias); + shader.AddInput("past_value", ShaderUsage::UseUniform); + shader.MainFunctionBody() << "if (sequence_id < past_sequence_length) {\n" + << " let pastOffset = " << past_key.IndicesToOffset("past_key_indices_t(batch, num_head_id, sequence_id, head_size_id)") << ";\n" + << " " << present_key.SetByOffset("present_offset", "past_key[pastOffset]") << ";\n" + << " " << present_value.SetByOffset("present_offset", "past_value[pastOffset]") << ";\n" + << "} else {\n" + << " let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id - past_sequence_length, head_size_id)" : "key_indices_t(batch, sequence_id - past_sequence_length, num_head_id, head_size_id)") << ";\n" + << " " << present_key.SetByOffset("present_offset", "key[offset]") << ";\n" + << " " << present_value.SetByOffset("present_offset", "value[offset]") << ";\n" + << "}"; + } } else { - shader.MainFunctionBody() << "if (kIdx >= uniforms.past_sequence_length) {\n"; + shader.MainFunctionBody() << "let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id, head_size_id)" : "key_indices_t(batch, sequence_id, num_head_id, head_size_id)") << ";\n" + << present_key.SetByOffset("present_offset", "key[offset]") << ";\n" + << present_value.SetByOffset("present_offset", "value[offset]") << ";\n"; } - shader.MainFunctionBody() << " let nkIdx = kIdx - uniforms.past_sequence_length;\n" - << " // Assumes kv have BSNH layout. num_workgroups.z is the num_head as per the dispatch requirement.\n" - << " let nOffset = nkIdx * uniforms.vectorized_head_size * num_workgroups.z + headIdx*uniforms.vectorized_head_size;\n" - << " // Assumes kv have BNSH layout.\n" - << " // let nOffset = headIdx * uniforms.kv_sequence_length * uniforms.vectorized_head_size + nkIdx * uniforms.vectorized_head_size;\n" - << " for (var w: u32 = 0u; w < uniforms.vectorized_head_size; w ++) {\n" - << " present_key[presentKeyOffset+w] = key[nOffset+w];\n" - << " present_value[presentKeyOffset+w] = value[nOffset+w];\n" - << " }\n" - << "}\n"; - return Status::OK(); } Status CopyKVCache(onnxruntime::webgpu::ComputeContext& context, const WebgpuAttentionParameters& parameters, const Tensor* K, const Tensor* past_key, Tensor* present_key, - const Tensor* V, const Tensor* past_value, Tensor* present_value, - int past_sequence_length, int total_sequence_length) { + const Tensor* V, const Tensor* past_value, Tensor* present_value) { // CopyKVCache takes past key/value and current key/value and copies them to present key and value. // This makes it so that FlashAttention only needs to look at present key and value, and saves // number of input buffers in the shader, which we run out of (<=8) without this optimization. const int components = parameters.head_size_ % 4 == 0 ? 4 : (parameters.head_size_ % 2 == 0 ? 2 : 1); - bool has_past = (past_sequence_length != 0); - CopyKVCacheProgram program{"CopyKVCache", has_past}; - if (has_past) { - program.AddInputs({{K, ProgramTensorMetadataDependency::TypeAndRank, components}, - {V, ProgramTensorMetadataDependency::TypeAndRank, components}, - {past_key, ProgramTensorMetadataDependency::TypeAndRank, components}, - {past_value, ProgramTensorMetadataDependency::TypeAndRank, components}}); - } else { + // parameters.total_sequence_length_ is past_sequence_length + kv_sequence_length. + // parameters.kv_num_heads_ may be smaller than parameters.num_heads_ when parameters.is_gqa_ is true. + int num_heads = parameters.is_gqa_ ? parameters.kv_num_heads_ : parameters.num_heads_; + TensorShape valid_present_shape{parameters.batch_size_, num_heads, parameters.total_sequence_length_, parameters.head_size_ / components}; + int64_t valid_kv_size = valid_present_shape.Size(); + bool has_past = (parameters.past_sequence_length_ > 0); + CopyKVCacheProgram program{"CopyKVCache", has_past, parameters.qkv_format_ == Q_K_V_BSNH_BNSH_BNSH, parameters.past_present_share_buffer_}; + if (parameters.qkv_format_ == Q_K_V_BSNH_BNSH_BNSH) { program.AddInputs({{K, ProgramTensorMetadataDependency::TypeAndRank, components}, {V, ProgramTensorMetadataDependency::TypeAndRank, components}}); + } else { + ORT_ENFORCE(parameters.qkv_format_ == Q_K_V_BSNH, "qkv format ", parameters.qkv_format_, " is not supported yet in CopyKVCache."); + TensorShape reshaped_KV_shape{parameters.batch_size_, parameters.kv_sequence_length_, num_heads, parameters.head_size_ / components}; + program.AddInputs({{K, ProgramTensorMetadataDependency::TypeAndRank, reshaped_KV_shape, components}, + {V, ProgramTensorMetadataDependency::TypeAndRank, reshaped_KV_shape, components}}); + } + if (has_past && !parameters.past_present_share_buffer_) { + program.AddInputs({{past_key, ProgramTensorMetadataDependency::TypeAndRank, components}, + {past_value, ProgramTensorMetadataDependency::TypeAndRank, components}}); } - program.AddOutputs({{present_key, ProgramTensorMetadataDependency::Rank, components}, - {present_value, ProgramTensorMetadataDependency::Rank, components}}); - - program.SetDispatchGroupSize(total_sequence_length, 1, parameters.num_heads_) - .SetWorkgroupSize(1) - .CacheHint(std::to_string(components) + std::to_string(has_past)) - .AddUniformVariables({{static_cast(past_sequence_length)}, - {static_cast(parameters.kv_sequence_length_)}, - {static_cast(parameters.head_size_ / components)}}); + {present_value, ProgramTensorMetadataDependency::Rank, components}}) + .AddIndices(valid_present_shape); + program.SetDispatchGroupSize(gsl::narrow(valid_kv_size + 63 / 64)) + .SetWorkgroupSize(64) + .CacheHint(has_past, parameters.qkv_format_, parameters.past_present_share_buffer_) + .AddUniformVariables({{static_cast(valid_kv_size)}, + // Note that when parameters.past_present_share_buffer_ is true, parameters.past_sequence_length_ will become to + // max_sequence_length. To get a valid past_sequence_length, we use total_sequence_length - kv_sequence_length. + {static_cast(parameters.total_sequence_length_ - parameters.kv_sequence_length_)}}); return context.RunProgram(program); } @@ -156,7 +168,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { for (var idx:u32 = local_idx; idx < qkv_head_size_vec*k_step; idx+=workgroup_size_x) { let slot = u32(idx/qkv_head_size_vec); - let val = select(q_value_t(0), present_key[offset+idx], k_start + slot < uniforms.present_sequence_length); + let val = select(q_value_t(0), present_key[offset+idx], k_start + slot < uniforms.total_sequence_length); k_tile[slot][idx%qkv_head_size_vec] = val; } } @@ -167,7 +179,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { for (var idx:u32 = local_idx; idx < qkv_head_size_vec*k_step; idx+=workgroup_size_x) { let slot = u32(idx/qkv_head_size_vec); - let val = select(q_value_t(0), present_value[offset+idx], v_start + slot < uniforms.present_sequence_length); + let val = select(q_value_t(0), present_value[offset+idx], v_start + slot < uniforms.total_sequence_length); v_tile[slot][idx%qkv_head_size_vec] = val; } } @@ -187,12 +199,12 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { fn loadAttentionBias(q_idx_global : u32, k_idx_global : u32, head_idx: u32) -> vec4 { // Stored as float16[batch_size,num_heads,new_seq_length,total_sequence_length] - if (q_idx_global >= uniforms.new_sequence_length || k_idx_global >= uniforms.present_sequence_length) { + if (q_idx_global >= uniforms.new_sequence_length || k_idx_global >= uniforms.total_sequence_length) { return vec4(0); } - let offset_base = head_idx * uniforms.new_sequence_length * uniforms.present_sequence_length + q_idx_global * uniforms.present_sequence_length; + let offset_base = head_idx * uniforms.new_sequence_length * uniforms.total_sequence_length + q_idx_global * uniforms.total_sequence_length; let offset = offset_base + k_idx_global; - let offset_max = offset_base + uniforms.present_sequence_length; + let offset_max = offset_base + uniforms.total_sequence_length; let c1 = q_element_t(attention_bias[min(offset, offset_max)]); let c2 = q_element_t(attention_bias[min(offset+1, offset_max)]); let c3 = q_element_t(attention_bias[min(offset+2, offset_max)]); @@ -227,11 +239,11 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { var previous_max : q_element_t = min_value; var previous_denom : q_element_t = 0; - for(var k_start = 0u; k_start < uniforms.present_sequence_length; k_start+=capped_sg_size) + for(var k_start = 0u; k_start < uniforms.total_sequence_length; k_start+=capped_sg_size) { workgroupBarrier(); - loadk(k_start, head_idx, local_idx, capped_sg_size); - loadv(k_start, head_idx, local_idx, capped_sg_size); + loadk(k_start, head_idx / uniforms.n_reps, local_idx, capped_sg_size); + loadv(k_start, head_idx / uniforms.n_reps, local_idx, capped_sg_size); workgroupBarrier(); // Compute QKt @@ -288,24 +300,26 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { qk_4 = qk_4 * q_element_t(uniforms.alpha) + loadAttentionBias(q_idx_global, k_start+12, head_idx); } + let seq_causal_length = select(uniforms.total_sequence_length, q_idx_global + 1, uniforms.is_gqa > 0); // Neuter qk values where K is out of bounds. - qk_1[1] = select(min_value, qk_1[1], k_start+1 < uniforms.present_sequence_length); - qk_1[2] = select(min_value, qk_1[2], k_start+2 < uniforms.present_sequence_length); - qk_1[3] = select(min_value, qk_1[3], k_start+3 < uniforms.present_sequence_length); - qk_2[0] = select(min_value, qk_2[0], k_start+4 < uniforms.present_sequence_length); - qk_2[1] = select(min_value, qk_2[1], k_start+5 < uniforms.present_sequence_length); - qk_2[2] = select(min_value, qk_2[2], k_start+6 < uniforms.present_sequence_length); - qk_2[3] = select(min_value, qk_2[3], k_start+7 < uniforms.present_sequence_length); + qk_1[0] = select(min_value, qk_1[0], k_start+0 < seq_causal_length); + qk_1[1] = select(min_value, qk_1[1], k_start+1 < seq_causal_length); + qk_1[2] = select(min_value, qk_1[2], k_start+2 < seq_causal_length); + qk_1[3] = select(min_value, qk_1[3], k_start+3 < seq_causal_length); + qk_2[0] = select(min_value, qk_2[0], k_start+4 < seq_causal_length); + qk_2[1] = select(min_value, qk_2[1], k_start+5 < seq_causal_length); + qk_2[2] = select(min_value, qk_2[2], k_start+6 < seq_causal_length); + qk_2[3] = select(min_value, qk_2[3], k_start+7 < seq_causal_length); if (sg_size > 8) { - qk_3[0] = select(min_value, qk_3[0], k_start+8 < uniforms.present_sequence_length); - qk_3[1] = select(min_value, qk_3[1], k_start+9 < uniforms.present_sequence_length); - qk_3[2] = select(min_value, qk_3[2], k_start+10 < uniforms.present_sequence_length); - qk_3[3] = select(min_value, qk_3[3], k_start+11 < uniforms.present_sequence_length); - qk_4[0] = select(min_value, qk_4[0], k_start+12 < uniforms.present_sequence_length); - qk_4[1] = select(min_value, qk_4[1], k_start+13 < uniforms.present_sequence_length); - qk_4[2] = select(min_value, qk_4[2], k_start+14 < uniforms.present_sequence_length); - qk_4[3] = select(min_value, qk_4[3], k_start+15 < uniforms.present_sequence_length); + qk_3[0] = select(min_value, qk_3[0], k_start+8 < seq_causal_length); + qk_3[1] = select(min_value, qk_3[1], k_start+9 < seq_causal_length); + qk_3[2] = select(min_value, qk_3[2], k_start+10 < seq_causal_length); + qk_3[3] = select(min_value, qk_3[3], k_start+11 < seq_causal_length); + qk_4[0] = select(min_value, qk_4[0], k_start+12 < seq_causal_length); + qk_4[1] = select(min_value, qk_4[1], k_start+13 < seq_causal_length); + qk_4[2] = select(min_value, qk_4[2], k_start+14 < seq_causal_length); + qk_4[3] = select(min_value, qk_4[3], k_start+15 < seq_causal_length); } // @@ -347,6 +361,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { } let sum_vec = qk_1 + qk_2 + qk_3 + qk_4; let sum = sum_vec.x + sum_vec.y + sum_vec.z + sum_vec.w; + // Compute lhs term of update di prime and the compute di prime. let dleft = previous_denom * exp(previous_max-new_max); var d = dleft + sum; @@ -364,7 +379,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { if (sg_size > 8) { for (var i:u32 = 0; i < qkv_head_size_vec; i++) { - var val = select(vec4(0), v_tile[capped_sg_id][i], k_start + capped_sg_id < uniforms.present_sequence_length); + var val = select(vec4(0), v_tile[capped_sg_id][i], k_start + capped_sg_id < seq_causal_length); var sum = subgroupShuffle(val, 0) * qk_1[0]; sum += subgroupShuffle(val, 1) * qk_1[1]; sum += subgroupShuffle(val, 2) * qk_1[2]; @@ -388,7 +403,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { { for (var i:u32 = 0; i < qkv_head_size_vec; i++) { - var val = select(vec4(0), v_tile[capped_sg_id][i], k_start + capped_sg_id < uniforms.present_sequence_length); + var val = select(vec4(0), v_tile[capped_sg_id][i], k_start + capped_sg_id < seq_causal_length); var sum = subgroupShuffle(val, 0) * qk_1[0]; sum += subgroupShuffle(val, 1) * qk_1[1]; sum += subgroupShuffle(val, 2) * qk_1[2]; @@ -413,15 +428,17 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, const Tensor* attention_bias, Tensor* output, const Tensor* past_key, Tensor* present_key, const Tensor* past_value, Tensor* present_value, const WebgpuAttentionParameters& parameters, onnxruntime::webgpu::ComputeContext& context) { - ORT_RETURN_IF_ERROR(CopyKVCache(context, parameters, K, past_key, present_key, V, past_value, present_value, parameters.past_sequence_length_, parameters.total_sequence_length_)); + ORT_RETURN_IF_ERROR(CopyKVCache(context, parameters, K, past_key, present_key, V, past_value, present_value)); const uint32_t tile_size = 64; bool has_attention_bias = attention_bias != nullptr; FlashAttentionProgram program{"FlashAttention", has_attention_bias, parameters.head_size_, parameters.num_heads_}; program.AddInputs({{Q, ProgramTensorMetadataDependency::TypeAndRank, 4}, {present_key, ProgramTensorMetadataDependency::TypeAndRank, 4}, - {present_value, ProgramTensorMetadataDependency::TypeAndRank, 4}, - {attention_bias, ProgramTensorMetadataDependency::TypeAndRank}}); + {present_value, ProgramTensorMetadataDependency::TypeAndRank, 4}}); + if (has_attention_bias) { + program.AddInputs({{attention_bias, ProgramTensorMetadataDependency::TypeAndRank}}); + } program.AddOutputs({{output, ProgramTensorMetadataDependency::TypeAndRank, 4}}); const float alpha = parameters.scale_ == 0.0f ? 1.f / sqrt(static_cast(parameters.head_size_)) : parameters.scale_; @@ -433,6 +450,9 @@ Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, co .CacheHint(cache_hint) .AddUniformVariables({{static_cast(parameters.sequence_length_)}, {static_cast(parameters.total_sequence_length_)}, + {static_cast(parameters.past_present_share_buffer_ ? parameters.past_sequence_length_ : parameters.total_sequence_length_)}, + {static_cast(parameters.is_gqa_ ? 1 : 0)}, + {static_cast(parameters.n_reps)}, {alpha}}); return context.RunProgram(program); @@ -441,6 +461,8 @@ Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, co bool CanApplyFlashAttention(const Tensor* bias, const Tensor* present_key, const Tensor* present_value, const WebgpuAttentionParameters& parameters, onnxruntime::webgpu::ComputeContext& context) { return parameters.batch_size_ == 1 && + !parameters.is_packed_qkv_ && + parameters.head_size_ == parameters.v_head_size_ && bias == nullptr && parameters.sequence_length_ > 1 && context.Device().HasFeature(wgpu::FeatureName::Subgroups) && diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h index 489ae7375ecc3..c31a3bf9b7907 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h @@ -17,18 +17,19 @@ using namespace onnxruntime::webgpu; class CopyKVCacheProgram final : public Program { public: - CopyKVCacheProgram(const std::string& kernel_name, bool has_past) - : Program{kernel_name}, has_past_(has_past) { + CopyKVCacheProgram(const std::string& kernel_name, bool has_past, bool kv_BNSH, bool past_present_share_buffer) + : Program{kernel_name}, has_past_(has_past), kv_BNSH_(kv_BNSH), past_present_share_buffer_(past_present_share_buffer) { } Status GenerateShaderCode(ShaderHelper& sh) const override; - WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"past_sequence_length", ProgramUniformVariableDataType::Uint32}, - {"kv_sequence_length", ProgramUniformVariableDataType::Uint32}, - {"vectorized_head_size", ProgramUniformVariableDataType::Uint32}); + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"valid_present_size", ProgramUniformVariableDataType::Uint32}, + {"past_sequence_length", ProgramUniformVariableDataType::Uint32}); private: bool has_past_; + bool kv_BNSH_; + bool past_present_share_buffer_; }; class FlashAttentionProgram final : public Program { @@ -46,7 +47,10 @@ class FlashAttentionProgram final : public Program { Status GenerateShaderCode(ShaderHelper& sh) const override; WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"new_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"total_sequence_length", ProgramUniformVariableDataType::Uint32}, {"present_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"is_gqa", ProgramUniformVariableDataType::Uint32}, + {"n_reps", ProgramUniformVariableDataType::Uint32}, {"alpha", ProgramUniformVariableDataType::Float32}); private: diff --git a/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc index 31c8af9b4f922..72ccbbb9b23e2 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc @@ -5,6 +5,7 @@ #include "contrib_ops/webgpu/bert/attention_common.h" #include "contrib_ops/webgpu/bert/group_query_attention.h" #include "contrib_ops/webgpu/webgpu_contrib_kernels.h" +#include "contrib_ops/webgpu/bert/flash_attention.h" #include "core/providers/webgpu/webgpu_supported_types.h" @@ -74,6 +75,11 @@ Status GroupQueryAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& Tensor* present_value = context.Output(2, present_kv_shape); parameters.past_present_share_buffer_ = present_key != nullptr && present_value != nullptr && past_key != nullptr && past_value != nullptr && past_key->DataRaw() == present_key->DataRaw() && past_value->DataRaw() == present_value->DataRaw(); + if (CanApplyFlashAttention(nullptr /* bias */, present_key, present_value, parameters, context)) { + return ApplyFlashAttention(query, key, value, nullptr /* attention_bias */, output, past_key, present_key, past_value, + present_value, parameters, context); + } + TensorShapeVector q_new_dims({parameters.batch_size_, parameters.num_heads_, parameters.sequence_length_, parameters.head_size_}); TensorShape q_new_shape(q_new_dims); From 7864192c9c5ff37be69aa3e8a16e217de22eb74a Mon Sep 17 00:00:00 2001 From: amarin16 <91211819+amarin16@users.noreply.github.com> Date: Sat, 22 Feb 2025 16:11:02 -0800 Subject: [PATCH 003/266] Bump version from 1.21 to 1.22 (#23787) The [1.21 release branch](https://github.com/microsoft/onnxruntime/tree/rel-1.21.0) has been cut, so we need to update the version in main from `1.21.0` to `1.22.0`. --- VERSION_NUMBER | 2 +- .../Training/NativeTrainingMethods.shared.cs | 2 +- docs/python/README.rst | 5 +++++ include/onnxruntime/core/session/onnxruntime_c_api.h | 2 +- js/common/lib/version.ts | 2 +- js/common/package-lock.json | 4 ++-- js/common/package.json | 2 +- js/node/lib/version.ts | 2 +- js/node/package-lock.json | 6 +++--- js/node/package.json | 2 +- js/react_native/lib/version.ts | 2 +- js/react_native/package.json | 2 +- js/react_native/yarn.lock | 2 +- js/web/lib/version.ts | 2 +- js/web/package-lock.json | 6 +++--- js/web/package.json | 2 +- onnxruntime/__init__.py | 2 +- onnxruntime/core/session/onnxruntime_c_api.cc | 8 ++++---- 18 files changed, 30 insertions(+), 25 deletions(-) diff --git a/VERSION_NUMBER b/VERSION_NUMBER index 3500250a4b05b..57807d6d0d0c0 100644 --- a/VERSION_NUMBER +++ b/VERSION_NUMBER @@ -1 +1 @@ -1.21.0 +1.22.0 diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs index b4067806c5f93..5dd5b3ac620ab 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs @@ -76,7 +76,7 @@ static NativeTrainingMethods() DOrtGetApi OrtGetApi = (DOrtGetApi)Marshal.GetDelegateForFunctionPointer(NativeMethods.OrtGetApiBase().GetApi, typeof(DOrtGetApi)); #endif - const uint ORT_API_VERSION = 21; + const uint ORT_API_VERSION = 22; #if NETSTANDARD2_0 IntPtr ortApiPtr = OrtGetApi(ORT_API_VERSION); api_ = (OrtApi)Marshal.PtrToStructure(ortApiPtr, typeof(OrtApi)); diff --git a/docs/python/README.rst b/docs/python/README.rst index cce966f7d7d0c..dbffd1d32c052 100644 --- a/docs/python/README.rst +++ b/docs/python/README.rst @@ -8,6 +8,11 @@ For more information on ONNX Runtime, please see `aka.ms/onnxruntime `_. """ -__version__ = "1.21.0" +__version__ = "1.22.0" __author__ = "Microsoft" # we need to do device version validation (for example to check Cuda version for an onnxruntime-training package). diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index ca6950af0227a..4eedcd591154f 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -2469,7 +2469,7 @@ Second example, if we wanted to add and remove some members, we'd do this: In GetApi we now make it return ort_api_3 for version 3. */ -static constexpr OrtApi ort_api_1_to_21 = { +static constexpr OrtApi ort_api_1_to_22 = { // NOTE: The ordering of these fields MUST not change after that version has shipped since existing binaries depend on this ordering. // Shipped as version 1 - DO NOT MODIFY (see above text for more information) @@ -2847,16 +2847,16 @@ static_assert(offsetof(OrtApi, AddExternalInitializersFromFilesInMemory) / sizeo static_assert(offsetof(OrtApi, SetEpDynamicOptions) / sizeof(void*) == 284, "Size of version 20 API cannot change"); // So that nobody forgets to finish an API version, this check will serve as a reminder: -static_assert(std::string_view(ORT_VERSION) == "1.21.0", +static_assert(std::string_view(ORT_VERSION) == "1.22.0", "ORT_Version change detected, please follow below steps to ensure OrtApi is updated properly"); // 1. Update the hardcoded version string in above static_assert to silence it -// 2. If there were any APIs added to ort_api_1_to_21 above: +// 2. If there were any APIs added to ort_api_1_to_22 above: // a. Add the 'End of version #' markers (pattern above should be obvious) // b. Add a static_assert in the directly above list of version sizes to ensure nobody adds any more functions to the just shipped API version ORT_API(const OrtApi*, OrtApis::GetApi, uint32_t version) { if (version >= 1 && version <= ORT_API_VERSION) - return &ort_api_1_to_21; + return &ort_api_1_to_22; fprintf(stderr, "The requested API version [%u] is not available, only API versions [1, %u] are supported in this build." From e46c0d86b9cd15fce1dd6d53fdf03a22edce1ff7 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Sun, 23 Feb 2025 22:20:09 -0800 Subject: [PATCH 004/266] [QNN EP] Use absolute path of libcdsprpc.dll on Windows so it doesn't need to be copied anywhere. (#23791) ### Description Look up and use absolute path of libcdsprpc.dll on Windows. ### Motivation and Context The QNN EP's HTP shared memory allocator requires use of the libcdsprpc shared library. On Windows, this previously required copying libcdsprpc.dll from some driver-specific path to somewhere the running code could find it. After this change, libcdsprpc.dll no longer needs to be copied. --- .../core/providers/qnn/rpcmem_library.cc | 159 +++++++++++++++--- .../core/providers/qnn/rpcmem_library.h | 8 +- .../test/providers/qnn/qnn_basic_test.cc | 14 +- onnxruntime/test/shared_lib/test_inference.cc | 15 +- 4 files changed, 146 insertions(+), 50 deletions(-) diff --git a/onnxruntime/core/providers/qnn/rpcmem_library.cc b/onnxruntime/core/providers/qnn/rpcmem_library.cc index 93c5ed54ab371..20918f8bc6de1 100644 --- a/onnxruntime/core/providers/qnn/rpcmem_library.cc +++ b/onnxruntime/core/providers/qnn/rpcmem_library.cc @@ -2,44 +2,157 @@ // Licensed under the MIT License #include "core/providers/qnn/rpcmem_library.h" + +#if defined(_WIN32) +#include + +#include +#include +#endif // defined(_WIN32) + #include "core/providers/qnn/ort_api.h" namespace onnxruntime::qnn { +// Unload the dynamic library referenced by `library_handle`. +// Avoid throwing because this may run from a dtor. +void DynamicLibraryHandleDeleter::operator()(void* library_handle) noexcept { + if (library_handle == nullptr) { + return; + } + + const auto& env = GetDefaultEnv(); + const auto unload_status = env.UnloadDynamicLibrary(library_handle); + + if (!unload_status.IsOK()) { + LOGS_DEFAULT(WARNING) << "Failed to unload dynamic library. Error: " << unload_status.ErrorMessage(); + } +} + namespace { -const PathChar* GetRpcMemSharedLibraryPath() { #if defined(_WIN32) - return ORT_TSTR("libcdsprpc.dll"); -#else - return ORT_TSTR("libcdsprpc.so"); -#endif + +struct ServiceHandleDeleter { + void operator()(SC_HANDLE handle) { ::CloseServiceHandle(handle); } +}; + +using UniqueServiceHandle = std::unique_ptr, ServiceHandleDeleter>; + +Status ReadEnvironmentVariable(const wchar_t* name, std::wstring& value_out) { + const DWORD value_size = ::GetEnvironmentVariableW(name, nullptr, 0); + ORT_RETURN_IF(value_size == 0, + "Failed to get environment variable length. GetEnvironmentVariableW error: ", ::GetLastError()); + + std::vector value(value_size); + + ORT_RETURN_IF(::GetEnvironmentVariableW(name, value.data(), value_size) == 0, + "Failed to get environment variable value. GetEnvironmentVariableW error: ", ::GetLastError()); + + value_out = std::wstring{value.data()}; + return Status::OK(); } -DynamicLibraryHandle LoadDynamicLibrary(const PathString& path, bool global_symbols) { - // Custom deleter to unload the shared library. Avoid throwing from it because it may run in dtor. - const auto unload_library = [](void* library_handle) { - if (library_handle == nullptr) { - return; - } +Status GetServiceBinaryDirectoryPath(const wchar_t* service_name, + std::filesystem::path& service_binary_directory_path_out) { + SC_HANDLE scm_handle_raw = ::OpenSCManagerW(nullptr, // local computer + nullptr, // SERVICES_ACTIVE_DATABASE + STANDARD_RIGHTS_READ); + ORT_RETURN_IF(scm_handle_raw == nullptr, + "Failed to open handle to service control manager. OpenSCManagerW error: ", ::GetLastError()); + + auto scm_handle = UniqueServiceHandle{scm_handle_raw}; + + SC_HANDLE service_handle_raw = ::OpenServiceW(scm_handle.get(), + service_name, + SERVICE_QUERY_CONFIG); + ORT_RETURN_IF(service_handle_raw == nullptr, + "Failed to open service handle. OpenServiceW error: ", ::GetLastError()); + + auto service_handle = UniqueServiceHandle{service_handle_raw}; + + // get service config required buffer size + DWORD service_config_buffer_size{}; + ORT_RETURN_IF(!::QueryServiceConfigW(service_handle.get(), nullptr, 0, &service_config_buffer_size) && + ::GetLastError() != ERROR_INSUFFICIENT_BUFFER, + "Failed to query service configuration buffer size. QueryServiceConfigW error: ", ::GetLastError()); - const auto& env = GetDefaultEnv(); - const auto unload_status = env.UnloadDynamicLibrary(library_handle); + // get the service config + std::vector service_config_buffer(service_config_buffer_size); + QUERY_SERVICE_CONFIGW* service_config = reinterpret_cast(service_config_buffer.data()); + ORT_RETURN_IF(!::QueryServiceConfigW(service_handle.get(), service_config, service_config_buffer_size, + &service_config_buffer_size), + "Failed to query service configuration. QueryServiceConfigW error: ", ::GetLastError()); - if (!unload_status.IsOK()) { - LOGS_DEFAULT(WARNING) << "Failed to unload shared library. Error: " << unload_status.ErrorMessage(); - } - }; + std::wstring service_binary_path_name = service_config->lpBinaryPathName; + // replace system root placeholder with the value of the SYSTEMROOT environment variable + const std::wstring system_root_placeholder = L"\\SystemRoot"; + + ORT_RETURN_IF(service_binary_path_name.find(system_root_placeholder, 0) != 0, + "Service binary path '", ToUTF8String(service_binary_path_name), + "' does not start with expected system root placeholder value '", + ToUTF8String(system_root_placeholder), "'."); + + std::wstring system_root{}; + ORT_RETURN_IF_ERROR(ReadEnvironmentVariable(L"SYSTEMROOT", system_root)); + service_binary_path_name.replace(0, system_root_placeholder.size(), system_root); + + const auto service_binary_path = std::filesystem::path{service_binary_path_name}; + auto service_binary_directory_path = service_binary_path.parent_path(); + + ORT_RETURN_IF(!std::filesystem::exists(service_binary_directory_path), + "Service binary directory path does not exist: ", service_binary_directory_path.string()); + + service_binary_directory_path_out = std::move(service_binary_directory_path); + return Status::OK(); +} + +#endif // defined(_WIN32) + +Status GetRpcMemDynamicLibraryPath(PathString& path_out) { +#if defined(_WIN32) + + std::filesystem::path qcnspmcdm_dir_path{}; + ORT_RETURN_IF_ERROR(GetServiceBinaryDirectoryPath(L"qcnspmcdm", qcnspmcdm_dir_path)); + const auto libcdsprpc_path = qcnspmcdm_dir_path / L"libcdsprpc.dll"; + path_out = libcdsprpc_path.wstring(); + return Status::OK(); + +#else // ^^^ defined(_WIN32) / vvv !defined(_WIN32) + + path_out = ORT_TSTR("libcdsprpc.so"); + return Status::OK(); + +#endif // !defined(_WIN32) +} + +Status LoadDynamicLibrary(const PathString& path, bool global_symbols, + UniqueDynamicLibraryHandle& library_handle_out) { const auto& env = GetDefaultEnv(); - void* library_handle = nullptr; + void* library_handle_raw = nullptr; + ORT_RETURN_IF_ERROR(env.LoadDynamicLibrary(path, global_symbols, &library_handle_raw)); + + library_handle_out = UniqueDynamicLibraryHandle{library_handle_raw}; + return Status::OK(); +} + +UniqueDynamicLibraryHandle GetRpcMemDynamicLibraryHandle() { + std::string_view error_message_prefix = "Failed to initialize RPCMEM dynamic library handle: "; + + PathString rpcmem_library_path{}; + auto status = GetRpcMemDynamicLibraryPath(rpcmem_library_path); + if (!status.IsOK()) { + ORT_THROW(error_message_prefix, status.ErrorMessage()); + } - const auto load_status = env.LoadDynamicLibrary(path, global_symbols, &library_handle); - if (!load_status.IsOK()) { - ORT_THROW("Failed to load ", ToUTF8String(path), ": ", load_status.ErrorMessage()); + UniqueDynamicLibraryHandle library_handle{}; + status = LoadDynamicLibrary(rpcmem_library_path, /* global_symbols */ false, library_handle); + if (!status.IsOK()) { + ORT_THROW(error_message_prefix, status.ErrorMessage()); } - return DynamicLibraryHandle{library_handle, unload_library}; + return library_handle; } RpcMemApi CreateApi(void* library_handle) { @@ -58,7 +171,7 @@ RpcMemApi CreateApi(void* library_handle) { } // namespace RpcMemLibrary::RpcMemLibrary() - : library_handle_(LoadDynamicLibrary(GetRpcMemSharedLibraryPath(), /* global_symbols */ false)), + : library_handle_(GetRpcMemDynamicLibraryHandle()), api_{CreateApi(library_handle_.get())} { } diff --git a/onnxruntime/core/providers/qnn/rpcmem_library.h b/onnxruntime/core/providers/qnn/rpcmem_library.h index 0642c96798188..2746e147373bb 100644 --- a/onnxruntime/core/providers/qnn/rpcmem_library.h +++ b/onnxruntime/core/providers/qnn/rpcmem_library.h @@ -10,7 +10,11 @@ namespace onnxruntime::qnn { -using DynamicLibraryHandle = std::unique_ptr; +struct DynamicLibraryHandleDeleter { + void operator()(void* library_handle) noexcept; +}; + +using UniqueDynamicLibraryHandle = std::unique_ptr; // This namespace contains constants and typedefs corresponding to functions from rpcmem.h. // https://github.com/quic/fastrpc/blob/v0.1.1/inc/rpcmem.h @@ -61,7 +65,7 @@ class RpcMemLibrary { const RpcMemApi& Api() const { return api_; } private: - DynamicLibraryHandle library_handle_; + UniqueDynamicLibraryHandle library_handle_; RpcMemApi api_; }; diff --git a/onnxruntime/test/providers/qnn/qnn_basic_test.cc b/onnxruntime/test/providers/qnn/qnn_basic_test.cc index 98d07fa06c009..0b51b6f8e503d 100644 --- a/onnxruntime/test/providers/qnn/qnn_basic_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_basic_test.cc @@ -1166,18 +1166,8 @@ TEST_F(QnnHTPBackendTests, UseHtpSharedMemoryAllocatorForInputs) { try { qnn_ep = QnnExecutionProviderWithOptions(provider_options); } catch (const OnnxRuntimeException& e) { - // handle particular exception that indicates that the libcdsprpc.so / dll can't be loaded - // NOTE: To run this on a local Windows ARM64 device, you need to copy libcdsprpc.dll to the build directory: - // - Open File Explorer - // - Go to C:/Windows/System32/DriverStore/FileRepository/ - // - Search for a folder that begins with qcnspmcdm8380.inf_arm64_ and open it - // - Copy the libcdsprpc.dll into the build/[PATH CONTAINING onnxruntime.dll] directory of the application. - // TODO(adrianlizarraga): Update CMake build for unittests to automatically copy libcdsprpc.dll into build directory -#if defined(_WIN32) - constexpr const char* expected_error_message = "Failed to load libcdsprpc.dll"; -#else - constexpr const char* expected_error_message = "Failed to load libcdsprpc.so"; -#endif + // handle exception that indicates that the libcdsprpc.so / dll can't be loaded + constexpr const char* expected_error_message = "Failed to initialize RPCMEM dynamic library handle"; ASSERT_THAT(e.what(), testing::HasSubstr(expected_error_message)); GTEST_SKIP() << "HTP shared memory allocator is unavailable."; } diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc index 59920487a7248..ca9ca0f82a25a 100644 --- a/onnxruntime/test/shared_lib/test_inference.cc +++ b/onnxruntime/test/shared_lib/test_inference.cc @@ -1960,20 +1960,9 @@ static bool CreateSessionWithQnnEpAndQnnHtpSharedMemoryAllocator(PATH_TYPE model session = Ort::Session{*ort_env, model_path, session_options}; return true; } catch (const Ort::Exception& e) { - // handle particular exception that indicates that the libcdsprpc.so / dll can't be loaded - // NOTE: To run this on a local Windows ARM64 device, you need to copy libcdsprpc.dll to the build directory: - // - Open File Explorer - // - Go to C:/Windows/System32/DriverStore/FileRepository/ - // - Search for a folder that begins with qcnspmcdm8380.inf_arm64_ and open it - // - Copy the libcdsprpc.dll into the build/[PATH CONTAINING onnxruntime.dll] directory of the application. - // TODO(adrianlizarraga): Update CMake build for unittests to automatically copy libcdsprpc.dll into build directory + // handle exception that indicates that the libcdsprpc.so / dll can't be loaded std::string_view error_message = e.what(); - -#if defined(_WIN32) - std::string_view expected_error_message = "Failed to load libcdsprpc.dll"; -#else - std::string_view expected_error_message = "Failed to load libcdsprpc.so"; -#endif + std::string_view expected_error_message = "Failed to initialize RPCMEM dynamic library handle"; if (e.GetOrtErrorCode() == ORT_FAIL && error_message.find(expected_error_message) != std::string_view::npos) { From 5abb75ff191e0c5e43239b6e28836512c3108966 Mon Sep 17 00:00:00 2001 From: "genmingz@AMD" Date: Wed, 26 Feb 2025 05:33:26 +0800 Subject: [PATCH 005/266] [VitisAI] add new interfece (#23777) ### Description A new interface for interaction between ONNX Runtime and Vitis AI has been added, which uses `std::filesystem::path` to pass paths. ### Motivation and Context Vitis AI uses `std::string` to pass paths, which causes errors on Windows when the model name contains Chinese characters. Therefore, this PR adds an interface that uses `std::filesystem::path` to pass paths, ensuring that file paths are correctly transmitted. Co-authored-by: genmingz --- .../core/providers/vitisai/imp/global_api.cc | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index f67cd28137d4d..6547f00cd47c7 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -49,6 +49,8 @@ struct OrtVitisAIEpAPI { const std::string& model_path, const onnxruntime::Graph& graph, const onnxruntime::ProviderOptions& options); std::vector>* (*compile_onnx_model_vitisai_ep_with_error_handling)( const std::string& model_path, const onnxruntime::Graph& graph, const onnxruntime::ProviderOptions& options, void* status, vaip_core::error_report_func func); + std::vector>* (*compile_onnx_model_vitisai_ep_v3)( + const std::filesystem::path& model_path, const onnxruntime::Graph& graph, const onnxruntime::ProviderOptions& options, void* status, vaip_core::error_report_func func); uint32_t (*vaip_get_version)(); void (*create_ep_context_nodes)( const std::vector>& eps, @@ -82,7 +84,8 @@ struct OrtVitisAIEpAPI { ORT_THROW_IF_ERROR(env.GetSymbolFromLibrary(handle_, "initialize_onnxruntime_vitisai_ep", (void**)&initialize_onnxruntime_vitisai_ep)); auto status1 = env.GetSymbolFromLibrary(handle_, "compile_onnx_model_vitisai_ep_with_error_handling", (void**)&compile_onnx_model_vitisai_ep_with_error_handling); auto status2 = env.GetSymbolFromLibrary(handle_, "compile_onnx_model_vitisai_ep_with_options", (void**)&compile_onnx_model_with_options); - if ((!status1.IsOK()) && (!status2.IsOK())) { + auto status3 = env.GetSymbolFromLibrary(handle_, "compile_onnx_model_vitisai_ep_v3", (void**)&compile_onnx_model_vitisai_ep_v3); + if ((!status1.IsOK()) && (!status2.IsOK()) && (!status3.IsOK())) { ::onnxruntime::LogRuntimeError(0, status2, __FILE__, static_cast(__FUNCTION__), __LINE__); ORT_THROW(status2); } @@ -129,17 +132,25 @@ void change_status_with_error(void* status_ptr, int error_code, const char* erro vaip_core::DllSafe>> compile_onnx_model( const onnxruntime::GraphViewer& graph_viewer, const onnxruntime::logging::Logger& logger, const onnxruntime::ProviderOptions& options) { - auto model_path = graph_viewer.ModelPath().string(); - if (s_library_vitisaiep.compile_onnx_model_vitisai_ep_with_error_handling) { + auto model_path = graph_viewer.ModelPath(); + if (s_library_vitisaiep.compile_onnx_model_vitisai_ep_v3) { Status status = Status::OK(); auto status_ptr = reinterpret_cast(&status); - auto ret = vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_vitisai_ep_with_error_handling(model_path, graph_viewer.GetGraph(), options, status_ptr, change_status_with_error)); + auto ret = vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_vitisai_ep_v3(model_path, graph_viewer.GetGraph(), options, status_ptr, change_status_with_error)); + if (!status.IsOK()) { + ORT_THROW(status); + } + return ret; + } else if (s_library_vitisaiep.compile_onnx_model_vitisai_ep_with_error_handling) { + Status status = Status::OK(); + auto status_ptr = reinterpret_cast(&status); + auto ret = vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_vitisai_ep_with_error_handling(model_path.u8string(), graph_viewer.GetGraph(), options, status_ptr, change_status_with_error)); if (!status.IsOK()) { ORT_THROW(status); } return ret; } else { - return vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_with_options(model_path, graph_viewer.GetGraph(), options)); + return vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_with_options(model_path.u8string(), graph_viewer.GetGraph(), options)); } } From 5be82eb7b2b48515eff5d12506bc92f4cd061b3e Mon Sep 17 00:00:00 2001 From: kuanyul-quic Date: Thu, 27 Feb 2025 00:35:53 +0800 Subject: [PATCH 006/266] [QNN EP] Re-enable several disabled QNN-EP UTs (#23799) ### Description 1. Re-enable UTs which passed 2.30 2. Update resize UT because "round_prefer_floor" is no longer supported in QNN SDK since 2.21. ### Motivation and Context 1. Make the UT of QNN EP pass as much as possible to improve the test coverage. --------- Co-authored-by: Kuan-Yu Lin --- onnxruntime/test/providers/qnn/resize_test.cc | 5 +++-- onnxruntime/test/providers/qnn/simple_op_htp_test.cc | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/onnxruntime/test/providers/qnn/resize_test.cc b/onnxruntime/test/providers/qnn/resize_test.cc index f323713d6082d..4964e593e9521 100644 --- a/onnxruntime/test/providers/qnn/resize_test.cc +++ b/onnxruntime/test/providers/qnn/resize_test.cc @@ -456,11 +456,12 @@ TEST_F(QnnHTPBackendTests, ResizeU8_2xNearestAsymmetricRoundPreferFloor_Unsuppor // ORT CPU EP (f32 model) outputs: -10.0000000 -10.0000000 -3.33333349 -3.33333349 -3.33333349 -3.33333349 -10.00 ... // ORT CPU EP (qdq model) outputs: -9.96078491 -9.96078491 -3.29411769 -3.29411769 -3.29411769 -3.29411769 -9.961 ... // ORT QNN EP (qdq model) outputs: -9.96078491 -9.96078491 -9.96078491 -3.37254906 -3.37254906 -3.37254906 -9.961 ... -TEST_F(QnnHTPBackendTests, DISABLED_ResizeU8_3xNearestAsymmetricRoundPreferFloor) { +// UPDATE: "round_prefer_floor" no longer supported in QNN SDK 2.21 (supported in QNN SDK 2.19) +TEST_F(QnnHTPBackendTests, ResizeU8_3xNearestAsymmetricRoundPreferFloor_Unsupported) { std::vector input_data = GetFloatDataInRange(-10.0f, 10.0f, 4); RunQDQResizeOpTest(TestInputDef({1, 1, 2, 2}, false, input_data), {1, 1, 6, 6}, "nearest", "asymmetric", "round_prefer_floor", - ExpectedEPNodeAssignment::All); + ExpectedEPNodeAssignment::None); // No longer supported as of QNN SDK 2.21 } // Test 0.5x QDQ Resize mode: "nearest", coordinate_transformation_mode: "asymmetric", nearest_mode: "floor" diff --git a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc index 3a557c5708900..5ce376f5c6063 100644 --- a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc @@ -297,7 +297,8 @@ TEST_F(QnnHTPBackendTests, UnaryOp_Elu) { // Expected val: -0.99751651287078857 // QNN QDQ val: 6.2726154327392578 (err 7.2701320648193359) // CPU QDQ val: -0.99753034114837646 (err 1.3828277587890625e-05) -TEST_F(QnnHTPBackendTests, DISABLE_UnaryOp_Elu_U16) { +// Issue fixed in 2.30 +TEST_F(QnnHTPBackendTests, UnaryOp_Elu_U16) { RunQDQOpTest("Elu", {TestInputDef({1, 2, 3}, false, GetFloatDataInRange(-10.0f, 10.0f, 6))}, {}, From 839d9dcd28478e79b065cdc0baa870262a36b73a Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 26 Feb 2025 14:21:05 -0500 Subject: [PATCH 007/266] Make Nuget package pipeline 1ES compliant (#23803) ### Description Make[Nuget Publishing](https://dev.azure.com/aiinfra/Lotus/_build?definitionId=1313&_a=summary) 1ES compliant ### Motivation and Context --- .../github/azure-pipelines/publish-nuget.yml | 59 +++++---- .../stages/java-cuda-publishing-stage.yml | 3 +- .../stages/nuget-cuda-publishing-stage.yml | 118 +++++++++--------- .../stages/py-cuda-publishing-stage.yml | 6 +- .../templates/publish-nuget-steps.yml | 47 +++---- 5 files changed, 125 insertions(+), 108 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/publish-nuget.yml b/tools/ci_build/github/azure-pipelines/publish-nuget.yml index b78d586288ba3..7ad0aa3b95d9d 100644 --- a/tools/ci_build/github/azure-pipelines/publish-nuget.yml +++ b/tools/ci_build/github/azure-pipelines/publish-nuget.yml @@ -8,35 +8,48 @@ resources: - main - rel-* branch: main - + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release parameters: - - name: isReleaseBuild - type: boolean - default: false +- name: isReleaseBuild + type: boolean + default: false variables: - - name: ArtifactFeed - ${{ if eq(parameters.isReleaseBuild, false) }}: - value: ort-cuda-11-nightly - ${{ else }}: - value: onnxruntime-cuda-11 - -stages: - - template: templates/publish-nuget-steps.yml - parameters: - stage_name: 'Publish_NuGet_Package_And_Report' - include_cpu_ep: true - download_artifacts_steps: +- name: ArtifactFeed + ${{ if eq(parameters.isReleaseBuild, false) }}: + value: ort-cuda-11-nightly + ${{ else }}: + value: onnxruntime-cuda-11 +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: + - template: templates/publish-nuget-steps.yml + parameters: + stage_name: 'Publish_NuGet_Package_And_Report' + include_cpu_ep: true + download_artifacts_steps: - download: build displayName: 'Download Pipeline Artifact - Signed NuGet Package' artifact: 'drop-signed-nuget-dml' - script: move "$(Pipeline.Workspace)\build\drop-signed-nuget-dml\*" $(Build.BinariesDirectory)\nuget-artifact\final-package - # Publish CUDA 11 Nuget/Java pkgs to ADO feed - - template: stages/nuget-cuda-publishing-stage.yml - parameters: - artifact_feed: $(ArtifactFeed) + # Publish CUDA 11 Nuget/Java pkgs to ADO feed + - template: stages/nuget-cuda-publishing-stage.yml + parameters: + artifact_feed: $(ArtifactFeed) - - template: stages/java-cuda-publishing-stage.yml - parameters: - artifact_feed: $(ArtifactFeed) + - template: stages/java-cuda-publishing-stage.yml + parameters: + artifact_feed: $(ArtifactFeed) diff --git a/tools/ci_build/github/azure-pipelines/stages/java-cuda-publishing-stage.yml b/tools/ci_build/github/azure-pipelines/stages/java-cuda-publishing-stage.yml index 946d651b795d4..8f14b315d899d 100644 --- a/tools/ci_build/github/azure-pipelines/stages/java-cuda-publishing-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/java-cuda-publishing-stage.yml @@ -11,7 +11,8 @@ stages: condition: ${{ or(eq(parameters.artifact_feed, 'onnxruntime-cuda-11'), eq(parameters.artifact_feed, 'onnxruntime-cuda-12')) }} workspace: clean: all - pool: 'onnxruntime-Win-CPU-2022' + pool: + name: 'onnxruntime-Win-CPU-2022' variables: - name: SYSTEM_ACCESSTOKEN value: $(System.AccessToken) diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-publishing-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-publishing-stage.yml index b802dd43f9058..f6d78707d5b9c 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-publishing-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-publishing-stage.yml @@ -1,71 +1,71 @@ parameters: - - name: artifact_feed - type: string - default: 'onnxruntime-cuda-12' +- name: artifact_feed + type: string + default: 'onnxruntime-cuda-12' stages: - - stage: NuGet_Publishing_GPU - jobs: - - job: NuGet_Publishing_GPU - workspace: - clean: all - variables: - - name: GDN_CODESIGN_TARGETDIRECTORY - value: '$(Build.BinariesDirectory)/nuget-artifact/final-package' - pool: 'onnxruntime-Win-CPU-2022' - steps: - - checkout: none +- stage: NuGet_Publishing_GPU + jobs: + - job: NuGet_Publishing_GPU + workspace: + clean: all + variables: + - name: GDN_CODESIGN_TARGETDIRECTORY + value: '$(Build.BinariesDirectory)/nuget-artifact/final-package' + pool: 'onnxruntime-Win-CPU-2022' + steps: + - checkout: none - - task: NuGetToolInstaller@1 - inputs: - versionSpec: 6.8.x + - task: NuGetToolInstaller@1 + inputs: + versionSpec: 6.8.x - - script: mkdir "$(Build.BinariesDirectory)\nuget-artifact\final-package" - - - download: build - displayName: 'Download Pipeline Artifact - Signed NuGet Package' - artifact: 'drop-signed-nuget-GPU' - - - script: move "$(Pipeline.Workspace)\build\drop-signed-nuget-GPU\*" "$(Build.BinariesDirectory)\nuget-artifact\final-package" - - - powershell: | - New-Item -Path $(Agent.TempDirectory) -Name "binfiles" -ItemType "directory" - $base_path_name = Join-Path -Path $(Agent.TempDirectory) -ChildPath "binfiles" - Get-ChildItem $Env:BUILD_BINARIESDIRECTORY\nuget-artifact\final-package -Filter *.nupkg | - Foreach-Object { - $dir_name = Join-Path -Path $base_path_name -ChildPath $_.Basename - $cmd = "7z.exe x $($_.FullName) -y -o$dir_name" - Write-Output $cmd - Invoke-Expression -Command $cmd - } - dir $(Agent.TempDirectory) - tree $(Agent.TempDirectory) - workingDirectory: '$(Agent.TempDirectory)' + - script: mkdir "$(Build.BinariesDirectory)\nuget-artifact\final-package" - - task: CodeSign@1 - displayName: 'Run Codesign Validation' + - download: build + displayName: 'Download Pipeline Artifact - Signed NuGet Package' + artifact: 'drop-signed-nuget-GPU' - - task: PublishSecurityAnalysisLogs@3 - displayName: 'Publish Security Analysis Logs' - continueOnError: true + - script: move "$(Pipeline.Workspace)\build\drop-signed-nuget-GPU\*" "$(Build.BinariesDirectory)\nuget-artifact\final-package" - - task: PostAnalysis@2 - inputs: - GdnBreakAllTools: true - GdnBreakPolicy: M365 - GdnBreakPolicyMinSev: Error + - powershell: | + New-Item -Path $(Agent.TempDirectory) -Name "binfiles" -ItemType "directory" + $base_path_name = Join-Path -Path $(Agent.TempDirectory) -ChildPath "binfiles" + Get-ChildItem $Env:BUILD_BINARIESDIRECTORY\nuget-artifact\final-package -Filter *.nupkg | + Foreach-Object { + $dir_name = Join-Path -Path $base_path_name -ChildPath $_.Basename + $cmd = "7z.exe x $($_.FullName) -y -o$dir_name" + Write-Output $cmd + Invoke-Expression -Command $cmd + } + dir $(Agent.TempDirectory) + tree $(Agent.TempDirectory) + workingDirectory: '$(Agent.TempDirectory)' - - template: ../nuget/templates/get-nuget-package-version-as-variable.yml - parameters: - packageFolder: '$(Build.BinariesDirectory)/nuget-artifact/final-package' - #This task must be run on a Windows machine - - task: NuGetCommand@2 - displayName: 'NuGet push ${{ parameters.artifact_feed }}' - inputs: - command: push - packagesToPush: '$(Build.BinariesDirectory)/nuget-artifact/final-package/*.nupkg' - publishVstsFeed: 'PublicPackages/${{ parameters.artifact_feed }}' - allowPackageConflicts: true + - task: CodeSign@1 + displayName: 'Run Codesign Validation' + + - task: PublishSecurityAnalysisLogs@3 + displayName: 'Publish Security Analysis Logs' + continueOnError: true + + - task: PostAnalysis@2 + inputs: + GdnBreakAllTools: true + GdnBreakPolicy: M365 + GdnBreakPolicyMinSev: Error + + - template: ../nuget/templates/get-nuget-package-version-as-variable.yml + parameters: + packageFolder: '$(Build.BinariesDirectory)/nuget-artifact/final-package' + #This task must be run on a Windows machine + - task: 1ES.PublishNuget@1 + displayName: 'NuGet push ${{ parameters.artifact_feed }}' + inputs: + packagesToPush: '$(Build.BinariesDirectory)/nuget-artifact/final-package/*.nupkg' + packageParentPath: '$(Build.BinariesDirectory)' + publishVstsFeed: 'PublicPackages/${{ parameters.artifact_feed }}' + allowPackageConflicts: true diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cuda-publishing-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cuda-publishing-stage.yml index 1ff43667f4788..fbfbc69bce0a8 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cuda-publishing-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cuda-publishing-stage.yml @@ -7,13 +7,15 @@ stages: - stage: Python_Publishing_GPU jobs: - job: Python_Publishing_GPU - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + pool: + name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: linux steps: - checkout: none - download: build displayName: 'Download Pipeline Artifact' artifact: 'whl' - + - task: UsePythonVersion@0 inputs: versionSpec: '3.13' diff --git a/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml b/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml index 6671d3870dd67..aa47294acac2b 100644 --- a/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml @@ -17,7 +17,8 @@ stages: variables: - name: GDN_CODESIGN_TARGETDIRECTORY value: '$(Agent.TempDirectory)\binfiles' - pool: 'onnxruntime-Win-CPU-2022' + pool: + name: 'onnxruntime-Win-CPU-2022' steps: # https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/resources-pipelines-pipeline?view=azure-pipelines#pipeline-resource-metadata-as-predefined-variables @@ -53,25 +54,25 @@ stages: displayName: 'Post binary sizes to the dashboard database using command line' inputs: script: | - echo changing directory to artifact download path - cd $(Build.BinariesDirectory)/nuget-artifact/final-package - echo processing nupkg - SETLOCAL EnableDelayedExpansion - FOR /R %%i IN (*.nupkg) do ( - set filename=%%~ni - IF NOT "!filename:~25,7!"=="Managed" ( - echo processing %%~ni.nupkg - copy %%~ni.nupkg %%~ni.zip - echo copied to zip - echo listing lib files in the zip - REM use a single .csv file to put the data - echo os,arch,build_config,size > $(Build.BinariesDirectory)\binary_size_data.txt - 7z.exe l -slt %%~ni.zip runtimes\linux-arm64\native\libonnxruntime.so | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo linux,aarch64,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt - 7z.exe l -slt %%~ni.zip runtimes\osx-x64\native\libonnxruntime.dylib | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo osx,x64,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt - 7z.exe l -slt %%~ni.zip runtimes\win-x64\native\onnxruntime.dll | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo win,x64,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt - 7z.exe l -slt %%~ni.zip runtimes\win-x86\native\onnxruntime.dll | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo win,x86,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt - ) + echo changing directory to artifact download path + cd $(Build.BinariesDirectory)/nuget-artifact/final-package + echo processing nupkg + SETLOCAL EnableDelayedExpansion + FOR /R %%i IN (*.nupkg) do ( + set filename=%%~ni + IF NOT "!filename:~25,7!"=="Managed" ( + echo processing %%~ni.nupkg + copy %%~ni.nupkg %%~ni.zip + echo copied to zip + echo listing lib files in the zip + REM use a single .csv file to put the data + echo os,arch,build_config,size > $(Build.BinariesDirectory)\binary_size_data.txt + 7z.exe l -slt %%~ni.zip runtimes\linux-arm64\native\libonnxruntime.so | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo linux,aarch64,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt + 7z.exe l -slt %%~ni.zip runtimes\osx-x64\native\libonnxruntime.dylib | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo osx,x64,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt + 7z.exe l -slt %%~ni.zip runtimes\win-x64\native\onnxruntime.dll | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo win,x64,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt + 7z.exe l -slt %%~ni.zip runtimes\win-x86\native\onnxruntime.dll | findstr /R /C:"^Size = [0-9]*" | for /F "tokens=3" %%a in ('more') do if not "%%a" == "" echo win,x86,default,%%a >> $(Build.BinariesDirectory)\binary_size_data.txt ) + ) - task: AzureCLI@2 displayName: 'Azure CLI' @@ -123,14 +124,14 @@ stages: GdnBreakPolicyMinSev: Error #TODO: allow choosing different feeds - - task: NuGetCommand@2 + - task: 1ES.PublishNuget@1 displayName: 'Copy Signed Native NuGet Package to ORT-NIGHTLY' inputs: - command: 'push' packagesToPush: '$(Build.BinariesDirectory)/nuget-artifact/final-package/*.nupkg' + packageParentPath: '$(Build.BinariesDirectory)' publishVstsFeed: '2692857e-05ef-43b4-ba9c-ccf1c22c437c/7982ae20-ed19-4a35-a362-a96ac99897b7' allowPackageConflicts: true - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' From 9a2e00906a2d8da6d6931c1ac917c2979223ffab Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 26 Feb 2025 14:39:53 -0500 Subject: [PATCH 008/266] Conveting npm packaging pipeline to 1ES (#23767) ### Description ### Motivation and Context --- .../mac-react-native-ci-pipeline.yml | 28 +++- .../npm-packaging-pipeline.yml | 138 ++++++++++-------- .../react-natvie-andriod-e2e-test-job.yml | 46 ++++-- .../templates/android-java-api-aar.yml | 30 +++- .../templates/linux-wasm-ci.yml | 62 ++++---- .../templates/react-native-ci.yml | 30 +++- .../azure-pipelines/templates/web-ci.yml | 36 ++++- .../azure-pipelines/templates/win-web-ci.yml | 123 +++++++++------- 8 files changed, 310 insertions(+), 183 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml index e72f088cfeb55..9d63fe9cc118d 100644 --- a/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml @@ -27,6 +27,12 @@ pr: - 'js/web' - 'onnxruntime/core/providers/js' #### end trigger #### +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release parameters: - name: NpmPublish @@ -50,10 +56,20 @@ variables: ${{ if eq(parameters.NpmPublish, 'custom') }}: NpmPackagingMode: '$(VersionSuffix)' -stages: -- template: templates/react-native-ci.yml +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: - NpmPackagingMode: ${{ variables.NpmPackagingMode }} - BuildConfig: 'Release' - PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' - enable_code_sign: false + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: + - template: templates/react-native-ci.yml + parameters: + NpmPackagingMode: ${{ variables.NpmPackagingMode }} + BuildConfig: 'Release' + PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' + enable_code_sign: false diff --git a/tools/ci_build/github/azure-pipelines/npm-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/npm-packaging-pipeline.yml index 73719426e2875..e5d45f9f07bfb 100644 --- a/tools/ci_build/github/azure-pipelines/npm-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/npm-packaging-pipeline.yml @@ -35,71 +35,87 @@ resources: endpoint: Microsoft name: pypa/manylinux ref: 5eda9aded5462201e6310105728d33016e637ea7 - -stages: -- template: templates/web-ci.yml + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: - NpmPackagingMode: ${{ variables.NpmPackagingMode }} - IsReleasePipeline: true - PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' - PackageName: 'onnxruntime-web' - ExtraBuildArgs: '' - UseWebPoolName: true - RunWebGpuTestsForDebugBuild: false - RunWebGpuTestsForReleaseBuild: true - WebGpuPoolName: 'onnxruntime-Win2022-VS2022-webgpu-A10' - WebCpuPoolName: 'onnxruntime-Win2022-VS2022-webgpu-A10' + # Update the pool with your team's 1ES hosted pool. + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: + - template: templates/web-ci.yml + parameters: + NpmPackagingMode: ${{ variables.NpmPackagingMode }} + IsReleasePipeline: true + PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' + PackageName: 'onnxruntime-web' + ExtraBuildArgs: '' + UseWebPoolName: true + RunWebGpuTestsForDebugBuild: false + RunWebGpuTestsForReleaseBuild: true + WebGpuPoolName: 'onnxruntime-Win2022-VS2022-webgpu-A10' + WebCpuPoolName: 'onnxruntime-Win2022-VS2022-webgpu-A10' + is1ES: true -- template: templates/react-native-ci.yml - parameters: - NpmPackagingMode: ${{ variables.NpmPackagingMode }} - BuildConfig: 'Release' - PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' - PackageName: 'onnxruntime-react-native' - InitialStageDependsOn: 'Precheck_and_extract_commit' - enable_code_sign: false + - template: templates/react-native-ci.yml + parameters: + NpmPackagingMode: ${{ variables.NpmPackagingMode }} + BuildConfig: 'Release' + PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' + PackageName: 'onnxruntime-react-native' + InitialStageDependsOn: 'Precheck_and_extract_commit' + enable_code_sign: false + is1ES: true -- stage: Download_Node_Package_And_Publish_Validation_Script - dependsOn: - - ReactNative_CI_Android - - ReactNative_CI_iOS - - Build_web_Release - - Build_web_Debug - jobs: - - job: Download_Node_Package_And_Publish_Validation_Script - pool: 'Onnxruntime-Win-CPU-2022' - variables: - runCodesignValidationInjection: false - timeoutInMinutes: 10 - steps: -# This pipeline usually are triggered by Zip-Nuget-Java-Nodejs Packaging Pipeline, -# The NPM_packages is from Android_Java_API_AAR_Packaging_QNN, not from RN_CI - - download: build - artifact: 'NPM_packages' - displayName: 'Download NPM_packages from Zip-Nuget-Java-Nodejs Packaging Pipeline Pipeline Artifact' + - stage: Download_Node_Package_And_Publish_Validation_Script + dependsOn: + - ReactNative_CI_Android + - ReactNative_CI_iOS + - Build_web_Release + - Build_web_Debug + jobs: + - job: Download_Node_Package_And_Publish_Validation_Script + pool: 'Onnxruntime-Win-CPU-2022' + variables: + runCodesignValidationInjection: false + timeoutInMinutes: 10 + steps: + # This pipeline usually are triggered by Zip-Nuget-Java-Nodejs Packaging Pipeline, + # The NPM_packages is from Android_Java_API_AAR_Packaging_QNN, not from RN_CI + - download: build + artifact: 'NPM_packages' + displayName: 'Download NPM_packages from Zip-Nuget-Java-Nodejs Packaging Pipeline Pipeline Artifact' - - task: CopyFiles@2 - inputs: - sourceFolder: '$(Pipeline.Workspace)\build\NPM_packages' - contents: onnxruntime-*.tgz - targetFolder: $(Build.ArtifactStagingDirectory)\node-artifacts - displayName: 'Copy onnxruntime-node Artifacts' + - task: CopyFiles@2 + inputs: + sourceFolder: '$(Pipeline.Workspace)\build\NPM_packages' + contents: onnxruntime-*.tgz + targetFolder: $(Build.ArtifactStagingDirectory)\node-artifacts + displayName: 'Copy onnxruntime-node Artifacts' - - task: PublishPipelineArtifact@0 - inputs: - artifactName: 'onnxruntime-node' - targetPath: '$(Build.ArtifactStagingDirectory)\node-artifacts' - displayName: 'Publish onnxruntime-node Pipeline Artifact' + - task: 1ES.PublishPipelineArtifact@1 + inputs: + artifactName: 'onnxruntime-node' + targetPath: '$(Build.ArtifactStagingDirectory)\node-artifacts' + displayName: 'Publish onnxruntime-node Pipeline Artifact' - - task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)\tools\ci_build\github\js - contents: validate-npm-packages.py - targetFolder: $(Build.ArtifactStagingDirectory)\validation-scripts - displayName: 'Copy validation scripts' + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)\tools\ci_build\github\js + contents: validate-npm-packages.py + targetFolder: $(Build.ArtifactStagingDirectory)\validation-scripts + displayName: 'Copy validation scripts' - - task: PublishPipelineArtifact@0 - inputs: - artifactName: 'validation_scripts' - targetPath: '$(Build.ArtifactStagingDirectory)\validation-scripts' - displayName: 'Publish validation scripts' + - task: 1ES.PublishPipelineArtifact@1 + inputs: + artifactName: 'validation_scripts' + targetPath: '$(Build.ArtifactStagingDirectory)\validation-scripts' + displayName: 'Publish validation scripts' diff --git a/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml b/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml index 638da2866bdef..ed7d77246e862 100644 --- a/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml +++ b/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml @@ -12,10 +12,14 @@ parameters: displayName: 'NPM packages publish configuration' type: string default: 'dev' - +- name: is1ES + type: boolean + default: false jobs: - job: ReactNative_CI_Android - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + pool: + name: onnxruntime-Ubuntu2204-AMD-CPU + os: linux variables: runCodesignValidationInjection: false ANDROID_AVD_HOME: $(Agent.TempDirectory) @@ -195,18 +199,30 @@ jobs: contents: onnxruntime-react-native*.tgz targetFolder: $(Build.ArtifactStagingDirectory) displayName: Create Artifacts onnxruntime-react-native - - - task: PublishPipelineArtifact@1 - inputs: - artifact: android_e2e_test_logs_$(Build.BuildId)_$(Build.BuildNumber)_$(System.JobAttempt) - targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts' - condition: succeededOrFailed() - displayName: Publish React Native Detox E2E test logs - - - task: PublishPipelineArtifact@0 - inputs: - artifactName: '${{parameters.PackageName}}' - targetPath: '$(Build.ArtifactStagingDirectory)' - displayName: Publish Pipeline Artifact + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + inputs: + artifact: android_e2e_test_logs_$(Build.BuildId)_$(Build.BuildNumber)_$(System.JobAttempt) + targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts' + condition: succeededOrFailed() + displayName: Publish React Native Detox E2E test logs + - task: 1ES.PublishPipelineArtifact@1 + inputs: + artifactName: '${{parameters.PackageName}}' + targetPath: '$(Build.ArtifactStagingDirectory)' + displayName: Publish Pipeline Artifact + + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + inputs: + artifact: android_e2e_test_logs_$(Build.BuildId)_$(Build.BuildNumber)_$(System.JobAttempt) + targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts' + condition: succeededOrFailed() + displayName: Publish React Native Detox E2E test logs + - task: PublishPipelineArtifact@1 + inputs: + artifactName: '${{parameters.PackageName}}' + targetPath: '$(Build.ArtifactStagingDirectory)' + displayName: Publish Pipeline Artifact - template: ../../templates/explicitly-defined-final-tasks.yml \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml index cecd6fd912270..2f891360c626a 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml @@ -53,12 +53,25 @@ parameters: type: string default: '2.31.0.250130' +- name: is1ES + displayName: Is 1ES pipeline + type: boolean + default: false + jobs: - job: Android_Java_API_AAR_Packaging_${{ parameters.job_name_suffix }} timeoutInMinutes: 120 workspace: clean: all - pool: ${{parameters.pool_name}} + pool: + name: ${{ parameters.pool_name }} + ${{ if or(contains(parameters.pool_name, 'ubuntu'), contains(parameters.PoolName, 'linux')) }}: + os: linux + ${{ if contains(parameters.pool_name, 'win')}}: + os: windows + ${{ if contains(parameters.pool_name, 'mac')}}: + os: macOS + variables: artifacts_directory: $(Build.BinariesDirectory)/.artifacts @@ -135,8 +148,13 @@ jobs: - template: jar-maven-signing-linux.yml parameters: JarFileDirectory: '$(artifacts_directory)' - - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: '$(artifacts_directory)' - artifactName: '${{parameters.artifactName}}' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + inputs: + targetPath: '$(artifacts_directory)' + artifactName: '${{parameters.artifactName}}' + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(artifacts_directory)' + artifactName: '${{parameters.artifactName}}' diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index e3098841adfba..02dd5faec0fe8 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -39,10 +39,16 @@ parameters: type: boolean default: false +- name: is1ES + displayName: 'Is 1ES pipeline' + type: boolean + default: false + jobs: - job: build_WASM pool: name: ${{ parameters.PoolName }} + os: linux variables: buildArch: x64 CommonBuildArgs: '--parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --config ${{ parameters.BuildConfig }} --skip_submodule_sync --build_wasm --enable_wasm_simd --enable_wasm_threads ${{ parameters.ExtraBuildArgs }}' @@ -61,15 +67,15 @@ jobs: displayName: 'Get commit SHA' condition: eq('${{ parameters.CommitOverride }}', 'true') - script: | - export __commit__=<$(Pipeline.Workspace)/__commit.txt - git fetch origin +$__commit__:refs/remotes/origin/$__commit__ - git checkout --force $__commit__ + export __commit__=<$(Pipeline.Workspace)/__commit.txt + git fetch origin +$__commit__:refs/remotes/origin/$__commit__ + git checkout --force $__commit__ workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Read commit SHA and checkout' condition: eq('${{ parameters.CommitOverride }}', 'true') - script: | - git submodule sync --recursive - git submodule update --init --recursive + git submodule sync --recursive + git submodule update --init --recursive workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Checkout submodules' - task: UsePythonVersion@0 @@ -79,19 +85,19 @@ jobs: architecture: $(buildArch) - ${{if eq(parameters.WithCache, true)}}: - - script: | - set -ex - cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 4.0.3 ccache-git-emscripten-64bit - ./emsdk activate 4.0.3 ccache-git-emscripten-64bit - displayName: 'emsdk install and activate ccache for emscripten' + - script: | + set -ex + cd '$(Build.SourcesDirectory)/cmake/external/emsdk' + ./emsdk install 4.0.3 ccache-git-emscripten-64bit + ./emsdk activate 4.0.3 ccache-git-emscripten-64bit + displayName: 'emsdk install and activate ccache for emscripten' - ${{if eq(parameters.WithCache, false)}}: - - script: | - set -ex - cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 4.0.3 - ./emsdk activate 4.0.3 - displayName: 'emsdk install and activate ccache for emscripten' + - script: | + set -ex + cd '$(Build.SourcesDirectory)/cmake/external/emsdk' + ./emsdk install 4.0.3 + ./emsdk activate 4.0.3 + displayName: 'emsdk install and activate ccache for emscripten' - template: build-linux-wasm-step.yml parameters: @@ -145,12 +151,18 @@ jobs: cp $(Build.BinariesDirectory)/wasm_inferencing_jsep/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.mjs $(Build.ArtifactStagingDirectory) fi displayName: 'Create Artifacts' - - ${{ if eq(parameters.SkipPublish, false) }}: - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline Artifact' - inputs: - artifactName: '${{ parameters.BuildConfig }}_wasm' - targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Pipeline Artifact' + inputs: + artifactName: '${{ parameters.BuildConfig }}_wasm' + targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline Artifact' + inputs: + artifactName: '${{ parameters.BuildConfig }}_wasm' + targetPath: '$(Build.ArtifactStagingDirectory)' - task: PublishTestResults@2 displayName: 'Publish unit test results' inputs: @@ -159,5 +171,5 @@ jobs: testRunTitle: 'Unit Test Run' condition: and(succeededOrFailed(), eq('${{ parameters.BuildConfig }}', 'Debug')) - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index b46fae79899e2..3f4581f63217e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -28,6 +28,9 @@ parameters: displayName: Use GPG to sign the jars type: boolean +- name: is1ES + type: boolean + default: false stages: - stage: Build_Android_Packages displayName: Build_Android_Packages @@ -42,6 +45,7 @@ stages: enable_code_sign: '${{parameters.enable_code_sign}}' pool_name: '${{parameters.PoolName}}' packageName: 'onnxruntime-android' + is1ES: '${{parameters.is1ES}}' - stage: ReactNative_CI_Android displayName: ReactNative_CI_Android dependsOn: Build_Android_Packages @@ -51,6 +55,7 @@ stages: PackageName: '${{parameters.PackageName}}' ArtifactName: 'onnxruntime-android-full-aar' NpmPackagingMode: '${{parameters.NpmPackagingMode}}' + is1ES: '${{parameters.is1ES}}' - stage: ReactNative_CI_iOS displayName: ReactNative_CI_iOS @@ -58,7 +63,9 @@ stages: jobs: - job: ReactNative_CI_iOS pool: - vmImage: 'macOS-13' + name: 'Azure Pipelines' + image: 'macOS-13' + os: 'macOS' timeoutInMinutes: 90 @@ -242,13 +249,20 @@ stages: testRunTitle: 'React Native Detox iOS e2e Test Results' condition: succeededOrFailed() displayName: Publish React Native Detox iOS e2e Test Results - - - task: PublishPipelineArtifact@1 - inputs: - artifact: ios_e2e_test_logs_$(Build.BuildId)_$(Build.BuildNumber)_$(System.JobAttempt) - targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts' - condition: succeededOrFailed() - displayName: Publish React Native Detox E2E test logs + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + inputs: + artifactName: 'ios_e2e_test_logs_$(Build.BuildId)_$(Build.BuildNumber)_$(System.JobAttempt)' + targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts' + condition: succeededOrFailed() + displayName: Publish React Native Detox E2E test logs + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + inputs: + artifact: ios_e2e_test_logs_$(Build.BuildId)_$(Build.BuildNumber)_$(System.JobAttempt) + targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts' + condition: succeededOrFailed() + displayName: Publish React Native Detox E2E test logs - template: explicitly-defined-final-tasks.yml diff --git a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml index d059921bb74c9..87836880cbdb8 100644 --- a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml @@ -57,11 +57,19 @@ parameters: type: boolean default: false +- name: is1ES + displayName: 'Is 1ES pipeline' + type: boolean + default: false + stages: - stage: Precheck_and_extract_commit jobs: - job: Precheck_and_extract_commit - pool: ${{ parameters.PoolName }} + pool: + name: ${{ parameters.PoolName }} + ${{ if or(contains(parameters.PoolName, 'ubuntu'), contains(parameters.PoolName, 'linux')) }}: + os: linux variables: runCodesignValidationInjection: false timeoutInMinutes: 30 @@ -71,8 +79,8 @@ stages: - checkout: self submodules: false - script: | - git submodule sync -- cmake/external/onnx - git submodule update --init -- cmake/external/onnx + git submodule sync -- cmake/external/onnx + git submodule update --init -- cmake/external/onnx workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Checkout submodule onnx' - task: NodeTool@0 @@ -86,11 +94,18 @@ stages: script: | echo $(Build.SourceVersion) echo $(Build.SourceVersion) > "$(Build.ArtifactStagingDirectory)"/__commit.txt - - task: PublishPipelineArtifact@0 - displayName: 'Publish __commit.txt' - inputs: - artifactName: '__commit' - targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish __commit.txt' + inputs: + artifactName: '__commit' + targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, True) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish __commit.txt' + inputs: + artifactName: '__commit' + targetPath: '$(Build.ArtifactStagingDirectory)' - stage: Build_wasm_Debug dependsOn: Precheck_and_extract_commit @@ -104,6 +119,7 @@ stages: BuildJsep: ${{ parameters.BuildJsep }} BuildWebGPU: ${{ parameters.BuildWebGPU }} WithCache: ${{ parameters.WithCache }} + is1ES: ${{ parameters.is1ES }} - stage: Build_web_Debug dependsOn: Build_wasm_Debug @@ -111,6 +127,7 @@ stages: - template: win-web-ci.yml parameters: CommitOverride: true + is1ES: ${{ parameters.is1ES }} BuildConfig: 'Debug' NpmPackagingMode: ${{ parameters.NpmPackagingMode }} ${{ if eq(parameters.UseWebPoolName, true)}}: @@ -135,6 +152,7 @@ stages: BuildJsep: ${{ parameters.BuildJsep }} BuildWebGPU: false WithCache: ${{ parameters.WithCache }} + is1ES: ${{ parameters.is1ES }} - ${{ if eq(parameters.BuildStaticLib, 'true') }}: - stage: Build_wasm_Release_static_library @@ -150,12 +168,14 @@ stages: TimeoutInMinutes: 270 BuildStaticLib: true WithCache: ${{ parameters.WithCache }} + is1ES: ${{ parameters.is1ES }} - stage: Build_web_Release dependsOn: Build_wasm_Release jobs: - template: win-web-ci.yml parameters: + is1ES: ${{ parameters.is1ES }} CommitOverride: true BuildConfig: 'Release' NpmPackagingMode: ${{ parameters.NpmPackagingMode }} diff --git a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml index 06e16dcc25046..b77cab6a19ba0 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml @@ -24,9 +24,16 @@ parameters: type: boolean default: false +- name: is1ES + displayName: 'Is 1ES pipeline' + type: boolean + default: false + jobs: - job: build_onnxruntime_web - pool: ${{ parameters.PoolName }} + pool: + name: ${{ parameters.PoolName }} + os: windows variables: webgpuCommandlineExtraFlags: '--chromium-flags=--ignore-gpu-blocklist --chromium-flags=--gpu-vendor-id=0x10de' @@ -45,28 +52,28 @@ jobs: displayName: 'Get commit SHA' condition: eq('${{ parameters.CommitOverride }}', 'true') - script: | - set /p __commit__=<$(Pipeline.Workspace)\__commit.txt - git fetch origin +%__commit__%:refs/remotes/origin/%__commit__% - git checkout --force %__commit__% + set /p __commit__=<$(Pipeline.Workspace)\__commit.txt + git fetch origin +%__commit__%:refs/remotes/origin/%__commit__% + git checkout --force %__commit__% workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Read commit SHA and checkout' condition: eq('${{ parameters.CommitOverride }}', 'true') - script: | - echo.$(Build.SourceVersion)>$(Pipeline.Workspace)\__commit.txt + echo.$(Build.SourceVersion)>$(Pipeline.Workspace)\__commit.txt workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Write commit SHA to __commit.txt' condition: ne('${{ parameters.CommitOverride }}', 'true') - script: | - git submodule sync -- cmake\external\onnx - git submodule update --init -- cmake\external\onnx + git submodule sync -- cmake\external\onnx + git submodule update --init -- cmake\external\onnx workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Checkout submodule onnx' - script: | - echo.>>.gitattributes - echo /js/** text=auto eol=lf>>.gitattributes - rd /s /q js - git checkout -- js/** - git checkout -- .gitattributes + echo.>>.gitattributes + echo /js/** text=auto eol=lf>>.gitattributes + rd /s /q js + git checkout -- js/** + git checkout -- .gitattributes workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Testing: force EOL to lf on windows for /js/**' - task: NodeTool@0 @@ -86,43 +93,43 @@ jobs: flattenFolders: true displayName: 'Binplace dist files' - script: | - npm ci + npm ci workingDirectory: '$(Build.SourcesDirectory)\js' displayName: 'npm ci /js/' - script: | - npm ci + npm ci workingDirectory: '$(Build.SourcesDirectory)\js\common' displayName: 'npm ci /js/common/' - script: | - npm test + npm test workingDirectory: '$(Build.SourcesDirectory)\js\common' displayName: 'run onnxruntime-common tests' - script: | - npm ci + npm ci workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'npm ci /js/web/' - script: | - npm run prebuild + npm run prebuild workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'run TypeScript type check in /js/web/' - script: | - npm run lint + npm run lint workingDirectory: '$(Build.SourcesDirectory)\js' displayName: 'run ESLint' - script: | - npm run format + npm run format workingDirectory: '$(Build.SourcesDirectory)\js' displayName: 'Clang-format' - script: | - node -e "a=require('child_process').execSync('git diff --name-only').toString();if(a)throw new Error('Following source files are not formatted: (did you run \"npm run format\"?)\n'+a)" + node -e "a=require('child_process').execSync('git diff --name-only').toString();if(a)throw new Error('Following source files are not formatted: (did you run \"npm run format\"?)\n'+a)" workingDirectory: '$(Build.SourcesDirectory)\js' displayName: 'Check unformatted files' - script: | - npm run build:doc + npm run build:doc workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Generating documents' - script: | - node -e "a=require('child_process').execSync('git diff --name-only').toString();if(a)throw new Error('Following documents are not up-to-date: (did you run \"npm run build:doc\"?)\n'+a)" + node -e "a=require('child_process').execSync('git diff --name-only').toString();if(a)throw new Error('Following documents are not up-to-date: (did you run \"npm run build:doc\"?)\n'+a)" workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Check out of dated documents' - task: Cache@2 @@ -142,67 +149,67 @@ jobs: errorActionPreference: stop displayName: 'Pack NPM packages' - script: | - powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" displayName: 'Check active Chrome processes (before test)' condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) - script: | - mkdir $(Agent.TempDirectory)\web\test\01 - dir $(Agent.TempDirectory)\web\test\01 - npm test -- -e=chrome -b=webgl,wasm --user-data-dir=$(Agent.TempDirectory)\web\test\01 --chromium-flags=--enable-logging --chromium-flags=--v=1 + mkdir $(Agent.TempDirectory)\web\test\01 + dir $(Agent.TempDirectory)\web\test\01 + npm test -- -e=chrome -b=webgl,wasm --user-data-dir=$(Agent.TempDirectory)\web\test\01 --chromium-flags=--enable-logging --chromium-flags=--v=1 workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests (wasm,webgl backend)' condition: and(succeeded(), eq('${{ parameters.RunWebGpuTests }}', 'false')) - script: | - powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" displayName: 'Check active Chrome processes (before test)' condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) - script: | - mkdir $(Agent.TempDirectory)\web\test\02 - dir $(Agent.TempDirectory)\web\test\02 - npm test -- -e=chrome -b=webgl,wasm,webgpu $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\02 --chromium-flags=--enable-logging --chromium-flags=--v=1 + mkdir $(Agent.TempDirectory)\web\test\02 + dir $(Agent.TempDirectory)\web\test\02 + npm test -- -e=chrome -b=webgl,wasm,webgpu $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\02 --chromium-flags=--enable-logging --chromium-flags=--v=1 workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests (ALL backends)' condition: and(succeeded(), eq('${{ parameters.RunWebGpuTests }}', 'true')) - script: | - powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" displayName: 'Check active Chrome processes (before test)' condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) - script: | - mkdir $(Agent.TempDirectory)\web\test\03 - dir $(Agent.TempDirectory)\web\test\03 - npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-tensor $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\03 --chromium-flags=--enable-logging --chromium-flags=--v=1 + mkdir $(Agent.TempDirectory)\web\test\03 + dir $(Agent.TempDirectory)\web\test\03 + npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-tensor $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\03 --chromium-flags=--enable-logging --chromium-flags=--v=1 workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests (Suite1, webgpu, IO-binding=gpu-tensor)' condition: and(succeeded(), eq('${{ parameters.RunWebGpuTests }}', 'true')) - script: | - powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" displayName: 'Check active Chrome processes (before test)' condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) - script: | - mkdir $(Agent.TempDirectory)\web\test\04 - dir $(Agent.TempDirectory)\web\test\04 - npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-location $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\04 --chromium-flags=--enable-logging --chromium-flags=--v=1 + mkdir $(Agent.TempDirectory)\web\test\04 + dir $(Agent.TempDirectory)\web\test\04 + npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-location $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\04 --chromium-flags=--enable-logging --chromium-flags=--v=1 workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests (Suite1, webgpu, IO-binding=gpu-location)' condition: and(succeeded(), eq('${{ parameters.RunWebGpuTests }}', 'true')) - script: | - powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" displayName: 'Check active Chrome processes (before test)' condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) - script: | - mkdir $(Agent.TempDirectory)\web\test\05 - dir $(Agent.TempDirectory)\web\test\05 - npm test -- --webgl.pack -b=webgl -e=chrome --user-data-dir=$(Agent.TempDirectory)\web\test\05 --chromium-flags=--enable-logging --chromium-flags=--v=1 + mkdir $(Agent.TempDirectory)\web\test\05 + dir $(Agent.TempDirectory)\web\test\05 + npm test -- --webgl.pack -b=webgl -e=chrome --user-data-dir=$(Agent.TempDirectory)\web\test\05 --chromium-flags=--enable-logging --chromium-flags=--v=1 workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests - WebGL: packed mode' - script: | - powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" displayName: 'Check active Chrome processes (before test)' condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) - script: | - mkdir $(Agent.TempDirectory)\web\test\06 - dir $(Agent.TempDirectory)\web\test\06 - npm test -- --wasm.proxy -b=wasm -e=chrome --user-data-dir=$(Agent.TempDirectory)\web\test\06 --chromium-flags=--enable-logging --chromium-flags=--v=1 + mkdir $(Agent.TempDirectory)\web\test\06 + dir $(Agent.TempDirectory)\web\test\06 + npm test -- --wasm.proxy -b=wasm -e=chrome --user-data-dir=$(Agent.TempDirectory)\web\test\06 --chromium-flags=--enable-logging --chromium-flags=--v=1 workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests - WebAssembly: proxy' condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) @@ -226,12 +233,20 @@ jobs: targetFolder: $(Build.ArtifactStagingDirectory) displayName: 'Create Artifacts (onnxruntime-web)' condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) - - task: PublishPipelineArtifact@0 - inputs: - artifactName: '${{ parameters.PackageName }}' - targetPath: '$(Build.ArtifactStagingDirectory)' - displayName: 'Publish Pipeline Artifact' - condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@0 + inputs: + artifactName: '${{ parameters.PackageName }}' + targetPath: '$(Build.ArtifactStagingDirectory)' + displayName: 'Publish Pipeline Artifact' + condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + inputs: + artifactName: '${{ parameters.PackageName }}' + targetPath: '$(Build.ArtifactStagingDirectory)' + displayName: 'Publish Pipeline Artifact' + condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) - script: | if exist 01 (echo ------------------- BEGIN 01 -------------------&&type 01\chrome_debug.log&&echo ------------------- END 01 ------------------- ) if exist 02 (echo ------------------- BEGIN 02 -------------------&&type 02\chrome_debug.log&&echo ------------------- END 02 ------------------- ) @@ -243,5 +258,5 @@ jobs: workingDirectory: '$(Agent.TempDirectory)\web\test' condition: always() - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' From cc3f4120402b4be3611a57b3ee37cf1e2354c0f9 Mon Sep 17 00:00:00 2001 From: xhcao Date: Thu, 27 Feb 2025 04:55:51 +0800 Subject: [PATCH 009/266] [webgpu] support resize operator (#23780) ### Description ### Motivation and Context --- .../layout_transformation.cc | 9 + .../core/providers/webgpu/tensor/resize.cc | 69 ++ .../core/providers/webgpu/tensor/resize.h | 24 + .../providers/webgpu/tensor/resize_impl.cc | 603 ++++++++++++++++++ .../providers/webgpu/tensor/resize_impl.h | 123 ++++ .../core/providers/webgpu/tensor/upsample.cc | 132 ++++ .../core/providers/webgpu/tensor/upsample.h | 23 + .../webgpu/webgpu_execution_provider.cc | 10 +- .../providers/cpu/tensor/resize_op_test.cc | 12 +- 9 files changed, 995 insertions(+), 10 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/tensor/resize.cc create mode 100644 onnxruntime/core/providers/webgpu/tensor/resize.h create mode 100644 onnxruntime/core/providers/webgpu/tensor/resize_impl.cc create mode 100644 onnxruntime/core/providers/webgpu/tensor/resize_impl.h create mode 100644 onnxruntime/core/providers/webgpu/tensor/upsample.cc create mode 100644 onnxruntime/core/providers/webgpu/tensor/upsample.h diff --git a/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc b/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc index 56f7d28cd5b77..6f1d9d9c6611d 100644 --- a/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc +++ b/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc @@ -81,6 +81,15 @@ bool ConvertNodeLayout(const api::NodeRef& node) { } #endif +// NHWC for Resize operator is not implemented on kWebGpuExecutionProvider +#if defined(USE_WEBGPU) + if (node.GetExecutionProviderType() == kWebGpuExecutionProvider) { + if (node.OpType() == "Resize") { + return false; + } + } +#endif + #if defined(USE_CUDA) && ENABLE_CUDA_NHWC_OPS if (node.GetExecutionProviderType() == kCudaExecutionProvider) { if (layout_sensitive_ops.count(node.OpType())) { diff --git a/onnxruntime/core/providers/webgpu/tensor/resize.cc b/onnxruntime/core/providers/webgpu/tensor/resize.cc new file mode 100644 index 0000000000000..daacced0df871 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/resize.cc @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/tensor/resize.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +namespace onnxruntime { +namespace webgpu { + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Resize, + kOnnxDomain, + 10, 10, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Resize); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Resize, + kOnnxDomain, + 11, 12, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T1", WebGpuSupportedNumberTypes()), + Resize); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Resize, + kOnnxDomain, + 13, 17, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T1", WebGpuSupportedNumberTypes()), + Resize); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Resize, + kOnnxDomain, + 18, 18, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T1", WebGpuSupportedNumberTypes()), + Resize); + +ONNX_OPERATOR_KERNEL_EX( + Resize, + kOnnxDomain, + 19, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T1", WebGpuSupportedNumberTypes()), + Resize); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/resize.h b/onnxruntime/core/providers/webgpu/tensor/resize.h new file mode 100644 index 0000000000000..a37d784bcf8fd --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/resize.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/tensor/upsample.h" + +namespace onnxruntime { +namespace webgpu { + +class Resize : public Upsample { + public: + Resize(const OpKernelInfo& info) : Upsample(info) { + } + + Status ComputeInternal(ComputeContext& context) const override { + return Upsample::ComputeInternal(context); + } +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc b/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc new file mode 100644 index 0000000000000..455e7dc54bf1d --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc @@ -0,0 +1,603 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/common/inlined_containers.h" +#include "core/providers/webgpu/tensor/resize_impl.h" +#include "core/providers/cpu/tensor/utils.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +namespace onnxruntime { +namespace webgpu { + +std::string GetSafeIntegerDivision(ResizeCoordinateTransformationMode transform_coordinate) { + // The whole part and the fractional part are calculated separately due to inaccuracy of floating + // point division. As an example, f32(21) / f32(7) may evaluate to 2.99... instead of 3, causing an + // offset-by-one error later in floor(). + switch (transform_coordinate) { + case ResizeCoordinateTransformationMode::ASYMMETRIC: + return std::string("select(f32(x_resized * length_original / length_resized) + ") + + "f32(x_resized * length_original % length_resized) / f32(length_resized), " + + "f32(x_resized) / x_scale, x_scale < 1.0 || floor(x_scale) != x_scale)"; + break; + case ResizeCoordinateTransformationMode::ALIGN_CORNERS: + return std::string("select(f32(x_resized * (length_original - 1) / (length_resized - 1)) + ") + + "f32(x_resized * (length_original - 1) % (length_resized - 1)) / f32(length_resized - 1), " + + "0.0, length_resized == 1)"; + break; + default: + ORT_THROW("The transform coordinate mode does not need to use SafeIntegerDivision"); + } +} + +void TransformCoordinate(std::ostream& os, ResizeCoordinateTransformationMode transform_coordinate) { + std::string params; + std::string body; + switch (transform_coordinate) { + case ResizeCoordinateTransformationMode::HALF_PIXEL: + params = "x_resized: u32, x_scale: f32"; + body = "(f32(x_resized) + 0.5) / x_scale - 0.5"; + break; + case ResizeCoordinateTransformationMode::ASYMMETRIC: + params = "x_resized: u32, x_scale: f32, length_resized: u32, length_original: u32"; + body = GetSafeIntegerDivision(transform_coordinate); + break; + case ResizeCoordinateTransformationMode::PYTORCH_HALF_PIXEL: + params = "x_resized: u32, x_scale: f32, length_resized: u32"; + body = "select(0.0, (f32(x_resized) + 0.5) / x_scale - 0.5, length_resized > 1)"; + break; + case ResizeCoordinateTransformationMode::TF_HALF_PIXEL_FOR_NN: + params = "x_resized: u32, x_scale: f32"; + body = "(f32(x_resized) + 0.5) / x_scale"; + break; + case ResizeCoordinateTransformationMode::ALIGN_CORNERS: + params = "x_resized: u32, length_resized: u32, length_original: u32"; + body = GetSafeIntegerDivision(transform_coordinate); + break; + case ResizeCoordinateTransformationMode::TF_CROP_AND_RESIZE: + params = "x_resized: u32, length_resized: u32, length_original: u32, roi_start: f32, roi_end: f32"; + body = std::string("select(0.5 * (roi_start + roi_end) * f32(length_original - 1),") + + "roi_start * f32(length_original - 1) + (f32(x_resized) * (roi_end - roi_start) * " + + "f32(length_original - 1)) / f32(length_resized - 1), length_resized > 1)"; + break; + case ResizeCoordinateTransformationMode::HALF_PIXEL_SYMMETRIC: + params = "x_resized: u32, x_scale: f32, length_resized: u32, length_original: u32"; + body = std::string("(f32(length_original) / 2.0) * (1.0 - f32(length_resized) / ") + + "(x_scale * f32(length_original))) + (f32(x_resized) + 0.5) / x_scale - 0.5"; + break; + default: + ORT_THROW("unknown ResizeCoordinateTransformationMode"); + } + + os << "fn transform_coordinate(" << params << ") -> f32 {\n"; + os << "return " << body << ";\n}\n"; +} + +std::string GetCoordinateCaller(ResizeCoordinateTransformationMode transform_coordinate, int32_t rank) { + std::string scales_index_str = GetElementAt("uniforms.scales", "axis", rank); + std::string input_shape_index_str = GetElementAt("uniforms.input_shape", "axis", rank); + std::string output_shape_index_str = GetElementAt("uniforms.output_shape", "axis", rank); + std::string roi_start_str = GetElementAt("uniforms.roi", "axis", rank * 2); + std::string roi_end_str = GetElementAt("uniforms.roi", "axis + " + std::to_string(rank), rank * 2); + std::stringstream caller_ss; + caller_ss << "transform_coordinate(output_coord, "; + switch (transform_coordinate) { + case ResizeCoordinateTransformationMode::HALF_PIXEL: + case ResizeCoordinateTransformationMode::TF_HALF_PIXEL_FOR_NN: + caller_ss << scales_index_str; + break; + case ResizeCoordinateTransformationMode::ASYMMETRIC: + caller_ss << scales_index_str << ", " << output_shape_index_str << ", " << input_shape_index_str; + break; + case ResizeCoordinateTransformationMode::PYTORCH_HALF_PIXEL: + caller_ss << scales_index_str << ", " << output_shape_index_str; + break; + case ResizeCoordinateTransformationMode::ALIGN_CORNERS: + caller_ss << output_shape_index_str << ", " << input_shape_index_str; + break; + case ResizeCoordinateTransformationMode::TF_CROP_AND_RESIZE: + caller_ss << output_shape_index_str << ", " << input_shape_index_str + << ", f32(" << roi_start_str << "), f32(" << roi_end_str << ")"; + break; + case ResizeCoordinateTransformationMode::HALF_PIXEL_SYMMETRIC: + caller_ss << scales_index_str << ", " << output_shape_index_str << ", " << input_shape_index_str; + break; + default: + ORT_THROW("unknown ResizeCoordinateTransformationMode"); + } + caller_ss << ")"; + + return caller_ss.str(); +} + +void CalcNearestPixel(std::ostream& os, ResizeNearestMode mode) { + std::string params = "x_original: f32"; + std::string body; + switch (mode) { + case ResizeNearestMode::SIMPLE: + params += ", is_down_sampling: bool"; + body = "select(i32(x_original), i32(ceil(x_original)), is_down_sampling)"; + break; + case ResizeNearestMode::ROUND_PREFER_FLOOR: + body = "select(i32(round(x_original)), i32(floor(x_original)), x_original == f32(i32(x_original)) + 0.5)"; + break; + case ResizeNearestMode::ROUND_PREFER_CEIL: + body = "i32(round(x_original))"; + break; + case ResizeNearestMode::FLOOR: + body = "i32(floor(x_original))"; + break; + case ResizeNearestMode::CEIL: + body = "i32(ceil(x_original))"; + break; + default: + ORT_THROW("unknown ResizeNearestMode"); + } + + os << "fn calc_nearest_pixel(" << params << ") -> i32 {\n"; + os << "return " << body << ";\n}\n"; +} + +std::string GetNearestPixelCaller(ResizeNearestMode mode) { + switch (mode) { + case ResizeNearestMode::SIMPLE: + return "calc_nearest_pixel(input_coord, uniforms.scales[axis] < 1.0)"; + break; + case ResizeNearestMode::ROUND_PREFER_FLOOR: + case ResizeNearestMode::ROUND_PREFER_CEIL: + case ResizeNearestMode::FLOOR: + case ResizeNearestMode::CEIL: + return "calc_nearest_pixel(input_coord)"; + break; + default: + ORT_THROW("unknown ResizeNearestMode"); + } +} + +Status ResizeNearestProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride | + ShaderUsage::UseValueTypeAlias); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride); + + std::string scales_index_str = GetElementAt("uniforms.scales", "axis", rank_); + std::string input_shape_index_str = GetElementAt("uniforms.input_shape", "axis", rank_); + std::string input_stride_index_str = GetElementAt("uniforms.input_stride", "axis", rank_ - 1); + + std::stringstream extrapolation_ss; + if (extrapolation_enabled_) { + extrapolation_ss << " if ((input_coord < 0.0 || input_coord > f32(" << input_shape_index_str << " - 1))) {\n" + << " " << output.SetByOffset("global_idx", "input_value_t(uniforms.extrapolation_value)") << ";\n" + << " return;\n" + << " }\n"; + } + + TransformCoordinate(shader.AdditionalImplementation(), coordinate_transform_mode_); + CalcNearestPixel(shader.AdditionalImplementation(), nearest_mode_); + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << " let output_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var input_index = u32(0);\n" + << " for(var axis = 0; axis < " << rank_ << "; axis++) {\n" + << " var output_coord = output_indices[axis];\n" + << " if (" << scales_index_str << " != 1.0) {\n" + << " let input_coord = " << GetCoordinateCaller(coordinate_transform_mode_, rank_) << ";\n" + << extrapolation_ss.str() + << " var nearest_coord = " << GetNearestPixelCaller(nearest_mode_) << ";\n" + << " if (nearest_coord >= i32(" << input_shape_index_str << ")) {\n" + << " output_coord = " << input_shape_index_str << " - 1;\n" + << " } else if (nearest_coord < 0) {\n" + << " output_coord = 0;\n" + << " } else {\n" + << " output_coord = u32(nearest_coord);\n" + << " }" + << " }\n" + << " input_index += select(output_coord * " << input_stride_index_str << ", output_coord, axis == " << rank_ - 1 << ");\n" + << " }\n" + << " " << output.SetByOffset("global_idx", input.GetByOffset("input_index")) << ";\n"; + + return Status::OK(); +} + +Status ResizeNearestImpl(ComputeContext& context, + const Tensor* input_tensor, + int32_t rank, + gsl::span& output_dims, + gsl::span roi, + gsl::span scales, + bool extrapolation_enabled, + const float extrapolation_value, + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + onnxruntime::ResizeNearestMode nearest_mode) { + TensorShape output_shape(output_dims); + auto* output_tensor = context.Output(0, output_shape); + uint32_t output_size = gsl::narrow(output_shape.Size()); + + ResizeNearestProgram program{coordinate_transform_mode, nearest_mode, extrapolation_enabled, rank}; + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .CacheHint(std::to_string(static_cast(extrapolation_enabled)), + std::to_string(static_cast(coordinate_transform_mode)), + std::to_string(static_cast(nearest_mode))) + .AddUniformVariables({{roi}, {scales}, {output_size}, {extrapolation_value}}); + + return context.RunProgram(program); +} + +Status ResizeBilinearProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride | + ShaderUsage::UseValueTypeAlias); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride); + + std::string scales_index_str = GetElementAt("uniforms.scales", "axis", rank_); + std::string input_shape_index_str = GetElementAt("uniforms.input_shape", "axis", rank_); + + std::stringstream extrapolation_ss; + if (extrapolation_enabled_) { + extrapolation_ss << " if ((input_coord < 0.0 || input_coord > input_max_coord)) {\n" + << " " << output.SetByOffset("global_idx", "input_value_t(uniforms.extrapolation_value)") << ";\n" + << " return;\n" + << " }\n"; + } + + TransformCoordinate(shader.AdditionalImplementation(), coordinate_transform_mode_); + std::string transform_coordinate_caller = GetCoordinateCaller(coordinate_transform_mode_, rank_); + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << " let output_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var input_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var axis = " << rank_ - 2 << ";\n" + << " let input_height = u32(" << input_shape_index_str << ");\n" + << " var input_max_coord = f32(input_height - 1);\n" + << " var output_coord = output_indices[axis];\n" + << " var input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_ss.str() + << " input_coord = max(0.0, min(input_coord, input_max_coord));\n" + << " let input_y_coord_int = u32(input_coord);\n" + << " let y_weight_0 = select(input_coord - f32(input_y_coord_int), 0.5, input_coord >= input_max_coord);\n" + << " axis = " << rank_ - 1 << ";\n" + << " let input_width = u32(" << input_shape_index_str << ");\n" + << " input_max_coord = f32(input_width - 1);\n" + << " output_coord = output_indices[axis];\n" + << " input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_ss.str() + << " input_coord = max(0.0, min(input_coord, input_max_coord));\n" + << " let input_x_coord_int = u32(input_coord);\n" + << " let x_weight_0 = select(input_coord - f32(input_x_coord_int), 0.5, input_coord >= input_max_coord);\n" + << " let end_of_h = (input_y_coord_int >= input_height - 1);\n" + << " let end_of_w = (input_x_coord_int >= input_width - 1);\n" + << " let rank = " << rank_ << ";\n" + << " input_indices[rank - 2] = input_y_coord_int;\n" + << " input_indices[rank - 1] = input_x_coord_int;\n" + << " let x00 = " << input.GetByIndices("input_indices") << ";\n" + << " input_indices[rank - 1] = input_x_coord_int + 1;\n" + << " let x10 = select(" << input.GetByIndices("input_indices") << ", x00, end_of_w);\n" + << " input_indices[rank - 2] = input_y_coord_int + 1;\n" + << " input_indices[rank - 1] = input_x_coord_int;\n" + << " let x01 = select(" << input.GetByIndices("input_indices") << ", x00, end_of_h);\n" + << " input_indices[rank - 1] = input_x_coord_int + 1;\n" + << " let x11 = select(select(" << input.GetByIndices("input_indices") << ", x10, end_of_h), x01, end_of_w);\n" + << " let y_weight_1 = 1.0 - y_weight_0;\n" + << " let x_weight_1 = 1.0 - x_weight_0;\n" + << " var value = input_value_t(f32(x00) * y_weight_1 * x_weight_1 + f32(x01) * y_weight_0 * x_weight_1 + f32(x10) * " + << "y_weight_1 * x_weight_0 + f32(x11) * y_weight_0 * x_weight_0);\n" + << " " << output.SetByOffset("global_idx", "value"); + + return Status::OK(); +} + +Status ResizeBilinearImpl(ComputeContext& context, + const Tensor* input_tensor, + int32_t rank, + gsl::span& output_dims, + gsl::span roi, + gsl::span scales, + bool extrapolation_enabled, + const float extrapolation_value, + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode) { + TensorShape output_shape(output_dims); + auto* output_tensor = context.Output(0, output_shape); + uint32_t output_size = gsl::narrow(output_shape.Size()); + + ResizeBilinearProgram program{coordinate_transform_mode, extrapolation_enabled, rank}; + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .CacheHint(std::to_string(static_cast(extrapolation_enabled)), + std::to_string(static_cast(coordinate_transform_mode))) + .AddUniformVariables({{roi}, {scales}, {output_size}, {extrapolation_value}}); + + return context.RunProgram(program); +} + +Status ResizeTrilinearProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride | + ShaderUsage::UseValueTypeAlias); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride); + + std::string scales_index_str = GetElementAt("uniforms.scales", "axis", rank_); + std::string input_shape_index_str = GetElementAt("uniforms.input_shape", "axis", rank_); + + std::stringstream extrapolation_ss; + if (extrapolation_enabled_) { + extrapolation_ss << " if ((input_coord < 0.0 || input_coord > f32(" << input_shape_index_str << " - 1))) {\n" + << " " << output.SetByOffset("global_idx", "input_value_t(uniforms.extrapolation_value)") << ";\n" + << " return;\n" + << " }\n"; + } + + TransformCoordinate(shader.AdditionalImplementation(), coordinate_transform_mode_); + std::string transform_coordinate_caller = GetCoordinateCaller(coordinate_transform_mode_, rank_); + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << " let output_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var input_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var axis = " << rank_ - 3 << ";\n" + << " let input_depth = u32(" << input_shape_index_str << ");\n" + << " var input_max_coord = f32(input_depth - 1);\n" + << " var output_coord = output_indices[axis];\n" + << " var input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_ss.str() + << " input_coord = max(0.0, min(input_coord, input_max_coord));\n" + << " let input_z_coord_int = u32(input_coord);\n" + << " let z_weight_0 = select(input_coord - f32(input_z_coord_int), 0.5, input_coord >= input_max_coord);\n" + << " axis = " << rank_ - 2 << ";\n" + << " let input_height = u32(" << input_shape_index_str << ");\n" + << " input_max_coord = f32(input_height - 1);\n" + << " output_coord = output_indices[axis];\n" + << " input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_ss.str() + << " input_coord = max(0.0, min(input_coord, input_max_coord));\n" + << " let input_y_coord_int = u32(input_coord);\n" + << " let y_weight_0 = select(input_coord - f32(input_y_coord_int), 0.5, input_coord >= input_max_coord);\n" + << " axis = " << rank_ - 1 << ";\n" + << " let input_width = u32(" << input_shape_index_str << ");\n" + << " input_max_coord = f32(input_width - 1);\n" + << " output_coord = output_indices[axis];\n" + << " input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_ss.str() + << " input_coord = max(0.0, min(input_coord, input_max_coord));\n" + << " let input_x_coord_int = u32(input_coord);\n" + << " let x_weight_0 = select(input_coord - f32(input_x_coord_int), 0.5, input_coord >= input_max_coord);\n" + << " let end_of_d = (input_z_coord_int >= input_depth - 1);\n" + << " let end_of_h = (input_y_coord_int >= input_height - 1);\n" + << " let end_of_w = (input_x_coord_int >= input_width - 1);\n" + << " let rank = " << rank_ << ";\n" + << " input_indices[rank - 3] = input_z_coord_int;\n" + << " input_indices[rank - 2] = input_y_coord_int;\n" + << " input_indices[rank - 1] = input_x_coord_int;\n" + << " let x000 = " << input.GetByIndices("input_indices") << ";\n" + << " input_indices[rank - 1] = input_x_coord_int + 1;\n" + << " let x100 = select(" << input.GetByIndices("input_indices") << ", x000, end_of_w);\n" + << " input_indices[rank - 2] = input_y_coord_int + 1;\n" + << " input_indices[rank - 1] = input_x_coord_int;\n" + << " let x010 = select(" << input.GetByIndices("input_indices") << ", x000, end_of_h);\n" + << " input_indices[rank - 1] = input_x_coord_int + 1;\n" + << " let x110 = select(select(" << input.GetByIndices("input_indices") << ", x100, end_of_h), x010, end_of_w);\n" + << " input_indices[rank - 1] = input_x_coord_int;\n" + << " input_indices[rank - 2] = input_y_coord_int;\n" + << " input_indices[rank - 3] = select(input_z_coord_int + 1, input_z_coord_int, end_of_d);\n" + << " let x001 = select(" << input.GetByIndices("input_indices") << ", x000, end_of_d);\n" + << " input_indices[rank - 1] = input_x_coord_int + 1;\n" + << " let x101 = select(" << input.GetByIndices("input_indices") << ", x001, end_of_w);\n" + << " input_indices[rank - 2] = input_y_coord_int + 1;\n" + << " input_indices[rank - 1] = input_x_coord_int;\n" + << " let x011 = select(" << input.GetByIndices("input_indices") << ", x001, end_of_h);\n" + << " input_indices[rank - 1] = input_x_coord_int + 1;\n" + << " let x111 = select(select(" << input.GetByIndices("input_indices") << ", x101, end_of_h), x011, end_of_w);\n" + << " let z_weight_1 = 1.0 - z_weight_0;\n" + << " let y_weight_1 = 1.0 - y_weight_0;\n" + << " let x_weight_1 = 1.0 - x_weight_0;\n" + << " var value = input_value_t(" + << "f32(x000) * z_weight_1 * y_weight_1 * x_weight_1 + f32(x010) * z_weight_1 * y_weight_0 * x_weight_1 + " + << "f32(x100) * z_weight_1 * y_weight_1 * x_weight_0 + f32(x110) * z_weight_1 * y_weight_0 * x_weight_0 + " + << "f32(x001) * z_weight_0 * y_weight_1 * x_weight_1 + f32(x011) * z_weight_0 * y_weight_0 * x_weight_1 + " + << "f32(x101) * z_weight_0 * y_weight_1 * x_weight_0 + f32(x111) * z_weight_0 * y_weight_0 * x_weight_0" + << ");\n" + << " " << output.SetByOffset("global_idx", "value"); + + return Status::OK(); +} + +Status ResizeTrilinearImpl(ComputeContext& context, + const Tensor* input_tensor, + int32_t rank, + gsl::span& output_dims, + gsl::span roi, + gsl::span scales, + bool extrapolation_enabled, + const float extrapolation_value, + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode) { + TensorShape output_shape(output_dims); + auto* output_tensor = context.Output(0, output_shape); + uint32_t output_size = gsl::narrow(output_shape.Size()); + + ResizeTrilinearProgram program{coordinate_transform_mode, extrapolation_enabled, rank}; + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .CacheHint(std::to_string(static_cast(extrapolation_enabled)), + std::to_string(static_cast(coordinate_transform_mode))) + .AddUniformVariables({{roi}, {scales}, {output_size}, {extrapolation_value}}); + + return context.RunProgram(program); +} + +Status ResizeBiCubicProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride | + ShaderUsage::UseValueTypeAlias); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform | + ShaderUsage::UseShapeAndStride); + + std::string scales_index_str = GetElementAt("uniforms.scales", "axis", rank_); + std::string input_shape_index_str = GetElementAt("uniforms.input_shape", "axis", rank_); + + std::stringstream exclude_outside_ss; + std::stringstream extrapolation_enabled_ss; + if (exclude_outside_) { + exclude_outside_ss << " coeff[0] = select(coeff[0], 0.0, (input_coord_int - 1 < 0 || input_coord_int - 1 >= input_max_coord));\n" + << " coeff[1] = select(coeff[1], 0.0, (input_coord_int + 0 < 0 || input_coord_int + 0 >= input_max_coord));\n" + << " coeff[2] = select(coeff[2], 0.0, (input_coord_int + 1 < 0 || input_coord_int + 1 >= input_max_coord));\n" + << " coeff[3] = select(coeff[3], 0.0, (input_coord_int + 2 < 0 || input_coord_int + 2 >= input_max_coord));\n" + << " coeff_sum = dot(coeff, vec4(1.0));\n"; + } + + if (extrapolation_enabled_) { + extrapolation_enabled_ss << " if ((input_coord < 0.0 || input_coord > f32(input_max_coord - 1))) {\n" + << " " << output.SetByOffset("global_idx", "input_value_t(uniforms.extrapolation_value)") << ";\n" + << " return;\n" + << " }\n"; + } + + std::stringstream coeff_ss; + coeff_ss << " coeff[0] = ((cubic_coeff_a * (s_coord + 1.0) - 5.0 * cubic_coeff_a) * (s_coord + 1.0) + 8.0 * cubic_coeff_a) * (s_coord + 1.0) - 4.0 * cubic_coeff_a;\n" + << " coeff[1] = ((cubic_coeff_a + 2.0) * s_coord - (cubic_coeff_a + 3.0)) * s_coord * s_coord + 1.0;\n" + << " coeff[2] = ((cubic_coeff_a + 2.0) * (1.0 - s_coord) - (cubic_coeff_a + 3.0)) * (1.0 - s_coord) * (1.0 - s_coord) + 1.0;\n" + << " coeff[3] = ((cubic_coeff_a * (2.0 - s_coord) - 5.0 * cubic_coeff_a) * (2.0 - s_coord) + 8.0 * cubic_coeff_a) * (2.0 - s_coord) - 4.0 * cubic_coeff_a;\n"; + + std::stringstream cubic_interpolation_rowwise_ss; + cubic_interpolation_rowwise_ss << " input_indices[" << rank_ - 2 << "] = u32(clamp(y, 0, input_height - 1));\n" + << " input_indices[" << rank_ - 1 << "] = u32(clamp(input_x_coord_int - 1, 0, input_width - 1));\n" + << " value_rowwise = x_coeff[0] * " << input.GetByIndices("input_indices") << ";\n" + << " input_indices[" << rank_ - 1 << "] = u32(clamp(input_x_coord_int, 0, input_width - 1));\n" + << " value_rowwise += x_coeff[1] * " << input.GetByIndices("input_indices") << ";\n" + << " input_indices[" << rank_ - 1 << "] = u32(clamp(input_x_coord_int + 1, 0, input_width - 1));\n" + << " value_rowwise += x_coeff[2] * " << input.GetByIndices("input_indices") << ";\n" + << " input_indices[" << rank_ - 1 << "] = u32(clamp(input_x_coord_int + 2, 0, input_width - 1));\n" + << " value_rowwise += x_coeff[3] * " << input.GetByIndices("input_indices") << ";\n"; + + TransformCoordinate(shader.AdditionalImplementation(), coordinate_transform_mode_); + std::string transform_coordinate_caller = GetCoordinateCaller(coordinate_transform_mode_, rank_); + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << " let output_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var input_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var axis = " << rank_ - 2 << ";\n" + << " let input_height = i32(" << input_shape_index_str << ");\n" + << " var input_max_coord = input_height;\n" + << " var output_coord = output_indices[axis];\n" + << " var input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_enabled_ss.str() + << " var coeff_sum = 1.0;\n" + << " let cubic_coeff_a = uniforms.cubic_coeff_a;\n" + << " var input_coord_int = i32(floor(input_coord));\n" + << " var s_coord = abs(input_coord - f32(input_coord_int));\n" + << " var coeff = vec4(0.0);\n" + << coeff_ss.str() + << exclude_outside_ss.str() + << " let input_y_coord_int = input_coord_int;\n" + << " let y_coeff = coeff / coeff_sum;\n" + << " axis = " << rank_ - 1 << ";\n" + << " let input_width = i32(" << input_shape_index_str << ");\n" + << " input_max_coord = input_width;\n" + << " output_coord = output_indices[axis];\n" + << " input_coord = select(f32(output_coord), " << transform_coordinate_caller << " , " << scales_index_str << " != 1.0);\n" + << extrapolation_enabled_ss.str() + << " input_coord_int = i32(floor(input_coord));\n" + << " s_coord = abs(input_coord - f32(input_coord_int));\n" + << coeff_ss.str() + << exclude_outside_ss.str() + << " let input_x_coord_int = input_coord_int;\n" + << " let x_coeff = coeff / coeff_sum;\n" + << " var y = input_y_coord_int - 1;\n" + << " var value_rowwise = 0.0;\n" + << " var value = 0.0;\n" + << cubic_interpolation_rowwise_ss.str() + << " value += y_coeff[0] * value_rowwise;\n" + << " y = input_y_coord_int;\n" + << cubic_interpolation_rowwise_ss.str() + << " value += y_coeff[1] * value_rowwise;\n" + << " y = input_y_coord_int + 1;\n" + << cubic_interpolation_rowwise_ss.str() + << " value += y_coeff[2] * value_rowwise;\n" + << " y = input_y_coord_int + 2;\n" + << cubic_interpolation_rowwise_ss.str() + << " value += y_coeff[3] * value_rowwise;\n" + << output.SetByOffset("global_idx", "input_value_t(value)"); + + return Status::OK(); +} + +Status ResizeBiCubicImpl(ComputeContext& context, + const Tensor* input_tensor, + int32_t rank, + gsl::span& output_dims, + gsl::span roi, + gsl::span scales, + bool extrapolation_enabled, + const float extrapolation_value, + float cubic_coeff_a, + bool exclude_outside, + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode) { + TensorShape output_shape(output_dims); + auto* output_tensor = context.Output(0, output_shape); + uint32_t output_size = gsl::narrow(output_shape.Size()); + + ResizeBiCubicProgram program{coordinate_transform_mode, extrapolation_enabled, exclude_outside, rank}; + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .CacheHint(std::to_string(static_cast(extrapolation_enabled)), + std::to_string(static_cast(exclude_outside)), + std::to_string(static_cast(coordinate_transform_mode))) + .AddUniformVariables({{roi}, {scales}, {output_size}, {extrapolation_value}, {cubic_coeff_a}}); + + return context.RunProgram(program); +} + +Status ResizeImpl(ComputeContext& context, + const Tensor* input, + const onnxruntime::UpsampleMode upsample_mode, + gsl::span& output_dims, + gsl::span roi, + gsl::span scales, + bool extrapolation_enabled, + const float extrapolation_value, + float cubic_coeff_a, + bool exclude_outside, + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + onnxruntime::ResizeNearestMode nearest_mode) { + int32_t rank = static_cast(output_dims.size()); + // We support a special case of bilinear or bicubic if the input data is 4D with the outer 2 scales being 1.0 + // We would have validated the outer scale values by the time execution reaches this + bool is_2D = (rank == 2 || rank == 4); + + // We support a special case of trilinear or tricubic if the input data is 5D with the outer 2 scales being 1.0 + // We would have validated the outer scale values by the time execution reaches this + bool is_3D = (rank == 3 || rank == 5); + + // Should not hit this as we have already validated input rank/scales and we provide verbose error messages + // to the user. + ORT_ENFORCE(is_2D || is_3D, "Only bilinear/trilinear and bicubic modes are supported in Resize"); + + switch (upsample_mode) { + case UpsampleMode::NN: + return ResizeNearestImpl(context, input, rank, output_dims, roi, scales, extrapolation_enabled, + extrapolation_value, coordinate_transform_mode, nearest_mode); + break; + case UpsampleMode::LINEAR: + if (is_2D) { + return ResizeBilinearImpl(context, input, rank, output_dims, roi, scales, extrapolation_enabled, + extrapolation_value, coordinate_transform_mode); + } else if (is_3D) { + return ResizeTrilinearImpl(context, input, rank, output_dims, roi, scales, extrapolation_enabled, + extrapolation_value, coordinate_transform_mode); + } + ORT_THROW("Resize support 2-D and 3-D dimensions in LINEAR mode."); + break; + case UpsampleMode::CUBIC: + if (is_2D) { + return ResizeBiCubicImpl(context, input, rank, output_dims, roi, scales, extrapolation_enabled, + extrapolation_value, cubic_coeff_a, exclude_outside, coordinate_transform_mode); + } + ORT_THROW("Resize supports only 2-D in CUBIC mode."); + default: + ORT_THROW("Only nearest, bilinear/trilinear and bicubic modes are supported in Resize"); + } +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/resize_impl.h b/onnxruntime/core/providers/webgpu/tensor/resize_impl.h new file mode 100644 index 0000000000000..9bf622405355a --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/resize_impl.h @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/cpu/tensor/upsample.h" + +namespace onnxruntime { +namespace webgpu { + +class ResizeNearestProgram final : public Program { + public: + ResizeNearestProgram(onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + onnxruntime::ResizeNearestMode nearest_mode, + bool extrapolation_enabled, + int32_t rank) : Program{"ResizeNearest2D"}, + coordinate_transform_mode_{coordinate_transform_mode}, + nearest_mode_{nearest_mode}, + extrapolation_enabled_{extrapolation_enabled}, + rank_{rank} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"roi", ProgramUniformVariableDataType::Float32}, + {"scales", ProgramUniformVariableDataType::Float32}, + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"extrapolation_value", ProgramUniformVariableDataType::Float32}); + + private: + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode_; + onnxruntime::ResizeNearestMode nearest_mode_; + bool extrapolation_enabled_; + int32_t rank_; +}; + +class ResizeBilinearProgram final : public Program { + public: + ResizeBilinearProgram(onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + bool extrapolation_enabled, + int32_t rank) : Program{"ResizeBilinear"}, + coordinate_transform_mode_{coordinate_transform_mode}, + extrapolation_enabled_{extrapolation_enabled}, + rank_{rank} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"roi", ProgramUniformVariableDataType::Float32}, + {"scales", ProgramUniformVariableDataType::Float32}, + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"extrapolation_value", ProgramUniformVariableDataType::Float32}); + + private: + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode_; + bool extrapolation_enabled_; + int32_t rank_; +}; + +class ResizeTrilinearProgram final : public Program { + public: + ResizeTrilinearProgram(onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + bool extrapolation_enabled, + int32_t rank) : Program{"ResizeTrilinear"}, + coordinate_transform_mode_{coordinate_transform_mode}, + extrapolation_enabled_{extrapolation_enabled}, + rank_{rank} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"roi", ProgramUniformVariableDataType::Float32}, + {"scales", ProgramUniformVariableDataType::Float32}, + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"extrapolation_value", ProgramUniformVariableDataType::Float32}); + + private: + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode_; + bool extrapolation_enabled_; + int32_t rank_; +}; + +class ResizeBiCubicProgram final : public Program { + public: + ResizeBiCubicProgram(onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + bool extrapolation_enabled, + bool exclude_outside, + int32_t rank) : Program{"ResizeBiCubic"}, + coordinate_transform_mode_{coordinate_transform_mode}, + extrapolation_enabled_{extrapolation_enabled}, + exclude_outside_{exclude_outside}, + rank_{rank} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"roi", ProgramUniformVariableDataType::Float32}, + {"scales", ProgramUniformVariableDataType::Float32}, + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"extrapolation_value", ProgramUniformVariableDataType::Float32}, + {"cubic_coeff_a", ProgramUniformVariableDataType::Float32}); + + private: + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode_; + bool extrapolation_enabled_; + bool exclude_outside_; + int32_t rank_; +}; + +Status ResizeImpl( + ComputeContext& context, + const Tensor* input, + const onnxruntime::UpsampleMode upsample_mode, + gsl::span& output_dims, + gsl::span roi, + gsl::span scales, + bool extrapolation_enabled, + const float extrapolation_value, + float cubic_coeff_a, + bool exclude_outside, + onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode, + onnxruntime::ResizeNearestMode nearest_mode); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/upsample.cc b/onnxruntime/core/providers/webgpu/tensor/upsample.cc new file mode 100644 index 0000000000000..fb406883ba4ba --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/upsample.cc @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/tensor/resize_impl.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/tensor/upsample.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +using namespace onnxruntime::common; + +namespace onnxruntime { +namespace webgpu { + +Status Upsample::BaseCompute(ComputeContext& context, + gsl::span roi, + gsl::span scales, + gsl::span output_dims) const { + const auto* X = context.Input(0); + auto dims = X->Shape().GetDims(); + ORT_ENFORCE(output_dims.size() == dims.size(), "Rank of input and output tensor should be same."); + + if (dims.size() == 0) { + return Status(ONNXRUNTIME, INVALID_ARGUMENT, + is_resize_ ? "Resize: input tensor cannot be scalar." + : "Upsample: input tensor cannot be scalar."); + } + if (dims.size() != scales.size()) { + return Status(ONNXRUNTIME, INVALID_ARGUMENT, + is_resize_ ? "Resize: input tensor's dimension does not match the scales." + : "Upsample: input tensor's dimension does not match the scales."); + } + if (roi.size() != 2 * dims.size()) { + return Status(ONNXRUNTIME, INVALID_ARGUMENT, + "Resize: size of roi array should be 2 * N where N is the rank of input tensor X."); + } + + Tensor* Y = context.Output(0, output_dims); + // Return early if the output tensor is going to be of size 0 + if (Y->Shape().Size() == 0) { + return Status::OK(); + } + + if (is_resize_) { + if (!antialias_) { + return ResizeImpl(context, X, mode_, output_dims, roi, scales, use_extrapolation_, extrapolation_value_, + cubic_coeff_a_, exclude_outside_, coordinate_transform_mode_, nearest_mode_); + } else { + return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, + "The antialias attribute of Resize operator is NOT implemented."); + } + } else { + return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, "Upsample operator is NOT implemented."); + } +} + +Status Upsample::ComputeInternal(ComputeContext& context) const { + const auto* X = context.Input(0); + auto input_dims = X->Shape().GetDims(); + TensorShapeVector output_dims(input_dims.size()); + + // Get roi data + // Initialize the roi array to all zeros as this will be the most common case + // Roi data is needed only when coordinate transformation mode is set to tf_crop_and_resize + // for all other cases we need a 0 initialized roi array + InlinedVector roi_array(roi_); + + if (!roi_cached_) { + bool use_default_roi = true; + if (need_roi_input_) { + ORT_ENFORCE(roi_input_idx_ > 0, "Invalid roi input index."); + const auto* roi = context.Input(roi_input_idx_); + if (roi != nullptr) { + ParseRoiData(roi, roi_array); + use_default_roi = false; + } + } + if (use_default_roi) { + // default roi includes ensures all the values in that axis are included in the roi + // normalized roi is thus : [start, end] = [0, 1] + size_t input_rank = input_dims.size(); + roi_array.resize(input_rank * 2); + for (size_t i = 0; i < input_rank; ++i) { + roi_array[i] = 0; + roi_array[i + input_rank] = 1; + } + } + } + + ComputeROIWithAxes(roi_array, input_dims.size()); + + InlinedVector scales_array(input_dims.size()); + // opset < 10 + if (OpKernel::Node().InputDefs().size() == 1) { + scales_array = scales_; + // Compute output shape from scales attributes and input dims + ComputeOutputShape(scales_array, input_dims, output_dims); + return BaseCompute(context, roi_array, scales_array, output_dims); + } + + const auto* scales = context.Input(scales_input_idx_); + const auto* sizes = context.Input(sizes_input_idx_); + + // This is when scales are obtained and cached from a constant initializer + if (scales_cached_) { + ORT_RETURN_IF_NOT(sizes == nullptr, "Only one of scales or sizes must be provided as input."); + scales_array = scales_; + // Compute output shape from scales and input dims + ComputeOutputShape(scales_array, input_dims, output_dims); + return BaseCompute(context, roi_array, scales_array, output_dims); + } + + // Scales and sizes are input to the node + if (scales != nullptr && scales->Shape().Size() != 0) { + // use scales input data + ORT_ENFORCE(sizes == nullptr, "Only one of scales or sizes must be provided as input."); + ORT_RETURN_IF_ERROR(ParseScalesData(scales, scales_array, input_dims.size())); + + // Compute output shape from scales and input dims + ComputeOutputShape(scales_array, input_dims, output_dims); + } else { + // When sizes input is available directly populate it into the output_dims array. + ORT_ENFORCE(sizes != nullptr && sizes->Shape().Size() != 0, + "Either scales or sizes MUST be provided as input."); + ORT_RETURN_IF_ERROR(ParseSizesData(sizes, output_dims, input_dims)); + ORT_RETURN_IF_ERROR(ParseScalesDataAndAdjustOutputSize(output_dims, input_dims, scales_array)); + } + + return BaseCompute(context, roi_array, scales_array, output_dims); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/upsample.h b/onnxruntime/core/providers/webgpu/tensor/upsample.h new file mode 100644 index 0000000000000..ecfbc3c728703 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/upsample.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/cpu/tensor/upsample.h" + +namespace onnxruntime { +namespace webgpu { + +class Upsample : public UpsampleBase, public WebGpuKernel { + public: + explicit Upsample(const OpKernelInfo& info) : UpsampleBase(info), WebGpuKernel(info) {}; + + Status ComputeInternal(ComputeContext& context) const override; + Status BaseCompute(ComputeContext& context, gsl::span roi, gsl::span scales, + gsl::span output_dims) const; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 87383fe197477..d44cf4674d8a3 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -650,11 +650,11 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index 84fb6157b8884..f0d3a53f0ac81 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -107,11 +107,11 @@ TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_tf_crop_and_resize_with_extr 10.0f, 10.0f, 10.0f}; test.AddOutput("Y", {N, static_cast(H * scales[1]), static_cast(W * scales[2]), C}, Y); - // CUDA: result mismatch due to not implementing NHWC support + // CUDA | WEBGPU: result mismatch due to not implementing NHWC support // TensorRT: results mismatch // ROCm: results mismatch test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider}); + {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider, kWebGpuExecutionProvider}); } TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_tf_crop_and_resize_with_extrapolation_uint8) { @@ -282,10 +282,10 @@ TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_4DBilinear) { std::vector Y = {2.66666651f, 4.3333331f}; test.AddOutput("Y", {N, static_cast(H * scales[1]), static_cast(W * scales[2]), C}, Y); - // CUDA: result mismatch due to not implementing NHWC support + // CUDA | WEBGPU: result mismatch due to not implementing NHWC support // ROCm: results mismatch // TRT: Segmentation fault in A100 - std::unordered_set excluded_providers({kCudaExecutionProvider, kCudaNHWCExecutionProvider, kRocmExecutionProvider}); + std::unordered_set excluded_providers({kCudaExecutionProvider, kCudaNHWCExecutionProvider, kRocmExecutionProvider, kWebGpuExecutionProvider}); test.Run(OpTester::ExpectResult::kExpectSuccess, "", ExcludeTrtOnA100(excluded_providers)); } @@ -2034,6 +2034,8 @@ void TestAntialiasing(std::map attributes, excluded_eps.insert(kTensorrtExecutionProvider); // Test is flaky on kCudaNHWCExecutionProvider excluded_eps.insert(kCudaNHWCExecutionProvider); + // Not implementing Antialias support on kWebGpuExecutionProvider + excluded_eps.insert(kWebGpuExecutionProvider); test.Run(OpTester::ExpectResult::kExpectSuccess, "", excluded_eps); } @@ -2473,7 +2475,7 @@ TEST(ResizeOpTest, Antialias_Large_half_pixel) { // DML implementation is equivalent to resize with variable input window size while ORT using a convolution approach. // Absolute error is for ORT CPU. test.AddOutput("Y", output_shape, Y, false, /*rel_error*/ 0.0f, /*abs_error*/ 0.12f); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kQnnExecutionProvider}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kQnnExecutionProvider, kWebGpuExecutionProvider}); } // Test without anti-aliasing for better comparison with DirectML From 40c329ef59f4ec99ef4c51860470439bec95412c Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 26 Feb 2025 16:25:59 -0500 Subject: [PATCH 010/266] Upgrade React Native to 0.73 (#23575) Description Upgrading RN to 0.73.11, including Android and iOS changes.. This PR also include the E2E test changes. Used React-Native upgrade [helper](https://react-native-community.github.io/upgrade-helper/?from=0.72.11&to=0.73.11&package=onnxruntime-android&name=onnxruntime) as the reference. Motivation and Context Need newer RN version to fix S360 work items. --- js/react_native/android/gradle.properties | 4 +- js/react_native/babel.config.js | 5 - js/react_native/e2e/android/app/build.gradle | 70 +- .../DetoxTest.java | 2 +- .../android/app/src/debug/AndroidManifest.xml | 8 - .../ReactNativeFlipper.java | 75 - .../android/app/src/main/AndroidManifest.xml | 1 - .../MainActivity.java | 17 - .../MainApplication.java | 83 - .../DataHandlerPackage.java | 2 +- .../MNISTDataHandler.java | 4 +- .../MNISTPackage.java | 28 + .../MainActivity.kt | 22 + .../MainApplication.kt | 53 + js/react_native/e2e/android/build.gradle | 10 +- js/react_native/e2e/android/gradle.properties | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- js/react_native/e2e/babel.config.js | 18 - .../project.pbxproj | 46 +- .../ios/OnnxruntimeModuleExample/Info.plist | 11 +- js/react_native/e2e/ios/Podfile | 6 - js/react_native/e2e/package.json | 31 +- js/react_native/e2e/src/App.tsx | 2 +- js/react_native/e2e/yarn.lock | 1694 ++++--- .../project.pbxproj | 44 +- js/react_native/ios/Podfile | 10 +- js/react_native/package.json | 16 +- js/react_native/yarn.lock | 3977 +++++------------ 28 files changed, 2318 insertions(+), 3927 deletions(-) delete mode 100644 js/react_native/babel.config.js rename js/react_native/e2e/android/app/src/androidTest/java/com/{example => }/reactnativeonnxruntimemodule/DetoxTest.java (96%) delete mode 100644 js/react_native/e2e/android/app/src/debug/AndroidManifest.xml delete mode 100644 js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java delete mode 100644 js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java delete mode 100644 js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java rename js/react_native/e2e/android/app/src/main/java/com/{example => }/reactnativeonnxruntimemodule/DataHandlerPackage.java (94%) rename js/react_native/e2e/android/app/src/main/java/com/{example => }/reactnativeonnxruntimemodule/MNISTDataHandler.java (97%) create mode 100644 js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java create mode 100644 js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt create mode 100644 js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt delete mode 100644 js/react_native/e2e/babel.config.js diff --git a/js/react_native/android/gradle.properties b/js/react_native/android/gradle.properties index 3461ce4919d38..6f0e50c7151a8 100644 --- a/js/react_native/android/gradle.properties +++ b/js/react_native/android/gradle.properties @@ -4,7 +4,7 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx1024m -XX:MaxPermSize=256m -org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Djavax.xml.accessExternalSchema=all -Djavax.xml.accessExternalDTD=all +org.gradle.jvmargs=-Xmx8192m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Djavax.xml.accessExternalSchema=all -Djavax.xml.accessExternalDTD=all # # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit @@ -13,7 +13,7 @@ org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF #Tue Jan 26 17:36:02 PST 2021 android.enableJetifier=true android.useAndroidX=true -OnnxruntimeModule_buildToolsVersion=33.0.0 +OnnxruntimeModule_buildToolsVersion=34.0.0 OnnxruntimeModule_compileSdkVersion=34 OnnxruntimeModule_minSdkVersion=24 OnnxruntimeModule_targetSdkVersion=34 diff --git a/js/react_native/babel.config.js b/js/react_native/babel.config.js deleted file mode 100644 index e2240f1f51f8b..0000000000000 --- a/js/react_native/babel.config.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = { - presets: ['module:metro-react-native-babel-preset'], -}; diff --git a/js/react_native/e2e/android/app/build.gradle b/js/react_native/e2e/android/app/build.gradle index 68eaacc1908c3..fa94c00a32bd0 100644 --- a/js/react_native/e2e/android/app/build.gradle +++ b/js/react_native/e2e/android/app/build.gradle @@ -1,8 +1,7 @@ apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" -import com.android.build.OutputFile - /** * This is the configuration block to customize your React Native Android app. * By default you don't need to apply any configuration, just uncomment the lines you need. @@ -13,8 +12,8 @@ react { // root = file("../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node_modules/react-native-codegen") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") @@ -52,14 +51,6 @@ react { // hermesFlags = ["-O", "-output-source-map"] } -/** - * Set this to true to create four separate APKs instead of one, - * one for each native architecture. This is useful if you don't - * use App Bundles (https://developer.android.com/guide/app-bundle/) - * and want to have separate APKs to upload to the Play Store. - */ -def enableSeparateBuildPerCPUArchitecture = false - /** * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ @@ -78,20 +69,12 @@ def enableProguardInReleaseBuilds = false */ def jscFlavor = 'org.webkit:android-jsc:+' -/** - * Private function to get the list of Native Architectures you want to build. - * This reads the value from reactNativeArchitectures in your gradle.properties - * file and works together with the --active-arch-only flag of react-native run-android. - */ -def reactNativeArchitectures() { - def value = project.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} android { + buildToolsVersion rootProject.ext.buildToolsVersion compileSdkVersion rootProject.ext.compileSdkVersion - namespace "com.example.reactnativeonnxruntimemodule" + namespace "com.reactnativeonnxruntimemodule" compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 @@ -99,9 +82,13 @@ android { packagingOptions { pickFirst '**/libc++_shared.so' pickFirst '**/libfbjni.so' + excludes = [ + "META-INF", + "META-INF/**", + ] } defaultConfig { - applicationId "com.example.reactnativeonnxruntimemodule" + applicationId "com.reactnativeonnxruntimemodule" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 @@ -109,14 +96,6 @@ android { testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" - } - } signingConfigs { debug { storeFile rootProject.file('debug.keystore') @@ -135,20 +114,6 @@ android { proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro" } } - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - versionCodes.get(abi) * 1048576 + defaultConfig.versionCode - } - - } - } } repositories { @@ -164,19 +129,8 @@ dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + implementation("com.facebook.react:flipper-integration") implementation 'androidx.test.ext:junit:1.1.5' - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { - exclude group:'com.facebook.fbjni' - } - debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { - exclude group:'com.facebook.flipper' - exclude group:'com.squareup.okhttp3', module:'okhttp' - } - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { - exclude group:'com.facebook.flipper' - } if (hermesEnabled.toBoolean()) { implementation("com.facebook.react:hermes-android") @@ -188,7 +142,7 @@ dependencies { androidTestImplementation "androidx.test:runner:1.5.2" androidTestImplementation "androidx.test:rules:1.5.0" - implementation project(':onnxruntime-react-native') + implementation (project(':onnxruntime-react-native')) // specify ORT dependency here so it can be found in libs flatDir repository implementation "com.microsoft.onnxruntime:onnxruntime-android:latest.integration@aar" } diff --git a/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java b/js/react_native/e2e/android/app/src/androidTest/java/com/reactnativeonnxruntimemodule/DetoxTest.java similarity index 96% rename from js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java rename to js/react_native/e2e/android/app/src/androidTest/java/com/reactnativeonnxruntimemodule/DetoxTest.java index 9425e1365fedf..4a5142a60ebc6 100644 --- a/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java +++ b/js/react_native/e2e/android/app/src/androidTest/java/com/reactnativeonnxruntimemodule/DetoxTest.java @@ -2,7 +2,7 @@ // Detox requires the project to have a single dummy native Android Test with some special content, // which will be picked up by the testRunner. -package com.example.reactnativeonnxruntimemodule; +package com.reactnativeonnxruntimemodule; import android.content.Intent; diff --git a/js/react_native/e2e/android/app/src/debug/AndroidManifest.xml b/js/react_native/e2e/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index fa26aa56e1c14..0000000000000 --- a/js/react_native/e2e/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java b/js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java deleted file mode 100644 index 3f0a2311b6b6f..0000000000000 --- a/js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.example.reactnativeonnxruntimemodule; - -import android.content.Context; -import com.facebook.flipper.android.AndroidFlipperClient; -import com.facebook.flipper.android.utils.FlipperUtils; -import com.facebook.flipper.core.FlipperClient; -import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; -import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; -import com.facebook.flipper.plugins.inspector.DescriptorMapping; -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; -import com.facebook.react.ReactInstanceEventListener; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.network.NetworkingModule; -import okhttp3.OkHttpClient; - -/** - * Class responsible of loading Flipper inside your React Native application. This is the debug - * flavor of it. Here you can add your own plugins and customize the Flipper setup. - */ -public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (FlipperUtils.shouldEnableFlipper(context)) { - final FlipperClient client = AndroidFlipperClient.getInstance(context); - - client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new DatabasesFlipperPlugin(context)); - client.addPlugin(new SharedPreferencesFlipperPlugin(context)); - client.addPlugin(CrashReporterPlugin.getInstance()); - - NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); - NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); - } - }); - client.addPlugin(networkFlipperPlugin); - client.start(); - - // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized - // Hence we run if after all native modules have been initialized - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); - if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - reactInstanceManager.removeReactInstanceEventListener(this); - reactContext.runOnNativeModulesQueueThread( - new Runnable() { - @Override - public void run() { - client.addPlugin(new FrescoFlipperPlugin()); - } - }); - } - }); - } else { - client.addPlugin(new FrescoFlipperPlugin()); - } - } - } -} \ No newline at end of file diff --git a/js/react_native/e2e/android/app/src/main/AndroidManifest.xml b/js/react_native/e2e/android/app/src/main/AndroidManifest.xml index d219c7c18f3c2..a44d8099522a9 100644 --- a/js/react_native/e2e/android/app/src/main/AndroidManifest.xml +++ b/js/react_native/e2e/android/app/src/main/AndroidManifest.xml @@ -24,7 +24,6 @@ - diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java b/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java deleted file mode 100644 index e2e48633ddb6e..0000000000000 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.example.reactnativeonnxruntimemodule; - -import com.facebook.react.ReactActivity; - -public class MainActivity extends ReactActivity { - /** - * Returns the name of the main component registered from JavaScript. This is used to schedule - * rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "OnnxruntimeModuleExample"; - } -} diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java b/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java deleted file mode 100644 index 2c59e5dd3d3b1..0000000000000 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.example.reactnativeonnxruntimemodule; - -import ai.onnxruntime.reactnative.OnnxruntimePackage; -import android.app.Application; -import android.content.Context; -import com.facebook.react.PackageList; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.soloader.SoLoader; -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -public class MainApplication extends Application implements ReactApplication { - private static Context appContext; - - private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); - packages.add(new DataHandlerPackage()); - - return packages; - } - - @Override - protected String getJSMainModuleName() { - return "index"; - } - }; - - @Override - public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; - } - - @Override - public void onCreate() { - super.onCreate(); - appContext = getApplicationContext(); - SoLoader.init(this, /* native exopackage */ false); - initializeFlipper( - this, getReactNativeHost().getReactInstanceManager()); // Remove this line if you don't want Flipper enabled - } - - public static Context getAppContext() { return appContext; } - - /** - * Loads Flipper in React Native templates. - * - * @param context - */ - private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (BuildConfig.DEBUG) { - try { - /* - We use reflection here to pick up the class that initializes Flipper, - since Flipper library is not available in release mode - */ - Class aClass = Class.forName("com.onnxruntimereactnativeExample.ReactNativeFlipper"); - aClass.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) - .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - } -} diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/DataHandlerPackage.java b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/DataHandlerPackage.java similarity index 94% rename from js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/DataHandlerPackage.java rename to js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/DataHandlerPackage.java index fa321e15c615b..adfd4e0bb755a 100644 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/DataHandlerPackage.java +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/DataHandlerPackage.java @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.example.reactnativeonnxruntimemodule; +package com.reactnativeonnxruntimemodule; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MNISTDataHandler.java b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTDataHandler.java similarity index 97% rename from js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MNISTDataHandler.java rename to js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTDataHandler.java index a458901b5314c..b5f58f39ea8ca 100644 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MNISTDataHandler.java +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTDataHandler.java @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.example.reactnativeonnxruntimemodule; +package com.reactnativeonnxruntimemodule; import static java.util.stream.Collectors.joining; @@ -114,7 +114,7 @@ private WritableMap preprocess(String uri) throws Exception { final int imageHeight = 28; final int imageWidth = 28; - InputStream is = MainApplication.getAppContext().getContentResolver().openInputStream(Uri.parse(uri)); + InputStream is = reactContext.getContentResolver().openInputStream(Uri.parse(uri)); BufferedInputStream bis = new BufferedInputStream(is); byte[] imageArray = new byte[bis.available()]; bis.read(imageArray); diff --git a/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java new file mode 100644 index 0000000000000..5b09a4b8aeea1 --- /dev/null +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java @@ -0,0 +1,28 @@ +package com.reactnativeonnxruntimemodule; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MNISTPackage implements ReactPackage { + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + try { + modules.add(new MNISTDataHandler(reactContext)); + } catch (Exception e) { + throw new RuntimeException("Failed to initialize MNISTDataHandler", e); + } + return modules; + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt new file mode 100644 index 0000000000000..e572f50dfdab1 --- /dev/null +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt @@ -0,0 +1,22 @@ +package com.reactnativeonnxruntimemodule + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "OnnxruntimeModuleExample" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} \ No newline at end of file diff --git a/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt new file mode 100644 index 0000000000000..f28660d9915e5 --- /dev/null +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt @@ -0,0 +1,53 @@ +package com.reactnativeonnxruntimemodule + +import android.app.Application +import android.content.Context +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +class MainApplication : Application(), ReactApplication { + companion object { + private lateinit var appContext: Context + + fun getAppContext(): Context { + return appContext + } + } + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + add(MNISTPackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + override fun onCreate() { + super.onCreate() + appContext = applicationContext + SoLoader.init(this, false) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } +} \ No newline at end of file diff --git a/js/react_native/e2e/android/build.gradle b/js/react_native/e2e/android/build.gradle index abe57d3d4521d..9ad8256fc52dc 100644 --- a/js/react_native/e2e/android/build.gradle +++ b/js/react_native/e2e/android/build.gradle @@ -2,11 +2,11 @@ buildscript { ext { - buildToolsVersion = "33.0.0" + buildToolsVersion = "34.0.0" minSdkVersion = 24 compileSdkVersion = 34 targetSdkVersion = 34 - kotlinVersion = "1.5.30" + kotlinVersion = "1.8.0" } repositories { google() @@ -14,9 +14,11 @@ buildscript { } dependencies { classpath('com.android.tools.build:gradle:7.4.2') - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") classpath("com.facebook.react:react-native-gradle-plugin") + + // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -43,3 +45,5 @@ allprojects { maven { url 'https://www.jitpack.io' } } } + +apply plugin: "com.facebook.react.rootproject" \ No newline at end of file diff --git a/js/react_native/e2e/android/gradle.properties b/js/react_native/e2e/android/gradle.properties index 92d178de62ce2..ede6147623f19 100644 --- a/js/react_native/e2e/android/gradle.properties +++ b/js/react_native/e2e/android/gradle.properties @@ -19,9 +19,7 @@ android.useAndroidX=true android.enableJetifier=true -FLIPPER_VERSION=0.182.0 -org.gradle.jvmargs=-Xmx4096M - +org.gradle.jvmargs=-Xmx8192m -XX:MaxMetaspaceSize=2048m -Dkotlin.daemon.jvm.options=-Xmx8192m # Use this property to enable or disable the Hermes JS engine. # If set to false, you will be using JSC instead. hermesEnabled=false diff --git a/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties b/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties index 36268b17b88ae..d11cdd907dd9d 100644 --- a/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties +++ b/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/js/react_native/e2e/babel.config.js b/js/react_native/e2e/babel.config.js deleted file mode 100644 index 96ef381f7825d..0000000000000 --- a/js/react_native/e2e/babel.config.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -const path = require('path'); -const pak = require('../package.json'); - -module.exports = { - presets: ['module:metro-react-native-babel-preset'], - plugins: [ - [ - 'module-resolver', - { - alias: { - [pak.name]: path.join(__dirname, '..', pak.source), - }, - }, - ], - ], -}; diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj b/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj index 07604cd4beec9..e3a5a1447a68e 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj @@ -291,10 +291,15 @@ "${BUILT_PRODUCTS_DIR}/React-Codegen/React_Codegen.framework", "${BUILT_PRODUCTS_DIR}/React-Core/React.framework", "${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework", + "${BUILT_PRODUCTS_DIR}/React-Fabric/React_Fabric.framework", + "${BUILT_PRODUCTS_DIR}/React-FabricImage/React_FabricImage.framework", + "${BUILT_PRODUCTS_DIR}/React-ImageManager/React_ImageManager.framework", + "${BUILT_PRODUCTS_DIR}/React-Mapbuffer/React_Mapbuffer.framework", "${BUILT_PRODUCTS_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework", "${BUILT_PRODUCTS_DIR}/React-RCTAnimation/RCTAnimation.framework", "${BUILT_PRODUCTS_DIR}/React-RCTAppDelegate/React_RCTAppDelegate.framework", "${BUILT_PRODUCTS_DIR}/React-RCTBlob/RCTBlob.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTFabric/RCTFabric.framework", "${BUILT_PRODUCTS_DIR}/React-RCTImage/RCTImage.framework", "${BUILT_PRODUCTS_DIR}/React-RCTLinking/RCTLinking.framework", "${BUILT_PRODUCTS_DIR}/React-RCTNetwork/RCTNetwork.framework", @@ -303,12 +308,16 @@ "${BUILT_PRODUCTS_DIR}/React-RCTVibration/RCTVibration.framework", "${BUILT_PRODUCTS_DIR}/React-cxxreact/cxxreact.framework", "${BUILT_PRODUCTS_DIR}/React-debug/React_debug.framework", - "${BUILT_PRODUCTS_DIR}/React-jsc/React_jsc.framework", + "${BUILT_PRODUCTS_DIR}/React-graphics/React_graphics.framework", + "${BUILT_PRODUCTS_DIR}/React-hermes/reacthermes.framework", + "${BUILT_PRODUCTS_DIR}/React-jserrorhandler/React_jserrorhandler.framework", "${BUILT_PRODUCTS_DIR}/React-jsi/jsi.framework", "${BUILT_PRODUCTS_DIR}/React-jsiexecutor/jsireact.framework", "${BUILT_PRODUCTS_DIR}/React-jsinspector/jsinspector.framework", "${BUILT_PRODUCTS_DIR}/React-logger/logger.framework", + "${BUILT_PRODUCTS_DIR}/React-nativeconfig/React_nativeconfig.framework", "${BUILT_PRODUCTS_DIR}/React-perflogger/reactperflogger.framework", + "${BUILT_PRODUCTS_DIR}/React-rendererdebug/React_rendererdebug.framework", "${BUILT_PRODUCTS_DIR}/React-runtimescheduler/React_runtimescheduler.framework", "${BUILT_PRODUCTS_DIR}/React-utils/React_utils.framework", "${BUILT_PRODUCTS_DIR}/ReactCommon/ReactCommon.framework", @@ -316,6 +325,8 @@ "${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework", "${BUILT_PRODUCTS_DIR}/fmt/fmt.framework", "${BUILT_PRODUCTS_DIR}/glog/glog.framework", + "${BUILT_PRODUCTS_DIR}/libevent/libevent.framework", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -326,10 +337,15 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Codegen.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Fabric.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_FabricImage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_ImageManager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Mapbuffer.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_NativeModulesApple.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTAnimation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_RCTAppDelegate.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTBlob.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTFabric.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTLinking.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTNetwork.framework", @@ -338,12 +354,16 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTVibration.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cxxreact.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_debug.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_jsc.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_graphics.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reacthermes.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_jserrorhandler.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsi.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsireact.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsinspector.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/logger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_nativeconfig.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reactperflogger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_rendererdebug.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_runtimescheduler.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_utils.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactCommon.framework", @@ -351,6 +371,8 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fmt.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libevent.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -447,7 +469,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.reactnativeonnxruntimemodule; + PRODUCT_BUNDLE_IDENTIFIER = com.reactnativeonnxruntimemodule; PRODUCT_NAME = OnnxruntimeModuleExample; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -471,7 +493,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.reactnativeonnxruntimemodule; + PRODUCT_BUNDLE_IDENTIFIER = com.reactnativeonnxruntimemodule; PRODUCT_NAME = OnnxruntimeModuleExample; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -484,7 +506,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -511,7 +533,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -535,6 +557,9 @@ "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); "HEADER_SEARCH_PATHS[arch=*]" = ""; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -551,6 +576,7 @@ OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; }; name = Debug; }; @@ -560,7 +586,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -587,7 +613,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -607,6 +633,9 @@ "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; @@ -621,6 +650,7 @@ OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist b/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist index d73af62336182..b8b2ff3059eb7 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist @@ -28,15 +28,12 @@ NSAllowsArbitraryLoads - NSExceptionDomains - - localhost - - NSExceptionAllowsInsecureHTTPLoads + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking - - NSLocationWhenInUseUsageDescription UILaunchStoryboardName diff --git a/js/react_native/e2e/ios/Podfile b/js/react_native/e2e/ios/Podfile index ba2226c144826..95c915cb41dca 100644 --- a/js/react_native/e2e/ios/Podfile +++ b/js/react_native/e2e/ios/Podfile @@ -19,11 +19,6 @@ target 'OnnxruntimeModuleExample' do use_react_native!( :path => config[:reactNativePath], - # Hermes is now enabled by default. Disable by setting this flag to false. - # Upcoming versions of React Native may rely on get_default_flags(), but - # we make it explicit here to aid in the React Native upgrade process. - - :hermes_enabled => false, # :flipper_configuration => FlipperConfiguration.enabled, :app_path => "#{Pod::Config.instance.installation_root}/.." ) @@ -43,6 +38,5 @@ target 'OnnxruntimeModuleExample' do config[:reactNativePath], :mac_catalyst_enabled => false, ) - __apply_Xcode_12_5_M1_post_install_workaround(installer) end end diff --git a/js/react_native/e2e/package.json b/js/react_native/e2e/package.json index 6a5291b9930ec..794452eda7f31 100644 --- a/js/react_native/e2e/package.json +++ b/js/react_native/e2e/package.json @@ -6,35 +6,34 @@ "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", - "start": "react-native start", "lint": "eslint .", + "start": "react-native start", "test": "jest" }, - "engines": { - "node": ">=16" - }, "dependencies": { "react": "^18.2.0", - "react-native": "^0.72.17", + "react-native": "^0.73.11", "react-native-fs": "^2.20.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", - "@react-native/eslint-config": "^0.72.2", - "@react-native/metro-config": "^0.72.12", - "@tsconfig/react-native": "^3.0.0", - "@types/jest": "^29.2.1", - "@types/react": "^18.0.24", + "@react-native/babel-preset": "0.73.21", + "@react-native/eslint-config": "^0.73.2", + "@react-native/metro-config": "^0.73.5", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", - "babel-jest": "^29.2.1", - "babel-plugin-module-resolver": "^4.0.0", + "babel-jest": "^29.6.3", "detox": "20.10.0", - "jest": "^29.2.1", - "metro-react-native-babel-preset": "0.76.9", - "prettier": "^2.4.1", + "eslint": "^8.19.0", + "jest": "^29.6.3", + "prettier": "^2.8.8", "react-test-renderer": "18.2.0", - "typescript": "4.8.4" + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" } } diff --git a/js/react_native/e2e/src/App.tsx b/js/react_native/e2e/src/App.tsx index 8a76edabc613e..1045bb1c0e2ce 100644 --- a/js/react_native/e2e/src/App.tsx +++ b/js/react_native/e2e/src/App.tsx @@ -100,7 +100,7 @@ export default class App extends React.PureComponent<{}, State> { } }; - render(): JSX.Element { + render(): React.JSX.Element { const { output, imagePath } = this.state; return ( diff --git a/js/react_native/e2e/yarn.lock b/js/react_native/e2e/yarn.lock index c764eec7950c2..32bb0eea55bc5 100644 --- a/js/react_native/e2e/yarn.lock +++ b/js/react_native/e2e/yarn.lock @@ -10,7 +10,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.2": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -19,26 +19,26 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.5.tgz#df93ac37f4417854130e21d72c66ff3d4b897fc7" - integrity sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg== +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5", "@babel/compat-data@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" + integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.20.0", "@babel/core@^7.23.9": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.7.tgz#0439347a183b97534d52811144d763a17f9d2b24" - integrity sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" + integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.5" + "@babel/generator" "^7.26.9" "@babel/helper-compilation-targets" "^7.26.5" "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.7" - "@babel/parser" "^7.26.7" - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.26.7" - "@babel/types" "^7.26.7" + "@babel/helpers" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.9" + "@babel/types" "^7.26.9" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -46,21 +46,21 @@ semver "^6.3.1" "@babel/eslint-parser@^7.20.0": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.26.5.tgz#aa669f4d873f9cd617050cf3c40c19cd96307efb" - integrity sha512-Kkm8C8uxI842AwQADxl0GbcG1rupELYLShazYEZO/2DYjhyWXJIOUVOE3tBYm6JXzUCNJOZEzqc4rCW/jsEQYQ== + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz#55c4f4aae4970ae127f7a12369182ed6250e6f09" + integrity sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.20.0", "@babel/generator@^7.26.5", "@babel/generator@^7.7.2": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.5.tgz#e44d4ab3176bbcaf78a5725da5f1dc28802a9458" - integrity sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw== +"@babel/generator@^7.20.0", "@babel/generator@^7.26.9", "@babel/generator@^7.7.2": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" + integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== dependencies: - "@babel/parser" "^7.26.5" - "@babel/types" "^7.26.5" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" @@ -84,16 +84,16 @@ semver "^6.3.1" "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83" - integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" + integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== dependencies: "@babel/helper-annotate-as-pure" "^7.25.9" "@babel/helper-member-expression-to-functions" "^7.25.9" "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" + "@babel/helper-replace-supers" "^7.26.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/traverse" "^7.26.9" semver "^6.3.1" "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": @@ -169,7 +169,7 @@ "@babel/helper-wrap-function" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/helper-replace-supers@^7.25.9": +"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== @@ -210,20 +210,20 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helpers@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.7.tgz#fd1d2a7c431b6e39290277aacfd8367857c576a4" - integrity sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A== +"@babel/helpers@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" + integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== dependencies: - "@babel/template" "^7.25.9" - "@babel/types" "^7.26.7" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" -"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.25.9", "@babel/parser@^7.26.5", "@babel/parser@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.7.tgz#e114cd099e5f7d17b05368678da0fb9f69b3385c" - integrity sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w== +"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" + integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== dependencies: - "@babel/types" "^7.26.7" + "@babel/types" "^7.26.9" "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": version "7.25.9" @@ -274,7 +274,7 @@ "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": +"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== @@ -305,7 +305,7 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.20.0": +"@babel/plugin-proposal-object-rest-spread@^7.20.0": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== @@ -352,7 +352,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.12.13": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== @@ -380,7 +380,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.26.0": +"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz#96507595c21b45fccfc2bc758d5c45452e6164fa" integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg== @@ -415,7 +415,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.25.9", "@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.25.9", "@babel/plugin-syntax-jsx@^7.7.2": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== @@ -443,7 +443,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== @@ -500,14 +500,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-async-generator-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz#1b18530b077d18a407c494eb3d1d72da505283a2" - integrity sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw== +"@babel/plugin-transform-async-generator-functions@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" + integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" "@babel/helper-remap-async-to-generator" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/traverse" "^7.26.8" "@babel/plugin-transform-async-to-generator@^7.20.0", "@babel/plugin-transform-async-to-generator@^7.25.9": version "7.25.9" @@ -518,7 +518,7 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/helper-remap-async-to-generator" "^7.25.9" -"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.26.5": +"@babel/plugin-transform-block-scoped-functions@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== @@ -568,7 +568,7 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/template" "^7.25.9" -"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.20.0", "@babel/plugin-transform-destructuring@^7.25.9": +"@babel/plugin-transform-destructuring@^7.20.0", "@babel/plugin-transform-destructuring@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== @@ -619,7 +619,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.25.9": +"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.25.9": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz#2904c85a814e7abb1f4850b8baf4f07d0a2389d4" integrity sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ== @@ -627,12 +627,12 @@ "@babel/helper-plugin-utils" "^7.26.5" "@babel/plugin-syntax-flow" "^7.26.0" -"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz#4bdc7d42a213397905d89f02350c5267866d5755" - integrity sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A== +"@babel/plugin-transform-for-of@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz#27231f79d5170ef33b5111f07fe5cafeb2c96a56" + integrity sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" "@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.25.9": @@ -665,7 +665,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.25.9": +"@babel/plugin-transform-member-expression-literals@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== @@ -744,7 +744,7 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-parameters" "^7.25.9" -"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.25.9": +"@babel/plugin-transform-object-super@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== @@ -774,7 +774,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-private-methods@^7.25.9": +"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== @@ -782,7 +782,7 @@ "@babel/helper-create-class-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-private-property-in-object@^7.25.9": +"@babel/plugin-transform-private-property-in-object@^7.22.11", "@babel/plugin-transform-private-property-in-object@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== @@ -791,7 +791,7 @@ "@babel/helper-create-class-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.25.9": +"@babel/plugin-transform-property-literals@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== @@ -854,12 +854,12 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-runtime@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz#62723ea3f5b31ffbe676da9d6dae17138ae580ea" - integrity sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" + integrity sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ== dependencies: "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" babel-plugin-polyfill-corejs2 "^0.4.10" babel-plugin-polyfill-corejs3 "^0.10.6" babel-plugin-polyfill-regenerator "^0.6.1" @@ -887,12 +887,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz#6dbd4a24e8fad024df76d1fac6a03cf413f60fe1" - integrity sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw== +"@babel/plugin-transform-template-literals@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" + integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" "@babel/plugin-transform-typeof-symbol@^7.26.7": version "7.26.7" @@ -902,9 +902,9 @@ "@babel/helper-plugin-utils" "^7.26.5" "@babel/plugin-transform-typescript@^7.25.9", "@babel/plugin-transform-typescript@^7.5.0": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.7.tgz#64339515ea3eff610160f62499c3ef437d0ac83d" - integrity sha512-5cJurntg+AT+cgelGP9Bt788DKiAw9gIMSMU2NJrLAilnj0m8WZWUNZPSLOmadYsujHutpgElO+50foX+ib/Wg== + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" + integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== dependencies: "@babel/helper-annotate-as-pure" "^7.25.9" "@babel/helper-create-class-features-plugin" "^7.25.9" @@ -944,11 +944,11 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/preset-env@^7.20.0": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.7.tgz#24d38e211f4570b8d806337035cc3ae798e0c36d" - integrity sha512-Ycg2tnXwixaXOVb29rana8HNPgLVBof8qqtNQ9LE22IoyZboQbGSxI6ZySMdW3K5nAe6gu35IaJefUJflhUFTQ== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.9.tgz#2ec64e903d0efe743699f77a10bdf7955c2123c3" + integrity sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ== dependencies: - "@babel/compat-data" "^7.26.5" + "@babel/compat-data" "^7.26.8" "@babel/helper-compilation-targets" "^7.26.5" "@babel/helper-plugin-utils" "^7.26.5" "@babel/helper-validator-option" "^7.25.9" @@ -962,7 +962,7 @@ "@babel/plugin-syntax-import-attributes" "^7.26.0" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" "@babel/plugin-transform-arrow-functions" "^7.25.9" - "@babel/plugin-transform-async-generator-functions" "^7.25.9" + "@babel/plugin-transform-async-generator-functions" "^7.26.8" "@babel/plugin-transform-async-to-generator" "^7.25.9" "@babel/plugin-transform-block-scoped-functions" "^7.26.5" "@babel/plugin-transform-block-scoping" "^7.25.9" @@ -977,7 +977,7 @@ "@babel/plugin-transform-dynamic-import" "^7.25.9" "@babel/plugin-transform-exponentiation-operator" "^7.26.3" "@babel/plugin-transform-export-namespace-from" "^7.25.9" - "@babel/plugin-transform-for-of" "^7.25.9" + "@babel/plugin-transform-for-of" "^7.26.9" "@babel/plugin-transform-function-name" "^7.25.9" "@babel/plugin-transform-json-strings" "^7.25.9" "@babel/plugin-transform-literals" "^7.25.9" @@ -1005,7 +1005,7 @@ "@babel/plugin-transform-shorthand-properties" "^7.25.9" "@babel/plugin-transform-spread" "^7.25.9" "@babel/plugin-transform-sticky-regex" "^7.25.9" - "@babel/plugin-transform-template-literals" "^7.25.9" + "@babel/plugin-transform-template-literals" "^7.26.8" "@babel/plugin-transform-typeof-symbol" "^7.26.7" "@babel/plugin-transform-unicode-escapes" "^7.25.9" "@babel/plugin-transform-unicode-property-regex" "^7.25.9" @@ -1013,9 +1013,9 @@ "@babel/plugin-transform-unicode-sets-regex" "^7.25.9" "@babel/preset-modules" "0.1.6-no-external-plugins" babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-corejs3 "^0.11.0" babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.38.1" + core-js-compat "^3.40.0" semver "^6.3.1" "@babel/preset-flow@^7.13.13": @@ -1058,39 +1058,39 @@ pirates "^4.0.6" source-map-support "^0.5.16" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.20.0", "@babel/runtime@^7.8.4": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.7.tgz#f4e7fe527cd710f8dc0618610b61b4b060c3c341" - integrity sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ== +"@babel/runtime@^7.20.0", "@babel/runtime@^7.25.0", "@babel/runtime@^7.8.4": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" + integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.0.0", "@babel/template@^7.25.9", "@babel/template@^7.3.3": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" - integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== +"@babel/template@^7.0.0", "@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.3.3": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== dependencies: - "@babel/code-frame" "^7.25.9" - "@babel/parser" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" -"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.7.tgz#99a0a136f6a75e7fb8b0a1ace421e0b25994b8bb" - integrity sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA== +"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" + integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== dependencies: "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.5" - "@babel/parser" "^7.26.7" - "@babel/template" "^7.25.9" - "@babel/types" "^7.26.7" + "@babel/generator" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.25.9", "@babel/types@^7.26.5", "@babel/types@^7.26.7", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" - integrity sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg== +"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== dependencies: "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" @@ -1107,11 +1107,31 @@ dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.4.0": +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.57.1": + version "8.57.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== + "@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -1124,6 +1144,30 @@ dependencies: "@hapi/hoek" "^9.0.0" +"@humanwhocodes/config-array@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== + dependencies: + "@humanwhocodes/object-schema" "^2.0.3" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@isaacs/ttlcache@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" + integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1186,7 +1230,7 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/create-cache-key-function@^29.2.1": +"@jest/create-cache-key-function@^29.6.3": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== @@ -1338,17 +1382,6 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@jest/types@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" - integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - "@jest/types@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" @@ -1421,7 +1454,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -1429,115 +1462,102 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@react-native-community/cli-clean@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-11.4.1.tgz#0155a02e4158c8a61ba3d7a2b08f3ebebed81906" - integrity sha512-cwUbY3c70oBGv3FvQJWe2Qkq6m1+/dcEBonMDTYyH6i+6OrkzI4RkIGpWmbG1IS5JfE9ISUZkNL3946sxyWNkw== +"@react-native-community/cli-clean@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz#303ddf1c930918a8bdc4cc58fe0ac2dd05603cd5" + integrity sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" execa "^5.0.0" - prompts "^2.4.0" -"@react-native-community/cli-config@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-11.4.1.tgz#c27f91d2753f0f803cc79bbf299f19648a5d5627" - integrity sha512-sLdv1HFVqu5xNpeaR1+std0t7FFZaobpmpR0lFCOzKV7H/l611qS2Vo8zssmMK+oQbCs5JsX3SFPciODeIlaWA== +"@react-native-community/cli-config@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-12.3.7.tgz#feb8b93e8ccd6116ac1df0f1d8a0f06872388e51" + integrity sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" cosmiconfig "^5.1.0" deepmerge "^4.3.0" glob "^7.1.3" joi "^17.2.1" -"@react-native-community/cli-debugger-ui@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-11.4.1.tgz#783cc276e1360baf8235dc8c6ebbbce0fe01d944" - integrity sha512-+pgIjGNW5TrJF37XG3djIOzP+WNoPp67to/ggDhrshuYgpymfb9XpDVsURJugy0Sy3RViqb83kQNK765QzTIvw== +"@react-native-community/cli-debugger-ui@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz#522aa11c7b4ff4a2ec86492fabee0366d5428b4c" + integrity sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-doctor@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-11.4.1.tgz#516ef5932de3e12989695e7cb7aba82b81e7b2de" - integrity sha512-O6oPiRsl8pdkcyNktpzvJAXUqdocoY4jh7Tt7wA69B1JKCJA7aPCecwJgpUZb63ZYoxOtRtYM3BYQKzRMLIuUw== +"@react-native-community/cli-doctor@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz#31e4784182d6bbfe62f2e728dca87ee23efe0564" + integrity sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg== dependencies: - "@react-native-community/cli-config" "11.4.1" - "@react-native-community/cli-platform-android" "11.4.1" - "@react-native-community/cli-platform-ios" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-config" "12.3.7" + "@react-native-community/cli-platform-android" "12.3.7" + "@react-native-community/cli-platform-ios" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" command-exists "^1.2.8" - envinfo "^7.7.2" + deepmerge "^4.3.0" + envinfo "^7.10.0" execa "^5.0.0" hermes-profile-transformer "^0.0.6" node-stream-zip "^1.9.1" ora "^5.4.1" - prompts "^2.4.0" semver "^7.5.2" strip-ansi "^5.2.0" - sudo-prompt "^9.0.0" wcwidth "^1.0.1" yaml "^2.2.1" -"@react-native-community/cli-hermes@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-11.4.1.tgz#abf487ae8ab53c66f6f1178bcd37ecbbbac9fb5c" - integrity sha512-1VAjwcmv+i9BJTMMVn5Grw7AcgURhTyfHVghJ1YgBE2euEJxPuqPKSxP54wBOQKnWUwsuDQAtQf+jPJoCxJSSA== +"@react-native-community/cli-hermes@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz#4a284e0091469f6cce8caad2fefcf6b45c0cf229" + integrity sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg== dependencies: - "@react-native-community/cli-platform-android" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-platform-android" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" hermes-profile-transformer "^0.0.6" -"@react-native-community/cli-platform-android@11.4.1", "@react-native-community/cli-platform-android@^11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-11.4.1.tgz#ec5fc97e87834f2e33cb0d34dcef6c17b20f60fc" - integrity sha512-VMmXWIzk0Dq5RAd+HIEa3Oe7xl2jso7+gOr6E2HALF4A3fCKUjKZQ6iK2t6AfnY04zftvaiKw6zUXtrfl52AVQ== +"@react-native-community/cli-platform-android@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz#4826f5126f950e29d7ef1ac779c4eed56d251f98" + integrity sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" execa "^5.0.0" + fast-xml-parser "^4.2.4" glob "^7.1.3" logkitty "^0.7.1" -"@react-native-community/cli-platform-ios@11.4.1", "@react-native-community/cli-platform-ios@^11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-11.4.1.tgz#12d72741273b684734d5ed021415b7f543a6f009" - integrity sha512-RPhwn+q3IY9MpWc9w/Qmzv03mo8sXdah2eSZcECgweqD5SHWtOoRCUt11zM8jASpAQ8Tm5Je7YE9bHvdwGl4hA== +"@react-native-community/cli-platform-ios@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz#ef90e5c4d9ff5f15071b18179b17cf16699a70e5" + integrity sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" execa "^5.0.0" fast-xml-parser "^4.0.12" glob "^7.1.3" ora "^5.4.1" -"@react-native-community/cli-plugin-metro@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-11.4.1.tgz#8d51c59a9a720f99150d4153e757d5d1d1dabd22" - integrity sha512-JxbIqknYcQ5Z4rWROtu5LNakLfMiKoWcMoPqIrBLrV5ILm1XUJj1/8fATCcotZqV3yzB3SCJ3RrhKx7dQ3YELw== - dependencies: - "@react-native-community/cli-server-api" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" - chalk "^4.1.2" - execa "^5.0.0" - metro "^0.76.9" - metro-config "^0.76.9" - metro-core "^0.76.9" - metro-react-native-babel-transformer "^0.76.9" - metro-resolver "^0.76.9" - metro-runtime "^0.76.9" - readline "^1.3.0" +"@react-native-community/cli-plugin-metro@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz#f9be724721a52d800a20f641a2241a7b4e6a9477" + integrity sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg== -"@react-native-community/cli-server-api@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-11.4.1.tgz#3dda094c4ab2369db34fe991c320e3cd78f097b3" - integrity sha512-isxXE8X5x+C4kN90yilD08jaLWD34hfqTfn/Xbl1u/igtdTsCaQGvWe9eaFamrpWFWTpVtj6k+vYfy8AtYSiKA== +"@react-native-community/cli-server-api@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz#81e2a067c120391242740598010abb8d5d36a739" + integrity sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg== dependencies: - "@react-native-community/cli-debugger-ui" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-debugger-ui" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" compression "^1.7.1" connect "^3.6.5" errorhandler "^1.5.1" @@ -1546,10 +1566,10 @@ serve-static "^1.13.1" ws "^7.5.1" -"@react-native-community/cli-tools@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-11.4.1.tgz#f6c69967e077b10cd8a884a83e53eb199dd9ee9f" - integrity sha512-GuQIuY/kCPfLeXB1aiPZ5HvF+e/wdO42AYuNEmT7FpH/0nAhdTxA9qjL8m3vatDD2/YK7WNOSVNsl2UBZuOISg== +"@react-native-community/cli-tools@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz#65cf1c81d13662a1b0396c753e6ff916e3e92083" + integrity sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw== dependencies: appdirsjs "^1.2.4" chalk "^4.1.2" @@ -1560,46 +1580,103 @@ ora "^5.4.1" semver "^7.5.2" shell-quote "^1.7.3" + sudo-prompt "^9.0.0" -"@react-native-community/cli-types@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-11.4.1.tgz#3842dc37ba3b09f929b485bcbd8218de19349ac2" - integrity sha512-B3q9A5BCneLDSoK/iSJ06MNyBn1qTxjdJeOgeS3MiCxgJpPcxyn/Yrc6+h0Cu9T9sgWj/dmectQPYWxtZeo5VA== +"@react-native-community/cli-types@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-12.3.7.tgz#6f55becdc41bb5ebf1a8f6fd27ad0d198831169d" + integrity sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w== dependencies: joi "^17.2.1" -"@react-native-community/cli@^11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-11.4.1.tgz#9a6346486622860dad721da406df70e29a45491f" - integrity sha512-NdAageVMtNhtvRsrq4NgJf5Ey2nA1CqmLvn7PhSawg+aIzMKmZuzWxGVwr9CoPGyjvNiqJlCWrLGR7NzOyi/sA== - dependencies: - "@react-native-community/cli-clean" "11.4.1" - "@react-native-community/cli-config" "11.4.1" - "@react-native-community/cli-debugger-ui" "11.4.1" - "@react-native-community/cli-doctor" "11.4.1" - "@react-native-community/cli-hermes" "11.4.1" - "@react-native-community/cli-plugin-metro" "11.4.1" - "@react-native-community/cli-server-api" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" - "@react-native-community/cli-types" "11.4.1" +"@react-native-community/cli@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-12.3.7.tgz#8f53ec9310367a0204d859005e9cd137f9888382" + integrity sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ== + dependencies: + "@react-native-community/cli-clean" "12.3.7" + "@react-native-community/cli-config" "12.3.7" + "@react-native-community/cli-debugger-ui" "12.3.7" + "@react-native-community/cli-doctor" "12.3.7" + "@react-native-community/cli-hermes" "12.3.7" + "@react-native-community/cli-plugin-metro" "12.3.7" + "@react-native-community/cli-server-api" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" + "@react-native-community/cli-types" "12.3.7" chalk "^4.1.2" commander "^9.4.1" + deepmerge "^4.3.0" execa "^5.0.0" find-up "^4.1.0" fs-extra "^8.1.0" graceful-fs "^4.1.3" - prompts "^2.4.0" + prompts "^2.4.2" semver "^7.5.2" -"@react-native/assets-registry@^0.72.0": - version "0.72.0" - resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.72.0.tgz#c82a76a1d86ec0c3907be76f7faf97a32bbed05d" - integrity sha512-Im93xRJuHHxb1wniGhBMsxLwcfzdYreSZVQGDoMJgkd6+Iky61LInGEHnQCTN0fKNYF1Dvcofb4uMmE1RQHXHQ== +"@react-native/assets-registry@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.73.1.tgz#e2a6b73b16c183a270f338dc69c36039b3946e85" + integrity sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg== + +"@react-native/babel-plugin-codegen@0.73.4": + version "0.73.4" + resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz#8a2037d5585b41877611498ae66adbf1dddfec1b" + integrity sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ== + dependencies: + "@react-native/codegen" "0.73.3" -"@react-native/codegen@^0.72.8": - version "0.72.8" - resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.72.8.tgz#0593f628e1310f430450a9479fbb4be35e7b63d6" - integrity sha512-jQCcBlXV7B7ap5VlHhwIPieYz89yiRgwd2FPUBu+unz+kcJ6pAiB2U8RdLDmyIs8fiWd+Vq1xxaWs4TR329/ng== +"@react-native/babel-preset@0.73.21": + version "0.73.21" + resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.73.21.tgz#174c16493fa4e311b2f5f0c58d4f3c6a5a68bbea" + integrity sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA== + dependencies: + "@babel/core" "^7.20.0" + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.18.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" + "@babel/plugin-proposal-numeric-separator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.20.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.20.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.18.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-async-to-generator" "^7.20.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.20.0" + "@babel/plugin-transform-flow-strip-types" "^7.20.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + "@react-native/babel-plugin-codegen" "0.73.4" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.14.0" + +"@react-native/codegen@0.73.3": + version "0.73.3" + resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.73.3.tgz#cc984a8b17334d986cc600254a0d4b7fa7d68a94" + integrity sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg== dependencies: "@babel/parser" "^7.20.0" flow-parser "^0.206.0" @@ -1609,16 +1686,55 @@ mkdirp "^0.5.1" nullthrows "^1.1.1" -"@react-native/eslint-config@^0.72.2": - version "0.72.2" - resolved "https://registry.yarnpkg.com/@react-native/eslint-config/-/eslint-config-0.72.2.tgz#31da4cec65ad2805d4db9fdda138452821d72133" - integrity sha512-rAYuQQXzi63W7+9Pu/+23od/b/lTSzHjMFibum3sKgdG2LIyvhoMEWQ5+Chu7TqebqYy1b9SDn/KEMHvpWFtNg== +"@react-native/community-cli-plugin@0.73.18": + version "0.73.18" + resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz#ba2a0933fad574684534eea29f1c5d2cab494854" + integrity sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww== + dependencies: + "@react-native-community/cli-server-api" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" + "@react-native/dev-middleware" "0.73.8" + "@react-native/metro-babel-transformer" "0.73.15" + chalk "^4.0.0" + execa "^5.1.1" + metro "^0.80.3" + metro-config "^0.80.3" + metro-core "^0.80.3" + node-fetch "^2.2.0" + readline "^1.3.0" + +"@react-native/debugger-frontend@0.73.3": + version "0.73.3" + resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz#033757614d2ada994c68a1deae78c1dd2ad33c2b" + integrity sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw== + +"@react-native/dev-middleware@0.73.8": + version "0.73.8" + resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz#2e43722a00c7b8db753f747f40267cbad6caba4d" + integrity sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg== + dependencies: + "@isaacs/ttlcache" "^1.4.1" + "@react-native/debugger-frontend" "0.73.3" + chrome-launcher "^0.15.2" + chromium-edge-launcher "^1.0.0" + connect "^3.6.5" + debug "^2.2.0" + node-fetch "^2.2.0" + open "^7.0.3" + serve-static "^1.13.1" + temp-dir "^2.0.0" + ws "^6.2.2" + +"@react-native/eslint-config@^0.73.2": + version "0.73.2" + resolved "https://registry.yarnpkg.com/@react-native/eslint-config/-/eslint-config-0.73.2.tgz#40b2cd8ce245e90c885b8ab15fae1219a946bfac" + integrity sha512-YzMfes19loTfbrkbYNAfHBDXX4oRBzc5wnvHs4h2GIHUj6YKs5ZK5lldqSrBJCdZAI3nuaO9Qj+t5JRwou571w== dependencies: "@babel/core" "^7.20.0" "@babel/eslint-parser" "^7.20.0" - "@react-native/eslint-plugin" "^0.72.0" - "@typescript-eslint/eslint-plugin" "^5.30.5" - "@typescript-eslint/parser" "^5.30.5" + "@react-native/eslint-plugin" "0.73.1" + "@typescript-eslint/eslint-plugin" "^5.57.1" + "@typescript-eslint/parser" "^5.57.1" eslint-config-prettier "^8.5.0" eslint-plugin-eslint-comments "^3.2.0" eslint-plugin-ft-flow "^2.0.1" @@ -1628,40 +1744,55 @@ eslint-plugin-react-hooks "^4.6.0" eslint-plugin-react-native "^4.0.0" -"@react-native/eslint-plugin@^0.72.0": - version "0.72.0" - resolved "https://registry.yarnpkg.com/@react-native/eslint-plugin/-/eslint-plugin-0.72.0.tgz#7ec4c6a73dfde4bd6b4a4d3c462cfdc2637bf91d" - integrity sha512-xWQthnyKd+H22TBqeJUTFebsyWAAwzUb7EQCT8F/WMZsS1sv5UG+2cM/cU9/2HEbVZgxHYuLIi915WznjKPvlg== - -"@react-native/gradle-plugin@^0.72.11": - version "0.72.11" - resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.72.11.tgz#c063ef12778706611de7a1e42b74b14d9405fb9f" - integrity sha512-P9iRnxiR2w7EHcZ0mJ+fmbPzMby77ZzV6y9sJI3lVLJzF7TLSdbwcQyD3lwMsiL+q5lKUHoZJS4sYmih+P2HXw== - -"@react-native/js-polyfills@^0.72.1": - version "0.72.1" - resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.72.1.tgz#905343ef0c51256f128256330fccbdb35b922291" - integrity sha512-cRPZh2rBswFnGt5X5EUEPs0r+pAsXxYsifv/fgy9ZLQokuT52bPH+9xjDR+7TafRua5CttGW83wP4TntRcWNDA== - -"@react-native/metro-config@^0.72.12": - version "0.72.12" - resolved "https://registry.yarnpkg.com/@react-native/metro-config/-/metro-config-0.72.12.tgz#f55a0a68100824ac57989ee9ae9518a69b0c43c5" - integrity sha512-6NC5nr70oV8gH5vTz0yVYig6TGn97NfE58DdYottuOGPEODZf9Jpb7gdLs6Rqj5ryFDsKVPU3NsFmXKBJwEgXQ== - dependencies: - "@react-native/js-polyfills" "^0.72.1" - metro-config "^0.76.9" - metro-react-native-babel-transformer "^0.76.9" - metro-runtime "^0.76.9" - -"@react-native/normalize-colors@<0.73.0", "@react-native/normalize-colors@^0.72.0": - version "0.72.0" - resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.72.0.tgz#14294b7ed3c1d92176d2a00df48456e8d7d62212" - integrity sha512-285lfdqSXaqKuBbbtP9qL2tDrfxdOFtIMvkKadtleRQkdOxx+uzGvFr82KHmc/sSiMtfXGp7JnFYWVh4sFl7Yw== - -"@react-native/virtualized-lists@^0.72.8": - version "0.72.8" - resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz#a2c6a91ea0f1d40eb5a122fb063daedb92ed1dc3" - integrity sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw== +"@react-native/eslint-plugin@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/eslint-plugin/-/eslint-plugin-0.73.1.tgz#79d2c4d90c80bfad8900db335bfbaf1ca599abdc" + integrity sha512-8BNMFE8CAI7JLWLOs3u33wcwcJ821LYs5g53Xyx9GhSg0h8AygTwDrwmYb/pp04FkCNCPjKPBoaYRthQZmxgwA== + +"@react-native/gradle-plugin@0.73.5": + version "0.73.5" + resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz#900126b4e5737eaac22a0fddb2fc5b4cc20da41c" + integrity sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA== + +"@react-native/js-polyfills@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz#730b0a7aaab947ae6f8e5aa9d995e788977191ed" + integrity sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g== + +"@react-native/metro-babel-transformer@0.73.15": + version "0.73.15" + resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz#c516584dde62d65a46668074084359c03e6a50f1" + integrity sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw== + dependencies: + "@babel/core" "^7.20.0" + "@react-native/babel-preset" "0.73.21" + hermes-parser "0.15.0" + nullthrows "^1.1.1" + +"@react-native/metro-config@^0.73.5": + version "0.73.5" + resolved "https://registry.yarnpkg.com/@react-native/metro-config/-/metro-config-0.73.5.tgz#791242ca93057d7299ce18379ea11d3bdb368ea9" + integrity sha512-3bNWoHzOzP/+qoLJtRhOVXrnxKmSY3i4y5PXyMQlIvvOI/GQbXulPpEZxK/yUrf1MmeXHLLFufFbQWlfDEDoxA== + dependencies: + "@react-native/js-polyfills" "0.73.1" + "@react-native/metro-babel-transformer" "0.73.15" + metro-config "^0.80.3" + metro-runtime "^0.80.3" + +"@react-native/normalize-colors@0.73.2", "@react-native/normalize-colors@^0.73.0": + version "0.73.2" + resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz#cc8e48fbae2bbfff53e12f209369e8d2e4cf34ec" + integrity sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w== + +"@react-native/typescript-config@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/typescript-config/-/typescript-config-0.73.1.tgz#c97a42f5cd264069bfe86b737c531ed2f042ae6d" + integrity sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w== + +"@react-native/virtualized-lists@0.73.4": + version "0.73.4" + resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz#640e594775806f63685435b5d9c3d05c378ccd8c" + integrity sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog== dependencies: invariant "^2.2.4" nullthrows "^1.1.1" @@ -1702,11 +1833,6 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@tsconfig/react-native@^3.0.0": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@tsconfig/react-native/-/react-native-3.0.5.tgz#c4971b1eca2e8cdf7b0d25f40193a782039c1abd" - integrity sha512-0+pmYzHccvwWpFz2Tv5AJxp6UroLALmAy+SX34tKlwaCie1mNbtCv6uOJp7x8pKchgNA9/n6BGrx7uLQvw8p9A== - "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -1766,23 +1892,15 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.2.1": - version "29.5.14" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" - integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/node@*": - version "22.13.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.0.tgz#d376dd9a0ee2f9382d86c2d5d7beb4d198b4ea8c" - integrity sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA== + version "22.13.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.4.tgz#3fe454d77cd4a2d73c214008b3e331bfaaf5038a" + integrity sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg== dependencies: undici-types "~6.20.0" @@ -1798,7 +1916,7 @@ dependencies: "@types/react" "^18" -"@types/react@^18", "@types/react@^18.0.24": +"@types/react@^18", "@types/react@^18.2.6": version "18.3.18" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== @@ -1828,13 +1946,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yargs@^16.0.0": - version "16.0.9" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.9.tgz#ba506215e45f7707e6cbcaf386981155b7ab956e" - integrity sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA== - dependencies: - "@types/yargs-parser" "*" - "@types/yargs@^17.0.8": version "17.0.33" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" @@ -1842,7 +1953,7 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.30.5": +"@typescript-eslint/eslint-plugin@^5.57.1": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== @@ -1858,7 +1969,7 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.30.5": +"@typescript-eslint/parser@^5.57.1": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== @@ -1926,6 +2037,11 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" +"@ungap/structured-clone@^1.2.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -1941,11 +2057,26 @@ accepts@^1.3.7, accepts@~1.3.7: mime-types "~2.1.34" negotiator "0.6.3" -acorn@^8.8.2: +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ajv@^8.6.3: version "8.17.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" @@ -2026,6 +2157,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" @@ -2134,11 +2270,6 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^3.2.2: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -2151,7 +2282,7 @@ babel-core@^7.0.0-bridge.0: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== -babel-jest@^29.2.1, babel-jest@^29.7.0: +babel-jest@^29.6.3, babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== @@ -2185,17 +2316,6 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-module-resolver@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2" - integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA== - dependencies: - find-babel-config "^1.2.0" - glob "^7.1.6" - pkg-up "^3.1.0" - reselect "^4.0.0" - resolve "^1.13.1" - babel-plugin-polyfill-corejs2@^0.4.10: version "0.4.12" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" @@ -2213,6 +2333,14 @@ babel-plugin-polyfill-corejs3@^0.10.6: "@babel/helper-define-polyfill-provider" "^0.6.2" core-js-compat "^3.38.0" +babel-plugin-polyfill-corejs3@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz#4e4e182f1bb37c7ba62e2af81d8dd09df31344f6" + integrity sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.3" + core-js-compat "^3.40.0" + babel-plugin-polyfill-regenerator@^0.6.1: version "0.6.3" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" @@ -2220,11 +2348,6 @@ babel-plugin-polyfill-regenerator@^0.6.1: dependencies: "@babel/helper-define-polyfill-provider" "^0.6.3" -babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: - version "7.0.0-beta.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" - integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== - babel-plugin-transform-flow-enums@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25" @@ -2253,39 +2376,6 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" -babel-preset-fbjs@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" - integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== - dependencies: - "@babel/plugin-proposal-class-properties" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-syntax-class-properties" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-block-scoped-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-flow-strip-types" "^7.0.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-member-expression-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-object-super" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-property-literals" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" - babel-preset-jest@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" @@ -2304,7 +2394,7 @@ base-64@^0.1.0: resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== -base64-js@^1.1.2, base64-js@^1.3.1: +base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2408,9 +2498,9 @@ caf@^15.0.1: integrity sha512-Xp/IK6vMwujxWZXra7djdYzPdPnEQKa7Mudu2wZgDQ3TJry1I0TgtjEgwZHpoBcMp68j4fb0/FZ1SJyMEgJrXQ== call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" - integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== dependencies: es-errors "^1.3.0" function-bind "^1.1.2" @@ -2468,9 +2558,9 @@ camelcase@^6.0.0, camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001688: - version "1.0.30001696" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz#00c30a2fc11e3c98c25e5125418752af3ae2f49f" - integrity sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ== + version "1.0.30001700" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" + integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" @@ -2494,6 +2584,28 @@ child-process-promise@^2.2.0: node-version "^1.0.0" promise-polyfill "^6.0.1" +chrome-launcher@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" + integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + +chromium-edge-launcher@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#0443083074715a13c669530b35df7bfea33b1509" + integrity sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + mkdirp "^1.0.4" + rimraf "^3.0.2" + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -2607,11 +2719,6 @@ commander@^9.4.1: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== -commander@~2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" - integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2625,9 +2732,9 @@ compressible@~2.0.18: mime-db ">= 1.43.0 < 2" compression@^1.7.1: - version "1.7.5" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.5.tgz#fdd256c0a642e39e314c478f6c2cd654edd74c93" - integrity sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q== + version "1.8.0" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.0.tgz#09420efc96e11a0f44f3a558de59e321364180f7" + integrity sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA== dependencies: bytes "3.1.2" compressible "~2.0.18" @@ -2657,7 +2764,7 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-js-compat@^3.38.0, core-js-compat@^3.38.1: +core-js-compat@^3.38.0, core-js-compat@^3.40.0: version "3.40.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== @@ -2700,7 +2807,7 @@ cross-spawn@^4.0.2: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -2746,14 +2853,14 @@ dayjs@^1.8.15: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -debug@2.6.9, debug@^2.2.0: +debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== @@ -2775,6 +2882,11 @@ dedent@^1.0.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + deepmerge@^4.2.2, deepmerge@^4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -2815,12 +2927,12 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -deprecated-react-native-prop-types@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.2.3.tgz#0ef845c1a80ef1636bd09060e4cdf70f9727e5ad" - integrity sha512-2rLTiMKidIFFYpIVM69UnQKngLqQfL6I11Ch8wGSBftS18FUXda+o2we2950X+1dmbgps28niI3qwyH4eX3Z1g== +deprecated-react-native-prop-types@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz#02a12f090da7bd9e8c3ac53c31cf786a1315d302" + integrity sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ== dependencies: - "@react-native/normalize-colors" "<0.73.0" + "@react-native/normalize-colors" "^0.73.0" invariant "^2.2.4" prop-types "^15.8.1" @@ -2893,6 +3005,13 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + dtrace-provider@~0.8: version "0.8.8" resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" @@ -2927,9 +3046,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.5.73: - version "1.5.90" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz#4717e5a5413f95bbb12d0af14c35057e9c65e0b6" - integrity sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug== + version "1.5.102" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz#81a452ace8e2c3fa7fba904ea4fed25052c53d3f" + integrity sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q== emittery@^0.13.1: version "0.13.1" @@ -2951,7 +3070,7 @@ encodeurl@~2.0.0: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== -envinfo@^7.7.2: +envinfo@^7.10.0: version "7.14.0" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== @@ -3085,11 +3204,11 @@ es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: hasown "^2.0.2" es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" es-to-primitive@^1.3.0: version "1.3.0" @@ -3120,6 +3239,11 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + eslint-config-prettier@^8.5.0: version "8.10.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" @@ -3204,21 +3328,89 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint@^8.19.0: + version "8.57.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" + integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.1" + "@humanwhocodes/config-array" "^0.13.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + esprima@^4.0.0, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.4.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -3231,7 +3423,7 @@ estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.2.0, estraverse@^5.3.0: +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== @@ -3276,7 +3468,7 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.0.0, expect@^29.7.0: +expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -3287,7 +3479,12 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" -fast-deep-equal@^3.1.3: +exponential-backoff@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91" + integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -3308,17 +3505,22 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.8" -fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + fast-uri@^3.0.1: version "3.0.6" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== -fast-xml-parser@^4.0.12: +fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: version "4.5.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz#a7e665ff79b7919100a5202f23984b6150f9b31e" integrity sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w== @@ -3339,6 +3541,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -3359,14 +3568,6 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-babel-config@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.2.tgz#41199b5cb9154dcb2fdc351cbe70eaf9198d5111" - integrity sha512-oK59njMyw2y3yxto1BCfVK7MQp/OYf4FleHu0RgosH3riFJ1aOuo/7naLDLAObfrgn3ueFhw5sAT/cp0QuJI3Q== - dependencies: - json5 "^1.0.2" - path-exists "^3.0.0" - find-cache-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -3399,20 +3600,34 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flow-enums-runtime@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.5.tgz#95884bfcc82edaf27eef7e1dd09732331cfbafbc" - integrity sha512-PSZF9ZuaZD03sT9YaIs0FrGJ7lSUw7rHZIex+73UYVXg46eL/wxN5PaVcPJFudE2cJu5f0fezitV5aBkLHPUOQ== +flatted@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== + +flow-enums-runtime@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" + integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== flow-parser@0.*: - version "0.259.1" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.259.1.tgz#2ab828be197bb87f47af299e5b734eab139bd269" - integrity sha512-xiXLmMH2Z7OmdE9Q+MjljUMr/rbemFqZIRxaeZieVScG4HzQrKKhNcCYZbWTGpoN7ZPi7z8ClQbeVPq6t5AszQ== + version "0.261.1" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.261.1.tgz#1ce84a0ea0f51f263be779c4988bf6ddd8e7aafb" + integrity sha512-2l5bBKeVtT+d+1CYSsTLJ+iP2FuoR7zjbDQI/v6dDRiBpx3Lb20Z/tLS37ReX/lcodyGSHC2eA/Nk63hB+mkYg== flow-parser@^0.206.0: version "0.206.0" @@ -3420,9 +3635,9 @@ flow-parser@^0.206.0: integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== for-each@^0.3.3: - version "0.3.4" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.4.tgz#814517ffc303d1399b2564d8165318e735d0341c" - integrity sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw== + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== dependencies: is-callable "^1.2.7" @@ -3546,6 +3761,13 @@ glob-parent@^5.1.2: dependencies: is-glob "^4.0.1" +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -3557,7 +3779,7 @@ glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3585,6 +3807,13 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -3656,24 +3885,36 @@ has-tostringtag@^1.0.2: dependencies: has-symbols "^1.0.3" -hasown@^2.0.0, hasown@^2.0.2: +hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" -hermes-estree@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.12.0.tgz#8a289f9aee854854422345e6995a48613bac2ca8" - integrity sha512-+e8xR6SCen0wyAKrMT3UD0ZCCLymKhRgjEB5sS28rKiFir/fXgLoeRilRUssFCILmGHb+OvHDUlhxs0+IEyvQw== +hermes-estree@0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba" + integrity sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ== -hermes-parser@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.12.0.tgz#114dc26697cfb41a6302c215b859b74224383773" - integrity sha512-d4PHnwq6SnDLhYl3LHNHvOg7nQ6rcI7QVil418REYksv0Mh3cEkHDcuhGxNQ3vgnLSLl4QSvDrFCwQNYdpWlzw== +hermes-estree@0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb" + integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg== + +hermes-parser@0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.15.0.tgz#f611a297c2a2dbbfbce8af8543242254f604c382" + integrity sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q== dependencies: - hermes-estree "0.12.0" + hermes-estree "0.15.0" + +hermes-parser@0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205" + integrity sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA== + dependencies: + hermes-estree "0.23.1" hermes-profile-transformer@^0.0.6: version "0.0.6" @@ -3728,6 +3969,14 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-local@^3.0.2: version "3.2.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" @@ -3808,11 +4057,11 @@ is-bigint@^1.1.0: has-bigints "^1.0.2" is-boolean-object@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.1.tgz#c20d0c654be05da4fbc23c562635c019e93daf89" - integrity sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng== + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== dependencies: - call-bound "^1.0.2" + call-bound "^1.0.3" has-tostringtag "^1.0.2" is-callable@^1.2.7: @@ -3849,6 +4098,11 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -3886,7 +4140,7 @@ is-generator-function@^1.0.10: has-tostringtag "^1.0.2" safe-regex-test "^1.1.0" -is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -3916,6 +4170,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -3990,11 +4249,11 @@ is-weakmap@^2.0.2: integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== is-weakref@^1.0.2, is-weakref@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.0.tgz#47e3472ae95a63fa9cf25660bcf0c181c39770ef" - integrity sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q== + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== dependencies: - call-bound "^1.0.2" + call-bound "^1.0.3" is-weakset@^2.0.3: version "2.0.4" @@ -4009,6 +4268,13 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -4202,7 +4468,7 @@ jest-each@^29.7.0: jest-util "^29.7.0" pretty-format "^29.7.0" -jest-environment-node@^29.2.1, jest-environment-node@^29.7.0: +jest-environment-node@^29.6.3, jest-environment-node@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== @@ -4285,11 +4551,6 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== -jest-regex-util@^27.0.6: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" - integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== - jest-regex-util@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" @@ -4399,18 +4660,6 @@ jest-snapshot@^29.7.0: pretty-format "^29.7.0" semver "^7.5.3" -jest-util@^27.2.0: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - jest-util@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" @@ -4423,7 +4672,7 @@ jest-util@^29.7.0: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.2.1, jest-validate@^29.7.0: +jest-validate@^29.6.3, jest-validate@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== @@ -4449,16 +4698,7 @@ jest-watcher@^29.7.0: jest-util "^29.7.0" string-length "^4.0.1" -jest-worker@^27.2.0: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest-worker@^29.7.0: +jest-worker@^29.6.3, jest-worker@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== @@ -4468,7 +4708,7 @@ jest-worker@^29.7.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.2.1: +jest@^29.6.3: version "29.7.0" resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== @@ -4514,6 +4754,13 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsc-android@^250231.0.0: version "250231.0.0" resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" @@ -4559,6 +4806,11 @@ jsesc@~3.0.2: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-cycle@^1.3.0: version "1.5.0" resolved "https://registry.yarnpkg.com/json-cycle/-/json-cycle-1.5.0.tgz#b1f1d976eee16cef51d5f3d3b3caece3e90ba23a" @@ -4574,17 +4826,20 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + json-schema-traverse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json5@^2.2.3: version "2.2.3" @@ -4617,6 +4872,13 @@ jsonfile@^6.0.1: object.assign "^4.1.4" object.values "^1.1.6" +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -4632,6 +4894,22 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lighthouse-logger@^1.0.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa" + integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== + dependencies: + debug "^2.6.9" + marky "^1.2.2" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -4664,6 +4942,11 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" @@ -4735,6 +5018,11 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +marky@^1.2.2: + version "1.2.5" + resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" + integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== + math-intrinsics@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" @@ -4755,62 +5043,67 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -metro-babel-transformer@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.76.9.tgz#659ba481d471b5f748c31a8f9397094b629f50ec" - integrity sha512-dAnAmBqRdTwTPVn4W4JrowPolxD1MDbuU97u3MqtWZgVRvDpmr+Cqnn5oSxLQk3Uc+Zy3wkqVrB/zXNRlLDSAQ== +metro-babel-transformer@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz#ad02ade921dd4ced27b26b18ff31eb60608e3f56" + integrity sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg== dependencies: "@babel/core" "^7.20.0" - hermes-parser "0.12.0" + flow-enums-runtime "^0.0.6" + hermes-parser "0.23.1" nullthrows "^1.1.1" -metro-cache-key@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.76.9.tgz#6f17f821d6f306fa9028b7e79445eb18387d03d9" - integrity sha512-ugJuYBLngHVh1t2Jj+uP9pSCQl7enzVXkuh6+N3l0FETfqjgOaSHlcnIhMPn6yueGsjmkiIfxQU4fyFVXRtSTw== +metro-cache-key@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.12.tgz#52f5de698b85866503ace45d0ad76f75aaec92a4" + integrity sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA== + dependencies: + flow-enums-runtime "^0.0.6" -metro-cache@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.76.9.tgz#64326d7a8b470c3886a5e97d5e2a20acab20bc5f" - integrity sha512-W6QFEU5AJG1gH4Ltv8S2IvhmEhSDYnbPafyj5fGR3YLysdykj+olKv9B0V+YQXtcLGyY5CqpXLYUx595GdiKzA== +metro-cache@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.12.tgz#bd81af02c4f17b5aeab19bb030566b14147cee8b" + integrity sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA== dependencies: - metro-core "0.76.9" - rimraf "^3.0.2" + exponential-backoff "^3.1.1" + flow-enums-runtime "^0.0.6" + metro-core "0.80.12" -metro-config@0.76.9, metro-config@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.76.9.tgz#5e60aff9d8894c1ee6bbc5de23b7c8515a0b84a3" - integrity sha512-oYyJ16PY3rprsfoi80L+gDJhFJqsKI3Pob5LKQbJpvL+gGr8qfZe1eQzYp5Xxxk9DOHKBV1xD94NB8GdT/DA8Q== +metro-config@0.80.12, metro-config@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.12.tgz#1543009f37f7ad26352ffc493fc6305d38bdf1c0" + integrity sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ== dependencies: connect "^3.6.5" cosmiconfig "^5.0.5" - jest-validate "^29.2.1" - metro "0.76.9" - metro-cache "0.76.9" - metro-core "0.76.9" - metro-runtime "0.76.9" - -metro-core@0.76.9, metro-core@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.76.9.tgz#5f55f0fbde41d28957e4f3bb187d32251403f00e" - integrity sha512-DSeEr43Wrd5Q7ySfRzYzDwfV89g2OZTQDf1s3exOcLjE5fb7awoLOkA2h46ZzN8NcmbbM0cuJy6hOwF073/yRQ== - dependencies: + flow-enums-runtime "^0.0.6" + jest-validate "^29.6.3" + metro "0.80.12" + metro-cache "0.80.12" + metro-core "0.80.12" + metro-runtime "0.80.12" + +metro-core@0.80.12, metro-core@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.12.tgz#5ae337923ab19ff524077efa1aeacdf4480cfa28" + integrity sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw== + dependencies: + flow-enums-runtime "^0.0.6" lodash.throttle "^4.1.1" - metro-resolver "0.76.9" + metro-resolver "0.80.12" -metro-file-map@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.76.9.tgz#dd3d76ec23fc0ba8cb7b3a3b8075bb09e0b5d378" - integrity sha512-7vJd8kksMDTO/0fbf3081bTrlw8SLiploeDf+vkkf0OwlrtDUWPOikfebp+MpZB2S61kamKjCNRfRkgrbPfSwg== +metro-file-map@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.12.tgz#b03240166a68aa16c5a168c26e190d9da547eefb" + integrity sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw== dependencies: anymatch "^3.0.3" debug "^2.2.0" fb-watchman "^2.0.0" + flow-enums-runtime "^0.0.6" graceful-fs "^4.2.4" invariant "^2.2.4" - jest-regex-util "^27.0.6" - jest-util "^27.2.0" - jest-worker "^27.2.0" + jest-worker "^29.6.3" micromatch "^4.0.4" node-abort-controller "^3.1.1" nullthrows "^1.1.1" @@ -4818,160 +5111,92 @@ metro-file-map@0.76.9: optionalDependencies: fsevents "^2.3.2" -metro-inspector-proxy@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.76.9.tgz#0d333e64a7bc9d156d712265faa7b7ae88c775e8" - integrity sha512-idIiPkb8CYshc0WZmbzwmr4B1QwsQUbpDwBzHwxE1ni27FWKWhV9CD5p+qlXZHgfwJuMRfPN+tIaLSR8+vttYg== - dependencies: - connect "^3.6.5" - debug "^2.2.0" - node-fetch "^2.2.0" - ws "^7.5.1" - yargs "^17.6.2" - -metro-minify-terser@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.76.9.tgz#3f6271da74dd57179852118443b62cc8dc578aab" - integrity sha512-ju2nUXTKvh96vHPoGZH/INhSvRRKM14CbGAJXQ98+g8K5z1v3luYJ/7+dFQB202eVzJdTB2QMtBjI1jUUpooCg== +metro-minify-terser@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz#9951030e3bc52d7f3ac8664ce5862401c673e3c6" + integrity sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ== dependencies: + flow-enums-runtime "^0.0.6" terser "^5.15.0" -metro-minify-uglify@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.76.9.tgz#e88c30c27911c053e1ee20e12077f0f4cbb154f8" - integrity sha512-MXRrM3lFo62FPISlPfTqC6n9HTEI3RJjDU5SvpE7sJFfJKLx02xXQEltsL/wzvEqK+DhRQ5DEYACTwf5W4Z3yA== - dependencies: - uglify-es "^3.1.9" - -metro-react-native-babel-preset@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.9.tgz#15868142122af14313429d7572c15cf01c16f077" - integrity sha512-eCBtW/UkJPDr6HlMgFEGF+964DZsUEF9RGeJdZLKWE7d/0nY3ABZ9ZAGxzu9efQ35EWRox5bDMXUGaOwUe5ikQ== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.4.0" - -metro-react-native-babel-transformer@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.76.9.tgz#464aab85669ed39f7a59f1fd993a05de9543b09e" - integrity sha512-xXzHcfngSIkbQj+U7i/anFkNL0q2QVarYSzr34CFkzKLa79Rp16B8ki7z9eVVqo9W3B4TBcTXl3BipgRoOoZSQ== +metro-resolver@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.12.tgz#e3815914c21315b04db200032c3243a4cc22dfb6" + integrity sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw== dependencies: - "@babel/core" "^7.20.0" - babel-preset-fbjs "^3.4.0" - hermes-parser "0.12.0" - metro-react-native-babel-preset "0.76.9" - nullthrows "^1.1.1" - -metro-resolver@0.76.9, metro-resolver@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.76.9.tgz#79c244784b16ca56076bc1fc816d2ba74860e882" - integrity sha512-s86ipNRas9vNR5lChzzSheF7HoaQEmzxBLzwFA6/2YcGmUCowcoyPAfs1yPh4cjMw9F1T4KlMLaiwniGE7HCyw== + flow-enums-runtime "^0.0.6" -metro-runtime@0.76.9, metro-runtime@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.76.9.tgz#f8ebe150f8896ce1aef5d7f3a52844f8b4f721fb" - integrity sha512-/5vezDpGUtA0Fv6cJg0+i6wB+QeBbvLeaw9cTSG7L76liP0b91f8vOcYzGaUbHI8pznJCCTerxRzpQ8e3/NcDw== +metro-runtime@0.80.12, metro-runtime@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.12.tgz#a68af3a2a013f5372d3b8cee234fdd467455550b" + integrity sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw== dependencies: - "@babel/runtime" "^7.0.0" - react-refresh "^0.4.0" + "@babel/runtime" "^7.25.0" + flow-enums-runtime "^0.0.6" -metro-source-map@0.76.9, metro-source-map@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.76.9.tgz#0f976ada836717f307427d3830aea52a2ca7ed5f" - integrity sha512-q5qsMlu8EFvsT46wUUh+ao+efDsicT30zmaPATNhq+PcTawDbDgnMuUD+FT0bvxxnisU2PWl91RdzKfNc2qPQA== +metro-source-map@0.80.12, metro-source-map@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.12.tgz#36a2768c880f8c459d6d758e2d0975e36479f49c" + integrity sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw== dependencies: "@babel/traverse" "^7.20.0" "@babel/types" "^7.20.0" + flow-enums-runtime "^0.0.6" invariant "^2.2.4" - metro-symbolicate "0.76.9" + metro-symbolicate "0.80.12" nullthrows "^1.1.1" - ob1 "0.76.9" + ob1 "0.80.12" source-map "^0.5.6" vlq "^1.0.0" -metro-symbolicate@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.76.9.tgz#f1627ef6f73bb0c4d48c55684d3c87866a0b0920" - integrity sha512-Yyq6Ukj/IeWnGST09kRt0sBK8TwzGZWoU7YAcQlh14+AREH454Olx4wbFTpkkhUkV05CzNCvUuXQ0efFxhA1bw== +metro-symbolicate@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz#3a6aa783c6e494e2879342d88d5379fab69d1ed2" + integrity sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw== dependencies: + flow-enums-runtime "^0.0.6" invariant "^2.2.4" - metro-source-map "0.76.9" + metro-source-map "0.80.12" nullthrows "^1.1.1" source-map "^0.5.6" through2 "^2.0.1" vlq "^1.0.0" -metro-transform-plugins@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.76.9.tgz#73e34f2014d3df3c336a882b13e541bceb826d37" - integrity sha512-YEQeNlOCt92I7S9A3xbrfaDfwfgcxz9PpD/1eeop3c4cO3z3Q3otYuxw0WJ/rUIW8pZfOm5XCehd+1NRbWlAaw== +metro-transform-plugins@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz#4a3853630ad0f36cc2bffd53bae659ee171a389c" + integrity sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA== dependencies: "@babel/core" "^7.20.0" "@babel/generator" "^7.20.0" "@babel/template" "^7.0.0" "@babel/traverse" "^7.20.0" + flow-enums-runtime "^0.0.6" nullthrows "^1.1.1" -metro-transform-worker@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.76.9.tgz#281fad223f0447e1ff9cc44d6f7e33dfab9ab120" - integrity sha512-F69A0q0qFdJmP2Clqr6TpTSn4WTV9p5A28h5t9o+mB22ryXBZfUQ6BFBBW/6Wp2k/UtPH+oOsBfV9guiqm3d2Q== +metro-transform-worker@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz#80be8a185b7deb93402b682f58a1dd6724317ad1" + integrity sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA== dependencies: "@babel/core" "^7.20.0" "@babel/generator" "^7.20.0" "@babel/parser" "^7.20.0" "@babel/types" "^7.20.0" - babel-preset-fbjs "^3.4.0" - metro "0.76.9" - metro-babel-transformer "0.76.9" - metro-cache "0.76.9" - metro-cache-key "0.76.9" - metro-minify-terser "0.76.9" - metro-source-map "0.76.9" - metro-transform-plugins "0.76.9" + flow-enums-runtime "^0.0.6" + metro "0.80.12" + metro-babel-transformer "0.80.12" + metro-cache "0.80.12" + metro-cache-key "0.80.12" + metro-minify-terser "0.80.12" + metro-source-map "0.80.12" + metro-transform-plugins "0.80.12" nullthrows "^1.1.1" -metro@0.76.9, metro@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.76.9.tgz#605fddf1a54d27762ddba2f636420ae2408862df" - integrity sha512-gcjcfs0l5qIPg0lc5P7pj0x7vPJ97tan+OnEjiYLbKjR1D7Oa78CE93YUPyymUPH6q7VzlzMm1UjT35waEkZUw== +metro@0.80.12, metro@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.12.tgz#29a61fb83581a71e50c4d8d5d8458270edfe34cc" + integrity sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA== dependencies: "@babel/code-frame" "^7.0.0" "@babel/core" "^7.20.0" @@ -4981,44 +5206,39 @@ metro@0.76.9, metro@^0.76.9: "@babel/traverse" "^7.20.0" "@babel/types" "^7.20.0" accepts "^1.3.7" - async "^3.2.2" chalk "^4.0.0" ci-info "^2.0.0" connect "^3.6.5" debug "^2.2.0" denodeify "^1.2.1" error-stack-parser "^2.0.6" + flow-enums-runtime "^0.0.6" graceful-fs "^4.2.4" - hermes-parser "0.12.0" + hermes-parser "0.23.1" image-size "^1.0.2" invariant "^2.2.4" - jest-worker "^27.2.0" + jest-worker "^29.6.3" jsc-safe-url "^0.2.2" lodash.throttle "^4.1.1" - metro-babel-transformer "0.76.9" - metro-cache "0.76.9" - metro-cache-key "0.76.9" - metro-config "0.76.9" - metro-core "0.76.9" - metro-file-map "0.76.9" - metro-inspector-proxy "0.76.9" - metro-minify-uglify "0.76.9" - metro-react-native-babel-preset "0.76.9" - metro-resolver "0.76.9" - metro-runtime "0.76.9" - metro-source-map "0.76.9" - metro-symbolicate "0.76.9" - metro-transform-plugins "0.76.9" - metro-transform-worker "0.76.9" + metro-babel-transformer "0.80.12" + metro-cache "0.80.12" + metro-cache-key "0.80.12" + metro-config "0.80.12" + metro-core "0.80.12" + metro-file-map "0.80.12" + metro-resolver "0.80.12" + metro-runtime "0.80.12" + metro-source-map "0.80.12" + metro-symbolicate "0.80.12" + metro-transform-plugins "0.80.12" + metro-transform-worker "0.80.12" mime-types "^2.1.27" - node-fetch "^2.2.0" nullthrows "^1.1.1" - rimraf "^3.0.2" serialize-error "^2.1.0" source-map "^0.5.6" strip-ansi "^6.0.0" throat "^5.0.0" - ws "^7.5.1" + ws "^7.5.10" yargs "^17.6.2" micromatch@^4.0.4, micromatch@^4.0.8: @@ -5061,7 +5281,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -5075,7 +5295,7 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.6: +minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5087,6 +5307,11 @@ mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "^1.2.6" +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + moment@^2.19.3: version "2.30.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" @@ -5229,10 +5454,12 @@ nullthrows@^1.1.1: resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== -ob1@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.76.9.tgz#a493e4b83a0fb39200de639804b5d06eed5599dc" - integrity sha512-g0I/OLnSxf6OrN3QjSew3bTDJCdbZoWxnh8adh1z36alwCuGF1dgDeRA25bTYSakrG5WULSaWJPOdgnf1O/oQw== +ob1@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.12.tgz#0451944ba6e5be225cc9751d8cd0d7309d2d1537" + integrity sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw== + dependencies: + flow-enums-runtime "^0.0.6" object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" @@ -5240,9 +5467,9 @@ object-assign@^4.1.0, object-assign@^4.1.1: integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.13.3: - version "1.13.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" - integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== object-keys@^1.1.1: version "1.1.1" @@ -5330,6 +5557,26 @@ open@^6.2.0: dependencies: is-wsl "^1.1.0" +open@^7.0.3: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + ora@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" @@ -5394,6 +5641,13 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -5481,17 +5735,15 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-linter-helpers@^1.0.0: version "1.0.0" @@ -5500,7 +5752,7 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.4.1: +prettier@^2.8.8: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== @@ -5515,7 +5767,7 @@ pretty-format@^26.5.2, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" -pretty-format@^29.0.0, pretty-format@^29.7.0: +pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -5541,7 +5793,7 @@ promise@^8.3.0: dependencies: asap "~2.0.6" -prompts@^2.0.1, prompts@^2.4.0: +prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -5572,6 +5824,11 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pure-rand@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" @@ -5594,7 +5851,7 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -react-devtools-core@^4.27.2: +react-devtools-core@^4.27.7: version "4.28.5" resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508" integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA== @@ -5625,53 +5882,54 @@ react-native-fs@^2.20.0: base-64 "^0.1.0" utf8 "^3.0.0" -react-native@^0.72.17: - version "0.72.17" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.17.tgz#54d6de38adf6e56fdde1a6b83ef9b138abae7384" - integrity sha512-k3dNe0XqoYCGGWTenbupWSj+ljW3GIfmYS5P4s3if4j0csx2YbenKgH1aJNWLp+UP7ONwfId6G+uBoUJfyMxXg== - dependencies: - "@jest/create-cache-key-function" "^29.2.1" - "@react-native-community/cli" "^11.4.1" - "@react-native-community/cli-platform-android" "^11.4.1" - "@react-native-community/cli-platform-ios" "^11.4.1" - "@react-native/assets-registry" "^0.72.0" - "@react-native/codegen" "^0.72.8" - "@react-native/gradle-plugin" "^0.72.11" - "@react-native/js-polyfills" "^0.72.1" - "@react-native/normalize-colors" "^0.72.0" - "@react-native/virtualized-lists" "^0.72.8" +react-native@^0.73.11: + version "0.73.11" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.11.tgz#4661532efd146e1eab2abb69c252218795837ce5" + integrity sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg== + dependencies: + "@jest/create-cache-key-function" "^29.6.3" + "@react-native-community/cli" "12.3.7" + "@react-native-community/cli-platform-android" "12.3.7" + "@react-native-community/cli-platform-ios" "12.3.7" + "@react-native/assets-registry" "0.73.1" + "@react-native/codegen" "0.73.3" + "@react-native/community-cli-plugin" "0.73.18" + "@react-native/gradle-plugin" "0.73.5" + "@react-native/js-polyfills" "0.73.1" + "@react-native/normalize-colors" "0.73.2" + "@react-native/virtualized-lists" "0.73.4" abort-controller "^3.0.0" anser "^1.4.9" ansi-regex "^5.0.0" - base64-js "^1.1.2" - deprecated-react-native-prop-types "^4.2.3" + base64-js "^1.5.1" + chalk "^4.0.0" + deprecated-react-native-prop-types "^5.0.0" event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.5" + flow-enums-runtime "^0.0.6" invariant "^2.2.4" - jest-environment-node "^29.2.1" + jest-environment-node "^29.6.3" jsc-android "^250231.0.0" memoize-one "^5.0.0" - metro-runtime "^0.76.9" - metro-source-map "^0.76.9" + metro-runtime "^0.80.3" + metro-source-map "^0.80.3" mkdirp "^0.5.1" nullthrows "^1.1.1" pretty-format "^26.5.2" promise "^8.3.0" - react-devtools-core "^4.27.2" - react-refresh "^0.4.0" + react-devtools-core "^4.27.7" + react-refresh "^0.14.0" react-shallow-renderer "^16.15.0" regenerator-runtime "^0.13.2" scheduler "0.24.0-canary-efb381bbf-20230505" stacktrace-parser "^0.1.10" - use-sync-external-store "^1.0.0" whatwg-fetch "^3.0.0" ws "^6.2.2" yargs "^17.6.2" -react-refresh@^0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" - integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== +react-refresh@^0.14.0: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== react-shallow-renderer@^16.15.0: version "16.15.0" @@ -5828,11 +6086,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -reselect@^4.0.0: - version "4.1.8" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" - integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== - resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -5845,6 +6098,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" @@ -5855,7 +6113,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== -resolve@^1.13.1, resolve@^1.14.2, resolve@^1.20.0: +resolve@^1.14.2, resolve@^1.20.0: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -5994,9 +6252,9 @@ semver@^6.3.0, semver@^6.3.1: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.0.0, semver@^7.3.7, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: - version "7.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.0.tgz#9c6fe61d0c6f9fa9e26575162ee5a9180361b09c" - integrity sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ== + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== send@0.19.0: version "0.19.0" @@ -6410,6 +6668,11 @@ temp-dir@^1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + temp@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" @@ -6426,9 +6689,9 @@ tempfile@^2.0.0: uuid "^3.0.1" terser@^5.15.0: - version "5.37.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.37.0.tgz#38aa66d1cfc43d0638fab54e43ff8a4f72a21ba3" - integrity sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA== + version "5.39.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.39.0.tgz#0e82033ed57b3ddf1f96708d123cca717d86ca3a" + integrity sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -6444,6 +6707,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -6510,6 +6778,13 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -6575,18 +6850,10 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" -typescript@4.8.4: - version "4.8.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== - -uglify-es@^3.1.9: - version "3.3.9" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" - integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== - dependencies: - commander "~2.13.0" - source-map "~0.6.1" +typescript@5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== unbox-primitive@^1.1.0: version "1.1.0" @@ -6649,10 +6916,12 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.1" -use-sync-external-store@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" - integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" utf8-byte-length@^1.0.1: version "1.0.5" @@ -6801,6 +7070,11 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -6848,7 +7122,7 @@ ws@^6.2.2: dependencies: async-limiter "~1.0.0" -ws@^7, ws@^7.0.0, ws@^7.5.1: +ws@^7, ws@^7.0.0, ws@^7.5.1, ws@^7.5.10: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== diff --git a/js/react_native/ios/OnnxruntimeModule.xcodeproj/project.pbxproj b/js/react_native/ios/OnnxruntimeModule.xcodeproj/project.pbxproj index d0f6db84e51fb..079033b9194eb 100644 --- a/js/react_native/ios/OnnxruntimeModule.xcodeproj/project.pbxproj +++ b/js/react_native/ios/OnnxruntimeModule.xcodeproj/project.pbxproj @@ -273,10 +273,15 @@ "${BUILT_PRODUCTS_DIR}/React-Codegen/React_Codegen.framework", "${BUILT_PRODUCTS_DIR}/React-Core/React.framework", "${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework", + "${BUILT_PRODUCTS_DIR}/React-Fabric/React_Fabric.framework", + "${BUILT_PRODUCTS_DIR}/React-FabricImage/React_FabricImage.framework", + "${BUILT_PRODUCTS_DIR}/React-ImageManager/React_ImageManager.framework", + "${BUILT_PRODUCTS_DIR}/React-Mapbuffer/React_Mapbuffer.framework", "${BUILT_PRODUCTS_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework", "${BUILT_PRODUCTS_DIR}/React-RCTAnimation/RCTAnimation.framework", "${BUILT_PRODUCTS_DIR}/React-RCTAppDelegate/React_RCTAppDelegate.framework", "${BUILT_PRODUCTS_DIR}/React-RCTBlob/RCTBlob.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTFabric/RCTFabric.framework", "${BUILT_PRODUCTS_DIR}/React-RCTImage/RCTImage.framework", "${BUILT_PRODUCTS_DIR}/React-RCTLinking/RCTLinking.framework", "${BUILT_PRODUCTS_DIR}/React-RCTNetwork/RCTNetwork.framework", @@ -284,12 +289,17 @@ "${BUILT_PRODUCTS_DIR}/React-RCTText/RCTText.framework", "${BUILT_PRODUCTS_DIR}/React-RCTVibration/RCTVibration.framework", "${BUILT_PRODUCTS_DIR}/React-cxxreact/cxxreact.framework", - "${BUILT_PRODUCTS_DIR}/React-jsc/React_jsc.framework", + "${BUILT_PRODUCTS_DIR}/React-debug/React_debug.framework", + "${BUILT_PRODUCTS_DIR}/React-graphics/React_graphics.framework", + "${BUILT_PRODUCTS_DIR}/React-hermes/reacthermes.framework", + "${BUILT_PRODUCTS_DIR}/React-jserrorhandler/React_jserrorhandler.framework", "${BUILT_PRODUCTS_DIR}/React-jsi/jsi.framework", "${BUILT_PRODUCTS_DIR}/React-jsiexecutor/jsireact.framework", "${BUILT_PRODUCTS_DIR}/React-jsinspector/jsinspector.framework", "${BUILT_PRODUCTS_DIR}/React-logger/logger.framework", + "${BUILT_PRODUCTS_DIR}/React-nativeconfig/React_nativeconfig.framework", "${BUILT_PRODUCTS_DIR}/React-perflogger/reactperflogger.framework", + "${BUILT_PRODUCTS_DIR}/React-rendererdebug/React_rendererdebug.framework", "${BUILT_PRODUCTS_DIR}/React-runtimescheduler/React_runtimescheduler.framework", "${BUILT_PRODUCTS_DIR}/React-utils/React_utils.framework", "${BUILT_PRODUCTS_DIR}/ReactCommon/ReactCommon.framework", @@ -297,6 +307,8 @@ "${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework", "${BUILT_PRODUCTS_DIR}/fmt/fmt.framework", "${BUILT_PRODUCTS_DIR}/glog/glog.framework", + "${BUILT_PRODUCTS_DIR}/libevent/libevent.framework", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -306,10 +318,15 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Codegen.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Fabric.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_FabricImage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_ImageManager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Mapbuffer.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_NativeModulesApple.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTAnimation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_RCTAppDelegate.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTBlob.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTFabric.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTLinking.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTNetwork.framework", @@ -317,12 +334,17 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTText.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTVibration.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cxxreact.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_jsc.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_debug.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_graphics.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reacthermes.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_jserrorhandler.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsi.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsireact.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsinspector.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/logger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_nativeconfig.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reactperflogger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_rendererdebug.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_runtimescheduler.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_utils.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactCommon.framework", @@ -330,6 +352,8 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fmt.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libevent.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -395,7 +419,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -419,7 +443,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -443,6 +467,9 @@ "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); "HEADER_SEARCH_PATHS[arch=*]" = ""; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -454,6 +481,7 @@ OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; }; name = Debug; }; @@ -461,7 +489,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -485,7 +513,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -505,6 +533,9 @@ "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); "HEADER_SEARCH_PATHS[arch=*]" = ""; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -515,6 +546,7 @@ OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/js/react_native/ios/Podfile b/js/react_native/ios/Podfile index 95e43ee369910..c252d18965ad5 100644 --- a/js/react_native/ios/Podfile +++ b/js/react_native/ios/Podfile @@ -14,16 +14,9 @@ use_frameworks! def shared config = use_native_modules! - # Flags change depending on the env values. - flags = get_default_flags() - use_react_native!( :path => config[:reactNativePath], - # Hermes is now enabled by default. Disable by setting this flag to false. - # Upcoming versions of React Native may rely on get_default_flags(), but - # we make it explicit here to aid in the React Native upgrade process. - :hermes_enabled => false, - :fabric_enabled => false, + :app_path => "#{Pod::Config.instance.installation_root}/.." ) @@ -50,5 +43,4 @@ post_install do |installer| installer, :mac_catalyst_enabled => false ) - __apply_Xcode_12_5_M1_post_install_workaround(installer) end \ No newline at end of file diff --git a/js/react_native/package.json b/js/react_native/package.json index 676f73ff5b8a3..3a8004a716646 100644 --- a/js/react_native/package.json +++ b/js/react_native/package.json @@ -2,7 +2,7 @@ "react-native": "lib/index", "module": "dist/module/index", "engines": { - "node": ">=16" + "node": ">=18" }, "jest": { "modulePathIgnorePatterns": [ @@ -20,14 +20,12 @@ "ONNX Runtime" ], "devDependencies": { - "@types/jest": "^29.2.1", - "@types/react": "^18.0.24", - "@tsconfig/react-native": "^3.0.0", - "jest": "^29.2.1", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", "pod-install": "^0.1.36", - "prettier": "^2.6.2", + "prettier": "^2.8.8", "react": "^18.2.0", - "react-native": "^0.72.17" + "react-native": "^0.73.11" }, "peerDependencies": { "react": "*", @@ -63,9 +61,7 @@ "description": "ONNX Runtime bridge for react native", "repository": "https://github.com/Microsoft/onnxruntime.git", "dependencies": { - "@expo/config-plugins": "^7.2.4", - "buffer": "^6.0.3", - "onnxruntime-common": "file:../common" + "buffer": "^6.0.3" }, "scripts": { "typescript": "tsc --noEmit", diff --git a/js/react_native/yarn.lock b/js/react_native/yarn.lock index 177ad0acc4bc9..ff7caa295bf93 100644 --- a/js/react_native/yarn.lock +++ b/js/react_native/yarn.lock @@ -2,14 +2,6 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -18,29 +10,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/code-frame@^7.22.13": - version "7.22.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" - integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== - dependencies: - "@babel/highlight" "^7.22.13" - chalk "^2.4.2" - -"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.2": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -49,109 +19,43 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/code-frame@~7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.17.10": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" - integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== - -"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.5.tgz#df93ac37f4417854130e21d72c66ff3d4b897fc7" - integrity sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg== +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" + integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== -"@babel/core@^7.11.6", "@babel/core@^7.20.0", "@babel/core@^7.23.9": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.7.tgz#0439347a183b97534d52811144d763a17f9d2b24" - integrity sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA== +"@babel/core@^7.13.16", "@babel/core@^7.20.0": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" + integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.5" + "@babel/generator" "^7.26.9" "@babel/helper-compilation-targets" "^7.26.5" "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.7" - "@babel/parser" "^7.26.7" - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.26.7" - "@babel/types" "^7.26.7" + "@babel/helpers" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.9" + "@babel/types" "^7.26.9" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.12.3", "@babel/core@^7.13.16": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876" - integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-compilation-targets" "^7.18.2" - "@babel/helper-module-transforms" "^7.18.0" - "@babel/helpers" "^7.18.2" - "@babel/parser" "^7.18.0" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@^7.18.2", "@babel/generator@^7.7.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" - integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== +"@babel/generator@^7.20.0", "@babel/generator@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" + integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== dependencies: - "@babel/types" "^7.18.2" - "@jridgewell/gen-mapping" "^0.3.0" - jsesc "^2.5.1" - -"@babel/generator@^7.20.0", "@babel/generator@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.5.tgz#e44d4ab3176bbcaf78a5725da5f1dc28802a9458" - integrity sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw== - dependencies: - "@babel/parser" "^7.26.5" - "@babel/types" "^7.26.5" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/generator@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" - integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== - dependencies: - "@babel/types" "^7.23.0" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== - dependencies: - "@babel/types" "^7.18.6" - "@babel/helper-annotate-as-pure@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" @@ -159,17 +63,7 @@ dependencies: "@babel/types" "^7.25.9" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.17.10", "@babel/helper-compilation-targets@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b" - integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ== - dependencies: - "@babel/compat-data" "^7.17.10" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.26.5": +"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== @@ -180,114 +74,45 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.17.12", "@babel/helper-create-class-features-plugin@^7.18.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz#fac430912606331cb075ea8d82f9a4c145a4da19" - integrity sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-member-expression-to-functions" "^7.17.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - -"@babel/helper-create-class-features-plugin@^7.18.6": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83" - integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ== +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" + integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== dependencies: "@babel/helper-annotate-as-pure" "^7.25.9" "@babel/helper-member-expression-to-functions" "^7.25.9" "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" + "@babel/helper-replace-supers" "^7.26.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/traverse" "^7.26.9" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz#bb37ca467f9694bbe55b884ae7a5cc1e0084e4fd" - integrity sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw== +"@babel/helper-create-regexp-features-plugin@^7.25.9": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz#5169756ecbe1d95f7866b90bb555b022595302a0" + integrity sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^5.0.1" - -"@babel/helper-create-regexp-features-plugin@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz#3e35f4e04acbbf25f1b3534a657610a000543d3c" - integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.1.0" + "@babel/helper-annotate-as-pure" "^7.25.9" + regexpu-core "^6.2.0" + semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" - integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== +"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" + integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" - integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== - -"@babel/helper-environment-visitor@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz#b7eee2b5b9d70602e59d1a6cad7dd24de7ca6cd7" - integrity sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q== - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" - -"@babel/helper-function-name@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz#8334fecb0afba66e6d87a7e8c6bb7fed79926b83" - integrity sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw== - dependencies: - "@babel/template" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" -"@babel/helper-member-expression-to-functions@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz#a34013b57d8542a8c4ff8ba3f747c02452a4d8c4" - integrity sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw== +"@babel/helper-environment-visitor@^7.18.9": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== dependencies: - "@babel/types" "^7.17.0" + "@babel/types" "^7.24.7" "@babel/helper-member-expression-to-functions@^7.25.9": version "7.25.9" @@ -297,13 +122,6 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-module-imports@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" @@ -312,20 +130,6 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-transforms@^7.18.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd" - integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.0" - "@babel/types" "^7.18.0" - "@babel/helper-module-transforms@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" @@ -335,13 +139,6 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-optimise-call-expression@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" @@ -349,32 +146,12 @@ dependencies: "@babel/types" "^7.25.9" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96" - integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA== - -"@babel/helper-plugin-utils@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz#9448974dd4fb1d80fefe72e8a0af37809cd30d6d" - integrity sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg== - -"@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5": +"@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== -"@babel/helper-remap-async-to-generator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz#fa1f81acd19daee9d73de297c0308783cd3cfc23" - integrity sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.6" - "@babel/helper-wrap-function" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-remap-async-to-generator@^7.25.9": +"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== @@ -383,18 +160,7 @@ "@babel/helper-wrap-function" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/helper-replace-supers@^7.16.7": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.2.tgz#41fdfcc9abaf900e18ba6e5931816d9062a7b2e0" - integrity sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q== - dependencies: - "@babel/helper-environment-visitor" "^7.18.2" - "@babel/helper-member-expression-to-functions" "^7.17.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - -"@babel/helper-replace-supers@^7.25.9": +"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== @@ -403,20 +169,6 @@ "@babel/helper-optimise-call-expression" "^7.25.9" "@babel/traverse" "^7.26.5" -"@babel/helper-simple-access@^7.17.7", "@babel/helper-simple-access@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9" - integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ== - dependencies: - "@babel/types" "^7.18.2" - -"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== - dependencies: - "@babel/types" "^7.16.0" - "@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" @@ -425,70 +177,21 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== - "@babel/helper-string-parser@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== -"@babel/helper-validator-identifier@^7.16.7": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - "@babel/helper-validator-option@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== -"@babel/helper-wrap-function@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz#ec44ea4ad9d8988b90c3e465ba2382f4de81a073" - integrity sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw== - dependencies: - "@babel/helper-function-name" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.6" - "@babel/types" "^7.18.6" - "@babel/helper-wrap-function@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" @@ -498,91 +201,32 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helpers@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384" - integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - -"@babel/helpers@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.7.tgz#fd1d2a7c431b6e39290277aacfd8367857c576a4" - integrity sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A== - dependencies: - "@babel/template" "^7.25.9" - "@babel/types" "^7.26.7" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.16.7": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" - integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== +"@babel/helpers@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" + integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.22.13": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" - integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" -"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.18.0": - version "7.18.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.3.tgz#39e99c7b0c4c56cef4d1eed8de9f506411c2ebc2" - integrity sha512-rL50YcEuHbbauAFAysNsJA4/f89fGTOBRNs9P81sniKnKAr4xULe5AecolcsKbi88xu0ByWYDj/S1AJ3FSFuSQ== - -"@babel/parser@^7.18.6": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.8.tgz#822146080ac9c62dac0823bb3489622e0bc1cbdf" - integrity sha512-RSKRfYX20dyH+elbJK2uqAkVyucL+xXzhqlMD5/ZXx+dAAwpyB7HsvnHe/ZUGOF+xLr5Wx9/JoXVTj6BQE2/oA== - -"@babel/parser@^7.20.0", "@babel/parser@^7.23.9", "@babel/parser@^7.25.9", "@babel/parser@^7.26.5", "@babel/parser@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.7.tgz#e114cd099e5f7d17b05368678da0fb9f69b3385c" - integrity sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w== +"@babel/parser@^7.13.16", "@babel/parser@^7.20.0", "@babel/parser@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" + integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== dependencies: - "@babel/types" "^7.26.7" - -"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" - integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/types" "^7.26.9" "@babel/plugin-proposal-async-generator-functions@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz#aedac81e6fc12bb643374656dd5f2605bf743d17" - integrity sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w== + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" + integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== dependencies: - "@babel/helper-environment-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-remap-async-to-generator" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz#84f65c0cc247d46f40a6da99aadd6438315d80a4" - integrity sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.17.12" - "@babel/helper-plugin-utils" "^7.17.12" - -"@babel/plugin-proposal-class-properties@^7.18.0": +"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== @@ -591,22 +235,13 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-export-default-from@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.17.12.tgz#df785e638618d8ffa14e08c78c44d9695d083b73" - integrity sha512-LpsTRw725eBAXXKUOnJJct+SEaOzwR78zahcLuripD2+dKc2Sj+8Q2DzA+GC/jOpOu/KlDXuxrzG214o1zTauQ== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-export-default-from" "^7.16.7" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz#1e93079bbc2cbc756f6db6a1925157c4a92b94be" - integrity sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz#52702be6ef8367fc8f18b8438278332beeb8f87c" + integrity sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== @@ -622,17 +257,6 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.0.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz#79f2390c892ba2a68ec112eb0d895cfbd11155e8" - integrity sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw== - dependencies: - "@babel/compat-data" "^7.17.10" - "@babel/helper-compilation-targets" "^7.17.10" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.17.12" - "@babel/plugin-proposal-object-rest-spread@^7.20.0": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" @@ -645,23 +269,14 @@ "@babel/plugin-transform-parameters" "^7.20.7" "@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.13.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz#f96949e9bacace3a9066323a5cf90cfb9de67174" - integrity sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.20.0": +"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== @@ -677,20 +292,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -698,19 +299,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.16.7.tgz#fa89cf13b60de2c3f79acdc2b52a21174c6de060" - integrity sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.17.12.tgz#23d852902acd19f42923fca9d0f196984d124e73" - integrity sha512-B8QIgBvkIG6G2jgsOHQUist7Sm0EBLDCx8sen072IwqNuzMegZNXrYnSv77cYzA8mLDZAfQYqsLIhimiP1s2HQ== +"@babel/plugin-syntax-export-default-from@^7.0.0": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz#86614767a9ff140366f0c3766ef218beb32a730a" + integrity sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.26.0": version "7.26.0" @@ -719,41 +313,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz#834035b45061983a491f60096f61a2e7c5674a47" - integrity sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - -"@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" @@ -761,14 +327,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== @@ -789,26 +355,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.17.12", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz#b54fc3be6de734a56b87508f99d6428b5b605a7b" - integrity sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw== +"@babel/plugin-syntax-typescript@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" + integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-arrow-functions@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz#dddd783b473b1b1537ef46423e3944ff24898c45" - integrity sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" + integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-async-to-generator@^7.20.0": version "7.25.9" @@ -819,47 +378,32 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/helper-remap-async-to-generator" "^7.25.9" -"@babel/plugin-transform-block-scoped-functions@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-transform-block-scoping@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.17.12.tgz#68fc3c4b3bb7dfd809d97b7ed19a584052a2725c" - integrity sha512-jw8XW/B1i7Lqwqj2CbrViPcZijSxfguBWZP2aN59NHgxUyO/OcO1mfdCxH13QhN5LbWhPkX+f+brKGhZTiqtZQ== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" + integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-classes@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.17.12.tgz#da889e89a4d38375eeb24985218edeab93af4f29" - integrity sha512-cvO7lc7pZat6BsvH6l/EGaI8zpl8paICaoGk+7x7guvtfak/TbIf66nYmJOH13EuG0H+Xx3M+9LQDtSvZFKXKw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" + integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + "@babel/traverse" "^7.25.9" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz#bca616a83679698f3258e892ed422546e531387f" - integrity sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - -"@babel/plugin-transform-destructuring@^7.0.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz#dc4f92587e291b4daa78aa20cc2d7a63aa11e858" - integrity sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" + integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/template" "^7.25.9" "@babel/plugin-transform-destructuring@^7.20.0": version "7.25.9" @@ -868,15 +412,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.17.12.tgz#5e070f99a4152194bd9275de140e83a92966cab3" - integrity sha512-g8cSNt+cHCpG/uunPQELdq/TeV3eg1OLJYwxypwHtAWo9+nErH3lQx9CSO2uI9lF74A0mR0t4KoMjs1snSgnTw== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-flow" "^7.17.12" - -"@babel/plugin-transform-flow-strip-types@^7.20.0": +"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.25.9": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz#2904c85a814e7abb1f4850b8baf4f07d0a2389d4" integrity sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ== @@ -884,436 +420,233 @@ "@babel/helper-plugin-utils" "^7.26.5" "@babel/plugin-syntax-flow" "^7.26.0" -"@babel/plugin-transform-for-of@^7.0.0": - version "7.18.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz#ed14b657e162b72afbbb2b4cdad277bf2bb32036" - integrity sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-transform-function-name@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" + integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== dependencies: - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" "@babel/plugin-transform-literals@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz#97131fbc6bbb261487105b4b3edbf9ebf9c830ae" - integrity sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - -"@babel/plugin-transform-member-expression-literals@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" + integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz#1aa8efa2e2a6e818b6a7f2235fceaf09bdb31e9e" - integrity sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ== +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.25.9": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" + integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== dependencies: - "@babel/helper-module-transforms" "^7.18.0" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-simple-access" "^7.18.2" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-named-capturing-groups-regex@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz#c89bfbc7cc6805d692f3a49bc5fc1b630007246d" - integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-object-super@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - -"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz#eb467cd9586ff5ff115a9880d6fdbd4a846b7766" - integrity sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" + integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-parameters@^7.20.7": +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-property-literals@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== +"@babel/plugin-transform-private-methods@^7.22.5": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" + integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-private-property-in-object@^7.22.11": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" + integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-react-display-name@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" - integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" + integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-react-jsx-self@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.17.12.tgz#7f2e9b8c08d6a4204733138d8c29d4dba4bb66c2" - integrity sha512-7S9G2B44EnYOx74mue02t1uD8ckWZ/ee6Uz/qfdzc35uWHX5NgRy9i+iJSb2LFRgMd+QV9zNcStQaazzzZ3n3Q== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" + integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-react-jsx-source@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.16.7.tgz#1879c3f23629d287cc6186a6c683154509ec70c0" - integrity sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" + integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-react-jsx@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz#2aa20022709cd6a3f40b45d60603d5f269586dba" - integrity sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" + integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-jsx" "^7.17.12" - "@babel/types" "^7.17.12" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/types" "^7.25.9" "@babel/plugin-transform-runtime@^7.0.0": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz#04637de1e45ae8847ff14b9beead09c33d34374d" - integrity sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" + integrity sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ== dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.17.12" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - semver "^6.3.0" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-regenerator "^0.6.1" + semver "^6.3.1" "@babel/plugin-transform-shorthand-properties@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" + integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-spread@^7.0.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz#c112cad3064299f03ea32afed1d659223935d1f5" - integrity sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" + integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" "@babel/plugin-transform-sticky-regex@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-template-literals@^7.0.0": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz#31ed6915721864847c48b656281d0098ea1add28" - integrity sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" + integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-typescript@^7.17.12", "@babel/plugin-transform-typescript@^7.5.0": - version "7.18.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.1.tgz#5fd8b86130bad95c4a24377b41ab989a9ccad22d" - integrity sha512-F+RJmL479HJmC0KeqqwEGZMg1P7kWArLGbAKfEi9yPthJyMNjF+DjxFF/halfQvq1Q9GFM4TUbYDNV8xe4Ctqg== +"@babel/plugin-transform-typescript@^7.25.9", "@babel/plugin-transform-typescript@^7.5.0": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" + integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.0" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-typescript" "^7.17.12" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/plugin-syntax-typescript" "^7.25.9" "@babel/plugin-transform-unicode-regex@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" + integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/preset-flow@^7.13.13": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.17.12.tgz#664a5df59190260939eee862800a255bef3bd66f" - integrity sha512-7QDz7k4uiaBdu7N89VKjUn807pJRXmdirQu0KyR9LXnQrr5Jt41eIMKTS7ljej+H29erwmMrwq9Io9mJHLI3Lw== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.25.9.tgz#ef8b5e7e3f24a42b3711e77fb14919b87dffed0a" + integrity sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-flow-strip-types" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-transform-flow-strip-types" "^7.25.9" "@babel/preset-typescript@^7.13.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.17.12.tgz#40269e0a0084d56fc5731b6c40febe1c9a4a3e8c" - integrity sha512-S1ViF8W2QwAKUGJXxP9NAfNaqGDdEBJKpYkxHf5Yy2C4NPPzXGeR3Lhk7G8xJaaLcFTRfNjVbtbVtm8Gb0mqvg== + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" + integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-typescript" "^7.17.12" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/plugin-transform-modules-commonjs" "^7.25.9" + "@babel/plugin-transform-typescript" "^7.25.9" "@babel/register@^7.13.16": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.17.7.tgz#5eef3e0f4afc07e25e847720e7b987ae33f08d0b" - integrity sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.25.9.tgz#1c465acf7dc983d70ccc318eb5b887ecb04f021b" + integrity sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" make-dir "^2.1.0" - pirates "^4.0.5" + pirates "^4.0.6" source-map-support "^0.5.16" -"@babel/runtime@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" - integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.0.0", "@babel/template@^7.16.7", "@babel/template@^7.3.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" - integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== +"@babel/runtime@^7.25.0": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" + integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" + regenerator-runtime "^0.14.0" -"@babel/template@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" - integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== +"@babel/template@^7.0.0", "@babel/template@^7.25.9", "@babel/template@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== dependencies: - "@babel/code-frame" "^7.25.9" - "@babel/parser" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/traverse@^7.13.0", "@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.18.6": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" - integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.0" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.0" - "@babel/types" "^7.23.0" - debug "^4.1.0" - globals "^11.1.0" + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" -"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.7.tgz#99a0a136f6a75e7fb8b0a1ace421e0b25994b8bb" - integrity sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA== +"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" + integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== dependencies: "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.5" - "@babel/parser" "^7.26.7" - "@babel/template" "^7.25.9" - "@babel/types" "^7.26.7" + "@babel/generator" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.17.12", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.2.tgz#191abfed79ebe6f4242f643a9a5cbaa36b10b091" - integrity sha512-0On6B8A4/+mFUto5WERt3EEuG1NznDirvwca1O8UwXQHVY8g3R7OzYgxXdOfMwLO08UrpUD/2+3Bclyq+/C94Q== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.18.6": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.8.tgz#c5af199951bf41ba4a6a9a6d0d8ad722b30cd42f" - integrity sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - to-fast-properties "^2.0.0" - -"@babel/types@^7.20.0", "@babel/types@^7.25.9", "@babel/types@^7.26.5", "@babel/types@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" - integrity sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg== +"@babel/types@^7.20.0", "@babel/types@^7.24.7", "@babel/types@^7.25.9", "@babel/types@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== dependencies: "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" -"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" - integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== - dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@expo/config-plugins@^7.2.4": - version "7.2.5" - resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.5.tgz#b15f22878975fdc4ddcfa8cdc971937ddc4c0249" - integrity sha512-w+5ccu1IxBHgyQk9CPFKLZOk8yZQEyTjbJwOzESK1eR7QwosbcsLkN1c1WWUZYiCXwORu3UTwJYll4+X2xxJhQ== - dependencies: - "@expo/config-types" "^49.0.0-alpha.1" - "@expo/json-file" "~8.2.37" - "@expo/plist" "^0.0.20" - "@expo/sdk-runtime-versions" "^1.0.0" - "@react-native/normalize-color" "^2.0.0" - chalk "^4.1.2" - debug "^4.3.1" - find-up "~5.0.0" - getenv "^1.0.0" - glob "7.1.6" - resolve-from "^5.0.0" - semver "^7.5.3" - slash "^3.0.0" - xcode "^3.0.1" - xml2js "0.6.0" - -"@expo/config-types@^49.0.0-alpha.1": - version "49.0.0" - resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-49.0.0.tgz#15ffef715285c06703f6fb7ec0cda853f645cc09" - integrity sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA== - -"@expo/json-file@~8.2.37": - version "8.2.37" - resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049" - integrity sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q== - dependencies: - "@babel/code-frame" "~7.10.4" - json5 "^2.2.2" - write-file-atomic "^2.3.0" - -"@expo/plist@^0.0.20": - version "0.0.20" - resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.20.tgz#a6b3124438031c02b762bad5a47b70584d3c0072" - integrity sha512-UXQ4LXCfTZ580LDHGJ5q62jSTwJFFJ1GqBu8duQMThiHKWbMJ+gajJh6rsB6EJ3aLUr9wcauxneL5LVRFxwBEA== - dependencies: - "@xmldom/xmldom" "~0.7.7" - base64-js "^1.2.3" - xmlbuilder "^14.0.0" - -"@expo/sdk-runtime-versions@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c" - integrity sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ== - -"@hapi/hoek@^9.0.0": +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== -"@hapi/topo@^5.0.0": +"@hapi/topo@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== dependencies: "@hapi/hoek" "^9.0.0" -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/create-cache-key-function@^29.2.1": +"@isaacs/ttlcache@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" + integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== + +"@jest/create-cache-key-function@^29.6.3": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== @@ -1330,21 +663,6 @@ "@types/node" "*" jest-mock "^29.7.0" -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - "@jest/fake-timers@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" @@ -1357,46 +675,6 @@ jest-mock "^29.7.0" jest-util "^29.7.0" -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -1404,56 +682,6 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -1465,17 +693,6 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@jest/types@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" - integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - "@jest/types@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" @@ -1488,32 +705,6 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" - integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - "@jridgewell/gen-mapping@^0.3.5": version "0.3.8" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" @@ -1523,25 +714,10 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/set-array@^1.2.1": version "1.2.1" @@ -1556,17 +732,12 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== - -"@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -1574,131 +745,102 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@jridgewell/trace-mapping@^0.3.17": - version "0.3.19" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" - integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" - integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== +"@react-native-community/cli-clean@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz#303ddf1c930918a8bdc4cc58fe0ac2dd05603cd5" + integrity sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ== dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@react-native-community/cli-clean@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-11.4.1.tgz#0155a02e4158c8a61ba3d7a2b08f3ebebed81906" - integrity sha512-cwUbY3c70oBGv3FvQJWe2Qkq6m1+/dcEBonMDTYyH6i+6OrkzI4RkIGpWmbG1IS5JfE9ISUZkNL3946sxyWNkw== - dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" execa "^5.0.0" - prompts "^2.4.0" -"@react-native-community/cli-config@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-11.4.1.tgz#c27f91d2753f0f803cc79bbf299f19648a5d5627" - integrity sha512-sLdv1HFVqu5xNpeaR1+std0t7FFZaobpmpR0lFCOzKV7H/l611qS2Vo8zssmMK+oQbCs5JsX3SFPciODeIlaWA== +"@react-native-community/cli-config@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-12.3.7.tgz#feb8b93e8ccd6116ac1df0f1d8a0f06872388e51" + integrity sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" cosmiconfig "^5.1.0" deepmerge "^4.3.0" glob "^7.1.3" joi "^17.2.1" -"@react-native-community/cli-debugger-ui@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-11.4.1.tgz#783cc276e1360baf8235dc8c6ebbbce0fe01d944" - integrity sha512-+pgIjGNW5TrJF37XG3djIOzP+WNoPp67to/ggDhrshuYgpymfb9XpDVsURJugy0Sy3RViqb83kQNK765QzTIvw== +"@react-native-community/cli-debugger-ui@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz#522aa11c7b4ff4a2ec86492fabee0366d5428b4c" + integrity sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-doctor@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-11.4.1.tgz#516ef5932de3e12989695e7cb7aba82b81e7b2de" - integrity sha512-O6oPiRsl8pdkcyNktpzvJAXUqdocoY4jh7Tt7wA69B1JKCJA7aPCecwJgpUZb63ZYoxOtRtYM3BYQKzRMLIuUw== +"@react-native-community/cli-doctor@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz#31e4784182d6bbfe62f2e728dca87ee23efe0564" + integrity sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg== dependencies: - "@react-native-community/cli-config" "11.4.1" - "@react-native-community/cli-platform-android" "11.4.1" - "@react-native-community/cli-platform-ios" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-config" "12.3.7" + "@react-native-community/cli-platform-android" "12.3.7" + "@react-native-community/cli-platform-ios" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" command-exists "^1.2.8" - envinfo "^7.7.2" + deepmerge "^4.3.0" + envinfo "^7.10.0" execa "^5.0.0" hermes-profile-transformer "^0.0.6" node-stream-zip "^1.9.1" ora "^5.4.1" - prompts "^2.4.0" semver "^7.5.2" strip-ansi "^5.2.0" - sudo-prompt "^9.0.0" wcwidth "^1.0.1" yaml "^2.2.1" -"@react-native-community/cli-hermes@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-11.4.1.tgz#abf487ae8ab53c66f6f1178bcd37ecbbbac9fb5c" - integrity sha512-1VAjwcmv+i9BJTMMVn5Grw7AcgURhTyfHVghJ1YgBE2euEJxPuqPKSxP54wBOQKnWUwsuDQAtQf+jPJoCxJSSA== +"@react-native-community/cli-hermes@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz#4a284e0091469f6cce8caad2fefcf6b45c0cf229" + integrity sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg== dependencies: - "@react-native-community/cli-platform-android" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-platform-android" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" hermes-profile-transformer "^0.0.6" -"@react-native-community/cli-platform-android@11.4.1", "@react-native-community/cli-platform-android@^11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-11.4.1.tgz#ec5fc97e87834f2e33cb0d34dcef6c17b20f60fc" - integrity sha512-VMmXWIzk0Dq5RAd+HIEa3Oe7xl2jso7+gOr6E2HALF4A3fCKUjKZQ6iK2t6AfnY04zftvaiKw6zUXtrfl52AVQ== +"@react-native-community/cli-platform-android@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz#4826f5126f950e29d7ef1ac779c4eed56d251f98" + integrity sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" execa "^5.0.0" + fast-xml-parser "^4.2.4" glob "^7.1.3" logkitty "^0.7.1" -"@react-native-community/cli-platform-ios@11.4.1", "@react-native-community/cli-platform-ios@^11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-11.4.1.tgz#12d72741273b684734d5ed021415b7f543a6f009" - integrity sha512-RPhwn+q3IY9MpWc9w/Qmzv03mo8sXdah2eSZcECgweqD5SHWtOoRCUt11zM8jASpAQ8Tm5Je7YE9bHvdwGl4hA== +"@react-native-community/cli-platform-ios@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz#ef90e5c4d9ff5f15071b18179b17cf16699a70e5" + integrity sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow== dependencies: - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-tools" "12.3.7" chalk "^4.1.2" execa "^5.0.0" fast-xml-parser "^4.0.12" glob "^7.1.3" ora "^5.4.1" -"@react-native-community/cli-plugin-metro@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-11.4.1.tgz#8d51c59a9a720f99150d4153e757d5d1d1dabd22" - integrity sha512-JxbIqknYcQ5Z4rWROtu5LNakLfMiKoWcMoPqIrBLrV5ILm1XUJj1/8fATCcotZqV3yzB3SCJ3RrhKx7dQ3YELw== - dependencies: - "@react-native-community/cli-server-api" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" - chalk "^4.1.2" - execa "^5.0.0" - metro "^0.76.9" - metro-config "^0.76.9" - metro-core "^0.76.9" - metro-react-native-babel-transformer "^0.76.9" - metro-resolver "^0.76.9" - metro-runtime "^0.76.9" - readline "^1.3.0" +"@react-native-community/cli-plugin-metro@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz#f9be724721a52d800a20f641a2241a7b4e6a9477" + integrity sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg== -"@react-native-community/cli-server-api@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-11.4.1.tgz#3dda094c4ab2369db34fe991c320e3cd78f097b3" - integrity sha512-isxXE8X5x+C4kN90yilD08jaLWD34hfqTfn/Xbl1u/igtdTsCaQGvWe9eaFamrpWFWTpVtj6k+vYfy8AtYSiKA== +"@react-native-community/cli-server-api@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz#81e2a067c120391242740598010abb8d5d36a739" + integrity sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg== dependencies: - "@react-native-community/cli-debugger-ui" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" + "@react-native-community/cli-debugger-ui" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" compression "^1.7.1" connect "^3.6.5" errorhandler "^1.5.1" @@ -1707,10 +849,10 @@ serve-static "^1.13.1" ws "^7.5.1" -"@react-native-community/cli-tools@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-11.4.1.tgz#f6c69967e077b10cd8a884a83e53eb199dd9ee9f" - integrity sha512-GuQIuY/kCPfLeXB1aiPZ5HvF+e/wdO42AYuNEmT7FpH/0nAhdTxA9qjL8m3vatDD2/YK7WNOSVNsl2UBZuOISg== +"@react-native-community/cli-tools@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz#65cf1c81d13662a1b0396c753e6ff916e3e92083" + integrity sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw== dependencies: appdirsjs "^1.2.4" chalk "^4.1.2" @@ -1721,46 +863,103 @@ ora "^5.4.1" semver "^7.5.2" shell-quote "^1.7.3" + sudo-prompt "^9.0.0" -"@react-native-community/cli-types@11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-11.4.1.tgz#3842dc37ba3b09f929b485bcbd8218de19349ac2" - integrity sha512-B3q9A5BCneLDSoK/iSJ06MNyBn1qTxjdJeOgeS3MiCxgJpPcxyn/Yrc6+h0Cu9T9sgWj/dmectQPYWxtZeo5VA== +"@react-native-community/cli-types@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-12.3.7.tgz#6f55becdc41bb5ebf1a8f6fd27ad0d198831169d" + integrity sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w== dependencies: joi "^17.2.1" -"@react-native-community/cli@^11.4.1": - version "11.4.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-11.4.1.tgz#9a6346486622860dad721da406df70e29a45491f" - integrity sha512-NdAageVMtNhtvRsrq4NgJf5Ey2nA1CqmLvn7PhSawg+aIzMKmZuzWxGVwr9CoPGyjvNiqJlCWrLGR7NzOyi/sA== - dependencies: - "@react-native-community/cli-clean" "11.4.1" - "@react-native-community/cli-config" "11.4.1" - "@react-native-community/cli-debugger-ui" "11.4.1" - "@react-native-community/cli-doctor" "11.4.1" - "@react-native-community/cli-hermes" "11.4.1" - "@react-native-community/cli-plugin-metro" "11.4.1" - "@react-native-community/cli-server-api" "11.4.1" - "@react-native-community/cli-tools" "11.4.1" - "@react-native-community/cli-types" "11.4.1" +"@react-native-community/cli@12.3.7": + version "12.3.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-12.3.7.tgz#8f53ec9310367a0204d859005e9cd137f9888382" + integrity sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ== + dependencies: + "@react-native-community/cli-clean" "12.3.7" + "@react-native-community/cli-config" "12.3.7" + "@react-native-community/cli-debugger-ui" "12.3.7" + "@react-native-community/cli-doctor" "12.3.7" + "@react-native-community/cli-hermes" "12.3.7" + "@react-native-community/cli-plugin-metro" "12.3.7" + "@react-native-community/cli-server-api" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" + "@react-native-community/cli-types" "12.3.7" chalk "^4.1.2" commander "^9.4.1" + deepmerge "^4.3.0" execa "^5.0.0" find-up "^4.1.0" fs-extra "^8.1.0" graceful-fs "^4.1.3" - prompts "^2.4.0" + prompts "^2.4.2" semver "^7.5.2" -"@react-native/assets-registry@^0.72.0": - version "0.72.0" - resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.72.0.tgz#c82a76a1d86ec0c3907be76f7faf97a32bbed05d" - integrity sha512-Im93xRJuHHxb1wniGhBMsxLwcfzdYreSZVQGDoMJgkd6+Iky61LInGEHnQCTN0fKNYF1Dvcofb4uMmE1RQHXHQ== +"@react-native/assets-registry@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.73.1.tgz#e2a6b73b16c183a270f338dc69c36039b3946e85" + integrity sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg== + +"@react-native/babel-plugin-codegen@0.73.4": + version "0.73.4" + resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz#8a2037d5585b41877611498ae66adbf1dddfec1b" + integrity sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ== + dependencies: + "@react-native/codegen" "0.73.3" + +"@react-native/babel-preset@0.73.21": + version "0.73.21" + resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.73.21.tgz#174c16493fa4e311b2f5f0c58d4f3c6a5a68bbea" + integrity sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA== + dependencies: + "@babel/core" "^7.20.0" + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.18.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" + "@babel/plugin-proposal-numeric-separator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.20.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.20.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.18.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-async-to-generator" "^7.20.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.20.0" + "@babel/plugin-transform-flow-strip-types" "^7.20.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + "@react-native/babel-plugin-codegen" "0.73.4" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.14.0" -"@react-native/codegen@^0.72.8": - version "0.72.8" - resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.72.8.tgz#0593f628e1310f430450a9479fbb4be35e7b63d6" - integrity sha512-jQCcBlXV7B7ap5VlHhwIPieYz89yiRgwd2FPUBu+unz+kcJ6pAiB2U8RdLDmyIs8fiWd+Vq1xxaWs4TR329/ng== +"@react-native/codegen@0.73.3": + version "0.73.3" + resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.73.3.tgz#cc984a8b17334d986cc600254a0d4b7fa7d68a94" + integrity sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg== dependencies: "@babel/parser" "^7.20.0" flow-parser "^0.206.0" @@ -1770,42 +969,91 @@ mkdirp "^0.5.1" nullthrows "^1.1.1" -"@react-native/gradle-plugin@^0.72.11": - version "0.72.11" - resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.72.11.tgz#c063ef12778706611de7a1e42b74b14d9405fb9f" - integrity sha512-P9iRnxiR2w7EHcZ0mJ+fmbPzMby77ZzV6y9sJI3lVLJzF7TLSdbwcQyD3lwMsiL+q5lKUHoZJS4sYmih+P2HXw== +"@react-native/community-cli-plugin@0.73.18": + version "0.73.18" + resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz#ba2a0933fad574684534eea29f1c5d2cab494854" + integrity sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww== + dependencies: + "@react-native-community/cli-server-api" "12.3.7" + "@react-native-community/cli-tools" "12.3.7" + "@react-native/dev-middleware" "0.73.8" + "@react-native/metro-babel-transformer" "0.73.15" + chalk "^4.0.0" + execa "^5.1.1" + metro "^0.80.3" + metro-config "^0.80.3" + metro-core "^0.80.3" + node-fetch "^2.2.0" + readline "^1.3.0" -"@react-native/js-polyfills@^0.72.1": - version "0.72.1" - resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.72.1.tgz#905343ef0c51256f128256330fccbdb35b922291" - integrity sha512-cRPZh2rBswFnGt5X5EUEPs0r+pAsXxYsifv/fgy9ZLQokuT52bPH+9xjDR+7TafRua5CttGW83wP4TntRcWNDA== +"@react-native/debugger-frontend@0.73.3": + version "0.73.3" + resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz#033757614d2ada994c68a1deae78c1dd2ad33c2b" + integrity sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw== -"@react-native/normalize-color@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91" - integrity sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA== +"@react-native/dev-middleware@0.73.8": + version "0.73.8" + resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz#2e43722a00c7b8db753f747f40267cbad6caba4d" + integrity sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg== + dependencies: + "@isaacs/ttlcache" "^1.4.1" + "@react-native/debugger-frontend" "0.73.3" + chrome-launcher "^0.15.2" + chromium-edge-launcher "^1.0.0" + connect "^3.6.5" + debug "^2.2.0" + node-fetch "^2.2.0" + open "^7.0.3" + serve-static "^1.13.1" + temp-dir "^2.0.0" + ws "^6.2.2" -"@react-native/normalize-colors@<0.73.0", "@react-native/normalize-colors@^0.72.0": - version "0.72.0" - resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.72.0.tgz#14294b7ed3c1d92176d2a00df48456e8d7d62212" - integrity sha512-285lfdqSXaqKuBbbtP9qL2tDrfxdOFtIMvkKadtleRQkdOxx+uzGvFr82KHmc/sSiMtfXGp7JnFYWVh4sFl7Yw== +"@react-native/gradle-plugin@0.73.5": + version "0.73.5" + resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz#900126b4e5737eaac22a0fddb2fc5b4cc20da41c" + integrity sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA== -"@react-native/virtualized-lists@^0.72.8": - version "0.72.8" - resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz#a2c6a91ea0f1d40eb5a122fb063daedb92ed1dc3" - integrity sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw== +"@react-native/js-polyfills@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz#730b0a7aaab947ae6f8e5aa9d995e788977191ed" + integrity sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g== + +"@react-native/metro-babel-transformer@0.73.15": + version "0.73.15" + resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz#c516584dde62d65a46668074084359c03e6a50f1" + integrity sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw== + dependencies: + "@babel/core" "^7.20.0" + "@react-native/babel-preset" "0.73.21" + hermes-parser "0.15.0" + nullthrows "^1.1.1" + +"@react-native/normalize-colors@0.73.2", "@react-native/normalize-colors@^0.73.0": + version "0.73.2" + resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz#cc8e48fbae2bbfff53e12f209369e8d2e4cf34ec" + integrity sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w== + +"@react-native/typescript-config@0.73.1": + version "0.73.1" + resolved "https://registry.yarnpkg.com/@react-native/typescript-config/-/typescript-config-0.73.1.tgz#c97a42f5cd264069bfe86b737c531ed2f042ae6d" + integrity sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w== + +"@react-native/virtualized-lists@0.73.4": + version "0.73.4" + resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz#640e594775806f63685435b5d9c3d05c378ccd8c" + integrity sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog== dependencies: invariant "^2.2.4" nullthrows "^1.1.1" -"@sideway/address@^4.1.3": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" - integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== dependencies: "@hapi/hoek" "^9.0.0" -"@sideway/formula@^3.0.0": +"@sideway/formula@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== @@ -1834,89 +1082,38 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@tsconfig/react-native@^3.0.0": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@tsconfig/react-native/-/react-native-3.0.5.tgz#c4971b1eca2e8cdf7b0d25f40193a782039c1abd" - integrity sha512-0+pmYzHccvwWpFz2Tv5AJxp6UroLALmAy+SX34tKlwaCie1mNbtCv6uOJp7x8pKchgNA9/n6BGrx7uLQvw8p9A== - -"@types/babel__core@^7.1.14": - version "7.1.19" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" - integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.4" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" - integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314" - integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA== - dependencies: - "@babel/types" "^7.3.0" - -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== "@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.2.1": - version "29.5.14" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" - integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - "@types/node@*": - version "17.0.35" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.35.tgz#635b7586086d51fb40de0a2ec9d1014a5283ba4a" - integrity sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg== + version "22.13.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.4.tgz#3fe454d77cd4a2d73c214008b3e331bfaaf5038a" + integrity sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg== + dependencies: + undici-types "~6.20.0" "@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + version "15.7.14" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" + integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== -"@types/react@^18.0.24": +"@types/react@^18.2.6": version "18.3.18" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== @@ -1925,26 +1122,19 @@ csstype "^3.0.2" "@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^15.0.0": - version "15.0.14" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" - integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== - dependencies: - "@types/yargs-parser" "*" - -"@types/yargs@^16.0.0": - version "16.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" - integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + version "15.0.19" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.19.tgz#328fb89e46109ecbdb70c295d96ff2f46dfd01b9" + integrity sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA== dependencies: "@types/yargs-parser" "*" @@ -1955,11 +1145,6 @@ dependencies: "@types/yargs-parser" "*" -"@xmldom/xmldom@~0.7.7": - version "0.7.11" - resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.11.tgz#adecc134521274711d071d5b0200907cc83b38ee" - integrity sha512-UDi3g6Jss/W5FnSzO9jCtQwEpfymt0M+sPPlmLhDH6h2TJ8j4ESE/LpmNPBij15J5NKkk4/cg/qoVMdWI3vnlQ== - abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -1967,7 +1152,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7: +accepts@^1.3.7, accepts@~1.3.7: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -1985,13 +1170,6 @@ anser@^1.4.9: resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - ansi-fragments@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" @@ -2011,7 +1189,7 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -2031,17 +1209,17 @@ ansi-styles@^5.0.0: integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== anymatch@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" appdirsjs@^1.2.4: - version "1.2.6" - resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.6.tgz#fccf9ee543315492867cacfcfd4a2b32257d30ac" - integrity sha512-D8wJNkqMCeQs3kLasatELsddox/Xqkhp+J07iXGyL54fVN7oc+nmNfYzGuCs1IEP6uBw+TfpuO3JKwc+lECy4w== + version "1.2.7" + resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" + integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== argparse@^1.0.7: version "1.0.10" @@ -2072,85 +1250,34 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^3.2.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" - integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== - babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== -babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" - integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.12" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" + integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.1" - semver "^6.1.1" + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.3" + semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== +babel-plugin-polyfill-corejs3@^0.10.6: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" + "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" - integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" + integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" - -babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: - version "7.0.0-beta.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" - integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + "@babel/helper-define-polyfill-provider" "^0.6.3" babel-plugin-transform-flow-enums@^0.0.2: version "0.0.2" @@ -2159,80 +1286,16 @@ babel-plugin-transform-flow-enums@^0.0.2: dependencies: "@babel/plugin-syntax-flow" "^7.12.1" -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-fbjs@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" - integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== - dependencies: - "@babel/plugin-proposal-class-properties" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-syntax-class-properties" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-block-scoped-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-flow-strip-types" "^7.0.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-member-expression-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-object-super" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-property-literals" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" - -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: +base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -big-integer@1.6.x: - version "1.6.51" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" - integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== - bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -2242,20 +1305,6 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" -bplist-creator@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.1.0.tgz#018a2d1b587f769e379ef5519103730f8963ba1e" - integrity sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg== - dependencies: - stream-buffers "2.2.x" - -bplist-parser@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1" - integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA== - dependencies: - big-integer "1.6.x" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2264,25 +1313,14 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2: +braces@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" -browserslist@^4.20.2, browserslist@^4.20.3: - version "4.20.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" - integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== - dependencies: - caniuse-lite "^1.0.30001332" - electron-to-chromium "^1.4.118" - escalade "^3.1.1" - node-releases "^2.0.3" - picocolors "^1.0.0" - -browserslist@^4.24.0: +browserslist@^4.24.0, browserslist@^4.24.3: version "4.24.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -2320,18 +1358,10 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== - -call-bind@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== caller-callsite@^2.0.0: version "2.0.0" @@ -2352,12 +1382,7 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0, camelcase@^5.3.1: +camelcase@^5.0.0: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -2367,24 +1392,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001332: - version "1.0.30001342" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz#87152b1e3b950d1fbf0093e23f00b6c8e8f1da96" - integrity sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA== - caniuse-lite@^1.0.30001688: - version "1.0.30001695" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz#39dfedd8f94851132795fdf9b79d29659ad9c4d4" - integrity sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw== - -chalk@^2.0.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" + version "1.0.30001700" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" + integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" @@ -2394,10 +1405,27 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chrome-launcher@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" + integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + +chromium-edge-launcher@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#0443083074715a13c669530b35df7bfea33b1509" + integrity sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + mkdirp "^1.0.4" + rimraf "^3.0.2" ci-info@^2.0.0: version "2.0.0" @@ -2405,14 +1433,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" - integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg== - -cjs-module-lexer@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" - integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== cli-cursor@^3.1.0: version "3.1.0" @@ -2422,9 +1445,9 @@ cli-cursor@^3.1.0: restore-cursor "^3.1.0" cli-spinners@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" - integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== cliui@^6.0.0: version "6.0.0" @@ -2456,17 +1479,7 @@ clone-deep@^4.0.1: clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== color-convert@^1.9.0: version "1.9.3" @@ -2512,17 +1525,12 @@ commander@^9.4.1: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== -commander@~2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" - integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== -compressible@~2.0.16: +compressible@~2.0.18: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== @@ -2530,16 +1538,16 @@ compressible@~2.0.16: mime-db ">= 1.43.0 < 2" compression@^1.7.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + version "1.8.0" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.0.tgz#09420efc96e11a0f44f3a558de59e321364180f7" + integrity sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA== dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" + bytes "3.1.2" + compressible "~2.0.18" debug "2.6.9" + negotiator "~0.6.4" on-headers "~1.0.2" - safe-buffer "5.1.2" + safe-buffer "5.2.1" vary "~1.1.2" concat-map@0.0.1: @@ -2557,25 +1565,17 @@ connect@^3.6.5: parseurl "~1.3.3" utils-merge "1.0.1" -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-js-compat@^3.21.0: - version "3.22.7" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.7.tgz#8359eb66ecbf726dd0cfced8e48d5e73f3224239" - integrity sha512-uI9DAQKKiiE/mclIC5g4AjRpio27g+VMRhe6rQoz+q4Wm4L6A/fJhiLtBw+sfOpDG9wZ3O0pxIw7GbfOlBgjOA== +core-js-compat@^3.38.0: + version "3.40.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" + integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== dependencies: - browserslist "^4.20.3" - semver "7.0.0" + browserslist "^4.24.3" core-util-is@~1.0.0: version "1.0.3" @@ -2592,39 +1592,26 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: js-yaml "^3.13.1" parse-json "^4.0.0" -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" csstype@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" - integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== dayjs@^1.8.15: - version "1.11.2" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5" - integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw== + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -debug@2.6.9, debug@^2.2.0: +debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2632,26 +1619,16 @@ debug@2.6.9, debug@^2.2.0: ms "2.0.0" debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== dependencies: - ms "2.1.2" + ms "^2.1.3" decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -dedent@^1.0.0: - version "1.5.3" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" - integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== deepmerge@^4.3.0: version "4.3.1" @@ -2659,36 +1636,28 @@ deepmerge@^4.3.0: integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== dependencies: clone "^1.0.2" -define-properties@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - denodeify@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" - integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE= + integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -deprecated-react-native-prop-types@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.2.3.tgz#0ef845c1a80ef1636bd09060e4cdf70f9727e5ad" - integrity sha512-2rLTiMKidIFFYpIVM69UnQKngLqQfL6I11Ch8wGSBftS18FUXda+o2we2950X+1dmbgps28niI3qwyH4eX3Z1g== +deprecated-react-native-prop-types@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz#02a12f090da7bd9e8c3ac53c31cf786a1315d302" + integrity sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ== dependencies: - "@react-native/normalize-colors" "<0.73.0" + "@react-native/normalize-colors" "^0.73.0" invariant "^2.2.4" prop-types "^15.8.1" @@ -2697,35 +1666,15 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.4.118: - version "1.4.138" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.138.tgz#3ec41ca589aaf505dfe2034fde913329af801730" - integrity sha512-IOyp2Seq3w4QLln+yZWcMF3VXhhduz4bwg9gfI+CnP5TkzwNXQ8FCZuwwPsnes73AfWdf5J2n2OXdUwDUspDPQ== + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.5.73: - version "1.5.88" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.88.tgz#cdb6e2dda85e6521e8d7d3035ba391c8848e073a" - integrity sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + version "1.5.102" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz#81a452ace8e2c3fa7fba904ea4fed25052c53d3f" + integrity sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q== emoji-regex@^8.0.0: version "8.0.0" @@ -2735,12 +1684,17 @@ emoji-regex@^8.0.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== -envinfo@^7.7.2: - version "7.8.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" - integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== +envinfo@^7.10.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" + integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== error-ex@^1.3.1: version "1.3.2" @@ -2750,11 +1704,11 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" error-stack-parser@^2.0.6: - version "2.0.7" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.7.tgz#b0c6e2ce27d0495cf78ad98715e0cad1219abb57" - integrity sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA== + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== dependencies: - stackframe "^1.1.1" + stackframe "^1.3.4" errorhandler@^1.5.1: version "1.5.1" @@ -2764,12 +1718,7 @@ errorhandler@^1.5.1: accepts "~1.3.7" escape-html "~1.0.3" -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escalade@^3.2.0: +escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== @@ -2777,18 +1726,18 @@ escalade@^3.2.0: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + esprima@^4.0.0, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -2797,14 +1746,14 @@ esprima@^4.0.0, esprima@~4.0.0: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== event-target-shim@^5.0.0, event-target-shim@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -execa@^5.0.0: +execa@^5.0.0, execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -2819,28 +1768,12 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expect@^29.0.0, expect@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - -fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +exponential-backoff@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91" + integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA== -fast-xml-parser@^4.0.12: +fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: version "4.5.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz#a7e665ff79b7919100a5202f23984b6150f9b31e" integrity sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w== @@ -2848,9 +1781,9 @@ fast-xml-parser@^4.0.12: strnum "^1.0.5" fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" @@ -2890,7 +1823,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0, find-up@^4.1.0: +find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -2898,7 +1831,7 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@^5.0.0, find-up@~5.0.0: +find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -2906,15 +1839,15 @@ find-up@^5.0.0, find-up@~5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -flow-enums-runtime@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.5.tgz#95884bfcc82edaf27eef7e1dd09732331cfbafbc" - integrity sha512-PSZF9ZuaZD03sT9YaIs0FrGJ7lSUw7rHZIex+73UYVXg46eL/wxN5PaVcPJFudE2cJu5f0fezitV5aBkLHPUOQ== +flow-enums-runtime@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" + integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== flow-parser@0.*: - version "0.178.1" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.178.1.tgz#4efe62b3c551c615411bd4a75031c881ff53a7da" - integrity sha512-TOvOfZVOhCsKAVU2E4QgFD5vmmF/JWl4bX77H4aYoq8No1mZdtUV8GW6wv03l8N3dmlRqAC5rZcDQ5e8aLDBOg== + version "0.261.1" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.261.1.tgz#1ce84a0ea0f51f263be779c4988bf6ddd8e7aafb" + integrity sha512-2l5bBKeVtT+d+1CYSsTLJ+iP2FuoR7zjbDQI/v6dDRiBpx3Lb20Z/tLS37ReX/lcodyGSHC2eA/Nk63hB+mkYg== flow-parser@^0.206.0: version "0.206.0" @@ -2924,7 +1857,7 @@ flow-parser@^0.206.0: fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-extra@^8.1.0: version "8.1.0" @@ -2941,14 +1874,14 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" @@ -2960,43 +1893,12 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -getenv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/getenv/-/getenv-1.0.0.tgz#874f2e7544fbca53c7a4738f37de8605c3fcfc31" - integrity sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg== - -glob@7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3014,50 +1916,45 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: - get-intrinsic "^1.1.1" + function-bind "^1.1.2" -has-symbols@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +hermes-estree@0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba" + integrity sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ== -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" +hermes-estree@0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb" + integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg== -hermes-estree@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.12.0.tgz#8a289f9aee854854422345e6995a48613bac2ca8" - integrity sha512-+e8xR6SCen0wyAKrMT3UD0ZCCLymKhRgjEB5sS28rKiFir/fXgLoeRilRUssFCILmGHb+OvHDUlhxs0+IEyvQw== +hermes-parser@0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.15.0.tgz#f611a297c2a2dbbfbce8af8543242254f604c382" + integrity sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q== + dependencies: + hermes-estree "0.15.0" -hermes-parser@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.12.0.tgz#114dc26697cfb41a6302c215b859b74224383773" - integrity sha512-d4PHnwq6SnDLhYl3LHNHvOg7nQ6rcI7QVil418REYksv0Mh3cEkHDcuhGxNQ3vgnLSLl4QSvDrFCwQNYdpWlzw== +hermes-parser@0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205" + integrity sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA== dependencies: - hermes-estree "0.12.0" + hermes-estree "0.23.1" hermes-profile-transformer@^0.0.6: version "0.0.6" @@ -3066,11 +1963,6 @@ hermes-profile-transformer@^0.0.6: dependencies: source-map "^0.7.3" -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -3102,19 +1994,11 @@ image-size@^1.0.2: import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== dependencies: caller-path "^2.0.0" resolve-from "^3.0.0" -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -3143,35 +2027,35 @@ invariant@^2.2.4: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-core-module@^2.8.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== +is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - has "^1.0.3" + hasown "^2.0.2" is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" @@ -3202,392 +2086,70 @@ is-unicode-supported@^0.1.0: is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-instrument@^5.0.4: - version "5.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" - integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" - integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== - dependencies: - "@babel/core" "^7.23.9" - "@babel/parser" "^7.23.9" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-node@^29.2.1, jest-environment-node@^29.7.0: +jest-environment-node@^29.6.3: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^27.0.6: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" - integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== - -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" -jest-snapshot@^29.7.0: +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-message-util@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" + "@types/stack-utils" "^2.0.0" chalk "^4.0.0" - expect "^29.7.0" graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" + micromatch "^4.0.4" pretty-format "^29.7.0" - semver "^7.5.3" + slash "^3.0.0" + stack-utils "^2.0.3" -jest-util@^27.2.0: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^29.6.3" "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" + jest-util "^29.7.0" jest-util@^29.7.0: version "29.7.0" @@ -3601,7 +2163,7 @@ jest-util@^29.7.0: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.2.1, jest-validate@^29.7.0: +jest-validate@^29.6.3: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== @@ -3613,30 +2175,7 @@ jest-validate@^29.2.1, jest-validate@^29.7.0: leven "^3.1.0" pretty-format "^29.7.0" -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - -jest-worker@^27.2.0: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest-worker@^29.7.0: +jest-worker@^29.6.3: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== @@ -3646,25 +2185,15 @@ jest-worker@^29.7.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.2.1: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - joi@^17.2.1: - version "17.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" - integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== - dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.0" + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: @@ -3715,37 +2244,22 @@ jscodeshift@^0.14.0: temp "^0.8.4" write-file-atomic "^2.3.0" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - jsesc@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +jsesc@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -json5@^2.2.2, json5@^2.2.3: +json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -3753,7 +2267,7 @@ json5@^2.2.2, json5@^2.2.3: jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" @@ -3772,10 +2286,13 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +lighthouse-logger@^1.0.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa" + integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== + dependencies: + debug "^2.6.9" + marky "^1.2.2" locate-path@^3.0.0: version "3.0.0" @@ -3802,12 +2319,12 @@ locate-path@^6.0.0: lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== log-symbols@^4.1.0: version "4.1.0" @@ -3840,13 +2357,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -3855,13 +2365,6 @@ make-dir@^2.0.0, make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - makeerror@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" @@ -3869,6 +2372,11 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +marky@^1.2.2: + version "1.2.5" + resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" + integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== + memoize-one@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -3879,62 +2387,67 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -metro-babel-transformer@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.76.9.tgz#659ba481d471b5f748c31a8f9397094b629f50ec" - integrity sha512-dAnAmBqRdTwTPVn4W4JrowPolxD1MDbuU97u3MqtWZgVRvDpmr+Cqnn5oSxLQk3Uc+Zy3wkqVrB/zXNRlLDSAQ== +metro-babel-transformer@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz#ad02ade921dd4ced27b26b18ff31eb60608e3f56" + integrity sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg== dependencies: "@babel/core" "^7.20.0" - hermes-parser "0.12.0" + flow-enums-runtime "^0.0.6" + hermes-parser "0.23.1" nullthrows "^1.1.1" -metro-cache-key@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.76.9.tgz#6f17f821d6f306fa9028b7e79445eb18387d03d9" - integrity sha512-ugJuYBLngHVh1t2Jj+uP9pSCQl7enzVXkuh6+N3l0FETfqjgOaSHlcnIhMPn6yueGsjmkiIfxQU4fyFVXRtSTw== +metro-cache-key@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.12.tgz#52f5de698b85866503ace45d0ad76f75aaec92a4" + integrity sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA== + dependencies: + flow-enums-runtime "^0.0.6" -metro-cache@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.76.9.tgz#64326d7a8b470c3886a5e97d5e2a20acab20bc5f" - integrity sha512-W6QFEU5AJG1gH4Ltv8S2IvhmEhSDYnbPafyj5fGR3YLysdykj+olKv9B0V+YQXtcLGyY5CqpXLYUx595GdiKzA== +metro-cache@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.12.tgz#bd81af02c4f17b5aeab19bb030566b14147cee8b" + integrity sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA== dependencies: - metro-core "0.76.9" - rimraf "^3.0.2" + exponential-backoff "^3.1.1" + flow-enums-runtime "^0.0.6" + metro-core "0.80.12" -metro-config@0.76.9, metro-config@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.76.9.tgz#5e60aff9d8894c1ee6bbc5de23b7c8515a0b84a3" - integrity sha512-oYyJ16PY3rprsfoi80L+gDJhFJqsKI3Pob5LKQbJpvL+gGr8qfZe1eQzYp5Xxxk9DOHKBV1xD94NB8GdT/DA8Q== +metro-config@0.80.12, metro-config@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.12.tgz#1543009f37f7ad26352ffc493fc6305d38bdf1c0" + integrity sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ== dependencies: connect "^3.6.5" cosmiconfig "^5.0.5" - jest-validate "^29.2.1" - metro "0.76.9" - metro-cache "0.76.9" - metro-core "0.76.9" - metro-runtime "0.76.9" - -metro-core@0.76.9, metro-core@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.76.9.tgz#5f55f0fbde41d28957e4f3bb187d32251403f00e" - integrity sha512-DSeEr43Wrd5Q7ySfRzYzDwfV89g2OZTQDf1s3exOcLjE5fb7awoLOkA2h46ZzN8NcmbbM0cuJy6hOwF073/yRQ== - dependencies: + flow-enums-runtime "^0.0.6" + jest-validate "^29.6.3" + metro "0.80.12" + metro-cache "0.80.12" + metro-core "0.80.12" + metro-runtime "0.80.12" + +metro-core@0.80.12, metro-core@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.12.tgz#5ae337923ab19ff524077efa1aeacdf4480cfa28" + integrity sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw== + dependencies: + flow-enums-runtime "^0.0.6" lodash.throttle "^4.1.1" - metro-resolver "0.76.9" + metro-resolver "0.80.12" -metro-file-map@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.76.9.tgz#dd3d76ec23fc0ba8cb7b3a3b8075bb09e0b5d378" - integrity sha512-7vJd8kksMDTO/0fbf3081bTrlw8SLiploeDf+vkkf0OwlrtDUWPOikfebp+MpZB2S61kamKjCNRfRkgrbPfSwg== +metro-file-map@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.12.tgz#b03240166a68aa16c5a168c26e190d9da547eefb" + integrity sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw== dependencies: anymatch "^3.0.3" debug "^2.2.0" fb-watchman "^2.0.0" + flow-enums-runtime "^0.0.6" graceful-fs "^4.2.4" invariant "^2.2.4" - jest-regex-util "^27.0.6" - jest-util "^27.2.0" - jest-worker "^27.2.0" + jest-worker "^29.6.3" micromatch "^4.0.4" node-abort-controller "^3.1.1" nullthrows "^1.1.1" @@ -3942,160 +2455,92 @@ metro-file-map@0.76.9: optionalDependencies: fsevents "^2.3.2" -metro-inspector-proxy@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.76.9.tgz#0d333e64a7bc9d156d712265faa7b7ae88c775e8" - integrity sha512-idIiPkb8CYshc0WZmbzwmr4B1QwsQUbpDwBzHwxE1ni27FWKWhV9CD5p+qlXZHgfwJuMRfPN+tIaLSR8+vttYg== - dependencies: - connect "^3.6.5" - debug "^2.2.0" - node-fetch "^2.2.0" - ws "^7.5.1" - yargs "^17.6.2" - -metro-minify-terser@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.76.9.tgz#3f6271da74dd57179852118443b62cc8dc578aab" - integrity sha512-ju2nUXTKvh96vHPoGZH/INhSvRRKM14CbGAJXQ98+g8K5z1v3luYJ/7+dFQB202eVzJdTB2QMtBjI1jUUpooCg== +metro-minify-terser@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz#9951030e3bc52d7f3ac8664ce5862401c673e3c6" + integrity sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ== dependencies: + flow-enums-runtime "^0.0.6" terser "^5.15.0" -metro-minify-uglify@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.76.9.tgz#e88c30c27911c053e1ee20e12077f0f4cbb154f8" - integrity sha512-MXRrM3lFo62FPISlPfTqC6n9HTEI3RJjDU5SvpE7sJFfJKLx02xXQEltsL/wzvEqK+DhRQ5DEYACTwf5W4Z3yA== - dependencies: - uglify-es "^3.1.9" - -metro-react-native-babel-preset@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.9.tgz#15868142122af14313429d7572c15cf01c16f077" - integrity sha512-eCBtW/UkJPDr6HlMgFEGF+964DZsUEF9RGeJdZLKWE7d/0nY3ABZ9ZAGxzu9efQ35EWRox5bDMXUGaOwUe5ikQ== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.4.0" - -metro-react-native-babel-transformer@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.76.9.tgz#464aab85669ed39f7a59f1fd993a05de9543b09e" - integrity sha512-xXzHcfngSIkbQj+U7i/anFkNL0q2QVarYSzr34CFkzKLa79Rp16B8ki7z9eVVqo9W3B4TBcTXl3BipgRoOoZSQ== +metro-resolver@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.12.tgz#e3815914c21315b04db200032c3243a4cc22dfb6" + integrity sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw== dependencies: - "@babel/core" "^7.20.0" - babel-preset-fbjs "^3.4.0" - hermes-parser "0.12.0" - metro-react-native-babel-preset "0.76.9" - nullthrows "^1.1.1" - -metro-resolver@0.76.9, metro-resolver@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.76.9.tgz#79c244784b16ca56076bc1fc816d2ba74860e882" - integrity sha512-s86ipNRas9vNR5lChzzSheF7HoaQEmzxBLzwFA6/2YcGmUCowcoyPAfs1yPh4cjMw9F1T4KlMLaiwniGE7HCyw== + flow-enums-runtime "^0.0.6" -metro-runtime@0.76.9, metro-runtime@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.76.9.tgz#f8ebe150f8896ce1aef5d7f3a52844f8b4f721fb" - integrity sha512-/5vezDpGUtA0Fv6cJg0+i6wB+QeBbvLeaw9cTSG7L76liP0b91f8vOcYzGaUbHI8pznJCCTerxRzpQ8e3/NcDw== +metro-runtime@0.80.12, metro-runtime@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.12.tgz#a68af3a2a013f5372d3b8cee234fdd467455550b" + integrity sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw== dependencies: - "@babel/runtime" "^7.0.0" - react-refresh "^0.4.0" + "@babel/runtime" "^7.25.0" + flow-enums-runtime "^0.0.6" -metro-source-map@0.76.9, metro-source-map@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.76.9.tgz#0f976ada836717f307427d3830aea52a2ca7ed5f" - integrity sha512-q5qsMlu8EFvsT46wUUh+ao+efDsicT30zmaPATNhq+PcTawDbDgnMuUD+FT0bvxxnisU2PWl91RdzKfNc2qPQA== +metro-source-map@0.80.12, metro-source-map@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.12.tgz#36a2768c880f8c459d6d758e2d0975e36479f49c" + integrity sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw== dependencies: "@babel/traverse" "^7.20.0" "@babel/types" "^7.20.0" + flow-enums-runtime "^0.0.6" invariant "^2.2.4" - metro-symbolicate "0.76.9" + metro-symbolicate "0.80.12" nullthrows "^1.1.1" - ob1 "0.76.9" + ob1 "0.80.12" source-map "^0.5.6" vlq "^1.0.0" -metro-symbolicate@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.76.9.tgz#f1627ef6f73bb0c4d48c55684d3c87866a0b0920" - integrity sha512-Yyq6Ukj/IeWnGST09kRt0sBK8TwzGZWoU7YAcQlh14+AREH454Olx4wbFTpkkhUkV05CzNCvUuXQ0efFxhA1bw== +metro-symbolicate@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz#3a6aa783c6e494e2879342d88d5379fab69d1ed2" + integrity sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw== dependencies: + flow-enums-runtime "^0.0.6" invariant "^2.2.4" - metro-source-map "0.76.9" + metro-source-map "0.80.12" nullthrows "^1.1.1" source-map "^0.5.6" through2 "^2.0.1" vlq "^1.0.0" -metro-transform-plugins@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.76.9.tgz#73e34f2014d3df3c336a882b13e541bceb826d37" - integrity sha512-YEQeNlOCt92I7S9A3xbrfaDfwfgcxz9PpD/1eeop3c4cO3z3Q3otYuxw0WJ/rUIW8pZfOm5XCehd+1NRbWlAaw== +metro-transform-plugins@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz#4a3853630ad0f36cc2bffd53bae659ee171a389c" + integrity sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA== dependencies: "@babel/core" "^7.20.0" "@babel/generator" "^7.20.0" "@babel/template" "^7.0.0" "@babel/traverse" "^7.20.0" + flow-enums-runtime "^0.0.6" nullthrows "^1.1.1" -metro-transform-worker@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.76.9.tgz#281fad223f0447e1ff9cc44d6f7e33dfab9ab120" - integrity sha512-F69A0q0qFdJmP2Clqr6TpTSn4WTV9p5A28h5t9o+mB22ryXBZfUQ6BFBBW/6Wp2k/UtPH+oOsBfV9guiqm3d2Q== +metro-transform-worker@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz#80be8a185b7deb93402b682f58a1dd6724317ad1" + integrity sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA== dependencies: "@babel/core" "^7.20.0" "@babel/generator" "^7.20.0" "@babel/parser" "^7.20.0" "@babel/types" "^7.20.0" - babel-preset-fbjs "^3.4.0" - metro "0.76.9" - metro-babel-transformer "0.76.9" - metro-cache "0.76.9" - metro-cache-key "0.76.9" - metro-minify-terser "0.76.9" - metro-source-map "0.76.9" - metro-transform-plugins "0.76.9" + flow-enums-runtime "^0.0.6" + metro "0.80.12" + metro-babel-transformer "0.80.12" + metro-cache "0.80.12" + metro-cache-key "0.80.12" + metro-minify-terser "0.80.12" + metro-source-map "0.80.12" + metro-transform-plugins "0.80.12" nullthrows "^1.1.1" -metro@0.76.9, metro@^0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.76.9.tgz#605fddf1a54d27762ddba2f636420ae2408862df" - integrity sha512-gcjcfs0l5qIPg0lc5P7pj0x7vPJ97tan+OnEjiYLbKjR1D7Oa78CE93YUPyymUPH6q7VzlzMm1UjT35waEkZUw== +metro@0.80.12, metro@^0.80.3: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.12.tgz#29a61fb83581a71e50c4d8d5d8458270edfe34cc" + integrity sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA== dependencies: "@babel/code-frame" "^7.0.0" "@babel/core" "^7.20.0" @@ -4105,59 +2550,59 @@ metro@0.76.9, metro@^0.76.9: "@babel/traverse" "^7.20.0" "@babel/types" "^7.20.0" accepts "^1.3.7" - async "^3.2.2" chalk "^4.0.0" ci-info "^2.0.0" connect "^3.6.5" debug "^2.2.0" denodeify "^1.2.1" error-stack-parser "^2.0.6" + flow-enums-runtime "^0.0.6" graceful-fs "^4.2.4" - hermes-parser "0.12.0" + hermes-parser "0.23.1" image-size "^1.0.2" invariant "^2.2.4" - jest-worker "^27.2.0" + jest-worker "^29.6.3" jsc-safe-url "^0.2.2" lodash.throttle "^4.1.1" - metro-babel-transformer "0.76.9" - metro-cache "0.76.9" - metro-cache-key "0.76.9" - metro-config "0.76.9" - metro-core "0.76.9" - metro-file-map "0.76.9" - metro-inspector-proxy "0.76.9" - metro-minify-uglify "0.76.9" - metro-react-native-babel-preset "0.76.9" - metro-resolver "0.76.9" - metro-runtime "0.76.9" - metro-source-map "0.76.9" - metro-symbolicate "0.76.9" - metro-transform-plugins "0.76.9" - metro-transform-worker "0.76.9" + metro-babel-transformer "0.80.12" + metro-cache "0.80.12" + metro-cache-key "0.80.12" + metro-config "0.80.12" + metro-core "0.80.12" + metro-file-map "0.80.12" + metro-resolver "0.80.12" + metro-runtime "0.80.12" + metro-source-map "0.80.12" + metro-symbolicate "0.80.12" + metro-transform-plugins "0.80.12" + metro-transform-worker "0.80.12" mime-types "^2.1.27" - node-fetch "^2.2.0" nullthrows "^1.1.1" - rimraf "^3.0.2" serialize-error "^2.1.0" source-map "^0.5.6" strip-ansi "^6.0.0" throat "^5.0.0" - ws "^7.5.1" + ws "^7.5.10" yargs "^17.6.2" micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + mime-types@^2.1.27, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -4180,7 +2625,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.0.2, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -4188,9 +2633,9 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1: brace-expansion "^1.1.7" minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mkdirp@^0.5.1: version "0.5.6" @@ -4199,31 +2644,31 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.6" +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.3: +ms@2.1.3, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@~0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + neo-async@^2.5.0: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -4242,32 +2687,27 @@ node-abort-controller@^3.1.1: node-dir@^0.1.17: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU= + integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== dependencies: minimatch "^3.0.2" node-fetch@^2.2.0, node-fetch@^2.6.0: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-releases@^2.0.19: version "2.0.19" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== -node-releases@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" - integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== - node-stream-zip@^1.9.1: version "1.15.0" resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" @@ -4290,30 +2730,17 @@ nullthrows@^1.1.1: resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== -ob1@0.76.9: - version "0.76.9" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.76.9.tgz#a493e4b83a0fb39200de639804b5d06eed5599dc" - integrity sha512-g0I/OLnSxf6OrN3QjSew3bTDJCdbZoWxnh8adh1z36alwCuGF1dgDeRA25bTYSakrG5WULSaWJPOdgnf1O/oQw== +ob1@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.12.tgz#0451944ba6e5be225cc9751d8cd0d7309d2d1537" + integrity sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw== + dependencies: + flow-enums-runtime "^0.0.6" object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== on-finished@2.4.1: version "2.4.1" @@ -4325,7 +2752,7 @@ on-finished@2.4.1: on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" @@ -4348,9 +2775,6 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -"onnxruntime-common@file:../common": - version "1.22.0" - open@^6.2.0: version "6.4.0" resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" @@ -4358,6 +2782,14 @@ open@^6.2.0: dependencies: is-wsl "^1.1.0" +open@^7.0.3: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + ora@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" @@ -4380,7 +2812,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -4416,21 +2848,11 @@ p-try@^2.0.0: parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -4439,7 +2861,7 @@ parseurl@~1.3.3: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -4461,12 +2883,7 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picocolors@^1.1.1: +picocolors@^1.0.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -4481,10 +2898,10 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pirates@^4.0.4, pirates@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" - integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== +pirates@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== pkg-dir@^3.0.0: version "3.0.0" @@ -4493,30 +2910,15 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -plist@^3.0.5: - version "3.0.6" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.6.tgz#7cfb68a856a7834bca6dbfe3218eb9c7740145d3" - integrity sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA== - dependencies: - base64-js "^1.5.1" - xmlbuilder "^15.1.1" - pod-install@^0.1.36: - version "0.1.36" - resolved "https://registry.yarnpkg.com/pod-install/-/pod-install-0.1.36.tgz#8090f57f76b42acf24c4325711bfa5730613fcab" - integrity sha512-r+f2SAqtM4K81Wv4OAhedbfCtBZhPz+1c1CVkQ1vT33PGAhM5A6GpaJ0pfQVgfZ0tUwagWxlDQ3eOprNyIFO6w== + version "0.1.39" + resolved "https://registry.yarnpkg.com/pod-install/-/pod-install-0.1.39.tgz#853a0585bafbd332c2ca6543854fd4919958cfb3" + integrity sha512-0kVvdLYe0CtfJEr+ISvTMxAEB0UF4JMRToPjuu9xAAq1mEqA2Ql5u7uLWX1m45BMM+7NfU4LnBbnfNjmQE9GCw== -prettier@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== +prettier@^2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-format@^26.5.2, pretty-format@^26.6.2: version "26.6.2" @@ -4528,7 +2930,7 @@ pretty-format@^26.5.2, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" -pretty-format@^29.0.0, pretty-format@^29.7.0: +pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -4549,7 +2951,7 @@ promise@^8.3.0: dependencies: asap "~2.0.6" -prompts@^2.0.1, prompts@^2.4.0: +prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -4566,11 +2968,6 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -pure-rand@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" - integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== - queue@6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" @@ -4583,7 +2980,7 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -react-devtools-core@^4.27.2: +react-devtools-core@^4.27.7: version "4.28.5" resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508" integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA== @@ -4591,10 +2988,10 @@ react-devtools-core@^4.27.2: shell-quote "^1.6.1" ws "^7" -"react-is@^16.12.0 || ^17.0.0 || ^18.0.0": - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== react-is@^16.13.1: version "16.13.1" @@ -4606,58 +3003,54 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-is@^18.0.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== - -react-native@^0.72.17: - version "0.72.17" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.17.tgz#54d6de38adf6e56fdde1a6b83ef9b138abae7384" - integrity sha512-k3dNe0XqoYCGGWTenbupWSj+ljW3GIfmYS5P4s3if4j0csx2YbenKgH1aJNWLp+UP7ONwfId6G+uBoUJfyMxXg== - dependencies: - "@jest/create-cache-key-function" "^29.2.1" - "@react-native-community/cli" "^11.4.1" - "@react-native-community/cli-platform-android" "^11.4.1" - "@react-native-community/cli-platform-ios" "^11.4.1" - "@react-native/assets-registry" "^0.72.0" - "@react-native/codegen" "^0.72.8" - "@react-native/gradle-plugin" "^0.72.11" - "@react-native/js-polyfills" "^0.72.1" - "@react-native/normalize-colors" "^0.72.0" - "@react-native/virtualized-lists" "^0.72.8" +react-native@^0.73.11: + version "0.73.11" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.11.tgz#4661532efd146e1eab2abb69c252218795837ce5" + integrity sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg== + dependencies: + "@jest/create-cache-key-function" "^29.6.3" + "@react-native-community/cli" "12.3.7" + "@react-native-community/cli-platform-android" "12.3.7" + "@react-native-community/cli-platform-ios" "12.3.7" + "@react-native/assets-registry" "0.73.1" + "@react-native/codegen" "0.73.3" + "@react-native/community-cli-plugin" "0.73.18" + "@react-native/gradle-plugin" "0.73.5" + "@react-native/js-polyfills" "0.73.1" + "@react-native/normalize-colors" "0.73.2" + "@react-native/virtualized-lists" "0.73.4" abort-controller "^3.0.0" anser "^1.4.9" ansi-regex "^5.0.0" - base64-js "^1.1.2" - deprecated-react-native-prop-types "^4.2.3" + base64-js "^1.5.1" + chalk "^4.0.0" + deprecated-react-native-prop-types "^5.0.0" event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.5" + flow-enums-runtime "^0.0.6" invariant "^2.2.4" - jest-environment-node "^29.2.1" + jest-environment-node "^29.6.3" jsc-android "^250231.0.0" memoize-one "^5.0.0" - metro-runtime "^0.76.9" - metro-source-map "^0.76.9" + metro-runtime "^0.80.3" + metro-source-map "^0.80.3" mkdirp "^0.5.1" nullthrows "^1.1.1" pretty-format "^26.5.2" promise "^8.3.0" - react-devtools-core "^4.27.2" - react-refresh "^0.4.0" + react-devtools-core "^4.27.7" + react-refresh "^0.14.0" react-shallow-renderer "^16.15.0" regenerator-runtime "^0.13.2" scheduler "0.24.0-canary-efb381bbf-20230505" stacktrace-parser "^0.1.10" - use-sync-external-store "^1.0.0" whatwg-fetch "^3.0.0" ws "^6.2.2" yargs "^17.6.2" -react-refresh@^0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" - integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== +react-refresh@^0.14.0: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== react-shallow-renderer@^16.15.0: version "16.15.0" @@ -4675,18 +3068,18 @@ react@^18.2.0: loose-envify "^1.1.0" readable-stream@^3.4.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -4699,7 +3092,7 @@ readable-stream@~2.3.6: readline@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" - integrity sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw= + integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== recast@^0.21.0: version "0.21.5" @@ -4711,10 +3104,10 @@ recast@^0.21.0: source-map "~0.6.1" tslib "^2.0.1" -regenerate-unicode-properties@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" - integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== +regenerate-unicode-properties@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" + integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== dependencies: regenerate "^1.4.2" @@ -4723,85 +3116,61 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.2: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regexpu-core@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.1.0.tgz#2f8504c3fd0ebe11215783a41541e21c79942c6d" - integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA== +regexpu-core@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" + integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== dependencies: regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" + regenerate-unicode-properties "^10.2.0" + regjsgen "^0.8.0" + regjsparser "^0.12.0" unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" -regjsgen@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" - integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== +regjsgen@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" + integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== -regjsparser@^0.8.2: - version "0.8.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" - integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== +regjsparser@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" + integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== dependencies: - jsesc "~0.5.0" + jsesc "~3.0.2" require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== -resolve.exports@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" - integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== - -resolve@^1.14.2, resolve@^1.20.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== +resolve@^1.14.2: + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.16.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -4827,20 +3196,15 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== scheduler@0.24.0-canary-efb381bbf-20230505: version "0.24.0-canary-efb381bbf-20230505" @@ -4849,37 +3213,25 @@ scheduler@0.24.0-canary-efb381bbf-20230505: dependencies: loose-envify "^1.1.0" -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: +semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.2, semver@^7.5.4: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@^7.5.3: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" +semver@^7.5.2: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -4898,22 +3250,22 @@ send@0.18.0: serialize-error@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" - integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= + integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== serve-static@^1.13.1: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== setprototypeof@1.2.0: version "1.2.0" @@ -4940,24 +3292,15 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1, shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + version "1.8.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" + integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== -signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -simple-plist@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017" - integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw== - dependencies: - bplist-creator "0.1.0" - bplist-parser "0.3.1" - plist "^3.0.5" - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -4977,14 +3320,6 @@ slice-ansi@^2.0.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@^0.5.16, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -4996,34 +3331,34 @@ source-map-support@^0.5.16, source-map-support@~0.5.20: source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" -stackframe@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.1.tgz#1033a3473ee67f08e2f2fc8eba6aef4f845124e1" - integrity sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg== +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== stacktrace-parser@^0.1.10: version "0.1.10" @@ -5040,20 +3375,7 @@ statuses@2.0.1: statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stream-buffers@2.2.x: - version "2.2.0" - resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" - integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg== - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" @@ -5092,21 +3414,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - strnum@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" @@ -5117,13 +3429,6 @@ sudo-prompt@^9.0.0: resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -5143,6 +3448,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + temp@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" @@ -5151,24 +3461,15 @@ temp@^0.8.4: rimraf "~2.6.2" terser@^5.15.0: - version "5.37.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.37.0.tgz#38aa66d1cfc43d0638fab54e43ff8a4f72a21ba3" - integrity sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA== + version "5.39.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.39.0.tgz#0e82033ed57b3ddf1f96708d123cca717d86ca3a" + integrity sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -5187,11 +3488,6 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -5207,40 +3503,32 @@ toidentifier@1.0.1: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tslib@^2.0.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - type-fest@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== -uglify-es@^3.1.9: - version "3.3.9" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" - integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== - dependencies: - commander "~2.13.0" - source-map "~0.6.1" +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" + integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" @@ -5250,15 +3538,15 @@ unicode-match-property-ecmascript@^2.0.0: unicode-canonical-property-names-ecmascript "^2.0.0" unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== +unicode-match-property-value-ecmascript@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" + integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== universalify@^0.1.0: version "0.1.2" @@ -5268,7 +3556,7 @@ universalify@^0.1.0: unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== update-browserslist-db@^1.1.1: version "1.1.2" @@ -5278,46 +3566,27 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.1" -use-sync-external-store@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" - integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== - -v8-to-istanbul@^9.0.1: - version "9.3.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" - integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vlq@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== -walker@^1.0.7, walker@^1.0.8: +walker@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== @@ -5327,32 +3596,32 @@ walker@^1.0.7, walker@^1.0.8: wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== dependencies: defaults "^1.0.3" webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-fetch@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + version "3.6.20" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== which@^2.0.1: version "2.0.2" @@ -5393,14 +3662,6 @@ write-file-atomic@^2.3.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - ws@^6.2.2: version "6.2.3" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" @@ -5408,41 +3669,10 @@ ws@^6.2.2: dependencies: async-limiter "~1.0.0" -ws@^7, ws@^7.5.1: - version "7.5.7" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== - -xcode@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c" - integrity sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA== - dependencies: - simple-plist "^1.1.0" - uuid "^7.0.3" - -xml2js@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282" - integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c" - integrity sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg== - -xmlbuilder@^15.1.1: - version "15.1.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" - integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +ws@^7, ws@^7.5.1, ws@^7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== xtend@~4.0.1: version "4.0.2" @@ -5464,11 +3694,6 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yaml@^2.2.1: version "2.7.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" @@ -5504,7 +3729,7 @@ yargs@^15.1.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.3.1, yargs@^17.6.2: +yargs@^17.6.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From d5742708600051d2b170c78d27f25c5269e6223e Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 26 Feb 2025 17:46:31 -0500 Subject: [PATCH 011/266] Make Nuget CUDA package pipeline 1ES compliant (#23804) ### Description Make [Nuget CUDA 12 Publish Pipeline](https://dev.azure.com/aiinfra/Lotus/_build?definitionId=1312&_a=summary) 1ES compliant ### Motivation and Context --- .../nuget-cuda-publishing-pipeline.yml | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/nuget-cuda-publishing-pipeline.yml b/tools/ci_build/github/azure-pipelines/nuget-cuda-publishing-pipeline.yml index aeb250e1e0cbc..df4e328f49eaf 100644 --- a/tools/ci_build/github/azure-pipelines/nuget-cuda-publishing-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/nuget-cuda-publishing-pipeline.yml @@ -2,30 +2,44 @@ resources: pipelines: - pipeline: build source: 'CUDA-Zip-Nuget-Java-Packaging-Pipeline' - trigger: + trigger: branches: include: - main - rel-* branch: main + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release parameters: - - name: isReleaseBuild - type: boolean - default: false +- name: isReleaseBuild + type: boolean + default: false variables: - - name: ArtifactFeed - ${{ if eq(parameters.isReleaseBuild, false) }}: - value: ORT-Nightly - ${{ else }}: - value: onnxruntime-cuda-12 +- name: ArtifactFeed + ${{ if eq(parameters.isReleaseBuild, false) }}: + value: ORT-Nightly + ${{ else }}: + value: onnxruntime-cuda-12 +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: + - template: stages/nuget-cuda-publishing-stage.yml + parameters: + artifact_feed: $(ArtifactFeed) -stages: - - template: stages/nuget-cuda-publishing-stage.yml - parameters: - artifact_feed: $(ArtifactFeed) - - - template: stages/java-cuda-publishing-stage.yml - parameters: - artifact_feed: $(ArtifactFeed) \ No newline at end of file + - template: stages/java-cuda-publishing-stage.yml + parameters: + artifact_feed: $(ArtifactFeed) \ No newline at end of file From 7a3810d31e6130d1766731fb136fc06d597fe1a3 Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Wed, 26 Feb 2025 16:11:07 -0800 Subject: [PATCH 012/266] [ARM CPU] Fix flaky hgemmb ut (#23814) ### Description Original UT use random seed. Change to fixed seed. ### Motivation and Context Fix flaky UT. --- onnxruntime/test/mlas/unittest/test_hgemm_neon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/test/mlas/unittest/test_hgemm_neon.cpp b/onnxruntime/test/mlas/unittest/test_hgemm_neon.cpp index 6cb005d577fa3..d1622a14c8e33 100644 --- a/onnxruntime/test/mlas/unittest/test_hgemm_neon.cpp +++ b/onnxruntime/test/mlas/unittest/test_hgemm_neon.cpp @@ -388,7 +388,7 @@ class MlasNeonHGemmBTest : public MlasTestBase { public: MlasNeonHGemmBTest() - : seed_(rd_()), gen_(seed_), distrib_(-1.f, 1.f) { + : seed_(172387), gen_(seed_), distrib_(-1.f, 1.f) { } static const char* GetTestSuiteName() { From 000f2c9f17a638c39a3b5f6c1dd7928cc8380ec4 Mon Sep 17 00:00:00 2001 From: Yifan Li <109183385+yf711@users.noreply.github.com> Date: Wed, 26 Feb 2025 17:25:44 -0800 Subject: [PATCH 013/266] [TensorRT EP] update oss parser to latest (#23710) ### Description * Update oss parser version to latest commit of 10.8-GA branch ### Motivation and Context * Action needed to adapt latest onnx-tensorrt 10.8-GA branch to fix scatterND attribute issue and `plugin.h` not found issue --- cmake/deps.txt | 2 +- .../azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/deps.txt b/cmake/deps.txt index d2e0fd63215f4..d0bab93d3c16f 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -37,7 +37,7 @@ mimalloc;https://github.com/microsoft/mimalloc/archive/refs/tags/v2.1.1.zip;d5ee mp11;https://github.com/boostorg/mp11/archive/refs/tags/boost-1.82.0.zip;9bc9e01dffb64d9e0773b2e44d2f22c51aace063 onnx;https://github.com/onnx/onnx/archive/refs/tags/v1.17.0.zip;13a60ac5217c104139ce0fd024f48628e7bcf5bc # Use the latest commit of 10.8-GA -onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/118ed0aea197fa9a7d3ea66180a1d5ddb9deecc3.zip;b78aed3728ad4daf6dc47ea10c1d243dee1d95b1 +onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/c5ca8912f30e9ad630a0ef565e3d5f4bd5e91563.zip;588b294aaa9e84679ed5815cea1d399210ac98c2 protobuf;https://github.com/protocolbuffers/protobuf/archive/refs/tags/v21.12.zip;7cf2733949036c7d52fda017badcab093fe73bfa protoc_win64;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win64.zip;b4521f7ada5b260380f94c4bd7f1b7684c76969a protoc_win32;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win32.zip;3688010318192c46ce73213cdfb6b3e5656da874 diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml index 4417ebce60989..c44d3cff09e96 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml @@ -83,7 +83,7 @@ jobs: - name: parser ${{ if eq(parameters.UseTensorrtOssParser, true) }}: - value: --use_tensorrt_oss_parser $(parameters.UseTensorrtOssParser) }} + value: --use_tensorrt_oss_parser $(parameters.UseTensorrtOssParser) steps: - ${{ if and(eq(parameters.TrtVersion, 'BIN'), eq(parameters.UseTensorrtOssParser, false)) }}: From c6664e20522b16b39ba5d4d97ad9f2083f1a7ca8 Mon Sep 17 00:00:00 2001 From: Jianhui Dai Date: Thu, 27 Feb 2025 10:03:24 +0800 Subject: [PATCH 014/266] [webgpu] Fix alignment issues in shader code (#23776) ### Description This commit fixes alignment issues in shader code. ### Motivation and Context See above. --- onnxruntime/core/providers/webgpu/shader_helper.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/shader_helper.cc b/onnxruntime/core/providers/webgpu/shader_helper.cc index 305bbd2bd20b0..8fccbacac903b 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.cc +++ b/onnxruntime/core/providers/webgpu/shader_helper.cc @@ -65,8 +65,8 @@ Status ShaderHelper::Init() { " @builtin(local_invocation_id) local_id : vec3"; if (device_.HasFeature(wgpu::FeatureName::Subgroups)) { body_ss_ << ",\n" - " @builtin(subgroup_invocation_id) sg_id : u32,\n" - " @builtin(subgroup_size) sg_size : u32"; + " @builtin(subgroup_invocation_id) sg_id : u32,\n" + " @builtin(subgroup_size) sg_size : u32"; } if (!is_1d_dispatch) { body_ss_ << ",\n" From 6df0973e58ba5399fcaa98686f70ed9a9e59aaef Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 26 Feb 2025 23:27:43 -0800 Subject: [PATCH 015/266] upgrade emsdk to 4.0.4 (#23819) ### Description Upgrade EMSDK to 4.0.4 ### Motivation and Context Emscripten v4.0.4 brings 2 useful changes that are helpful for webgpu: - https://github.com/emscripten-core/emscripten/pull/23678 - https://github.com/emscripten-core/emscripten/pull/23631 --- .gitmodules | 2 +- cmake/external/emsdk | 2 +- tools/ci_build/build.py | 2 +- .../github/azure-pipelines/templates/linux-wasm-ci.yml | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules index 356447cbf7a98..7656fc429d005 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,4 +7,4 @@ [submodule "cmake/external/emsdk"] path = cmake/external/emsdk url = https://github.com/emscripten-core/emsdk.git - branch = 4.0.3 + branch = 4.0.4 diff --git a/cmake/external/emsdk b/cmake/external/emsdk index 127ce42cd5f0a..074211759c17c 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit 127ce42cd5f0aabe2d9b5d636041ccef7c66d165 +Subproject commit 074211759c17c646164d3271ca1d155cc174f78e diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index ecdffbe5fd6a0..d172961a70bc7 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -503,7 +503,7 @@ def convert_arg_line_to_args(self, arg_line): # WebAssembly build parser.add_argument("--build_wasm", action="store_true", help="Build for WebAssembly") parser.add_argument("--build_wasm_static_lib", action="store_true", help="Build for WebAssembly static library") - parser.add_argument("--emsdk_version", default="4.0.3", help="Specify version of emsdk") + parser.add_argument("--emsdk_version", default="4.0.4", help="Specify version of emsdk") parser.add_argument("--enable_wasm_simd", action="store_true", help="Enable WebAssembly SIMD") parser.add_argument("--enable_wasm_threads", action="store_true", help="Enable WebAssembly multi-threads support") diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index 02dd5faec0fe8..dffcea9500393 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -88,15 +88,15 @@ jobs: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 4.0.3 ccache-git-emscripten-64bit - ./emsdk activate 4.0.3 ccache-git-emscripten-64bit + ./emsdk install 4.0.4 ccache-git-emscripten-64bit + ./emsdk activate 4.0.4 ccache-git-emscripten-64bit displayName: 'emsdk install and activate ccache for emscripten' - ${{if eq(parameters.WithCache, false)}}: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 4.0.3 - ./emsdk activate 4.0.3 + ./emsdk install 4.0.4 + ./emsdk activate 4.0.4 displayName: 'emsdk install and activate ccache for emscripten' - template: build-linux-wasm-step.yml From 17f3947553655265b76f39674d90ed41d284c74f Mon Sep 17 00:00:00 2001 From: Ankit Maheshkar Date: Thu, 27 Feb 2025 21:11:06 +0530 Subject: [PATCH 016/266] [OVEP] Update support for Contrib Ops (#23789) ### Description This PR enables Contrib Ops support in OVEP namely below - DynamicQuantizeMatMul, FusedMatMul, QuickGelu, SkipSimplifiedLayerNormalization Co-authored-by: n1harika --- onnxruntime/core/providers/openvino/ov_versions/data_ops.cc | 4 ++++ onnxruntime/test/contrib_ops/dynamic_quantize_matmul_test.cc | 2 +- onnxruntime/test/contrib_ops/embed_layer_norm_op_test.cc | 4 ---- onnxruntime/test/contrib_ops/fused_matmul_op_test.cc | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index 548fe6b156329..f7326642a5544 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -121,6 +121,7 @@ std::vector supported_op_mode = { {"DepthToSpace", V_2020_4, {"CPU", "GPU"}}, {"DequantizeLinear", V_2021_4, {"CPU", "GPU"}}, {"DequantizeLinear", V_2024_4, {"NPU"}}, + {"DynamicQuantizeMatMul", V_2025_0, {"CPU", "GPU"}}, {"Div", V_2020_4, {"CPU", "GPU"}}, {"Dropout", V_2020_4, {"CPU", "GPU"}}, {"Elu", V_2020_4, {"CPU", "GPU"}}, @@ -136,6 +137,7 @@ std::vector supported_op_mode = { {"Floor", V_2020_4, {"CPU", "GPU"}}, {"FusedConv", V_2023_0, {"CPU", "GPU"}}, {"FusedGemm", V_2023_0, {"CPU", "GPU"}}, + {"FusedMatMul", V_2025_0, {"CPU", "GPU"}}, {"Gather", V_2020_4, {"CPU", "GPU"}}, {"GatherElements", V_2022_2, {"CPU", "GPU"}}, {"GatherND", V_2021_4, {"CPU", "GPU"}}, @@ -190,6 +192,7 @@ std::vector supported_op_mode = { {"PRelu", V_2020_4, {"CPU", "GPU"}}, {"QLinearMatMul", V_2022_3, {"CPU"}}, {"QuantizeLinear", V_2021_4, {"CPU", "GPU"}}, + {"QuickGelu", V_2025_0, {"CPU", "GPU"}}, {"RNN", V_2023_1, {"CPU", "GPU"}}, {"RandomNormalLike", V_2023_0, {"CPU", "GPU"}}, {"RandomNormalLike", V_2023_0, {"CPU", "GPU"}}, @@ -229,6 +232,7 @@ std::vector supported_op_mode = { {"Sinh", V_2020_4, {"CPU"}}, {"Size", V_2022_1, {"CPU", "GPU"}}, {"SkipLayerNormalization", V_2024_5, {"CPU", "GPU"}}, + {"SkipSimplifiedLayerNormalization", V_2025_0, {"CPU", "GPU"}}, {"Slice", V_2020_4, {"CPU", "GPU"}}, {"Softmax", V_2020_4, {"CPU", "GPU"}}, {"Softplus", V_2022_1, {"CPU", "GPU"}}, diff --git a/onnxruntime/test/contrib_ops/dynamic_quantize_matmul_test.cc b/onnxruntime/test/contrib_ops/dynamic_quantize_matmul_test.cc index 0b64ea3de8ded..c9a7116bf8052 100644 --- a/onnxruntime/test/contrib_ops/dynamic_quantize_matmul_test.cc +++ b/onnxruntime/test/contrib_ops/dynamic_quantize_matmul_test.cc @@ -141,7 +141,7 @@ void TestDynamicQuantizeMatMul(bool is_matrix_b_constant, per_column, has_zp, has_bias); test.AddOutput("Y", Y_dims, Y_data); test.SetOutputRelErr("Y", 0.02f); - test.Run(); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); } template diff --git a/onnxruntime/test/contrib_ops/embed_layer_norm_op_test.cc b/onnxruntime/test/contrib_ops/embed_layer_norm_op_test.cc index 043717a9f6e92..9ecbb04ebccca 100644 --- a/onnxruntime/test/contrib_ops/embed_layer_norm_op_test.cc +++ b/onnxruntime/test/contrib_ops/embed_layer_norm_op_test.cc @@ -158,11 +158,7 @@ static void RunTest(const embedlayernorm::OpData& data, execution_providers.push_back(DefaultDmlExecutionProvider()); tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); } else { -#if defined(USE_OPENVINO) tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); -#else - tester.Run(); -#endif } } } diff --git a/onnxruntime/test/contrib_ops/fused_matmul_op_test.cc b/onnxruntime/test/contrib_ops/fused_matmul_op_test.cc index db5ce1742e37c..b1762d16795d1 100644 --- a/onnxruntime/test/contrib_ops/fused_matmul_op_test.cc +++ b/onnxruntime/test/contrib_ops/fused_matmul_op_test.cc @@ -212,8 +212,8 @@ void RunFusedMatMulTest(const char* op_name, int32_t opset_version = 7, bool tra test.AddOutput("Y", t.expected_dims, t.expected_vals); - // Disable TensorRT because of unsupported data type - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + // Disable OpenVINO, TensorRT because of unsupported data type + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kOpenVINOExecutionProvider}); } } From b1f2a3f5f3a8ab2c8115b5321586205ed9f28e36 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Feb 2025 07:43:39 -0800 Subject: [PATCH 017/266] Update onnxruntime_external_deps.cmake: add missing EXCLUDE_FROM_ALL (#23829) ### Description To resolve #23821 ### Motivation and Context Similar to #23641 . --- cmake/external/onnxruntime_external_deps.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index 1b1e11c9772f9..ebf20ab21bbd2 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -301,6 +301,7 @@ if(NOT TARGET Boost::mp11) onnxruntime_fetchcontent_declare( mp11 URL ${DEP_URL_mp11} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES Boost ) onnxruntime_fetchcontent_makeavailable(mp11) From 5ab953cb8c4b63019540601b7c7f1ca531808bb8 Mon Sep 17 00:00:00 2001 From: Jambay Kinley Date: Thu, 27 Feb 2025 09:30:55 -0800 Subject: [PATCH 018/266] Quant tool: Add `nodes_to_exclude` in `get_qnn_qdq_config` (#23779) --- .../quantization/execution_providers/qnn/quant_config.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py b/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py index 9384bab13f3cc..ea995d4707ba3 100644 --- a/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py +++ b/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py @@ -55,6 +55,7 @@ def get_qnn_qdq_config( stride: int | None = None, calibration_providers: list[str] | None = None, op_types_to_quantize: list[str] | None = None, + nodes_to_exclude: list[str] | None = None, ) -> StaticQuantConfig: """ Returns a static quantization configuration suitable for running QDQ models on QNN EP. @@ -122,6 +123,8 @@ def get_qnn_qdq_config( calibration_providers: Execution providers to run the session during calibration. Default is None which uses [ "CPUExecutionProvider" ]. op_types_to_quantize: If set to None, all operator types will be quantized except for OP_TYPES_TO_EXCLUDE + nodes_to_exclude: List of nodes names to exclude from quantization. The nodes in this list will be excluded from + quantization when it is not None. Returns: A StaticQuantConfig object @@ -167,10 +170,13 @@ def get_qnn_qdq_config( ) op_types_to_quantize_set = set(op_types_to_quantize) if op_types_to_quantize else None + nodes_to_exclude_set = set(nodes_to_exclude) if nodes_to_exclude else None for node in model.graph.node: if op_types_to_quantize_set and node.op_type not in op_types_to_quantize_set: continue + if nodes_to_exclude_set and node.name in nodes_to_exclude_set: + continue op_types.add(node.op_type) qnn_compat.process_node(node) @@ -201,6 +207,7 @@ def get_qnn_qdq_config( op_types_to_quantize=op_types_to_quantize if op_types_to_quantize else list(op_types.difference(OP_TYPES_TO_EXCLUDE)), + nodes_to_exclude=nodes_to_exclude, per_channel=per_channel, use_external_data_format=(model_has_external_data or model.ByteSize() >= MODEL_SIZE_THRESHOLD), calibration_providers=calibration_providers, From 05642657161ddc320de0c18ae6c753e5e1c29d80 Mon Sep 17 00:00:00 2001 From: Karim Vadsariya Date: Thu, 27 Feb 2025 09:39:27 -0800 Subject: [PATCH 019/266] [ORT/CI_Pipeline] Use --enable_generic_interface in ORT builds for EP testing (#23801) Summary of changes: - Changed openVINO test case to use --enable_generic_interface - changed tensorRT test case to use --enable_generic_interface - Fixed ORT builds to USE_FULL_PROTOBUF as openVINO/TensorRT requires them - Fixed pre-processor macro definition which accidently got removed when ORT is build w/o EP ### Description ### Motivation and Context Co-authored-by: Karim Vadsariya --- cmake/CMakeLists.txt | 5 +++++ tools/ci_build/build.py | 2 +- .../github/azure-pipelines/linux-openvino-ci-pipeline.yml | 2 +- .../github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2714e6f59dbac..0b32d51884c05 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1512,6 +1512,11 @@ if (onnxruntime_USE_OPENVINO) endif() +if (onnxruntime_USE_OPENVINO_INTERFACE AND (NOT onnxruntime_USE_OPENVINO)) + add_definitions(-DUSE_OPENVINO=1) + add_definitions(-DOPENVINO_CONFIG_NPU=1) +endif() + if (onnxruntime_USE_VITISAI) set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}") endif() diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index d172961a70bc7..8607887072347 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -1502,7 +1502,7 @@ def generate_build_tree( ] # VitisAI and OpenVINO providers currently only support full_protobuf option. - if args.use_full_protobuf or args.use_openvino or args.use_vitisai or args.gen_doc: + if args.use_full_protobuf or args.use_openvino or args.use_vitisai or args.gen_doc or args.enable_generic_interface: cmake_args += ["-Donnxruntime_USE_FULL_PROTOBUF=ON", "-DProtobuf_USE_STATIC_LIBS=ON"] if args.use_cuda and not is_windows(): diff --git a/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml index c7b814f3dd52c..e89fa0ece2c76 100644 --- a/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml @@ -33,5 +33,5 @@ jobs: parameters: AgentPool : 'Linux-CPU-2019' JobName: 'Linux_CI_Dev' - RunDockerBuildArgs: '-o ubuntu22.04 -p 3.10 -d openvino -v 2024.5.0 -x "--use_openvino CPU --build_wheel"' + RunDockerBuildArgs: '-o ubuntu22.04 -p 3.10 -d openvino -v 2024.5.0 -x "--enable_generic_interface --use_openvino CPU --build_wheel"' TimeoutInMinutes: 120 diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml index 3d3e53b680d45..5c6d9dd6ed955 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml @@ -92,7 +92,7 @@ jobs: del wheel_filename_file python.exe -m pip install -q --upgrade %WHEEL_FILENAME% set PATH=$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo;%PATH% - python $(Build.SourcesDirectory)\tools\ci_build\build.py --config RelWithDebInfo --use_binskim_compliant_compile_flags --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --test --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\${{ variables.win_trt_folder }}" --cuda_home="$(Agent.TempDirectory)\v${{ parameters.CudaVersion }}" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + python $(Build.SourcesDirectory)\tools\ci_build\build.py --config RelWithDebInfo --use_binskim_compliant_compile_flags --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --enable_generic_interface --build_shared_lib --test --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\${{ variables.win_trt_folder }}" --cuda_home="$(Agent.TempDirectory)\v${{ parameters.CudaVersion }}" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' displayName: 'Run tests' From a189bfca4e76a199ee1d7f4f7b1cb8623d1189cf Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 27 Feb 2025 14:20:38 -0500 Subject: [PATCH 020/266] Increase npm package pipeline ReactNative_CI_iOS timeout to 120 mins (#23825) ### Description Increase [npm package pipeline](https://aiinfra.visualstudio.com/Lotus/_build?definitionId=1080&_a=summary) ReactNative_CI_iOS timeout to 120 mins ### Motivation and Context --- .../github/azure-pipelines/templates/react-native-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index 3f4581f63217e..7991916a47ca4 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -67,7 +67,7 @@ stages: image: 'macOS-13' os: 'macOS' - timeoutInMinutes: 90 + timeoutInMinutes: 120 variables: runCodesignValidationInjection: false From c61a4b115ea63b49660cf49bf9eec095fedd2040 Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Thu, 27 Feb 2025 13:24:06 -0800 Subject: [PATCH 021/266] [Mlas] Unblock hardcoded matmul blocking size (#23815) ### Description In GemmBatch, target matrix is cut into blocks to dispatch to multiple threads for intra-op parallelism. Currently the block size hard-coded to 16. If the CPU has > 16 cores, cores are not fully utilized in one op. This change unblocks the number of blocks in various MatMul. __Benchmark results__ Model: llmlingua-2-bert-base-multilingual-cased-meetingbank--add-force-token-100--max-seq-len-512-CPU-INT8.onnx set up: 96 core x86 linux Before: Setting intra_op_num_threads to 64 Overriding dimension with name, batch_size, to 3 Session creation time cost: 0.485097 s First inference time cost: 356 ms Total inference time cost: 17.731 s Total inference requests: 50 __Average inference time cost: 354.619 ms__ Total inference run time: 17.7312 s Number of inferences per second: 2.81989 Avg CPU usage: 65 % Peak working set size: 542265344 bytes Avg CPU usage:65 Peak working set size:542265344 After: Setting intra_op_num_threads to 32 Overriding dimension with name, batch_size, to 3 Session creation time cost: 0.523394 s First inference time cost: 316 ms Total inference time cost: 12.2739 s Total inference requests: 50 __Average inference time cost: 245.478 ms__ Total inference run time: 12.2741 s Number of inferences per second: 4.07362 Avg CPU usage: 33 % Peak working set size: 611241984 bytes Avg CPU usage:33 Peak working set size:611241984 Setting intra_op_num_threads to 64 Overriding dimension with name, batch_size, to 3 Session creation time cost: 0.497698 s First inference time cost: 289 ms Total inference time cost: 9.49205 s Total inference requests: 50 __Average inference time cost: 189.841 ms__ Total inference run time: 9.49226 s Number of inferences per second: 5.26745 Avg CPU usage: 65 % Peak working set size: 548470784 bytes Avg CPU usage:65 Peak working set size:548470784 Runs:50 ### Motivation and Context This issue is reported by M365 research team. --- onnxruntime/core/mlas/lib/halfgemm.cpp | 10 ++-------- onnxruntime/core/mlas/lib/qgemm.cpp | 13 +++---------- onnxruntime/core/mlas/lib/sgemm.cpp | 9 +-------- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/onnxruntime/core/mlas/lib/halfgemm.cpp b/onnxruntime/core/mlas/lib/halfgemm.cpp index 879eca8097176..66a335665d024 100644 --- a/onnxruntime/core/mlas/lib/halfgemm.cpp +++ b/onnxruntime/core/mlas/lib/halfgemm.cpp @@ -522,15 +522,9 @@ MlasGemmBatch( } const double Complexity = double(M) * double(N) * double(K) * double(BatchSize); - ptrdiff_t TargetThreadCount; - - if (Complexity < double(MLAS_HGEMM_THREAD_COMPLEXITY) * GetMlasPlatform().MaximumThreadCount) { - TargetThreadCount = ptrdiff_t(Complexity / double(MLAS_HGEMM_THREAD_COMPLEXITY)) + 1; - } else { - TargetThreadCount = GetMlasPlatform().MaximumThreadCount; - } - + ptrdiff_t TargetThreadCount = ptrdiff_t(Complexity / double(MLAS_HGEMM_THREAD_COMPLEXITY)) + 1; ptrdiff_t MaximumThreadCount = MlasGetMaximumThreadCount(ThreadPool); + if (TargetThreadCount >= MaximumThreadCount) { TargetThreadCount = MaximumThreadCount; } diff --git a/onnxruntime/core/mlas/lib/qgemm.cpp b/onnxruntime/core/mlas/lib/qgemm.cpp index 859fcd049ac7d..f5b33d2a9ad34 100644 --- a/onnxruntime/core/mlas/lib/qgemm.cpp +++ b/onnxruntime/core/mlas/lib/qgemm.cpp @@ -144,14 +144,7 @@ MlasGemmBatch( const double Complexity = double(M) * double(N) * double(K) * double(BatchN); - ptrdiff_t TargetThreadCount; - - if (Complexity < double(MLAS_QGEMM_THREAD_COMPLEXITY * GetMlasPlatform().MaximumThreadCount)) { - TargetThreadCount = ptrdiff_t(Complexity / double(MLAS_QGEMM_THREAD_COMPLEXITY)) + 1; - } else { - TargetThreadCount = GetMlasPlatform().MaximumThreadCount; - } - + ptrdiff_t TargetThreadCount = ptrdiff_t(Complexity / double(MLAS_QGEMM_THREAD_COMPLEXITY)) + 1; ptrdiff_t MaximumThreadCount = MlasGetMaximumThreadCount(ThreadPool); if (TargetThreadCount >= MaximumThreadCount) { @@ -308,7 +301,7 @@ size_t MLASCALL MlasGemmPackBSize( size_t N, - size_t K, + size_t K, bool AIsSigned, bool BIsSigned ) @@ -479,7 +472,7 @@ size_t MLASCALL MlasSymmQgemmPackBSize( size_t N, - size_t K, + size_t K, bool AIsSigned ) { diff --git a/onnxruntime/core/mlas/lib/sgemm.cpp b/onnxruntime/core/mlas/lib/sgemm.cpp index f8b25fb42caf3..616622a8c1f53 100644 --- a/onnxruntime/core/mlas/lib/sgemm.cpp +++ b/onnxruntime/core/mlas/lib/sgemm.cpp @@ -1580,14 +1580,7 @@ MlasGemmBatch( const double Complexity = double(M) * double(N) * double(K); - ptrdiff_t TargetThreadCount; - - if (Complexity < double(MLAS_SGEMM_THREAD_COMPLEXITY * GetMlasPlatform().MaximumThreadCount)) { - TargetThreadCount = ptrdiff_t(Complexity / double(MLAS_SGEMM_THREAD_COMPLEXITY)) + 1; - } else { - TargetThreadCount = GetMlasPlatform().MaximumThreadCount; - } - + ptrdiff_t TargetThreadCount = ptrdiff_t(Complexity / double(MLAS_SGEMM_THREAD_COMPLEXITY)) + 1; ptrdiff_t MaximumThreadCount = MlasGetMaximumThreadCount(ThreadPool); if (TargetThreadCount >= MaximumThreadCount) { From 2a4cfab46a8e9159f35b2418ab401937dd8b6502 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 27 Feb 2025 18:05:26 -0500 Subject: [PATCH 022/266] Revert changes onn mac-react-native-ci-pipeline.yml (#23845) ### Description ### Motivation and Context --- .../mac-react-native-ci-pipeline.yml | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml index 9d63fe9cc118d..e72f088cfeb55 100644 --- a/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml @@ -27,12 +27,6 @@ pr: - 'js/web' - 'onnxruntime/core/providers/js' #### end trigger #### -resources: - repositories: - - repository: 1esPipelines - type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release parameters: - name: NpmPublish @@ -56,20 +50,10 @@ variables: ${{ if eq(parameters.NpmPublish, 'custom') }}: NpmPackagingMode: '$(VersionSuffix)' -extends: - # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. - # For non-production pipelines, use "Unofficial" as defined below. - # For productions pipelines, use "Official". - template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines +stages: +- template: templates/react-native-ci.yml parameters: - sdl: - sourceAnalysisPool: - name: onnxruntime-Win-CPU-2022 - os: windows - stages: - - template: templates/react-native-ci.yml - parameters: - NpmPackagingMode: ${{ variables.NpmPackagingMode }} - BuildConfig: 'Release' - PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' - enable_code_sign: false + NpmPackagingMode: ${{ variables.NpmPackagingMode }} + BuildConfig: 'Release' + PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' + enable_code_sign: false From 1be64f883190f058256948c8d254c61d1a724008 Mon Sep 17 00:00:00 2001 From: Sushanth Rajasankar <44513542+sushraja-msft@users.noreply.github.com> Date: Fri, 28 Feb 2025 08:02:04 -0800 Subject: [PATCH 023/266] Fix flash attention for GQA (Phi4) (#23850) ### Description This change fixes GQA for Flash Attention on Nvidia GPUs. The root cause appears to be `k_start + capped_sg_id < seq_causal_length` check. This is either because, a. seq_causal_length varies per lane, so the check becomes non uniform control flow, which is having interactions with subgroupShuffle. or b. The check itself is incorrect and is wiping out values of v based on the source lane's seq_causal_length. While in actualness values of v need to be causal as per the lane that is going to multiply it with qkt. qkt is already causal because earlier values of qk for out of bounds k are set to min_value, and exp(<-4) are 0. This fix works by removing that causal check and relying on the qk being wiped out earlier. The documentation for causality behavior for GQA is missing to determine which of this reason is the true reason. Prior to this prompts with sequence length > 16 < 32 or 1k would break with Phi 4 but smaller prompts would work. Tested on Intel Alderlake, Nvidia 4070. --- onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 57ae8a7e5ba74..c1b025b10e067 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -379,7 +379,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { if (sg_size > 8) { for (var i:u32 = 0; i < qkv_head_size_vec; i++) { - var val = select(vec4(0), v_tile[capped_sg_id][i], k_start + capped_sg_id < seq_causal_length); + var val = v_tile[capped_sg_id][i]; var sum = subgroupShuffle(val, 0) * qk_1[0]; sum += subgroupShuffle(val, 1) * qk_1[1]; sum += subgroupShuffle(val, 2) * qk_1[2]; From 1088a1edfecc377958175dfdde8df425c43b9571 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Sat, 1 Mar 2025 09:09:13 +1000 Subject: [PATCH 024/266] Model Builder API (#23223) ### Description Supports creating a model programmatically using the ORT C or C++ API. Supports augmenting an existing model to add nodes. ### Motivation and Context --- cmake/onnxruntime_session.cmake | 1 + cmake/onnxruntime_unittests.cmake | 6 + include/onnxruntime/core/graph/graph.h | 32 +- include/onnxruntime/core/graph/graph_viewer.h | 6 + .../core/session/onnxruntime_c_api.h | 491 +++++++++++- .../core/session/onnxruntime_cxx_api.h | 258 ++++++- .../core/session/onnxruntime_cxx_inline.h | 350 ++++++++- .../core/framework/onnxruntime_typeinfo.cc | 71 +- .../core/framework/onnxruntime_typeinfo.h | 2 +- .../core/framework/session_state_utils.cc | 30 +- .../core/framework/tensor_type_and_shape.cc | 35 +- .../core/framework/tensorprotoutils.cc | 13 +- onnxruntime/core/graph/graph.cc | 295 +++++++- .../core/graph/graph_flatbuffers_utils.cc | 14 +- onnxruntime/core/graph/model.cc | 32 +- onnxruntime/core/graph/model.h | 8 +- .../core/graph/model_editor_api_types.h | 47 ++ .../core/session/abi_session_options.cc | 17 +- onnxruntime/core/session/api_utils.cc | 25 - onnxruntime/core/session/api_utils.h | 9 - onnxruntime/core/session/custom_ops.cc | 2 +- onnxruntime/core/session/inference_session.cc | 57 +- onnxruntime/core/session/inference_session.h | 35 +- onnxruntime/core/session/model_editor_api.h | 65 ++ .../core/session/model_editor_c_api.cc | 358 +++++++++ onnxruntime/core/session/onnxruntime_c_api.cc | 328 ++++---- onnxruntime/core/session/ort_apis.h | 16 + onnxruntime/core/session/utils.cc | 125 ++++ onnxruntime/core/session/utils.h | 28 + onnxruntime/test/framework/type_info_test.cc | 26 +- onnxruntime/test/shared_lib/custom_op_utils.h | 6 - onnxruntime/test/shared_lib/test_inference.cc | 162 ++-- .../test/shared_lib/test_model_builder_api.cc | 701 ++++++++++++++++++ .../test/shared_lib/test_ort_format_models.cc | 14 +- onnxruntime/test/shared_lib/utils.h | 52 ++ winml/adapter/winml_adapter_model.cpp | 18 +- 36 files changed, 3286 insertions(+), 449 deletions(-) create mode 100644 onnxruntime/core/graph/model_editor_api_types.h delete mode 100644 onnxruntime/core/session/api_utils.cc delete mode 100644 onnxruntime/core/session/api_utils.h create mode 100644 onnxruntime/core/session/model_editor_api.h create mode 100644 onnxruntime/core/session/model_editor_c_api.cc create mode 100644 onnxruntime/core/session/utils.cc create mode 100644 onnxruntime/core/session/utils.h create mode 100644 onnxruntime/test/shared_lib/test_model_builder_api.cc diff --git a/cmake/onnxruntime_session.cmake b/cmake/onnxruntime_session.cmake index 3d63285d50e72..2c2c59091fae5 100644 --- a/cmake/onnxruntime_session.cmake +++ b/cmake/onnxruntime_session.cmake @@ -22,6 +22,7 @@ endif() if (onnxruntime_MINIMAL_BUILD) set(onnxruntime_session_src_exclude "${ONNXRUNTIME_ROOT}/core/session/provider_bridge_ort.cc" + "${ONNXRUNTIME_ROOT}/core/session/model_builder_c_api.cc" ) list(REMOVE_ITEM onnxruntime_session_srcs ${onnxruntime_session_src_exclude}) diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index 0916aeb3dd92c..cb5a28f82de66 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -503,6 +503,7 @@ set (onnxruntime_shared_lib_test_SRC if (NOT onnxruntime_MINIMAL_BUILD) list(APPEND onnxruntime_shared_lib_test_SRC ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_inference.cc) + list(APPEND onnxruntime_shared_lib_test_SRC ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_model_builder_api.cc) endif() if(onnxruntime_RUN_ONNX_TESTS) @@ -1359,14 +1360,19 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) LIBS ${onnxruntime_shared_lib_test_LIBS} DEPENDS ${all_dependencies} ) + + target_include_directories(onnxruntime_shared_lib_test PRIVATE ${ONNXRUNTIME_ROOT}) + if (onnxruntime_USE_CUDA) target_include_directories(onnxruntime_shared_lib_test PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) target_sources(onnxruntime_shared_lib_test PRIVATE ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/cuda_ops.cu) endif() + if (onnxruntime_USE_ROCM) target_include_directories(onnxruntime_shared_lib_test PRIVATE ${onnxruntime_ROCM_HOME}/include) target_compile_definitions(onnxruntime_shared_lib_test PRIVATE __HIP_PLATFORM_AMD__) endif() + if (CMAKE_SYSTEM_NAME STREQUAL "Android") target_sources(onnxruntime_shared_lib_test PRIVATE "${ONNXRUNTIME_ROOT}/core/platform/android/cxa_demangle.cc" diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 7798394b045dc..35b568e3f8e28 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -27,6 +27,7 @@ #include "core/common/span_utils.h" #include "core/common/status.h" #include "core/common/logging/logging.h" +#include "core/framework/ort_value.h" #include "core/framework/prepacked_weights_container.h" #include "core/graph/onnx_protobuf.h" #include "core/graph/basic_types.h" @@ -39,6 +40,9 @@ #include "core/graph/node_arg.h" #include "core/graph/ort_format_load_options.h" +// Type from Model Editor API in ORT C API so can't be in a namespace +struct OrtGraph; + namespace onnxruntime { class Graph; struct IndexedSubGraph; @@ -763,6 +767,10 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi */ bool GetInitializedTensor(const std::string& tensor_name, const ONNX_NAMESPACE::TensorProto*& value) const; + /** Populate `value` if an externally allocated OrtValue exists for an initializer with the given name. + */ + bool GetOrtValueInitializer(const std::string& name, OrtValue& value) const; + /** Gets all the initializer tensors in this Graph. */ const InitializedTensorSet& GetAllInitializedTensors() const noexcept { return name_to_initial_tensor_; } @@ -1430,6 +1438,16 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi const OrtFormatLoadOptions& load_options, const logging::Logger& logger, std::unique_ptr& graph); + static Status LoadFromModelEditorApiModel(const OrtGraph& api_graph, + const Model& owning_model, + const std::unordered_map& domain_to_version, + IOnnxRuntimeOpSchemaCollectionPtr schema_registry, + bool strict_shape_type_inference, + const logging::Logger& logger, + std::unique_ptr& graph); + + Status UpdateUsingModelEditorApiModel(const OrtModel& api_model); + #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) const RuntimeOptimizationRecordContainer& RuntimeOptimizations() const { return runtime_optimizations_; @@ -1630,7 +1648,8 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // Implementation for initializer replacement Status ReplaceInitializedTensorImpl(ONNX_NAMESPACE::TensorProto new_initializer, bool is_external); - std::vector CreateNodeArgs(const google::protobuf::RepeatedPtrField& names, + template // range-initializer returning std::string + std::vector CreateNodeArgs(const StringRange& names, const ArgNameToTypeMap& name_to_type_map); void ToGraphProtoInternal(ONNX_NAMESPACE::GraphProto& graph_proto) const; @@ -1694,6 +1713,8 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi return nodes_[node_index].get(); } + Status LoadFromModelEditorApiModel(const OrtGraph& api_graph, bool updating_existing_graph = false); + const Model& owning_model_; // GraphProto to store name, version, initializer. @@ -1708,6 +1729,12 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi InitializedTensorSet name_to_initial_tensor_; + // Initializers that are external to the Graph. + // e.g. created from existing memory using CreateTensorWithDataAndDeleterAsOrtValue in the ORT API. + // As we need to convert to TensorProto for the optimizers to work and keep the deleter information we store them + // in the Graph instance and retrieve during session state finalization. + std::unordered_map ortvalue_initializers_; + std::unordered_set, std::hash, std::equal_to> sparse_tensor_names_; @@ -1744,6 +1771,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // in some case, a fused sub-graph will happens multiple times in one model, we use a map // to store reusable-schema in lookup. InlinedHashMap> reusable_fused_schema_map_; + #endif // !defined(ORT_MINIMAL_BUILD) // Graph nodes. @@ -1806,7 +1834,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi std::unordered_map> node_arg_to_consumer_nodes_; #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) - const std::unordered_map domain_to_version_; + std::unordered_map domain_to_version_; // Model IR version. Version ir_version_{ONNX_NAMESPACE::Version::IR_VERSION}; diff --git a/include/onnxruntime/core/graph/graph_viewer.h b/include/onnxruntime/core/graph/graph_viewer.h index 9385e2f092e58..6a664d8be9c05 100644 --- a/include/onnxruntime/core/graph/graph_viewer.h +++ b/include/onnxruntime/core/graph/graph_viewer.h @@ -193,6 +193,12 @@ class GraphViewer { IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const { return graph_->GetSchemaRegistry(); } #endif + /** Populate `value` if an externally allocated OrtValue exists for an initializer with the given name. + */ + bool GetOrtValueInitializer(const std::string& name, OrtValue& value) const { + return graph_->GetOrtValueInitializer(name, value); + } + private: ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(GraphViewer); GraphViewer(const Graph& graph, const IndexedSubGraph* filter_info); diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 47e6389492f30..098de14bdfd61 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -305,6 +305,10 @@ ORT_RUNTIME_CLASS(OpAttr); ORT_RUNTIME_CLASS(Logger); ORT_RUNTIME_CLASS(ShapeInferContext); ORT_RUNTIME_CLASS(LoraAdapter); +ORT_RUNTIME_CLASS(ValueInfo); +ORT_RUNTIME_CLASS(Node); +ORT_RUNTIME_CLASS(Graph); +ORT_RUNTIME_CLASS(Model); #ifdef _WIN32 typedef _Return_type_success_(return == 0) OrtStatus* OrtStatusPtr; @@ -665,6 +669,9 @@ typedef struct OrtApi OrtApi; struct OrtTrainingApi; typedef struct OrtTrainingApi OrtTrainingApi; +struct OrtModelEditorApi; +typedef struct OrtModelEditorApi OrtModelEditorApi; + /** \brief The helper interface to get the right version of OrtApi * * Get a pointer to this structure through ::OrtGetApiBase @@ -847,7 +854,8 @@ struct OrtApi { * * \snippet{doc} snippets.dox OrtStatus Return Value */ - ORT_API2_STATUS(CreateSessionFromArray, _In_ const OrtEnv* env, _In_ const void* model_data, size_t model_data_length, + ORT_API2_STATUS(CreateSessionFromArray, _In_ const OrtEnv* env, + _In_ const void* model_data, size_t model_data_length, _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out); /** \brief Run the model in an ::OrtSession @@ -1340,6 +1348,8 @@ struct OrtApi { * Create a tensor with user's buffer. You can fill the buffer either before calling this function or after. * p_data is owned by caller. ReleaseValue won't release p_data. * + * If you wish to transfer ownership of p_data to ORT use CreateTensorWithDataAndDeleterAsOrtValue. + * * \param[in] info Memory description of where the p_data buffer resides (CPU vs GPU etc). * \param[in] p_data Pointer to the data buffer. * \param[in] p_data_len The number of bytes in the data buffer. @@ -1997,7 +2007,8 @@ struct OrtApi { /** \brief Get the value type from an ::OrtMapTypeInfo * * \param[in] map_type_info - * \param[out] type_info + * \param[out] type_info A copy of the OrtTypeInfo for the map value type. + * The user must free this value with ReleaseTypeInfo. * * \snippet{doc} snippets.dox OrtStatus Return Value */ @@ -2012,7 +2023,8 @@ struct OrtApi { * This is used by WinML to support model reflection APIs. * * \param[in] sequence_type_info - * \param[out] type_info + * \param[out] type_info A copy of the OrtTypeInfo for the sequence element type. + * The user must free this value with ReleaseTypeInfo. * * \snippet{doc} snippets.dox OrtStatus Return Value */ @@ -2887,7 +2899,8 @@ struct OrtApi { * \snippet{doc} snippets.dox OrtStatus Return Value */ ORT_API2_STATUS(CreateSessionWithPrepackedWeightsContainer, _In_ const OrtEnv* env, _In_ const ORTCHAR_T* model_path, - _In_ const OrtSessionOptions* options, _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, + _In_ const OrtSessionOptions* options, + _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, _Outptr_ OrtSession** out); /** \brief Create session from memory with prepacked weights container @@ -2910,7 +2923,8 @@ struct OrtApi { */ ORT_API2_STATUS(CreateSessionFromArrayWithPrepackedWeightsContainer, _In_ const OrtEnv* env, _In_ const void* model_data, size_t model_data_length, - _In_ const OrtSessionOptions* options, _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, + _In_ const OrtSessionOptions* options, + _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, _Outptr_ OrtSession** out); /// @} @@ -4293,8 +4307,8 @@ struct OrtApi { * specific type that is described by the returned ::OrtTypeInfo. * * \param[in] optional_type_info - * \param[out] out A pointer to the ::OrtTypeInfo for what the optional value could be. - * it is owned by OrtOptionalTypeInfo instance. + * \param[out] out A copy of ::OrtTypeInfo for what the optional value could be. + * The user must free this value with ReleaseTypeInfo. * * \snippet{doc} snippets.dox OrtStatus Return Value * @@ -4786,6 +4800,75 @@ struct OrtApi { */ ORT_API2_STATUS(SetEpDynamicOptions, _Inout_ OrtSession* sess, _In_reads_(kv_len) const char* const* keys, _In_reads_(kv_len) const char* const* values, _In_ size_t kv_len); + + /** \brief Release an OrtValueInfo instance if it was not added to an OrtGraph. + * \since Version 1.21. + */ + ORT_CLASS_RELEASE(ValueInfo); + + /** \brief Release an OrtNode if it was not added to an OrtGraph. + * \since Version 1.21. + */ + ORT_CLASS_RELEASE(Node); + + /** \brief Release an OrtGraph. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.21. + */ + ORT_CLASS_RELEASE(Graph); + + /** \brief Release an OrtModel. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.21. + */ + ORT_CLASS_RELEASE(Model); + + /** \brief Get the value name from an OrtValueInfo instance. + * \param[in] value_info The OrtValueInfo instance. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.21. + */ + ORT_API2_STATUS(GetValueInfoName, _In_ const OrtValueInfo* value_info, _Out_ const char** name); + + /** \brief Get the type information from an OrtValueInfo instance. + * \param[in] value_info The OrtValueInfo instance. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.21. + */ + ORT_API2_STATUS(GetValueInfoTypeInfo, _In_ const OrtValueInfo* value_info, _Outptr_ const OrtTypeInfo** type_info); + + /** \brief Get the Model Editor API instance + * + * Get the Model Editor API instance to create a new model or augment an existing model. + * + * \return Model Editor API struct + * + * \since Version 1.21. + */ + const OrtModelEditorApi*(ORT_API_CALL* GetModelEditorApi)(); + + /** \brief Create an OrtValue for a Tensor that uses pre-existing memory. + * + * ORT will take ownership of the memory and free it using the provided deleter when no longer in use. + * + * \param[in] deleter OrtAllocator instance that will be used to free the memory. + * Only the OrtAllocator:Info and OrtAllocator::Release functions are required. + * The OrtMemoryInfo returned by OrtAllocator::Info must match the location of p_data. + * \param[in] p_data Pointer to the memory that will be used by the Tensor. ORT will take ownership of the memory. + * \param[in] p_data_len Length of the memory in bytes. + * \param[in] shape Dimensions of the Tensor. All values should be > 0. + * \param[in] shape_len Number of dimensions in the shape array. + * \param[in] type Data type of the Tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateTensorWithDataAndDeleterAsOrtValue, _In_ OrtAllocator* deleter, + _In_ void* p_data, size_t p_data_len, + _In_ const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type, + _Outptr_ OrtValue** out); }; /* @@ -4900,6 +4983,400 @@ struct OrtCustomOp { void(ORT_API_CALL* ReleaseAliasMap)(_Frees_ptr_opt_ int* input_index, _Frees_ptr_opt_ int* output_index); }; +/** + * ORT Model Editor API + */ + +/** + * \brief The OrtModelEditorApi struct provides functions to create or edit an ONNX model. + * + * See onnxruntime/test/shared_lib/test_model_editor_api.cc for example usage. + * + * \since Version 1.21. + */ +struct OrtModelEditorApi { + // Model building/editing requires a full build. We return nullptr from GetModelEditorApi if this is a minimal + // build, so it doesn't matter if there are no function pointers in this struct as a user will never get an + // OrtModelEditorApi instance. We do however need a dummy field to avoid empty struct warning. +#if defined(ORT_MINIMAL_BUILD) + const bool not_defined_in_this_build; +#else + /** \brief Create an OrtTypeInfo instance for a Tensor. + * + * Create an OrtTypeInfo instance for a Tensor to use as graph inputs/outputs with the Model Editor API. + * + * User can release `tensor_info` after creating the OrtTypeInfo. + * + * \param[in] tensor_info Tensor type and shape information. + * \param[out] TypeInfo instance for the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for a SparseTensor. + * + * Create an OrtTypeInfo instance for a SparseTensor to use as graph inputs/outputs with the Model Editor API. + * + * User can release `tensor_info` after creating the OrtTypeInfo. + * + * \param[in] tensor_info SparseTensor type and shape information. + * \param[out] TypeInfo instance for the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateSparseTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for a Map. + * + * Create an OrtTypeInfo instance for a Map to use as graph inputs/outputs with the Model Editor API. + * + * User can release `map_value_type` after creating the OrtTypeInfo. + * + * \param[in] map_key_type Key type for the map. + * \param[in] map_value_type Value type for the map. + * \param[out] TypeInfo instance for the map. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateMapTypeInfo, ONNXTensorElementDataType map_key_type, _In_ const OrtTypeInfo* map_value_type, + _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for a Sequence. + * + * Create an OrtTypeInfo instance for a Sequence to use as graph inputs/outputs with the Model Editor API. + * + * User can release `sequence_type` after creating the OrtTypeInfo. + * + * \param[in] sequence_type Sequence type and shape information. + * \param[out] TypeInfo instance for the sequence. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateSequenceTypeInfo, _In_ const OrtTypeInfo* sequence_type, _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for an Optional. + * + * Create an OrtTypeInfo instance for an Optional to use as graph inputs/outputs with the Model Editor API. + * + * User can release `contained_type` after creating the OrtTypeInfo. + * + * \param[in] tensor_info Tensor type and shape information. + * \param[out] TypeInfo instance for the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateOptionalTypeInfo, _In_ const OrtTypeInfo* contained_type, _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtValueInfo for use as an OrtGraph input or output. + * + * \param[in] name The name of the input or output. + * \param[in] type_info The type information for the input or output. The provided value is copied. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateValueInfo, _In_ const char* name, _In_ const OrtTypeInfo* type_info, + _Outptr_ OrtValueInfo** value_info); + + /** \brief Create an OrtNode to add to an OrtGraph. + * + * Create an OrtNode. + * + * Create attributes with CreateOpAttr. OrtOpAttr instances are copied. + * + * \param[in] operator_name The name of the operator. + * \param[in] domain_name The domain of the operator. Use an empty string for ONNX operators. + * \param[in] node_name The name of the node. + * \param[in] input_names The names of the inputs. + * \param[in] input_names_len The number of input names. + * \param[in] output_names The names of the outputs. + * \param[in] output_names_len The number of output names. + * \param[in] attributes The optional attributes of the node. + * \param[in] attribs_len The number of attributes. May be zero. + * \param[out] node The OrtNode instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateNode, _In_ const char* operator_name, _In_ const char* domain_name, _In_ const char* node_name, + _In_reads_(input_names_len) const char* const* input_names, size_t input_names_len, + _In_reads_(output_names_len) const char* const* output_names, size_t output_names_len, + _In_reads_(attribs_len) _In_opt_ OrtOpAttr** attributes, _In_ size_t attribs_len, + _Outptr_ OrtNode** node); + + /** \brief Create an OrtGraph + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateGraph, _Outptr_ OrtGraph** graph); + + /** \brief Set the inputs for the OrtGraph. + * + * Set the graph inputs. This will replace any existing inputs with the new values. + * The OrtGraph takes ownership of the OrtValueInfo instances and you should NOT call ReleaseOrtValueInfo. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] inputs The input OrtValueInfo instances. + * \param[in] inputs_len The number of input OrtValueInfo instances. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(SetGraphInputs, _Inout_ OrtGraph* graph, + _In_reads_(inputs_len) _In_ OrtValueInfo** inputs, _In_ size_t inputs_len); + + /** \brief Set the outputs for the OrtGraph. + * + * Set the graph outputs. This will replace any existing outputs with the new values. + * The OrtGraph takes ownership of the OrtValueInfo instances provided and you should NOT call ReleaseOrtValueInfo. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] outputs The output OrtValueInfo instances. + * \param[in] outputs_len The number of output OrtValueInfo instances. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(SetGraphOutputs, _Inout_ OrtGraph* graph, + _In_reads_(outputs_len) _In_ OrtValueInfo** outputs, _In_ size_t outputs_len); + + /** \brief Add an initializer to the OrtGraph + * + * ORT will take ownership of the OrtValue and you should NOT call ReleaseOrtValue. + * + * Two options: + * + * Allocated memory: + * Use CreateTensorAsOrtValue (allocates memory) and populate the tensor with the data. + * Set `data_is_external` to false. + * + * Pre-existing memory: + * Use CreateTensorWithDataAsOrtValue or CreateTensorWithDataAndDeleterAsOrtValue to create an OrtValue + * with a tensor that contains a pointer to the existing data. + * Set `data_is_external` to true. + * + * The pointer must remain valid for the duration of the inference session. + * If using CreateTensorWithDataAsOrtValue you are responsible for freeing the memory after the inference session + * is released. + * If using CreateTensorWithDataAndDeleterAsOrtValue, ORT will free the memory using the provided deleter as + * soon as the OrtValue is no longer in use. + * + * NOTE: A tensor containing pre-existing memory MUST have 128 bytes of data or more. + * For smaller tensors use CreateTensorAsOrtValue. + * + * ONNX shape inferencing does not support external data. An initializer involved in shape inferencing is + * typically small (a single value or limited by the rank of a tensor) and uses less than 128 bytes of + * memory, so this limit acts as a simple catch-all rule to avoid issues. + * e.g. Reshape's `shape`, Clip's `min` and `max`, various ops `axes`. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] name The value name for the initializer. + * \param[in] tensor The OrtValue instance containing the tensor data. + * \param[in] data_is_external Set to true if the data is external and should not be copied. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(AddInitializerToGraph, _Inout_ OrtGraph* graph, _In_ const char* name, _In_ OrtValue* tensor, + bool data_is_external); + + /** \brief Add an OrtNode to an OrtGraph + * + * Add the node to the graph. The OrtGraph will take ownership of OrtNode and you should NOT call ReleaseOrtNode. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] node The OrtNode instance to add to the graph. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(AddNodeToGraph, _Inout_ OrtGraph* graph, _In_ OrtNode* node); + + /** \brief Create an OrtModel. + * + * Create an OrtModel. + * + * This can be used to build a new model, or to augment an existing model. + * + * \param[in] domain_names The domain names for the model. + * If augmenting an existing model add additional domains if needed. + * \param[in] opset_versions The opset versions for the model. + * If augmenting an existing model add additional opset versions if needed. + * \param[in] opset_entries_len The number of domain_names and opset_versions entries. + * Domain and opset entries should be 1:1 + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateModel, + _In_reads_(opset_entries_len) const char* const* domain_names, + _In_reads_(opset_entries_len) const int* opset_versions, + size_t opset_entries_len, + _Outptr_ OrtModel** model); + + /** \brief Add an OrtGraph to an OrtModel. + * + * Add the graph to a model. This should be called once when creating a new model. + * + * The OrtModel takes ownership of the OrtGraph and you should NOT call ReleaseOrtGraph. + * + * \param[in] model The OrtModel instance to update. + * \param[in] graph The OrtGraph instance to add to the model. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(AddGraphToModel, _Inout_ OrtModel* model, _In_ OrtGraph* graph); + + /** \brief Create an OrtSession using the OrtModel. + * + * Create an inference session using the OrtModel instance. + * The OrtModel should have been populated with an OrtGraph containing nodes and initializers, and SetGraphInputs + * and SetGraphOutputs must have been called. + * This will validate the model, run optimizers, and prepare the session for inferencing. + * + * ReleaseOrtModel must be called to free the OrtModel after session creation. + * + * \param[in] env The OrtEnv instance. + * \param[in] model The OrtModel instance. + * \param[in] options The OrtSessionOptions instance. + * \param[out] out The OrtSession instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateSessionFromModel, _In_ const OrtEnv* env, _In_ const OrtModel* model, + _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out); + + /** \brief Create an OrtSession to augment an existing model. + * + * Create an OrtSession with an existing model that will be augmented with additional nodes and initializers. + * Nodes can be added before or after the existing nodes in the model. ONNX Runtime will connect the nodes when the + * model is finalized. + * + * To add nodes and initializers to the existing model, first create an OrtModel using CreateModel. + * Add nodes and initializers to the OrtModel using AddNodeToGraph and AddInitializerToGraph. + * Graph inputs/outputs should be updated with SetGraphInputs and SetGraphOutputs as needed to reflect changes made + * by the new nodes. The list of graph inputs/outputs should be for the overall model and not just the new nodes. + * + * Add the new information from the OrtModel to the original model using ApplyModelToSession, and prepare the + * session for inferencing by calling FinalizeModelEditorSession. + * + * \param{in} env The OrtEnv instance. + * \param{in} model_path The path to the existing ONNX model to augment. + * \param{in} options The OrtSessionOptions instance. + * \param{out} out The created OrtSession instance. + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateModelEditorSession, _In_ const OrtEnv* env, _In_ const ORTCHAR_T* model_path, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out); + + /** \brief Create an OrtSession to augment an existing model. + * + * Create an OrtSession with an existing model that will be augmented with additional nodes and initializers. + * Nodes can be added before or after the existing nodes in the model. ONNX Runtime will connect the nodes when the + * model is finalized. + * + * To add nodes and initializers to the existing model, first create an OrtModel using CreateModel. + * Add nodes and initializers to the OrtModel using AddNodeToGraph and AddInitializerToGraph. + * Graph inputs/outputs should be updated with SetGraphInputs and SetGraphOutputs as needed to reflect changes made + * by the new nodes. The list of graph inputs/outputs should be for the overall model and not just the new nodes. + * + * Add the new information from the OrtModel to the original model using ApplyModelToSession, and prepare the + * session for inferencing by calling FinalizeModelEditorSession. + * + * \param{in} env The OrtEnv instance. + * \param{in} model_data The model data for the existing model to augment. + * \param{in} model_data_length The length of the model data. + * \param{in} options The OrtSessionOptions instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(CreateModelEditorSessionFromArray, _In_ const OrtEnv* env, + _In_ const void* model_data, size_t model_data_length, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out); + + /** \brief Query the session for the opset version of a domain. + * + * When using the Model Editor API to augment a model, any new nodes must conform to the opset version of the + * original model. To do that the user must be able to discover that opset version. + * + * \param[in] session OrtSession to query + * \param[in] domain Domain to query. The ONNX domain is an empty string. + * \param[out] opset The opset version of the domain. + * + * \snippet{doc} snippets.dox OrtStatus Return Value. Returns an error if the domain is not used in the model. + * + * \since Version 1.21. + */ + ORT_API2_STATUS(SessionGetOpsetForDomain, _In_ const OrtSession* session, _In_ const char* domain, _Out_ int* opset); + + /** \brief Apply changes to augment the ONNX model in a session created using CreateModelEditorSession[FromArray] + * + * Adds new nodes and updates graph inputs/outputs using `model` to augment the original ONNX model in the session. + * All changes will be validated. + * Call FinalizeModelEditorSession to prepare the session for inferencing. + * + * Existing input/outputs will only be updated if the OrtGraph inputs/outputs are set in the OrtModel. + * i.e. you don't need to call SetGraphInputs/SetGraphOutputs if they are unchanged. + * + * ReleaseOrtModel must be called to free the OrtModel after it is applied to the session. + * + * \param[in] session OrtSession to update. Session must have been created using CreateModelEditorSession[FromArray]. + * \param[in] model OrtModel containing new nodes, new initializers, and updated graph input and/or output info. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(ApplyModelToModelEditorSession, _Inout_ OrtSession* session, _In_ OrtModel* model); + + /** \brief Finalize the Model Editor session that was created using CreateModelEditorSession[FromArray]. + * + * Finalize the Model Editor session that augmented an ONNX model by adding new nodes. + * This will run optimizers and prepare the session for inferencing. + * + * \param[in] session OrtSession to finalize. Session must have been created using CreateModelEditorSession[FromArray]. + * \param[in] options OrtSessionOptions to use for the session. + * \param[in] Optional prepacked_weights_container OrtPrepackedWeightsContainer to use for the session. + Set to nullptr if not used. + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.21. + */ + ORT_API2_STATUS(FinalizeModelEditorSession, _Inout_ OrtSession* session, _In_ const OrtSessionOptions* options, + _In_opt_ OrtPrepackedWeightsContainer* prepacked_weights_container); +#endif // !defined(ORT_MINIMAL_BUILD) +}; + /* * This is the old way to add the CUDA provider to the session, please use SessionOptionsAppendExecutionProvider_CUDA above to access the latest functionality * This function always exists, but will only succeed if Onnxruntime was built with CUDA support and the CUDA provider shared library exists diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 123ef98901003..89488b5158c93 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -26,16 +26,17 @@ #include "onnxruntime_c_api.h" #include "onnxruntime_float16.h" +#include #include #include -#include #include #include #include -#include +#include #include #include -#include +#include +#include #ifdef ORT_NO_EXCEPTIONS #include @@ -120,7 +121,7 @@ const OrtApi* Global::api_ = OrtGetApiBase()->GetApi(ORT_API_VERSION); #endif #endif -/// This returns a reference to the OrtApi interface in use +/// This returns a reference to the ORT C API. inline const OrtApi& GetApi() noexcept { return *Global::api_; } ///

@@ -143,6 +144,20 @@ std::string GetBuildInfoString(); /// vector of strings std::vector GetAvailableProviders(); +/// +/// This returns a reference to the ORT C Model Editor API. Used if building or augmenting a model at runtime. +/// +/// ORT C Model Editor API reference +inline const OrtModelEditorApi& GetModelEditorApi() { + auto* api = GetApi().GetModelEditorApi(); + if (api == nullptr) { + // minimal build + ORT_CXX_API_THROW("Model Editor API is not available in this build", ORT_FAIL); + } + + return *api; +} + /** \brief IEEE 754 half-precision floating point data type * * \details This struct is used for converting float to float16 and back @@ -523,6 +538,10 @@ ORT_DEFINE_RELEASE(Status); ORT_DEFINE_RELEASE(OpAttr); ORT_DEFINE_RELEASE(Op); ORT_DEFINE_RELEASE(KernelInfo); +ORT_DEFINE_RELEASE(ValueInfo); +ORT_DEFINE_RELEASE(Node); +ORT_DEFINE_RELEASE(Graph); +ORT_DEFINE_RELEASE(Model); #undef ORT_DEFINE_RELEASE @@ -559,7 +578,9 @@ struct Base { constexpr Base() = default; constexpr explicit Base(contained_type* p) noexcept : p_{p} {} - ~Base() { OrtRelease(p_); } + ~Base() { + OrtRelease(p_); + } Base(const Base&) = delete; Base& operator=(const Base&) = delete; @@ -635,9 +656,13 @@ struct AllocatedFree { struct AllocatorWithDefaultOptions; struct Env; +struct Graph; +struct Model; +struct Node; +struct ModelMetadata; struct TypeInfo; struct Value; -struct ModelMetadata; +struct ValueInfo; /** \brief unique_ptr typedef used to own strings allocated by OrtAllocators * and release them at the end of the scope. The lifespan of the given allocator @@ -1051,6 +1076,10 @@ struct ConstSessionImpl : Base { size_t GetOutputCount() const; ///< Returns the number of model outputs size_t GetOverridableInitializerCount() const; ///< Returns the number of inputs that have defaults that can be overridden + std::vector GetInputNames() const; + std::vector GetOutputNames() const; + std::vector GetOverridableInitializerNames() const; + /** \brief Returns a copy of input name at the specified index. * * \param index must less than the value returned by GetInputCount() @@ -1084,6 +1113,12 @@ struct ConstSessionImpl : Base { TypeInfo GetInputTypeInfo(size_t index) const; ///< Wraps OrtApi::SessionGetInputTypeInfo TypeInfo GetOutputTypeInfo(size_t index) const; ///< Wraps OrtApi::SessionGetOutputTypeInfo TypeInfo GetOverridableInitializerTypeInfo(size_t index) const; ///< Wraps OrtApi::SessionGetOverridableInitializerTypeInfo + + int GetOpset(const std::string& domain) const; ///< Wraps OrtApi::SessionGetOpsetForDomain + + // Will move before checkin if that's the case. + std::vector GetInputs() const; + std::vector GetOutputs() const; }; template @@ -1161,6 +1196,9 @@ struct SessionImpl : ConstSessionImpl { * \param[in] kv_len Number of elements in the keys and values arrays */ void SetEpDynamicOptions(const char* const* keys, const char* const* values, size_t kv_len); + + void FinalizeModelEditorSession(const Model& model, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container = nullptr); }; } // namespace detail @@ -1172,13 +1210,34 @@ using UnownedSession = detail::SessionImpl>; * */ struct Session : detail::SessionImpl { - explicit Session(std::nullptr_t) {} ///< Create an empty Session object, must be assigned a valid one to be used - Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options); ///< Wraps OrtApi::CreateSession + /// Create an empty Session object, must be assigned a valid one to be used. Wraps OrtApi::CreateSession + explicit Session(std::nullptr_t) {} + explicit Session(OrtSession* p) : SessionImpl{p} {} ///< C API Interop + + Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options); + + /// Wraps OrtApi::CreateSessionWithPrepackedWeightsContainer Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options, - OrtPrepackedWeightsContainer* prepacked_weights_container); ///< Wraps OrtApi::CreateSessionWithPrepackedWeightsContainer - Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options); ///< Wraps OrtApi::CreateSessionFromArray + OrtPrepackedWeightsContainer* prepacked_weights_container); + + /// Wraps OrtApi::CreateSessionFromArray + Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options); + + /// Wraps OrtApi::CreateSessionFromArrayWithPrepackedWeightsContainer Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options, - OrtPrepackedWeightsContainer* prepacked_weights_container); ///< Wraps OrtApi::CreateSessionFromArrayWithPrepackedWeightsContainer + OrtPrepackedWeightsContainer* prepacked_weights_container); + +#if !defined(ORT_MINIMAL_BUILD) + /// Wraps OrtModelEditorApi::CreateSessionFromModel + Session(const Env& env, const Model& model, const SessionOptions& options); + + /// Wraps OrtModelEditorApi::CreateModelEditorSession + static Session CreateModelEditorSession(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options); + + /// Wraps OrtModelEditorApi::CreateModelEditorSession + static Session CreateModelEditorSession(const Env& env, const void* model_data, size_t model_data_length, + const SessionOptions& options); +#endif // !defined(ORT_MINIMAL_BUILD) ConstSession GetConst() const { return ConstSession{this->p_}; } UnownedSession GetUnowned() const { return UnownedSession{this->p_}; } @@ -1210,7 +1269,7 @@ using ConstMemoryInfo = detail::MemoryInfoImpl { static MemoryInfo CreateCpu(OrtAllocatorType type, OrtMemType mem_type1); explicit MemoryInfo(std::nullptr_t) {} ///< No instance is created - explicit MemoryInfo(OrtMemoryInfo* p) : MemoryInfoImpl{p} {} ///< Take ownership of a pointer created by C Api + explicit MemoryInfo(OrtMemoryInfo* p) : MemoryInfoImpl{p} {} ///< Take ownership of a pointer created by C API MemoryInfo(const char* name, OrtAllocatorType type, int id, OrtMemType mem_type); ConstMemoryInfo GetConst() const { return ConstMemoryInfo{this->p_}; } }; @@ -1233,6 +1292,7 @@ struct TensorTypeAndShapeInfoImpl : Base { [[deprecated("use GetShape()")]] void GetDimensions(int64_t* values, size_t values_count) const; ///< Wraps OrtApi::GetDimensions void GetSymbolicDimensions(const char** values, size_t values_count) const; ///< Wraps OrtApi::GetSymbolicDimensions + std::vector GetSymbolicDimensions() const; std::vector GetShape() const; ///< Uses GetDimensionsCount & GetDimensions to return a std::vector of the shape }; @@ -1248,8 +1308,18 @@ struct TensorTypeAndShapeInfo : detail::TensorTypeAndShapeInfoImpl; using Base::Base; - explicit TensorTypeAndShapeInfo(std::nullptr_t) {} ///< Create an empty TensorTypeAndShapeInfo object, must be assigned a valid one to be used - explicit TensorTypeAndShapeInfo(OrtTensorTypeAndShapeInfo* p) : TensorTypeAndShapeInfoImpl{p} {} ///< Used for interop with the C API + /// Create an empty TensorTypeAndShapeInfo object, must be assigned a valid one to be used + explicit TensorTypeAndShapeInfo(std::nullptr_t) {} + /// Used for interop with the C API + explicit TensorTypeAndShapeInfo(OrtTensorTypeAndShapeInfo* p) : TensorTypeAndShapeInfoImpl{p} {} + + // Create a TensorTypeAndShapeInfo object with the specified element type and dimensions + // symbolic_dims are optional, but should be 1:1 with dims. + // The value in symbolic_dims will be used for all entries in dims that are -1. + explicit TensorTypeAndShapeInfo(ONNXTensorElementDataType element_type, + const std::vector& dims, + const std::vector* symbolic_dims = nullptr); + ConstTensorTypeAndShapeInfo GetConst() const { return ConstTensorTypeAndShapeInfo{this->p_}; } }; @@ -1344,9 +1414,18 @@ struct TypeInfo : detail::TypeInfoImpl { using Base = detail::TypeInfoImpl; using Base::Base; - explicit TypeInfo(std::nullptr_t) {} ///< Create an empty TypeInfo object, must be assigned a valid one to be used + /// Create an empty TypeInfo object, must be assigned a valid one to be used + explicit TypeInfo(std::nullptr_t) {} explicit TypeInfo(OrtTypeInfo* p) : TypeInfoImpl{p} {} ///< C API Interop +#if !defined(ORT_MINIMAL_BUILD) + static TypeInfo CreateTensorInfo(ConstTensorTypeAndShapeInfo tensor_info); + static TypeInfo CreateSparseTensorInfo(ConstTensorTypeAndShapeInfo sparse_tensor_info); + static TypeInfo CreateSequenceTypeInfo(ConstTypeInfo sequence_type); + static TypeInfo CreateMapTypeInfo(ONNXTensorElementDataType key_type, ConstTypeInfo value_type); + static TypeInfo CreateOptionalTypeInfo(ConstTypeInfo contained_type); +#endif // !defined(ORT_MINIMAL_BUILD) + ConstTypeInfo GetConst() const { return ConstTypeInfo{this->p_}; } }; @@ -1701,7 +1780,8 @@ struct Value : detail::ValueImpl { * \param shape_len The number of tensor shape dimensions. */ template - static Value CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, const int64_t* shape, size_t shape_len); + static Value CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, + const int64_t* shape, size_t shape_len); /** \brief Creates a tensor with a user supplied buffer. Wraps OrtApi::CreateTensorWithDataAsOrtValue. * @@ -1712,11 +1792,25 @@ struct Value : detail::ValueImpl { * \param shape_len The number of tensor shape dimensions. * \param type The data type. */ - static Value CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, const int64_t* shape, size_t shape_len, + static Value CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type); + + /** \brief Creates a tensor with a user supplied buffer. Wraps OrtApi::CreateTensorWithDataAndDeleterAsOrtValue. + * + * \param deleter OrtAllocator that will be used to free the buffer when no longer required. + * \param p_data Pointer to the data buffer. + * \param p_data_byte_count The number of bytes in the data buffer. + * \param shape Pointer to the tensor shape dimensions. + * \param shape_len The number of tensor shape dimensions. + * \param type The data type. + */ + static Value CreateTensor(OrtAllocator* deleter, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type); /** \brief Creates an OrtValue with a tensor using a supplied OrtAllocator. Wraps OrtApi::CreateTensorAsOrtValue. - * This overload will allocate the buffer for the tensor according to the supplied shape and data type. + * This overload will allocate the buffer for the tensor according to the supplied shape and data type. * The allocated buffer will be owned by the returned OrtValue and will be freed when the OrtValue is released. * The input data would need to be copied into the allocated buffer. * This API is not suitable for strings. @@ -1740,7 +1834,8 @@ struct Value : detail::ValueImpl { * \param shape_len The number of tensor shape dimensions. * \param type The data type. */ - static Value CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type); + static Value CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type); /** \brief Creates an OrtValue with a Map Onnx type representation. * The API would ref-count the supplied OrtValues and they will be released @@ -2459,6 +2554,129 @@ struct CustomOpBase : OrtCustomOp { int end_ver_ = MAX_CUSTOM_OP_END_VER; }; -} // namespace Ort +namespace detail { +template +struct ValueInfoImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + std::string Name() const; + ConstTypeInfo TypeInfo() const; +}; +} // namespace detail + +// Const object holder that does not own the underlying object +using ConstValueInfo = detail::ValueInfoImpl>; +/** \brief Wrapper around ::OrtValueInfo + * + */ +struct ValueInfo : detail::ValueInfoImpl { + explicit ValueInfo(std::nullptr_t) {} ///< No instance is created + /// Take ownership of a pointer created by C API + explicit ValueInfo(OrtValueInfo* p) : ValueInfoImpl{p} {} + + // Create ValueInfo for a tensor + explicit ValueInfo(const std::string& name, const ConstTypeInfo& type_info); + + ConstValueInfo GetConst() const { return ConstValueInfo{this->p_}; } +}; + +namespace detail { +template +struct NodeImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; +}; +} // namespace detail + +/** \brief Wrapper around ::OrtNode + * + */ +struct Node : detail::NodeImpl { + explicit Node(std::nullptr_t) {} ///< No instance is created + explicit Node(OrtNode* p) : NodeImpl{p} {} ///< Take ownership of a pointer created by C API + +#if !defined(ORT_MINIMAL_BUILD) + Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names); + + /// + /// Wraps CreateNode. Node takes ownership of attributes on success and updates the OpAttr in `attributes` to do so. + /// + Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes); + + private: + static void Init(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes, + OrtNode*& node); +#endif // !defined(ORT_MINIMAL_BUILD) +}; + +namespace detail { +template +struct GraphImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + +#if !defined(ORT_MINIMAL_BUILD) + void SetInputs(std::vector& inputs); + void SetOutputs(std::vector& outputs); + void AddInitializer(const std::string& name, Value& initializer, bool data_is_external); // Graph takes ownership of Value + void AddNode(Node& node); // Graph takes ownership of Node +#endif // !defined(ORT_MINIMAL_BUILD) +}; +} // namespace detail + +/** \brief Wrapper around ::OrtGraph + * + */ +struct Graph : detail::GraphImpl { + explicit Graph(std::nullptr_t) {} ///< No instance is created + explicit Graph(OrtGraph* p) : GraphImpl{p} {} ///< Take ownership of a pointer created by C API +#if !defined(ORT_MINIMAL_BUILD) + Graph(); +#endif +}; + +namespace detail { +template +struct ModelImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + +#if !defined(ORT_MINIMAL_BUILD) + void AddGraph(Graph& graph); +#endif +}; +} // namespace detail + +// Const object holder that does not own the underlying object +using ConstModel = detail::ModelImpl>; + +/** \brief Wrapper around ::OrtModel + * + */ +struct Model : detail::ModelImpl { + using DomainOpsetPair = std::pair; + + explicit Model(std::nullptr_t) {} ///< No instance is created + explicit Model(OrtModel* p) : ModelImpl{p} {} ///< Take ownership of a pointer created by C API + +#if !defined(ORT_MINIMAL_BUILD) + explicit Model(const std::vector& opsets); +#endif + + ConstModel GetConst() const { return ConstModel{this->p_}; } +}; +} // namespace Ort #include "onnxruntime_cxx_inline.h" diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 3aeb9412f350e..48c5e52e33c53 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include // Convert OrtStatus to Ort::Status and return // instead of throwing @@ -995,6 +997,59 @@ inline size_t ConstSessionImpl::GetOverridableInitializerCount() const { return out; } +template +inline std::vector ConstSessionImpl::GetInputNames() const { + AllocatorWithDefaultOptions allocator; + + auto num_inputs = GetInputCount(); + std::vector input_names; + input_names.reserve(num_inputs); + + for (size_t i = 0; i < num_inputs; ++i) { + char* name = nullptr; + ThrowOnError(GetApi().SessionGetInputName(this->p_, i, allocator, &name)); + input_names.push_back(name); + allocator.Free(name); + } + + return input_names; +} + +template +inline std::vector ConstSessionImpl::GetOutputNames() const { + AllocatorWithDefaultOptions allocator; + + auto num_inputs = GetOutputCount(); + std::vector output_names; + output_names.reserve(num_inputs); + + for (size_t i = 0; i < num_inputs; ++i) { + char* name = nullptr; + ThrowOnError(GetApi().SessionGetOutputName(this->p_, i, allocator, &name)); + output_names.push_back(name); + allocator.Free(name); + } + + return output_names; +} + +template +inline std::vector ConstSessionImpl::GetOverridableInitializerNames() const { + AllocatorWithDefaultOptions allocator; + + auto num_initializers = GetOverridableInitializerCount(); + std::vector initializer_names; + initializer_names.reserve(num_initializers); + + for (size_t i = 0; i < num_initializers; ++i) { + char* name = nullptr; + ThrowOnError(GetApi().SessionGetOverridableInitializerName(this->p_, i, allocator, &name)); + initializer_names.push_back(name); + } + + return initializer_names; +} + template inline AllocatedStringPtr ConstSessionImpl::GetInputNameAllocated(size_t index, OrtAllocator* allocator) const { char* out; @@ -1051,6 +1106,45 @@ inline TypeInfo ConstSessionImpl::GetOverridableInitializerTypeInfo(size_t in return TypeInfo{out}; } +#if !defined(ORT_MINIMAL_BUILD) +template +inline int ConstSessionImpl::GetOpset(const std::string& domain) const { + int opset; + ThrowOnError(GetModelEditorApi().SessionGetOpsetForDomain(this->p_, domain.c_str(), &opset)); + return opset; +} +#endif // !defined(ORT_MINIMAL_BUILD) + +template +std::vector ConstSessionImpl::GetInputs() const { + const std::vector input_names = GetInputNames(); + + std::vector inputs; + inputs.reserve(input_names.size()); + + for (size_t i = 0; i < input_names.size(); ++i) { + auto type_info = GetInputTypeInfo(i); + inputs.emplace_back(ValueInfo{input_names[i], type_info.GetConst()}); + } + + return inputs; +} + +template +std::vector ConstSessionImpl::GetOutputs() const { + const std::vector output_names = GetOutputNames(); + + std::vector outputs; + outputs.reserve(output_names.size()); + + for (size_t i = 0; i < output_names.size(); ++i) { + auto type_info = GetOutputTypeInfo(i); + outputs.emplace_back(ValueInfo{output_names[i], type_info.GetConst()}); + } + + return outputs; +} + template inline std::vector SessionImpl::Run(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, const char* const* output_names, size_t output_count) { @@ -1098,6 +1192,15 @@ inline void SessionImpl::SetEpDynamicOptions(const char* const* keys, const c ThrowOnError(GetApi().SetEpDynamicOptions(this->p_, keys, values, kv_len)); } +#if !defined(ORT_MINIMAL_BUILD) +template +inline void SessionImpl::FinalizeModelEditorSession(const Model& model, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container) { + ThrowOnError(GetModelEditorApi().ApplyModelToModelEditorSession(this->p_, model)); + ThrowOnError(GetModelEditorApi().FinalizeModelEditorSession(this->p_, options, prepacked_weights_container)); +} +#endif // #if !defined(ORT_MINIMAL_BUILD) + } // namespace detail inline SessionOptions::SessionOptions() { @@ -1144,6 +1247,32 @@ inline Session::Session(const Env& env, const void* model_data, size_t model_dat prepacked_weights_container, &this->p_)); } +#if !defined(ORT_MINIMAL_BUILD) +inline Session::Session(const Env& env, const Model& model, const SessionOptions& options) { + ThrowOnError(GetModelEditorApi().CreateSessionFromModel(env, model.GetConst(), options, &this->p_)); +} + +// static +inline Session Session::CreateModelEditorSession(const Env& env, const ORTCHAR_T* model_path, + const SessionOptions& options) { + OrtSession* session = nullptr; + ThrowOnError(GetModelEditorApi().CreateModelEditorSession(env, model_path, options, &session)); + return Session(session); +} + +// static +inline Session Session::CreateModelEditorSession(const Env& env, const void* model_data, size_t model_data_length, + const SessionOptions& options) { + OrtSession* session = nullptr; + ThrowOnError(GetModelEditorApi().CreateModelEditorSessionFromArray(env, model_data, model_data_length, options, + &session)); + return Session(session); +} + +void FinalizeModelEditorSession(const Model& model, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container); +#endif // #if !defined(ORT_MINIMAL_BUILD) + inline AllocatedStringPtr ModelMetadata::GetProducerNameAllocated(OrtAllocator* allocator) const { char* out; ThrowOnError(GetApi().ModelMetadataGetProducerName(p_, allocator, &out)); @@ -1211,6 +1340,59 @@ inline int64_t ModelMetadata::GetVersion() const { return out; } +inline TensorTypeAndShapeInfo::TensorTypeAndShapeInfo(ONNXTensorElementDataType element_type, + const std::vector& dims, + const std::vector* symbolic_dims) { + ThrowOnError(GetApi().CreateTensorTypeAndShapeInfo(&p_)); + ThrowOnError(GetApi().SetTensorElementType(p_, element_type)); + ThrowOnError(GetApi().SetDimensions(p_, dims.data(), dims.size())); + + if (symbolic_dims) { + std::vector symbolic_dims_cstr; + symbolic_dims_cstr.reserve(symbolic_dims->size()); + std::transform(symbolic_dims->begin(), symbolic_dims->end(), std::back_inserter(symbolic_dims_cstr), + [](const std::string& s) { return s.c_str(); }); + ThrowOnError(GetApi().SetSymbolicDimensions(p_, symbolic_dims_cstr.data(), symbolic_dims_cstr.size())); + } +} + +#if !defined(ORT_MINIMAL_BUILD) +// static +inline TypeInfo TypeInfo::CreateTensorInfo(ConstTensorTypeAndShapeInfo tensor_type_and_shape_info) { + OrtTypeInfo* output = nullptr; + ThrowOnError(GetModelEditorApi().CreateTensorTypeInfo(tensor_type_and_shape_info, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateSparseTensorInfo(ConstTensorTypeAndShapeInfo sparse_tensor_type_and_shape_info) { + OrtTypeInfo* output = nullptr; + ThrowOnError(GetModelEditorApi().CreateSparseTensorTypeInfo(sparse_tensor_type_and_shape_info, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateSequenceTypeInfo(ConstTypeInfo sequence_type) { + OrtTypeInfo* output; + ThrowOnError(GetModelEditorApi().CreateSequenceTypeInfo(sequence_type, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateMapTypeInfo(ONNXTensorElementDataType key_type, ConstTypeInfo value_type) { + OrtTypeInfo* output; + ThrowOnError(GetModelEditorApi().CreateMapTypeInfo(key_type, value_type, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateOptionalTypeInfo(ConstTypeInfo contained_type) { + OrtTypeInfo* output; + ThrowOnError(GetModelEditorApi().CreateOptionalTypeInfo(contained_type, &output)); + return TypeInfo{output}; +} +#endif // #if !defined(ORT_MINIMAL_BUILD) + namespace detail { template @@ -1244,9 +1426,16 @@ inline void TensorTypeAndShapeInfoImpl::GetSymbolicDimensions(const char** va ThrowOnError(GetApi().GetSymbolicDimensions(this->p_, values, values_count)); } +template +inline std::vector TensorTypeAndShapeInfoImpl::GetSymbolicDimensions() const { + std::vector out(GetDimensionsCount(), nullptr); + ThrowOnError(GetApi().GetSymbolicDimensions(this->p_, out.data(), out.size())); + return out; +} + template inline std::vector TensorTypeAndShapeInfoImpl::GetShape() const { - std::vector out(GetDimensionsCount(), 0); + std::vector out(GetDimensionsCount(), -1); ThrowOnError(GetApi().GetDimensions(this->p_, out.data(), out.size())); return out; } @@ -1560,23 +1749,35 @@ void ValueImpl::FillSparseTensorBlockSparse(const OrtMemoryInfo* data_mem_inf } // namespace detail template -inline Value Value::CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, const int64_t* shape, size_t shape_len) { +inline Value Value::CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, + const int64_t* shape, size_t shape_len) { return CreateTensor(info, p_data, p_data_element_count * sizeof(T), shape, shape_len, TypeToTensorType::type); } -inline Value Value::CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, const int64_t* shape, size_t shape_len, +inline Value Value::CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type) { OrtValue* out; ThrowOnError(GetApi().CreateTensorWithDataAsOrtValue(info, p_data, p_data_byte_count, shape, shape_len, type, &out)); return Value{out}; } +inline Value Value::CreateTensor(OrtAllocator* deleter, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type) { + OrtValue* out; + ThrowOnError(GetApi().CreateTensorWithDataAndDeleterAsOrtValue(deleter, p_data, p_data_byte_count, + shape, shape_len, type, &out)); + return Value{out}; +} + template inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len) { return CreateTensor(allocator, shape, shape_len, TypeToTensorType::type); } -inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type) { +inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type) { OrtValue* out; ThrowOnError(GetApi().CreateTensorAsOrtValue(allocator, shape, shape_len, type, &out)); return Value{out}; @@ -1594,7 +1795,8 @@ inline Value Value::CreateSparseTensor(const OrtMemoryInfo* info, void* p_data, const Shape& values_shape, ONNXTensorElementDataType type) { OrtValue* out; ThrowOnError(GetApi().CreateSparseTensorWithValuesAsOrtValue(info, p_data, dense_shape.shape, dense_shape.shape_len, - values_shape.shape, values_shape.shape_len, type, &out)); + values_shape.shape, values_shape.shape_len, type, + &out)); return Value{out}; } @@ -2167,4 +2369,142 @@ inline const OrtOpAttr* ShapeInferContext::GetAttrHdl(const char* attr_name) con return attr_hdl; } +namespace detail { +inline std::vector StringsToCharPtrs(const std::vector& strings) { + std::vector ptrs; + ptrs.reserve(strings.size()); + std::transform(strings.begin(), strings.end(), std::back_inserter(ptrs), + [](const std::string& s) { return s.c_str(); }); + + return ptrs; +} +} // namespace detail + +#if !defined(ORT_MINIMAL_BUILD) +// static +inline void Node::Init(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes, + OrtNode*& node) { + auto inputs = detail::StringsToCharPtrs(input_names); + auto outputs = detail::StringsToCharPtrs(output_names); + + std::vector attributes_ptrs; + attributes_ptrs.reserve(attributes.size()); + std::transform(attributes.begin(), attributes.end(), std::back_inserter(attributes_ptrs), + [](OpAttr& attr) -> OrtOpAttr* { return attr; }); + + ThrowOnError(GetModelEditorApi().CreateNode(operator_name.c_str(), operator_domain.c_str(), node_name.c_str(), + inputs.data(), inputs.size(), + outputs.data(), outputs.size(), + attributes_ptrs.data(), attributes_ptrs.size(), + &node)); + + // Node now owns the attributes + std::for_each(attributes.begin(), attributes.end(), [](OpAttr& attr) { attr.release(); }); +} + +inline Node::Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes) { + Init(operator_name, operator_domain, node_name, input_names, output_names, attributes, p_); +} + +inline Node::Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names) { + std::vector empty_attributes; + Init(operator_name, operator_domain, node_name, input_names, output_names, empty_attributes, p_); +} + +inline Graph::Graph() { + ThrowOnError(GetModelEditorApi().CreateGraph(&p_)); +} + +inline Model::Model(const std::vector& opsets) { + std::vector domains; + std::vector versions; + domains.reserve(opsets.size()); + versions.reserve(opsets.size()); + + for (const auto& pair : opsets) { + domains.push_back(pair.first.c_str()); + versions.push_back(pair.second); + } + + ThrowOnError(GetModelEditorApi().CreateModel(domains.data(), versions.data(), opsets.size(), &p_)); +} + +inline ValueInfo::ValueInfo(const std::string& name, const ConstTypeInfo& type_info) { + ThrowOnError(GetModelEditorApi().CreateValueInfo(name.c_str(), type_info, &p_)); +} +#endif // !defined(ORT_MINIMAL_BUILD) + +namespace detail { +template <> +inline std::string ValueInfoImpl::Name() const { + const char* name = nullptr; + ThrowOnError(GetApi().GetValueInfoName(this->p_, &name)); + return name; +} + +template <> +inline ConstTypeInfo ValueInfoImpl::TypeInfo() const { + const OrtTypeInfo* type_info = nullptr; + ThrowOnError(GetApi().GetValueInfoTypeInfo(this->p_, &type_info)); + return ConstTypeInfo{type_info}; +} + +#if !defined(ORT_MINIMAL_BUILD) +template <> +inline void GraphImpl::SetInputs(std::vector& inputs) { + std::vector inputs_ptrs; + inputs_ptrs.reserve(inputs.size()); + std::transform(inputs.begin(), inputs.end(), std::back_inserter(inputs_ptrs), + [](ValueInfo& vi) -> OrtValueInfo* { return vi; }); + + ThrowOnError(GetModelEditorApi().SetGraphInputs(p_, inputs_ptrs.data(), inputs_ptrs.size())); + + // Graph now owns the inputs + std::for_each(inputs.begin(), inputs.end(), [](ValueInfo& vi) { vi.release(); }); +} + +template <> +inline void GraphImpl::SetOutputs(std::vector& outputs) { + std::vector outputs_ptrs; + outputs_ptrs.reserve(outputs.size()); + std::transform(outputs.begin(), outputs.end(), std::back_inserter(outputs_ptrs), + [](ValueInfo& vi) -> OrtValueInfo* { return vi; }); + + ThrowOnError(GetModelEditorApi().SetGraphOutputs(p_, outputs_ptrs.data(), outputs_ptrs.size())); + + // Graph now owns the outputs + std::for_each(outputs.begin(), outputs.end(), [](ValueInfo& vi) { vi.release(); }); +} + +template <> +inline void GraphImpl::AddInitializer(const std::string& name, Value& initializer, bool data_is_external) { + // Graph takes ownership of `initializer` + ThrowOnError(GetModelEditorApi().AddInitializerToGraph(p_, name.c_str(), initializer.release(), data_is_external)); +} + +template <> +inline void GraphImpl::AddNode(Node& node) { + // Graph takes ownership of `node` + ThrowOnError(GetModelEditorApi().AddNodeToGraph(p_, node.release())); +} + +template <> +inline void ModelImpl::AddGraph(Graph& graph) { + // Model takes ownership of `graph` + ThrowOnError(GetModelEditorApi().AddGraphToModel(p_, graph.release())); +} +#endif // !defined(ORT_MINIMAL_BUILD) + +} // namespace detail } // namespace Ort diff --git a/onnxruntime/core/framework/onnxruntime_typeinfo.cc b/onnxruntime/core/framework/onnxruntime_typeinfo.cc index a884927abddb7..1c446840b7938 100644 --- a/onnxruntime/core/framework/onnxruntime_typeinfo.cc +++ b/onnxruntime/core/framework/onnxruntime_typeinfo.cc @@ -10,8 +10,8 @@ #include "core/framework/sparse_tensor.h" #include "core/graph/onnx_protobuf.h" #include "core/session/ort_apis.h" +#include "core/session/model_editor_api.h" #include "core/framework/error_code_helper.h" - #include "core/framework/tensor_type_and_shape.h" #include "core/framework/onnxruntime_map_type_info.h" #include "core/framework/onnxruntime_sequence_type_info.h" @@ -40,7 +40,7 @@ OrtTypeInfo::OrtTypeInfo(std::unique_ptr optional_type_info : type(ONNX_TYPE_OPTIONAL), optional_type_info(std::move(optional_type_info)) {} OrtTypeInfo::OrtTypeInfo(ONNXType type, std::unique_ptr data) noexcept - : type(type), data(std::move(data)) { + : type(type), tensor_type_info(std::move(data)) { } OrtTypeInfo::~OrtTypeInfo() = default; @@ -55,7 +55,9 @@ ORT_API_STATUS_IMPL(OrtApis::GetOnnxTypeFromTypeInfo, _In_ const struct OrtTypeI ORT_API_STATUS_IMPL(OrtApis::CastTypeInfoToTensorInfo, _In_ const struct OrtTypeInfo* input, _Outptr_result_maybenull_ const struct OrtTensorTypeAndShapeInfo** out) { API_IMPL_BEGIN - *out = (input->type == ONNX_TYPE_TENSOR || input->type == ONNX_TYPE_SPARSETENSOR) ? input->data.get() : nullptr; + *out = (input->type == ONNX_TYPE_TENSOR || input->type == ONNX_TYPE_SPARSETENSOR) + ? input->tensor_type_info.get() + : nullptr; return nullptr; API_IMPL_END } @@ -84,8 +86,8 @@ ORT_API_STATUS_IMPL(OrtApis::CastTypeInfoToOptionalTypeInfo, _In_ const OrtTypeI API_IMPL_END } -ORT_API_STATUS_IMPL(OrtApis::GetDenotationFromTypeInfo, _In_ const OrtTypeInfo* type_info, _Out_ const char** const out, - _Out_ size_t* len) { +ORT_API_STATUS_IMPL(OrtApis::GetDenotationFromTypeInfo, _In_ const OrtTypeInfo* type_info, + _Out_ const char** const out, _Out_ size_t* len) { API_IMPL_BEGIN *out = type_info->denotation.c_str(); *len = type_info->denotation.size(); @@ -93,6 +95,61 @@ ORT_API_STATUS_IMPL(OrtApis::GetDenotationFromTypeInfo, _In_ const OrtTypeInfo* API_IMPL_END } +#if !defined(ORT_MINIMAL_BUILD) +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Out_ OrtTypeInfo** type_info) { + API_IMPL_BEGIN + auto ti = std::make_unique(ONNXType::ONNX_TYPE_TENSOR); + ti->tensor_type_info = tensor_info->Clone(); + *type_info = ti.release(); + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateSparseTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Out_ OrtTypeInfo** type_info) { + API_IMPL_BEGIN + auto ti = std::make_unique(ONNXType::ONNX_TYPE_SPARSETENSOR); + ti->tensor_type_info = tensor_info->Clone(); + *type_info = ti.release(); + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateMapTypeInfo, ONNXTensorElementDataType map_key_type, + _In_ const OrtTypeInfo* map_value_type, _Out_ OrtTypeInfo** type_info) { + API_IMPL_BEGIN + auto ti = std::make_unique(ONNXType::ONNX_TYPE_MAP); + ti->map_type_info = std::make_unique(map_key_type, map_value_type->Clone()); + *type_info = ti.release(); + + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateSequenceTypeInfo, _In_ const OrtTypeInfo* sequence_type, + _Out_ OrtTypeInfo** type_info) { + API_IMPL_BEGIN + auto ti = std::make_unique(ONNXType::ONNX_TYPE_SEQUENCE); + ti->sequence_type_info = std::make_unique(sequence_type->Clone()); + *type_info = ti.release(); + + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateOptionalTypeInfo, _In_ const OrtTypeInfo* contained_type, + _Out_ OrtTypeInfo** type_info) { + API_IMPL_BEGIN + auto ti = std::make_unique(ONNXType::ONNX_TYPE_OPTIONAL); + ti->optional_type_info = std::make_unique(contained_type->Clone()); + *type_info = ti.release(); + + return nullptr; + API_IMPL_END +} +#endif // !defined(ORT_MINIMAL_BUILD) + ORT_API(void, OrtApis::ReleaseTypeInfo, _Frees_ptr_opt_ OrtTypeInfo* ptr) { std::unique_ptr p(ptr); } @@ -298,8 +355,8 @@ std::unique_ptr OrtTypeInfo::Clone() const { #endif case ONNX_TYPE_TENSOR: { std::unique_ptr info; - if (data) { - info = data->Clone(); + if (tensor_type_info) { + info = tensor_type_info->Clone(); } result = MakePtr(type, std::move(info)); result->denotation = denotation; diff --git a/onnxruntime/core/framework/onnxruntime_typeinfo.h b/onnxruntime/core/framework/onnxruntime_typeinfo.h index 72d263d5fa442..54bb946e0d36b 100644 --- a/onnxruntime/core/framework/onnxruntime_typeinfo.h +++ b/onnxruntime/core/framework/onnxruntime_typeinfo.h @@ -31,7 +31,7 @@ struct OrtTypeInfo { ONNXType type; std::string denotation; - std::unique_ptr data; + std::unique_ptr tensor_type_info; std::unique_ptr map_type_info; std::unique_ptr sequence_type_info; std::unique_ptr optional_type_info; diff --git a/onnxruntime/core/framework/session_state_utils.cc b/onnxruntime/core/framework/session_state_utils.cc index 83a353615bc35..343d634b44691 100644 --- a/onnxruntime/core/framework/session_state_utils.cc +++ b/onnxruntime/core/framework/session_state_utils.cc @@ -203,13 +203,12 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st } } -common::Status AllocateTensor( - const onnxruntime::MemBuffer* m, - std::unique_ptr& p_tensor, - const onnxruntime::DataTypeImpl* const& type, - onnxruntime::TensorShape& tensor_shape, - bool use_device_allocator_for_initializers, - const onnxruntime::AllocatorPtr& alloc) { +common::Status AllocateTensor(const onnxruntime::MemBuffer* m, + std::unique_ptr& p_tensor, + const onnxruntime::DataTypeImpl* const& type, + onnxruntime::TensorShape& tensor_shape, + bool use_device_allocator_for_initializers, + const onnxruntime::AllocatorPtr& alloc) { if (m != nullptr) { p_tensor = std::make_unique(type, tensor_shape, m->GetBuffer(), m->GetAllocInfo()); if (m->GetLen() < p_tensor->SizeInBytes()) { @@ -354,6 +353,7 @@ common::Status SaveInitializedTensors( } ORT_RETURN_IF_ERROR(planner.Trace(entry.first, entry.second)); } + // 2. allocate weight buffer on different locations // planned_initializers_memory_size_in_byte is not actual physical size. // It's the virtual size computed by planner. @@ -386,6 +386,9 @@ common::Status SaveInitializedTensors( if (user_supplied_initializer_ids.find(entry.first) != user_supplied_initializer_ids.end()) { ort_value = *(session_options.initializers_to_share_map.at(name)); LOGS(logger, INFO) << "Using user supplied initializer with name (" << name << ")."; + + } else if (graph.GetOrtValueInitializer(name, ort_value)) { + // populated OrtValue from the Graph instance } else { const ONNX_NAMESPACE::TensorProto& tensor_proto = *(entry.second); @@ -397,10 +400,9 @@ common::Status SaveInitializedTensors( session_options.config_options.GetConfigOrDefault(kOrtSessionOptionsUseDeviceAllocatorForInitializers, "0") == "1"; Tensor* p_tensor = nullptr; - if (auto iter = buffered_tensors.find(name); - iter != buffered_tensors.end()) { - p_tensor = iter->second.release(); - buffered_tensors.erase(iter); + auto buffered_tensors_iter = buffered_tensors.find(name); + if (buffered_tensors_iter != buffered_tensors.end()) { + p_tensor = buffered_tensors_iter->second.get(); } Status st = DeserializeTensorProto(env, graph_loc, tensor_proto, (m.has_value()) ? &*m : nullptr, alloc, @@ -412,6 +414,12 @@ common::Status SaveInitializedTensors( oss << "Deserialize tensor " << name << " failed." << st.ErrorMessage(); return Status(st.Category(), st.Code(), oss.str()); } + + if (p_tensor != nullptr) { + // p_tensor was wrapped in a deleter by DeserializeTensorProto so we can simply release it here. + ORT_IGNORE_RETURN_VALUE(buffered_tensors_iter->second.release()); + buffered_tensors.erase(buffered_tensors_iter); + } } // 'name' is a reference to a string within the TensorProto that save_tensor_func may free diff --git a/onnxruntime/core/framework/tensor_type_and_shape.cc b/onnxruntime/core/framework/tensor_type_and_shape.cc index 418e46924fb9f..9bbea279da82d 100644 --- a/onnxruntime/core/framework/tensor_type_and_shape.cc +++ b/onnxruntime/core/framework/tensor_type_and_shape.cc @@ -49,10 +49,27 @@ ORT_API_STATUS_IMPL(OrtApis::SetTensorElementType, _Inout_ OrtTensorTypeAndShape API_IMPL_END } -ORT_API_STATUS_IMPL(OrtApis::SetDimensions, OrtTensorTypeAndShapeInfo* this_ptr, +ORT_API_STATUS_IMPL(OrtApis::SetDimensions, OrtTensorTypeAndShapeInfo* info, _In_ const int64_t* dim_values, size_t dim_count) { API_IMPL_BEGIN - this_ptr->shape = onnxruntime::TensorShape(dim_values, dim_count); + if (std::any_of(dim_values, dim_values + dim_count, [](int64_t v) { return v < -1; })) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "dim_values must be -1 (symbolic dimension) or larger."); + } + + auto num_dims = std::max(dim_count, info->dim_params.size()); + + // make shape and dim_values consistent + info->dim_params.resize(num_dims, ""); + + onnxruntime::TensorShapeVector dims; + dims.resize(num_dims, -1); + + for (size_t idx = 0; idx < dim_count; ++idx) { + dims[idx] = dim_values[idx]; + } + + info->shape = onnxruntime::TensorShape(dims); + return nullptr; API_IMPL_END } @@ -88,10 +105,22 @@ ORT_API_STATUS_IMPL(OrtApis::GetSymbolicDimensions, ORT_API_STATUS_IMPL(OrtApis::SetSymbolicDimensions, _In_ struct OrtTensorTypeAndShapeInfo* info, _In_ const char** names, _In_ size_t dim_params_length) { + auto num_dims = std::max(info->shape.NumDimensions(), dim_params_length); + + // make shape and dim_values consistent + if (num_dims > info->shape.NumDimensions()) { + auto dim_values = info->shape.AsShapeVector(); + dim_values.resize(num_dims, -1); + info->shape = onnxruntime::TensorShape(dim_values); + } + info->dim_params.clear(); + info->dim_params.resize(num_dims, ""); + for (size_t idx = 0; idx < dim_params_length; ++idx) { - info->dim_params.push_back(names[idx]); + info->dim_params[idx] = names[idx]; } + return nullptr; } diff --git a/onnxruntime/core/framework/tensorprotoutils.cc b/onnxruntime/core/framework/tensorprotoutils.cc index 17c37b8882168..ae1ec2e53bd7c 100644 --- a/onnxruntime/core/framework/tensorprotoutils.cc +++ b/onnxruntime/core/framework/tensorprotoutils.cc @@ -1317,22 +1317,15 @@ ONNX_NAMESPACE::TensorProto TensorToTensorProto(const Tensor& tensor, const auto* raw_data = tensor.DataRaw(); ORT_ENFORCE(raw_data, "Missing raw data for tensor proto. Invalid tensor."); static_assert(sizeof(void*) <= sizeof(ExternalDataInfo::OFFSET_TYPE)); - tensor_proto.set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation_EXTERNAL); // we reinterpret_cast this back to void* in tensorprotoutils.cc:GetExtDataFromTensorProto. // use intptr_t as OFFSET_TYPE is signed. in theory you could get a weird looking value if the address uses the // high bit, but that should be unlikely in a scenario where we care about memory usage enough to use this path. auto offset = narrow(reinterpret_cast(raw_data)); - ONNX_NAMESPACE::StringStringEntryProto* entry = tensor_proto.mutable_external_data()->Add(); - entry->set_key("location"); - entry->set_value(ToUTF8String(onnxruntime::utils::kTensorProtoMemoryAddressTag)); - entry = tensor_proto.mutable_external_data()->Add(); - entry->set_key("offset"); - entry->set_value(std::to_string(offset)); - entry = tensor_proto.mutable_external_data()->Add(); - entry->set_key("length"); - entry->set_value(std::to_string(tensor.SizeInBytes())); + ExternalDataInfo::SetExternalLocationToProto(onnxruntime::utils::kTensorProtoMemoryAddressTag, + offset, tensor.SizeInBytes(), tensor_proto); + } else { utils::SetRawDataInTensorProto(tensor_proto, tensor.DataRaw(), tensor.SizeInBytes()); } diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index e4915616b7b7c..39ffc6a5b0cee 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -7,30 +7,34 @@ #include #include #include -#include #include +#include -#include "core/common/common.h" #include + +#include "core/common/common.h" #include "core/common/inlined_containers.h" #include "core/common/logging/logging.h" #include "core/common/narrow.h" #include "core/flatbuffers/flatbuffers_utils.h" +#include "core/framework/tensor_type_and_shape.h" #include "core/flatbuffers/schema/ort.fbs.h" -#include "core/framework/tensor_shape.h" #include "core/framework/tensor_external_data_info.h" +#include "core/framework/tensor_shape.h" +#include "core/framework/tensor_type_and_shape.h" #include "core/framework/tensorprotoutils.h" #include "core/framework/utils.h" +#include "core/graph/function_utils.h" #include "core/graph/graph_flatbuffers_utils.h" #include "core/graph/graph_viewer.h" #include "core/graph/indexed_sub_graph.h" #include "core/graph/model.h" +#include "core/graph/model_editor_api_types.h" #include "core/graph/model_load_utils.h" #include "core/graph/model_saving_options.h" #include "core/graph/node_attr_utils.h" #include "core/graph/op.h" #include "core/graph/runtime_optimization_record_container.h" -#include "core/graph/function_utils.h" #if !defined(ORT_MINIMAL_BUILD) #include "core/graph/function.h" @@ -3500,6 +3504,10 @@ void Graph::RemoveInitializedTensor(const std::string& tensor_name) { #if !defined(DISABLE_SPARSE_TENSORS) sparse_tensor_names_.erase(tensor_name); #endif + + // doesn't matter if it existed or not + ORT_IGNORE_RETURN_VALUE(ortvalue_initializers_.erase(tensor_name)); + SetGraphResolveNeeded(); } else { #if !defined(DISABLE_SPARSE_TENSORS) @@ -3631,8 +3639,8 @@ Status Graph::InjectExternalInitializersFromFilesInMemory( return Status::OK(); } -#endif // DISABLE_EXTERNAL_INITIALIZERS +#endif // DISABLE_EXTERNAL_INITIALIZERS #endif // !defined(ORT_MINIMAL_BUILD) bool Graph::GetInitializedTensor(const std::string& tensor_name, const TensorProto*& value) const { @@ -3645,6 +3653,16 @@ bool Graph::GetInitializedTensor(const std::string& tensor_name, const TensorPro return true; } +bool Graph::GetOrtValueInitializer(const std::string& name, OrtValue& value) const { + auto it = ortvalue_initializers_.find(name); + if (it == ortvalue_initializers_.end()) { + return false; + } + + value = it->second; + return true; +} + void Graph::CleanAllInitializedTensors() noexcept { name_to_initial_tensor_.clear(); #if !defined(DISABLE_SPARSE_TENSORS) @@ -3660,6 +3678,8 @@ void Graph::CleanAllInitializedTensors() noexcept { delete graph_proto_->mutable_initializer()->ReleaseCleared(); } #endif + + ortvalue_initializers_.clear(); } const ONNX_NAMESPACE::TensorProto* Graph::GetConstantInitializer(const std::string& initializer_name, @@ -3709,13 +3729,14 @@ void Graph::AddValueInfo(const NodeArg* new_value_info) { value_info_.insert(new_value_info); } -std::vector Graph::CreateNodeArgs(const google::protobuf::RepeatedPtrField& names, +template +std::vector Graph::CreateNodeArgs(const StringRange& names, const ArgNameToTypeMap& name_to_type_map) { const auto name_to_type_map_end = name_to_type_map.end(); std::vector results; results.reserve(names.size()); - for (auto& name : names) { + for (const std::string& name : names) { const TypeProto* type = nullptr; auto name_to_type_iter = name_to_type_map.find(name); @@ -4076,27 +4097,51 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProto() const { // This is used for constructing full path for external data // if it exists + auto add_initializer = [](TensorList& output_initializers, const TensorProto& initializer) -> void { + TensorProto& output = *output_initializers.Add(); + output = initializer; + + // copy any in-memory external data into raw data + if (utils::HasExternalData(initializer)) { + const std::filesystem::path ignored; + std::basic_string location; + onnxruntime::FileOffsetType file_offset; + SafeInt tensor_byte_size; + + ORT_THROW_IF_ERROR(utils::GetExternalDataInfo(initializer, ignored, location, file_offset, tensor_byte_size)); + + if (location == onnxruntime::utils::kTensorProtoMemoryAddressTag) { + // file_offset is address + void* data = reinterpret_cast(file_offset); + + // set in raw data + output.clear_data_location(); + output.set_raw_data(data, tensor_byte_size); + } + } + }; + + auto* mutable_initializers = result.mutable_initializer(); + #if !defined(DISABLE_SPARSE_TENSORS) const auto& model_path = ModelPath(); // We want to make sure that sparse initializers do not appear // as dense duplicates within the initializers list. - if (!sparse_tensor_names_.empty()) { - const auto sparse_end = sparse_tensor_names_.end(); - auto* mutable_initializer = result.mutable_initializer(); - for (const auto& initializer : graph_proto_->initializer()) { - if (sparse_end == sparse_tensor_names_.find(initializer.name())) { - *mutable_initializer->Add() = initializer; - } else { - auto& sparse_initializer = *result.add_sparse_initializer(); - auto status = utils::DenseTensorToSparseTensorProto(initializer, model_path, sparse_initializer); - ORT_ENFORCE(status.IsOK(), "Failed to convert dense initializer to sparse"); - } + const bool has_sparse_initializers = !sparse_tensor_names_.empty(); + const auto sparse_end = sparse_tensor_names_.end(); + for (const auto& initializer : graph_proto_->initializer()) { + if (!has_sparse_initializers || sparse_end == sparse_tensor_names_.find(initializer.name())) { + add_initializer(*mutable_initializers, initializer); + } else { + auto& sparse_initializer = *result.add_sparse_initializer(); + auto status = utils::DenseTensorToSparseTensorProto(initializer, model_path, sparse_initializer); + ORT_ENFORCE(status.IsOK(), "Failed to convert dense initializer to sparse"); } - } else { - *result.mutable_initializer() = graph_proto_->initializer(); } #else - *result.mutable_initializer() = graph_proto_->initializer(); + for (const auto& initializer : graph_proto_->initializer()) { + add_initializer(*mutable_initializers, initializer); + } #endif return result; @@ -5345,6 +5390,9 @@ Status Graph::InlineFunction(Node& callnode) { } void Graph::SetInputs(gsl::span inputs) { + graph_inputs_including_initializers_.clear(); + graph_inputs_excluding_initializers_.clear(); + // creating graph from scratch // rely on SetGraphInputsOutputs() to fix up graph_inputs_excluding_initializers_ // if is_loaded_from_model_file_ == false @@ -5353,7 +5401,6 @@ void Graph::SetInputs(gsl::span inputs) { if (is_loaded_from_model_file_) { // graph loaded from model file - graph_inputs_excluding_initializers_.clear(); for (const auto* input : inputs) { ORT_ENFORCE(input->Exists(), "Input to set must exist."); if (name_to_initial_tensor_.find(input->Name()) == name_to_initial_tensor_.end()) { @@ -5370,6 +5417,7 @@ void Graph::SetInputs(gsl::span inputs) { } void Graph::SetOutputs(gsl::span outputs) { + graph_outputs_.clear(); graph_outputs_.reserve(outputs.size()); graph_outputs_.assign(outputs.begin(), outputs.end()); @@ -5688,4 +5736,207 @@ common::Status Graph::LoadFromOrtFormat(const onnxruntime::fbs::Graph& fbs_graph return Status::OK(); } +#if !defined(ORT_MINIMAL_BUILD) +namespace { +ValueInfoProto OrtValueInfoToOnnx(const OrtValueInfo& vi) { + // the model builder API checks that the OrtValueInfo has a complete and valid OrtTypeInfo instance and that the + // name is not null/empty. + ORT_ENFORCE(vi.type_info->type == ONNX_TYPE_TENSOR, + "Internal error. Model Editor API should only allow OrtValueInfo for tensor to be created."); + + ValueInfoProto value_info_proto; + value_info_proto.set_name(vi.name); + + auto* tensor = value_info_proto.mutable_type()->mutable_tensor_type(); + const OrtTensorTypeAndShapeInfo& tensor_info = *vi.type_info->tensor_type_info.get(); + tensor->set_elem_type(tensor_info.type); + + auto& shape = *tensor->mutable_shape(); + + size_t idx = 0; + for (auto dim : tensor_info.shape.GetDims()) { + auto& dim_proto = *shape.add_dim(); + if (dim >= 0) { + dim_proto.set_dim_value(dim); + } else { + const std::string& dim_param = tensor_info.dim_params[idx]; + // if empty leave the new dim_proto with neither dim_value nor dim_param set. this represents an 'unknown' dim + if (!dim_param.empty()) { + dim_proto.set_dim_param(dim_param); + } + } + } + + return value_info_proto; +} +} // namespace + +Status Graph::LoadFromModelEditorApiModel(const OrtGraph& api_graph, bool updating_existing_graph) { + ArgNameToTypeMap name_to_type_map; + + // NOTE: need to create NodeArgs as we go along + + // add inputs first. the shape from an input for a non-const initializer is preferred, so we want to create the + // NodeArg for the value using that + + auto add_graph_inputs_outputs = [&, this]( + const InlinedVector>& graph_inputs_or_outputs, + bool is_input) { + // when updating a model we don't require the inputs or outputs to be set if they're unchanged. + if (updating_existing_graph && graph_inputs_or_outputs.empty()) { + return; + } + + std::vector node_args; + node_args.reserve(graph_inputs_or_outputs.size()); + for (auto& ort_value_info : graph_inputs_or_outputs) { + ValueInfoProto value_info = OrtValueInfoToOnnx(*ort_value_info); + + name_to_type_map[value_info.name()] = value_info.type(); + node_args.push_back(&GetOrCreateNodeArg(value_info.name(), &value_info.type())); + } + + if (is_input) { + SetInputs(node_args); + } else { + SetOutputs(node_args); + } + }; + + auto add_initializers = [this](const std::unordered_map>& initializers, + bool is_external) { + for (auto& name_and_ortvalue : initializers) { + // convert from OrtValue to TensorProto + const std::string& name = name_and_ortvalue.first; + OrtValue& v = *name_and_ortvalue.second; + + ORT_ENFORCE(v.IsTensor(), "Initializers must be Tensors"); + const Tensor& t = v.Get(); + TensorProto& tensor_proto = *graph_proto_->add_initializer(); + + tensor_proto.set_name(name); + tensor_proto.set_data_type(t.GetElementType()); + for (auto dim : t.Shape().GetDims()) { + tensor_proto.add_dims(dim); + } + + if (is_external) { + // pre-existing memory that we don't own. avoid a copy by storing the pointer in the ExternalDataInfo + const void* data_offset = t.DataRaw(); // address of memory not offset into file + auto offset = narrow(reinterpret_cast(data_offset)); + + ExternalDataInfo::SetExternalLocationToProto(onnxruntime::utils::kTensorProtoMemoryAddressTag, + offset, t.SizeInBytes(), tensor_proto); + + // add OrtValue to ortvalue_initializers_ to keep it alive and to store the deleter if provided. + ortvalue_initializers_.emplace(name, std::move(v)); + } else { + tensor_proto.set_raw_data(t.DataRaw(), t.SizeInBytes()); + } + + TypeProto type_proto{TypeProtoFromTensorProto(tensor_proto)}; + ORT_IGNORE_RETURN_VALUE(GetOrCreateNodeArg(name, &type_proto)); + + name_to_initial_tensor_.emplace(name, &tensor_proto); + } + }; + + // process graph inputs first as we want the type/shape from them to be preferred if a graph input + // has a matching initializer + add_graph_inputs_outputs(api_graph.inputs, /*input*/ true); + + // add initializers + ortvalue_initializers_.reserve(api_graph.external_initializers.size()); + add_initializers(api_graph.external_initializers, /*is_external*/ true); + add_initializers(api_graph.initializers, /*is_external*/ false); + + // add graph outputs + add_graph_inputs_outputs(api_graph.outputs, /*input*/ false); + + // add nodes + for (const auto& ort_node : api_graph.nodes) { + const OrtNode& node = *ort_node; + + // convert Constant nodes to initializers + if (node.operator_name == "Constant" && node.domain_name == kOnnxDomain) { + // graph_proto_ provides storage + TensorProto& tensor = *graph_proto_->add_initializer(); + + // create NodeProto from OrtNode so we can use the existing conversion functions + NodeProto node_proto; + + // 'Constant' node has no inputs or attributes + ORT_RETURN_IF_NOT(node.input_names.empty() && node.attributes.size() == 1 && node.output_names.size() == 1, + node.node_name, + " is an invalid 'Constant' node. " + "Must have no inputs, one attribute and one output. "); + + node_proto.add_attribute()->CopyFrom(node.attributes[0]); + node_proto.add_output(node.output_names[0]); + + node_proto.set_op_type(node.operator_name); + node_proto.set_name(node.node_name); + node_proto.set_domain(node.domain_name); + + ORT_RETURN_IF_ERROR(utils::ConstantNodeProtoToTensorProto(node_proto, /*model_path*/ "", tensor)); + name_to_initial_tensor_.emplace(node.output_names[0], &tensor); + + continue; + } + + auto input_defs = CreateNodeArgs(node.input_names, name_to_type_map); + auto output_defs = CreateNodeArgs(node.output_names, name_to_type_map); + + const auto num_attributes = node.attributes.size(); + + NodeAttributes attributes; + attributes.reserve(num_attributes); + + for (const auto& attr : node.attributes) { + attributes[attr.name()] = attr; + } + + ORT_IGNORE_RETURN_VALUE(AddNode(node.node_name, node.operator_name, /*doc_string*/ "", + input_defs, output_defs, &attributes, node.domain_name)); + } + + return Resolve(); +} + +// static +Status Graph::LoadFromModelEditorApiModel(const OrtGraph& api_graph, + const Model& owning_model, + const std::unordered_map& domain_to_version, + IOnnxRuntimeOpSchemaCollectionPtr schema_registry, + bool strict_shape_type_inference, + const logging::Logger& logger, + std::unique_ptr& graph) { + graph = std::make_unique(owning_model, + domain_to_version, + schema_registry, + /*parent_graph*/ nullptr, /*parent_node*/ nullptr, + logger, + strict_shape_type_inference); + + return graph->LoadFromModelEditorApiModel(api_graph); +} + +Status Graph::UpdateUsingModelEditorApiModel(const OrtModel& api_model) { + for (auto& entry : api_model.domain_to_version) { + if (auto it = domain_to_version_.find(entry.first); it != domain_to_version_.end()) { + if (it->second != entry.second) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "Domain version can not be changed for '", entry.first, + "'. Current version: ", it->second); + } + } else { + domain_to_version_.insert(entry); + } + } + + // this will replace inputs/outputs and add nodes. + return LoadFromModelEditorApiModel(*api_model.graph, /*updating_existing_graph*/ true); +} + +#endif // !defined(ORT_MINIMAL_BUILD) } // namespace onnxruntime diff --git a/onnxruntime/core/graph/graph_flatbuffers_utils.cc b/onnxruntime/core/graph/graph_flatbuffers_utils.cc index 922759b02e75f..199aa79cc1dde 100644 --- a/onnxruntime/core/graph/graph_flatbuffers_utils.cc +++ b/onnxruntime/core/graph/graph_flatbuffers_utils.cc @@ -300,8 +300,6 @@ Status LoadInitializerOrtFormat(const fbs::Tensor& fbs_tensor, TensorProto& init const auto* fbs_raw_data = fbs_tensor.raw_data(); if (fbs_raw_data) { if (load_options.can_use_flatbuffer_for_initializers && fbs_raw_data->size() > 127) { - initializer.set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation_EXTERNAL); - static_assert(sizeof(void*) <= sizeof(ExternalDataInfo::OFFSET_TYPE)); const void* data_offset = fbs_raw_data->Data(); // we reinterpret_cast this back to void* in tensorprotoutils.cc:GetExtDataFromTensorProto. @@ -309,15 +307,9 @@ Status LoadInitializerOrtFormat(const fbs::Tensor& fbs_tensor, TensorProto& init // high bit, but that should be unlikely in a scenario where we care about memory usage enough to use this path. auto offset = narrow(reinterpret_cast(data_offset)); - ONNX_NAMESPACE::StringStringEntryProto* entry = initializer.mutable_external_data()->Add(); - entry->set_key("location"); - entry->set_value(ToUTF8String(onnxruntime::utils::kTensorProtoMemoryAddressTag)); - entry = initializer.mutable_external_data()->Add(); - entry->set_key("offset"); - entry->set_value(std::to_string(offset)); - entry = initializer.mutable_external_data()->Add(); - entry->set_key("length"); - entry->set_value(std::to_string(fbs_raw_data->size())); + ExternalDataInfo::SetExternalLocationToProto(onnxruntime::utils::kTensorProtoMemoryAddressTag, + offset, fbs_raw_data->size(), initializer); + } else { // fbs_raw_data is uint8_t vector, so the size is byte size initializer.set_raw_data(fbs_raw_data->Data(), fbs_raw_data->size()); diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index be0531e6473fb..7629e40c1b5fe 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -7,6 +7,7 @@ #include "core/flatbuffers/flatbuffers_utils.h" #include "core/framework/tensorprotoutils.h" #include "core/graph/model.h" +#include "core/graph/model_editor_api_types.h" #include "core/graph/model_load_utils.h" #ifdef _MSC_VER @@ -738,6 +739,36 @@ Status Model::Load(int fd, const PathString& model_path, std::shared_ptr& return Status::OK(); } +// static +common::Status Model::LoadFromModelEditorApiModel(const OrtModel& model_editor_api_model, + const IOnnxRuntimeOpSchemaRegistryList* local_registries, + const ModelOptions& options, + const logging::Logger& logger, + std::unique_ptr& model) { + model = std::make_unique(); + model->model_proto_.set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION); + // The optimizer Initializer class requires a path if external data is used, however in the Graph API usage the + // external data is pointing to pre-allocated memory and does not require a path. Set a dummy value to make it happy. + model->model_path_ = std::filesystem::path("_GRAPH_API_MODEL_"); + + auto schema_registry = std::make_shared(); + if (local_registries != nullptr) { + for (const auto& schema_collection : *local_registries) { + schema_registry->RegisterRegistry(schema_collection); + } + } + + ORT_RETURN_IF_ERROR(Graph::LoadFromModelEditorApiModel(*model_editor_api_model.graph, + *model, + model_editor_api_model.domain_to_version, + schema_registry, + options.strict_shape_type_inference, + logger, + model->graph_)); + + return Status::OK(); +} + Status Model::Save(Model& model, int p_fd) { if (p_fd < 0) { return Status(ONNXRUNTIME, INVALID_ARGUMENT, " is less than 0."); @@ -917,5 +948,4 @@ common::Status Model::LoadFromOrtFormat(const fbs::Model& fbs_model, #endif return Status::OK(); } - } // namespace onnxruntime diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 2d2086aef41fd..6fd94c60d6b99 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -280,6 +280,12 @@ class Model { const logging::Logger& logger, const ModelOptions& options = {}); + static common::Status LoadFromModelEditorApiModel(const OrtModel& graph_api_model, + const IOnnxRuntimeOpSchemaRegistryList* local_registries, + const ModelOptions& options, + const logging::Logger& logger, + std::unique_ptr& model); + common::Status SaveToOrtFormat(flatbuffers::FlatBufferBuilder& builder, flatbuffers::Offset& model) const; @@ -333,7 +339,7 @@ class Model { ModelMetaData model_metadata_; // Path to model file. May be empty. - const std::filesystem::path model_path_; + std::filesystem::path model_path_; // Main graph of the model. std::unique_ptr graph_; diff --git a/onnxruntime/core/graph/model_editor_api_types.h b/onnxruntime/core/graph/model_editor_api_types.h new file mode 100644 index 0000000000000..d72bd13093b61 --- /dev/null +++ b/onnxruntime/core/graph/model_editor_api_types.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/common/inlined_containers_fwd.h" +#include "core/framework/ort_value.h" +#include "core/framework/onnxruntime_typeinfo.h" +#include "core/graph/onnx_protobuf.h" + +// ORT C interface types for OrtGraphApi can't be in a namespace. +// We need to define them here so onnxruntime::Model can be created from OrtModel. + +struct OrtValueInfo { + std::string name; + std::unique_ptr type_info; +}; + +struct OrtOpAttr { + ONNX_NAMESPACE::AttributeProto attr_proto; +}; + +struct OrtNode { + std::string operator_name; + std::string domain_name; + std::string node_name; + + // OrtOpAttr is 1:1 with ONNX_NAMESPACE::AttributeProto currently. + // https://github.com/microsoft/onnxruntime/blob/bd5a759d0cdbed6e7f611c990d4eb5457a9ecf60/onnxruntime/core/session/standalone_op_invoker.cc#L318 + onnxruntime::InlinedVector attributes; + onnxruntime::InlinedVector input_names; + onnxruntime::InlinedVector output_names; + + // FUTURE if we need control flow nodes + // std::unordered_map subgraphs; +}; + +struct OrtGraph { + onnxruntime::InlinedVector> inputs; + onnxruntime::InlinedVector> outputs; + std::unordered_map> initializers; + std::unordered_map> external_initializers; + std::vector> nodes; +}; + +struct OrtModel { + std::unique_ptr graph; + std::unordered_map domain_to_version; +}; diff --git a/onnxruntime/core/session/abi_session_options.cc b/onnxruntime/core/session/abi_session_options.cc index 7ef23d6c9e895..2e733f67a888c 100644 --- a/onnxruntime/core/session/abi_session_options.cc +++ b/onnxruntime/core/session/abi_session_options.cc @@ -1,17 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/graph/onnx_protobuf.h" -#include "core/common/inlined_containers.h" -#include "core/session/onnxruntime_c_api.h" -#include "core/session/ort_apis.h" -#include "core/framework/error_code_helper.h" -#include #include +#include #include + +#include "core/common/inlined_containers.h" +#include "core/framework/error_code_helper.h" +#include "core/graph/onnx_protobuf.h" +#include "core/session/abi_session_options_impl.h" #include "core/session/inference_session.h" -#include "abi_session_options_impl.h" -#include "api_utils.h" +#include "core/session/onnxruntime_c_api.h" +#include "core/session/ort_apis.h" +#include "core/session/utils.h" OrtSessionOptions::~OrtSessionOptions() = default; diff --git a/onnxruntime/core/session/api_utils.cc b/onnxruntime/core/session/api_utils.cc deleted file mode 100644 index f7cb8520b1e5d..0000000000000 --- a/onnxruntime/core/session/api_utils.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "api_utils.h" - -onnxruntime::common::Status CopyStringToOutputArg(std::string_view str, const char* err_msg, char* out, size_t* size) { - const size_t str_len = str.size(); - const size_t req_size = str_len + 1; - - if (out == nullptr) { // User is querying the total output buffer size - *size = req_size; - return onnxruntime::common::Status::OK(); - } - - if (*size >= req_size) { // User provided a buffer of sufficient size - std::memcpy(out, str.data(), str_len); - out[str_len] = '\0'; - *size = req_size; - return onnxruntime::common::Status::OK(); - } - - // User has provided a buffer that is not large enough - *size = req_size; - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, err_msg); -} diff --git a/onnxruntime/core/session/api_utils.h b/onnxruntime/core/session/api_utils.h deleted file mode 100644 index 27c2bbd66f8d5..0000000000000 --- a/onnxruntime/core/session/api_utils.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "core/common/common.h" -#include - -onnxruntime::common::Status CopyStringToOutputArg(std::string_view str, const char* err_msg, char* out, size_t* size); diff --git a/onnxruntime/core/session/custom_ops.cc b/onnxruntime/core/session/custom_ops.cc index 8492391172133..bb9f278d83cf7 100644 --- a/onnxruntime/core/session/custom_ops.cc +++ b/onnxruntime/core/session/custom_ops.cc @@ -20,7 +20,7 @@ #include "core/framework/tensorprotoutils.h" #include "core/graph/onnx_protobuf.h" #include "core/session/allocator_adapters.h" -#include "core/session/api_utils.h" +#include "core/session/utils.h" #include "core/session/custom_ops.h" #include "core/session/inference_session.h" #include "core/session/ort_apis.h" diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index a1903898ea7f0..e941b1ebbaba8 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -38,6 +38,7 @@ #include "core/framework/utils.h" #include "core/graph/graph_viewer.h" #include "core/graph/model.h" +#include "core/graph/model_editor_api_types.h" #include "core/graph/model_saving_options.h" #include "core/optimizer/graph_transformer_utils.h" #include "core/optimizer/graph_transformer.h" @@ -67,11 +68,11 @@ #include "core/optimizer/stft_decomposition.h" #endif #include "core/session/environment.h" -#include "core/session/user_logging_sink.h" #include "core/session/IOBinding.h" #include "core/session/inference_session_utils.h" #include "core/session/onnxruntime_session_options_config_keys.h" #include "core/session/onnxruntime_run_options_config_keys.h" +#include "core/session/user_logging_sink.h" #include "core/util/protobuf_parsing_utils.h" #include "core/util/thread_utils.h" @@ -1215,6 +1216,56 @@ common::Status InferenceSession::Load() { return LoadWithLoader(loader, "model_loading_from_saved_proto"); } +common::Status InferenceSession::Load(const OrtModel& model_editor_api_model) { + std::lock_guard l(session_mutex_); + + if (is_model_loaded_) { // already loaded + Status status(common::ONNXRUNTIME, common::MODEL_LOADED, "This session already contains a loaded model."); + LOGS(*session_logger_, ERROR) << status.ErrorMessage(); + return status; + } + + if (is_inited_) { + Status status(common::ONNXRUNTIME, common::MODEL_LOADED, "This session has already been initialized."); + LOGS(*session_logger_, ERROR) << status.ErrorMessage(); + return status; + } + + const bool strict_shape_type_inference = session_options_.config_options.GetConfigOrDefault( + kOrtSessionOptionsConfigStrictShapeTypeInference, "0") == "1"; + + // need to go from unique_ptr to shared_ptr when moving into model_ + std::unique_ptr tmp_model; + ORT_RETURN_IF_ERROR(Model::LoadFromModelEditorApiModel(model_editor_api_model, + HasLocalSchema() ? &custom_schema_registries_ : nullptr, + ModelOptions(true, strict_shape_type_inference), + *session_logger_, tmp_model)); + + model_ = std::move(tmp_model); + + is_model_loaded_ = true; + + return Status::OK(); +} + +common::Status InferenceSession::ApplyUpdates(const OrtModel& model_editor_api_model) { + std::lock_guard l(session_mutex_); + + if (!is_model_loaded_) { + Status status(common::ONNXRUNTIME, common::MODEL_LOADED, "This session does not contain a loaded model."); + LOGS(*session_logger_, ERROR) << status.ErrorMessage(); + return status; + } + + if (is_inited_) { + Status status(common::ONNXRUNTIME, common::MODEL_LOADED, "This session has already been initialized."); + LOGS(*session_logger_, ERROR) << status.ErrorMessage(); + return status; + } + + return model_->MainGraph().UpdateUsingModelEditorApiModel(model_editor_api_model); +} + common::Status InferenceSession::TransformGraph(onnxruntime::Graph& graph, bool saving_model_in_ort_format) { // The transformer order: // 1. Ensure we inline as many functions as possible. We refer to it as Ahead Of Time (AOT) function inlining. @@ -3336,6 +3387,10 @@ common::Status InferenceSession::WaitForNotification(Notification* p_executor_do return Status::OK(); } +const Model& InferenceSession::GetModel() const { + return *model_; +} + SessionIOBinding::SessionIOBinding(InferenceSession* session) : sess_(session) { ORT_ENFORCE(session->NewIOBinding(&binding_).IsOK()); } diff --git a/onnxruntime/core/session/inference_session.h b/onnxruntime/core/session/inference_session.h index 2c0c09dfd3e51..5b484103c9ecf 100644 --- a/onnxruntime/core/session/inference_session.h +++ b/onnxruntime/core/session/inference_session.h @@ -47,6 +47,9 @@ namespace ONNX_NAMESPACE { class ModelProto; } // namespace ONNX_NAMESPACE +// OrtModelEditorApi Model. Used to dynamically construct a model via C API at runtime. +struct OrtModel; + namespace onnxruntime { // forward declarations class CustomRegistry; class Environment; @@ -320,6 +323,27 @@ class InferenceSession { * @return OK if success. */ [[nodiscard]] common::Status Load(); + + /** + * Load an OrtModel that was dynamically constructed via OrtModelEditorApi. + * + * @param graph_api_model OrtModel from OrtModelEditorApi + * @return OK if success. + */ + [[nodiscard]] common::Status Load(const OrtModel& graph_api_model); + + /** + * Apply updates from an OrtModel that was created via OrtModelEditorApi. + * This can: + * - add nodes at the start and end of the model + * - add initializers + * - update the graph inputs/outputs + * + * @param graph_api_model OrtModel from OrtModelEditorApi + * @return OK if success. + */ + [[nodiscard]] common::Status ApplyUpdates(const OrtModel& graph_api_model); + #endif // !defined(ORT_MINIMAL_BUILD) /** @@ -571,6 +595,8 @@ class InferenceSession { #endif + const Model& GetModel() const; + protected: #if !defined(ORT_MINIMAL_BUILD) @@ -627,6 +653,12 @@ class InferenceSession { /// convenience pointer to logger. should always be the same as session_state_.Logger(); const logging::Logger* session_logger_; + // The list of execution providers. + // This MUST be prior to model_ in case there are values in the model that were allocated using an allocator + // provided by the EP. If that is the case the allocator's `free` implementation may depend on other parts of the + // EP instance. + ExecutionProviders execution_providers_; + // The model served by this inference session instance. // Currently this has to be a shared ptr because the Model::Load method // returns a shared_ptr only. Ideally factory functions should always return @@ -637,9 +669,6 @@ class InferenceSession { // The file path of where the model was loaded. e.g. /tmp/test_squeezenet/model.onnx PathString model_location_; - // The list of execution providers. - ExecutionProviders execution_providers_; - private: ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(InferenceSession); void SetLoggingManager(const SessionOptions& session_options, diff --git a/onnxruntime/core/session/model_editor_api.h b/onnxruntime/core/session/model_editor_api.h new file mode 100644 index 0000000000000..71004866bc867 --- /dev/null +++ b/onnxruntime/core/session/model_editor_api.h @@ -0,0 +1,65 @@ +namespace OrtModelEditorAPI { + +// implementation that returns the API struct +ORT_API(const OrtModelEditorApi*, GetModelEditorApi); + +// APIs to create/edit type info +ORT_API_STATUS_IMPL(CreateTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Out_ OrtTypeInfo** type_info); +ORT_API_STATUS_IMPL(CreateSparseTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Out_ OrtTypeInfo** type_info); +ORT_API_STATUS_IMPL(CreateMapTypeInfo, ONNXTensorElementDataType map_key_type, _In_ const OrtTypeInfo* map_value_type, + _Out_ OrtTypeInfo** type_info); +ORT_API_STATUS_IMPL(CreateSequenceTypeInfo, _In_ const OrtTypeInfo* sequence_type, _Out_ OrtTypeInfo** type_info); +ORT_API_STATUS_IMPL(CreateOptionalTypeInfo, _In_ const OrtTypeInfo* contained_type, _Out_ OrtTypeInfo** type_info); + +ORT_API_STATUS_IMPL(CreateValueInfo, _In_ const char* name, _In_ const OrtTypeInfo* type_info, + _Outptr_ OrtValueInfo** value_info); + +ORT_API_STATUS_IMPL(CreateNode, const char* operator_name, const char* domain_name, _In_ const char* node_name, + _In_reads_(input_names_len) const char* const* input_names, size_t input_names_len, + _In_reads_(output_names_len) const char* const* output_names, size_t output_names_len, + _In_reads_(attribs_len) _Inout_opt_ OrtOpAttr** attributes, _In_opt_ size_t attribs_len, + _Outptr_ OrtNode** node); + +ORT_API_STATUS_IMPL(CreateGraph, _Outptr_ OrtGraph** graph); +ORT_API_STATUS_IMPL(SetGraphInputs, _In_ OrtGraph* graph, + _In_reads_(inputs_len) _In_ OrtValueInfo** inputs, _In_ size_t inputs_len); +ORT_API_STATUS_IMPL(SetGraphOutputs, _In_ OrtGraph* graph, + _In_reads_(outputs_len) _In_ OrtValueInfo** outputs, _In_ size_t outputs_len); +ORT_API_STATUS_IMPL(AddInitializerToGraph, _In_ OrtGraph* graph, _In_ const char* name, _Inout_ OrtValue* tensor, + bool data_is_external); +ORT_API_STATUS_IMPL(AddNodeToGraph, _In_ OrtGraph* graph, _Inout_ OrtNode* node); + +ORT_API_STATUS_IMPL(CreateModel, + _In_reads_(opset_entries_len) const char* const* domain_names, + _In_reads_(opset_entries_len) const int* opset_versions, + size_t opset_entries_len, + _Outptr_ OrtModel** model); +ORT_API_STATUS_IMPL(AddGraphToModel, _In_ OrtModel* model, _Inout_ OrtGraph* graph); + +ORT_API_STATUS_IMPL(CreateSessionFromModel, _In_ const OrtEnv* env, _In_ const OrtModel* model, + _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out); + +// +// Model editing APIs for updating existing model by adding node/s at start or end. +// +ORT_API_STATUS_IMPL(CreateModelEditorSession, _In_ const OrtEnv* env, + _In_ const ORTCHAR_T* model_path, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out); + +ORT_API_STATUS_IMPL(CreateModelEditorSessionFromArray, _In_ const OrtEnv* env, + _In_ const void* model_data, size_t model_data_length, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out); + +ORT_API_STATUS_IMPL(SessionGetOpsetForDomain, _In_ const OrtSession* session, _In_ const char* domain, + _Out_ int* opset); + +ORT_API_STATUS_IMPL(ApplyModelToModelEditorSession, _In_ OrtSession* session, _In_ OrtModel* model); + +ORT_API_STATUS_IMPL(FinalizeModelEditorSession, _In_ OrtSession* session, _In_ const OrtSessionOptions* options, + _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container); + +} // namespace OrtModelEditorAPI diff --git a/onnxruntime/core/session/model_editor_c_api.cc b/onnxruntime/core/session/model_editor_c_api.cc new file mode 100644 index 0000000000000..2f09b903ed941 --- /dev/null +++ b/onnxruntime/core/session/model_editor_c_api.cc @@ -0,0 +1,358 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#if !defined(ORT_MINIMAL_BUILD) + +#include + +#include "core/framework/error_code_helper.h" +#include "core/framework/ort_value.h" +#include "core/framework/onnxruntime_typeinfo.h" +#include "core/framework/tensor_type_and_shape.h" +#include "core/graph/constants.h" +#include "core/graph/model.h" +#include "core/graph/model_editor_api_types.h" +#include "core/graph/onnx_protobuf.h" +#include "core/session/abi_session_options_impl.h" +#include "core/session/inference_session.h" +#include "core/session/model_editor_api.h" +#include "core/session/ort_apis.h" +#include "core/session/ort_env.h" +#include "core/session/utils.h" + +using namespace onnxruntime; + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateValueInfo, _In_ const char* name, _In_ const OrtTypeInfo* type_info, + _Outptr_ OrtValueInfo** value_info) { + API_IMPL_BEGIN + if (name == nullptr || *name == '\0') { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "name cannot be null or empty string"); + } + + if (type_info == nullptr) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "type_info cannot be null"); + } + + if (type_info->type != ONNX_TYPE_TENSOR) { + return OrtApis::CreateStatus(ORT_FAIL, "Only tensor types are supported currently"); + } + + if (type_info->tensor_type_info == nullptr) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "tensor_type_info cannot be null"); + } + + auto vi = std::make_unique(); + vi->name = name; + vi->type_info = type_info->Clone(); + + *value_info = vi.release(); + + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateNode, const char* operator_name, const char* domain_name, + _In_ const char* node_name, + _In_reads_(input_names_len) const char* const* input_names, size_t input_names_len, + _In_reads_(output_names_len) const char* const* output_names, size_t output_names_len, + _In_reads_(attribs_len) _Inout_opt_ OrtOpAttr** attributes, _In_opt_ size_t attribs_len, + _Outptr_ OrtNode** node) { + API_IMPL_BEGIN + auto n = std::make_unique(); + n->operator_name = operator_name; + n->domain_name = domain_name == kOnnxDomainAlias ? kOnnxDomain : domain_name; + n->node_name = node_name; + + n->input_names.reserve(input_names_len); + for (size_t i = 0; i < input_names_len; ++i) { + n->input_names.push_back(input_names[i]); + } + + n->output_names.reserve(output_names_len); + for (size_t i = 0; i < output_names_len; ++i) { + n->output_names.push_back(output_names[i]); + } + + if (attributes != nullptr) { + n->attributes.reserve(attribs_len); + for (size_t i = 0; i < attribs_len; ++i) { + n->attributes.push_back(*reinterpret_cast(attributes[i])); + // take ownership. as we took a copy that means releasing the original value + OrtApis::ReleaseOpAttr(attributes[i]); + attributes[i] = nullptr; + } + } + + *node = n.release(); + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateGraph, _Outptr_ OrtGraph** graph) { + API_IMPL_BEGIN + auto g = std::make_unique(); + + // do some reserves to reduce reallocation. if we had a hint about sizes upfront that would be optimal + g->initializers.reserve(32); + g->external_initializers.reserve(32); + g->nodes.reserve(64); + + *graph = g.release(); + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::SetGraphInputs, _In_ OrtGraph* graph, + _In_reads_(inputs_len) _In_ OrtValueInfo** inputs, _In_ size_t inputs_len) { + API_IMPL_BEGIN + graph->inputs.clear(); + for (size_t i = 0; i < inputs_len; ++i) { + if (inputs[i] == nullptr) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "inputs cannot contain null entries"); + } + + graph->inputs.push_back(std::unique_ptr(inputs[i])); // take ownership + inputs[i] = nullptr; + } + + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::SetGraphOutputs, _In_ OrtGraph* graph, + _In_reads_(outputs_len) _In_ OrtValueInfo** outputs, _In_ size_t outputs_len) { + API_IMPL_BEGIN + graph->outputs.clear(); + for (size_t i = 0; i < outputs_len; ++i) { + if (outputs[i] == nullptr) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "outputs cannot contain null entries"); + } + + graph->outputs.push_back(std::unique_ptr(outputs[i])); // take ownership + outputs[i] = nullptr; + } + + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::AddInitializerToGraph, _In_ OrtGraph* graph, _In_ const char* name, + _Inout_ OrtValue* tensor, bool data_is_external) { + API_IMPL_BEGIN + if (!tensor->IsTensor()) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "Only Tensor is currently supported."); + } + + if (!tensor->IsAllocated()) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "Tensor must be allocated."); + } + + const auto& t = tensor->Get(); + if (t.Location().device.Type() != OrtDevice::CPU) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "Only CPU based tensors are currently supported."); + } + + if (data_is_external) { + // enforce that an external initializer is not used if the data size is < 128 bytes. + // the reason for this is to avoid potential shape inferencing errors if this initializer is providing an + // input involved in that. the ONNX shape inferencing does not support external data for those values. + // e.g. Reshape's `shape` input, Reduce's `axes', Slice's `starts`, `ends`, `steps`, Clip's `min`, `max`, etc. + if (t.SizeInBytes() < 128) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, + "External initializer should only be used for data >= 128 bytes. " + "Please use CreateTensorAsOrtValue instead."); + } + + graph->external_initializers[name] = std::unique_ptr(tensor); // take ownership + } else { + graph->initializers[name] = std::unique_ptr(tensor); // take ownership + } + + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::AddNodeToGraph, _In_ OrtGraph* graph, _Inout_ OrtNode* node) { + API_IMPL_BEGIN + graph->nodes.push_back(std::unique_ptr(node)); // take ownership + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateModel, + _In_reads_(opset_entries_len) const char* const* domain_names, + _In_reads_(opset_entries_len) const int* opset_versions, + size_t opset_entries_len, + _Outptr_ OrtModel** model) { + API_IMPL_BEGIN + auto m = std::make_unique(); + for (size_t i = 0; i < opset_entries_len; ++i) { + m->domain_to_version[domain_names[i]] = opset_versions[i]; + } + + *model = m.release(); + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::AddGraphToModel, _In_ OrtModel* model, _Inout_ OrtGraph* graph) { + API_IMPL_BEGIN + + if (graph == nullptr) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "graph cannot be null"); + } + + model->graph = std::unique_ptr(graph); // take ownership + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateSessionFromModel, _In_ const OrtEnv* env, _In_ const OrtModel* model, + _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out) { + API_IMPL_BEGIN + + std::unique_ptr sess; + OrtStatus* status = nullptr; + *out = nullptr; + + ORT_TRY { + sess = std::make_unique( + options == nullptr ? onnxruntime::SessionOptions() : options->value, + env->GetEnvironment()); + + ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load(*model)); + + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); + + *out = reinterpret_cast(sess.release()); + } + ORT_CATCH(const std::exception& e) { + ORT_HANDLE_EXCEPTION([&]() { + status = OrtApis::CreateStatus(ORT_FAIL, e.what()); + }); + } + + return status; + + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateModelEditorSession, + _In_ const OrtEnv* env, _In_ const ORTCHAR_T* model_path, _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out) { + API_IMPL_BEGIN + std::unique_ptr session; + OrtStatus* status = nullptr; + *out = nullptr; + + ORT_TRY { + ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, model_path, nullptr, 0, session)); + *out = reinterpret_cast(session.release()); + } + ORT_CATCH(const std::exception& e) { + ORT_HANDLE_EXCEPTION([&]() { + status = OrtApis::CreateStatus(ORT_FAIL, e.what()); + }); + } + + return status; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::CreateModelEditorSessionFromArray, _In_ const OrtEnv* env, + _In_ const void* model_data, size_t model_data_length, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out) { + API_IMPL_BEGIN + std::unique_ptr session; + OrtStatus* status = nullptr; + *out = nullptr; + + ORT_TRY { + ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, nullptr, model_data, model_data_length, session)); + *out = reinterpret_cast(session.release()); + } + ORT_CATCH(const std::exception& e) { + ORT_HANDLE_EXCEPTION([&]() { + status = OrtApis::CreateStatus(ORT_FAIL, e.what()); + }); + } + + return status; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::SessionGetOpsetForDomain, _In_ const OrtSession* ort_session, + _In_ const char* domain, _Out_ int* opset) { + const auto& session = *reinterpret_cast(ort_session); + const auto& domain_opset_map = session.GetModel().MainGraph().DomainToVersionMap(); + + auto it = domain_opset_map.find(domain); + if (it == domain_opset_map.cend()) { + return OrtApis::CreateStatus(ORT_FAIL, "Domain not used by model."); + } + + *opset = it->second; + return nullptr; +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::ApplyModelToModelEditorSession, + _In_ OrtSession* session, _In_ OrtModel* model) { + API_IMPL_BEGIN + auto sess = reinterpret_cast(session); + ORT_API_RETURN_IF_STATUS_NOT_OK(sess->ApplyUpdates(*model)); + return nullptr; + API_IMPL_END +} + +ORT_API_STATUS_IMPL(OrtModelEditorAPI::FinalizeModelEditorSession, _In_ OrtSession* session, + _In_ const OrtSessionOptions* options, + _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container) { + API_IMPL_BEGIN + auto sess = reinterpret_cast(session); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess, prepacked_weights_container)); + return nullptr; + API_IMPL_END +} + +static constexpr OrtModelEditorApi ort_model_editor_api = { + // NOTE: The C# bindings depend on the API order within this struct so all additions must be at the end, + // and no functions can be removed (the implementation needs to change to return an error). + + &OrtModelEditorAPI::CreateTensorTypeInfo, + &OrtModelEditorAPI::CreateSparseTensorTypeInfo, + &OrtModelEditorAPI::CreateMapTypeInfo, + &OrtModelEditorAPI::CreateSequenceTypeInfo, + &OrtModelEditorAPI::CreateOptionalTypeInfo, + + &OrtModelEditorAPI::CreateValueInfo, + + &OrtModelEditorAPI::CreateNode, + + &OrtModelEditorAPI::CreateGraph, + &OrtModelEditorAPI::SetGraphInputs, + &OrtModelEditorAPI::SetGraphOutputs, + &OrtModelEditorAPI::AddInitializerToGraph, + &OrtModelEditorAPI::AddNodeToGraph, + + &OrtModelEditorAPI::CreateModel, + &OrtModelEditorAPI::AddGraphToModel, + + &OrtModelEditorAPI::CreateSessionFromModel, + + &OrtModelEditorAPI::CreateModelEditorSession, + &OrtModelEditorAPI::CreateModelEditorSessionFromArray, + &OrtModelEditorAPI::SessionGetOpsetForDomain, + &OrtModelEditorAPI::ApplyModelToModelEditorSession, + &OrtModelEditorAPI::FinalizeModelEditorSession, +}; + +// checks that we don't violate the rule that the functions must remain in the slots they were originally assigned +static_assert(offsetof(OrtModelEditorApi, FinalizeModelEditorSession) / sizeof(void*) == 19, + "Size of version 21 API cannot change"); // initial version in ORT 1.21 + +ORT_API(const OrtModelEditorApi*, OrtModelEditorAPI::GetModelEditorApi) { + return &ort_model_editor_api; +} + +#endif // !defined(ORT_MINIMAL_BUILD) diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 4eedcd591154f..0e23d7a791bec 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -1,45 +1,47 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/session/onnxruntime_c_api.h" -#include "core/session/allocator_adapters.h" -#include "core/session/inference_session_utils.h" -#include "core/session/IOBinding.h" -#include "core/framework/allocator.h" -#include "core/framework/error_code_helper.h" -#include "core/framework/execution_provider.h" -#include "core/framework/tensor_type_and_shape.h" -#include "core/framework/utils.h" #include #include #include +#include #include #include "core/common/common.h" #include "core/common/logging/logging.h" #include "core/common/narrow.h" -#include "core/common/status.h" #include "core/common/safeint.h" -#include "core/graph/constants.h" -#include "core/graph/graph.h" +#include "core/common/status.h" +#include "core/common/string_helper.h" #include "core/framework/allocator.h" -#include "core/framework/tensor.h" +#include "core/framework/allocator.h" +#include "core/framework/callback.h" +#include "core/framework/data_types.h" +#include "core/framework/error_code_helper.h" +#include "core/framework/execution_provider.h" +#include "core/framework/onnxruntime_typeinfo.h" #include "core/framework/ort_value.h" +#include "core/framework/tensor.h" +#include "core/framework/tensor_type_and_shape.h" +#include "core/framework/tensorprotoutils.h" +#include "core/framework/TensorSeq.h" +#include "core/framework/utils.h" +#include "core/graph/constants.h" +#include "core/graph/graph.h" +#include "core/graph/model_editor_api_types.h" #include "core/providers/get_execution_providers.h" +#include "core/session/abi_session_options_impl.h" +#include "core/session/allocator_adapters.h" #include "core/session/environment.h" -#include "core/framework/callback.h" -#include "core/framework/tensorprotoutils.h" -#include "core/framework/onnxruntime_typeinfo.h" #include "core/session/inference_session.h" +#include "core/session/inference_session_utils.h" +#include "core/session/IOBinding.h" +#include "core/session/lora_adapters.h" +#include "core/session/model_editor_api.h" +#include "core/session/onnxruntime_c_api.h" #include "core/session/ort_apis.h" #include "core/session/ort_env.h" -#include "core/framework/data_types.h" -#include "abi_session_options_impl.h" -#include "core/framework/TensorSeq.h" -#include -#include "core/common/string_helper.h" - -#include "core/session/lora_adapters.h" +#include "core/session/utils.h" #ifdef USE_CUDA #include "core/providers/cuda/cuda_provider_factory.h" @@ -114,6 +116,72 @@ using namespace onnxruntime; auto v = (value); \ auto tensor = v->GetMutable(); +namespace { +// Create tensor. Allocates memory. Tensor owns memory. Allocator is wrapped and stored in a shared_ptr in Tensor. +ORT_STATUS_PTR CreateTensorImpl(MLDataType ml_type, const int64_t* shape, size_t shape_len, + OrtAllocator* allocator, OrtValue& value) { + TensorShape tensor_shape(shape, shape_len); + AllocatorPtr alloc_ptr = std::make_shared(allocator); + Tensor::InitOrtValue(ml_type, tensor_shape, std::move(alloc_ptr), value); + return nullptr; +} + +// Create Tensor with existing data. Tensor does not own memory. +ORT_STATUS_PTR CreateTensorImpl(MLDataType ml_type, + const int64_t* shape, size_t shape_len, + const OrtMemoryInfo* info, + void* p_data, size_t p_data_len, + OrtValue& ort_value) { + TensorShape tensor_shape(shape, shape_len); + if (std::any_of(tensor_shape.GetDims().begin(), tensor_shape.GetDims().end(), [](int64_t v) { return v < 0; })) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "tried creating tensor with negative value in shape"); + } + + size_t size_to_allocate = 0; + Status status = Tensor::CalculateTensorStorageSize(ml_type, tensor_shape, 0 /*alignment*/, size_to_allocate); + if (!status.IsOK()) { + return ToOrtStatus(status); + } + if (size_to_allocate > p_data_len) { + std::ostringstream oss; + oss << "not enough space: expected " << size_to_allocate << ", got " << p_data_len; + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, oss.str().c_str()); + } + + Tensor::InitOrtValue(ml_type, tensor_shape, p_data, *info, ort_value); + return nullptr; +} + +ORT_STATUS_PTR CreateTensorImpl(MLDataType ml_type, + const int64_t* shape, size_t shape_len, + OrtAllocator* deleter, + void* p_data, size_t p_data_len, + OrtValue& ort_value) { + TensorShape tensor_shape(shape, shape_len); + if (std::any_of(tensor_shape.GetDims().begin(), tensor_shape.GetDims().end(), [](int64_t v) { return v < 0; })) { + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "tried creating tensor with negative value in shape"); + } + + size_t size_to_allocate = 0; + Status status = Tensor::CalculateTensorStorageSize(ml_type, tensor_shape, 0 /*alignment*/, size_to_allocate); + + if (!status.IsOK()) { + return ToOrtStatus(status); + } + + if (size_to_allocate > p_data_len) { + std::ostringstream oss; + oss << "p_data_len was smaller than expected. Expected:" << size_to_allocate << " Got:" << p_data_len; + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, oss.str().c_str()); + } + + AllocatorPtr alloc_ptr = std::make_shared(deleter); + Tensor::InitOrtValue(ml_type, tensor_shape, p_data, std::move(alloc_ptr), ort_value); + return nullptr; +} + +} // namespace + ORT_API_STATUS_IMPL(OrtApis::CreateEnvWithCustomLogger, OrtLoggingFunction logging_function, _In_opt_ void* logger_param, OrtLoggingLevel logging_level, _In_ const char* logid, _Outptr_ OrtEnv** out) { @@ -187,50 +255,6 @@ ORT_API_STATUS_IMPL(OrtApis::UpdateEnvWithCustomLogLevel, _In_ OrtEnv* ort_env, API_IMPL_END } -ORT_STATUS_PTR CreateTensorImpl(MLDataType ml_type, const int64_t* shape, size_t shape_len, - _Inout_ OrtAllocator* allocator, OrtValue& value) { - TensorShape tensor_shape(shape, shape_len); - AllocatorPtr alloc_ptr = std::make_shared(allocator); - Tensor::InitOrtValue(ml_type, tensor_shape, std::move(alloc_ptr), value); - return nullptr; -} - -ORT_STATUS_PTR CreateTensorImplForSeq(MLDataType elem_type, const int64_t* shape, size_t shape_len, Tensor& out) { - OrtAllocator* allocator; - // TODO(pranav): what allocator should be used to create the tensor here? - // for the sake of simplicity of the API using the default one here - ORT_API_RETURN_IF_ERROR(OrtApis::GetAllocatorWithDefaultOptions(&allocator)); - AllocatorPtr alloc_ptr = std::make_shared(allocator); - TensorShape tensor_shape(shape, shape_len); - out = Tensor(elem_type, tensor_shape, std::move(alloc_ptr)); - return nullptr; -} - -/** - * - * this function will create a copy of the allocator info - */ -ORT_STATUS_PTR CreateTensorImpl(MLDataType ml_type, const int64_t* shape, size_t shape_len, const OrtMemoryInfo* info, - void* p_data, size_t p_data_len, OrtValue& ort_value) { - TensorShape tensor_shape(shape, shape_len); - if (std::any_of(tensor_shape.GetDims().begin(), tensor_shape.GetDims().end(), [](int64_t v) { return v < 0; })) { - return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "tried creating tensor with negative value in shape"); - } - - size_t size_to_allocate = 0; - Status status = Tensor::CalculateTensorStorageSize(ml_type, tensor_shape, 0 /*alignment*/, size_to_allocate); - if (!status.IsOK()) { - return ToOrtStatus(status); - } - if (size_to_allocate > p_data_len) { - std::ostringstream oss; - oss << "not enough space: expected " << size_to_allocate << ", got " << p_data_len; - return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, oss.str().c_str()); - } - Tensor::InitOrtValue(ml_type, tensor_shape, p_data, *info, ort_value); - return nullptr; -} - ORT_API_STATUS_IMPL(OrtApis::CreateTensorWithDataAsOrtValue, _In_ const OrtMemoryInfo* info, _Inout_ void* p_data, size_t p_data_len, _In_ const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type, _Outptr_ OrtValue** out) { @@ -243,6 +267,20 @@ ORT_API_STATUS_IMPL(OrtApis::CreateTensorWithDataAsOrtValue, _In_ const OrtMemor API_IMPL_END } +ORT_API_STATUS_IMPL(OrtApis::CreateTensorWithDataAndDeleterAsOrtValue, _In_ OrtAllocator* deleter, + _In_ void* p_data, size_t p_data_len, + _In_ const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type, + _Outptr_ OrtValue** out) { + API_IMPL_BEGIN + auto ml_type = DataTypeImpl::TensorTypeFromONNXEnum(type)->GetElementType(); + auto value = std::make_unique(); + ORT_API_RETURN_IF_ERROR(CreateTensorImpl(ml_type, shape, shape_len, deleter, p_data, p_data_len, *value)); + *out = value.release(); + return nullptr; + API_IMPL_END +} + ORT_API_STATUS_IMPL(OrtApis::CreateTensorAsOrtValue, _Inout_ OrtAllocator* allocator, _In_ const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type, _Outptr_ OrtValue** out) { @@ -678,97 +716,6 @@ ORT_API_STATUS_IMPL(OrtApis::EnableOrtCustomOps, _Inout_ OrtSessionOptions* opti API_IMPL_END } -namespace { -// provider either model_path, or modal_data + model_data_length. -static ORT_STATUS_PTR CreateSessionAndLoadModel(_In_ const OrtSessionOptions* options, - _In_ const OrtEnv* env, - _In_opt_z_ const ORTCHAR_T* model_path, - _In_opt_ const void* model_data, - size_t model_data_length, - std::unique_ptr& sess) { - // quick check here to decide load path. InferenceSession will provide error message for invalid values. - // TODO: Could move to a helper - const Env& os_env = Env::Default(); // OS environment (!= ORT environment) - bool load_config_from_model = - os_env.GetEnvironmentVar(inference_session_utils::kOrtLoadConfigFromModelEnvVar) == "1"; - - if (load_config_from_model) { -#if !defined(ORT_MINIMAL_BUILD) - if (model_path != nullptr) { - sess = std::make_unique( - options == nullptr ? onnxruntime::SessionOptions() : options->value, - env->GetEnvironment(), - model_path); - } else { - sess = std::make_unique( - options == nullptr ? onnxruntime::SessionOptions() : options->value, - env->GetEnvironment(), - model_data, static_cast(model_data_length)); - } -#else - return OrtApis::CreateStatus(ORT_FAIL, "Loading config from ONNX models is not supported in this build."); -#endif - } else { - sess = std::make_unique( - options == nullptr ? onnxruntime::SessionOptions() : options->value, - env->GetEnvironment()); - } - -#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_MINIMAL_BUILD_CUSTOM_OPS) - // Add custom domains - if (options && !options->custom_op_domains_.empty()) { - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->AddCustomOpDomains(options->custom_op_domains_)); - } -#endif - - // Finish load - if (load_config_from_model) { -#if !defined(ORT_MINIMAL_BUILD) - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load()); -#endif - } else { - if (model_path != nullptr) { - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load(model_path)); - } else { - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load(model_data, static_cast(model_data_length))); - } - } - - return nullptr; -} - -static ORT_STATUS_PTR InitializeSession(_In_ const OrtSessionOptions* options, - _In_ std::unique_ptr<::onnxruntime::InferenceSession>& sess, - _Inout_opt_ OrtPrepackedWeightsContainer* prepacked_weights_container = nullptr) { - // we need to disable mem pattern if DML is one of the providers since DML doesn't have the concept of - // byte addressable memory - std::vector> provider_list; - if (options) { - for (auto& factory : options->provider_factories) { - auto provider = factory->CreateProvider(); - provider_list.push_back(std::move(provider)); - } - } - - // register the providers - for (auto& provider : provider_list) { - if (provider) { - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->RegisterExecutionProvider(std::move(provider))); - } - } - - if (prepacked_weights_container != nullptr) { - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->AddPrePackedWeightsContainer( - reinterpret_cast(prepacked_weights_container))); - } - - ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Initialize()); - - return nullptr; -} - -} // namespace - ORT_API_STATUS_IMPL(OrtApis::CreateSession, _In_ const OrtEnv* env, _In_ const ORTCHAR_T* model_path, _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out) { API_IMPL_BEGIN @@ -778,7 +725,7 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSession, _In_ const OrtEnv* env, _In_ const O ORT_TRY { ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, model_path, nullptr, 0, sess)); - ORT_API_RETURN_IF_ERROR(InitializeSession(options, sess)); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); *out = reinterpret_cast(sess.release()); } @@ -801,7 +748,7 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSessionFromArray, _In_ const OrtEnv* env, _In ORT_TRY { ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, nullptr, model_data, model_data_length, sess)); - ORT_API_RETURN_IF_ERROR(InitializeSession(options, sess)); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); *out = reinterpret_cast(sess.release()); } @@ -1208,7 +1155,6 @@ ORT_API_STATUS_IMPL(OrtApis::GetResizedStringTensorElementBuffer, _Inout_ OrtVal } namespace { - OrtStatusPtr GetTensorStringSpan(const ::OrtValue& v, gsl::span& span) { if (!v.IsAllocated()) { return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "OrtValue should contain a Tensor or a Sparse Tensor"); @@ -2112,7 +2058,6 @@ ORT_API_STATUS_IMPL(OrtApis::GetOpaqueValue, _In_ const char* domain_name, _In_ } namespace { - struct ProviderBuffer { char** buffer_; char* next_write_; @@ -2342,7 +2287,7 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSessionWithPrepackedWeightsContainer, _In_ co ORT_TRY { ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, model_path, nullptr, 0, sess)); - ORT_API_RETURN_IF_ERROR(InitializeSession(options, sess, prepacked_weights_container)); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess, prepacked_weights_container)); *out = reinterpret_cast(sess.release()); } @@ -2368,7 +2313,7 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSessionFromArrayWithPrepackedWeightsContainer ORT_TRY { ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, nullptr, model_data, model_data_length, sess)); - ORT_API_RETURN_IF_ERROR(InitializeSession(options, sess, prepacked_weights_container)); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess, prepacked_weights_container)); *out = reinterpret_cast(sess.release()); } @@ -2410,6 +2355,39 @@ ORT_API_STATUS_IMPL(OrtApis::SessionOptionsSetCustomJoinThreadFn, _Inout_ OrtSes API_IMPL_END } +ORT_API(void, OrtApis::ReleaseValueInfo, _Frees_ptr_opt_ OrtValueInfo* value_info) { + delete value_info; +} + +ORT_API(void, OrtApis::ReleaseNode, _Frees_ptr_opt_ OrtNode* node) { + delete node; +} + +ORT_API(void, OrtApis::ReleaseGraph, _Frees_ptr_opt_ OrtGraph* graph) { + delete graph; +} + +ORT_API(void, OrtApis::ReleaseModel, _Frees_ptr_opt_ OrtModel* model) { + delete model; +} + +ORT_API_STATUS_IMPL(OrtApis::GetValueInfoName, _In_ const OrtValueInfo* value_info, + _Out_ const char** name) { + API_IMPL_BEGIN + *name = value_info->name.c_str(); + return nullptr; + API_IMPL_END +} +ORT_API_STATUS_IMPL(OrtApis::GetValueInfoTypeInfo, _In_ const OrtValueInfo* value_info, + _Outptr_ const OrtTypeInfo** type_info) { + API_IMPL_BEGIN + + *type_info = value_info->type_info.get(); + + return nullptr; + API_IMPL_END +} + ORT_API(const OrtTrainingApi*, OrtApis::GetTrainingApi, uint32_t version) { #ifdef ENABLE_TRAINING_APIS if (version >= 13 && version <= ORT_API_VERSION) @@ -2419,13 +2397,21 @@ ORT_API(const OrtTrainingApi*, OrtApis::GetTrainingApi, uint32_t version) { version, ORT_API_VERSION); return nullptr; #else - ORT_UNUSED_PARAMETER(version); return nullptr; #endif } +ORT_API(const OrtModelEditorApi*, OrtApis::GetModelEditorApi) { +#if !defined(ORT_MINIMAL_BUILD) + return OrtModelEditorAPI::GetModelEditorApi(); +#else + fprintf(stderr, "The Model Editor API is not supported in a minimal build.\n"); + return nullptr; +#endif +} + static constexpr OrtApiBase ort_api_base = { &OrtApis::GetApi, &OrtApis::GetVersionString}; @@ -2812,6 +2798,18 @@ static constexpr OrtApi ort_api_1_to_22 = { &OrtApis::SetEpDynamicOptions, // End of Version 20 - DO NOT MODIFY ABOVE (see above text for more information) + + &OrtApis::ReleaseValueInfo, + &OrtApis::ReleaseNode, + &OrtApis::ReleaseGraph, + &OrtApis::ReleaseModel, + + &OrtApis::GetValueInfoName, + &OrtApis::GetValueInfoTypeInfo, + + &OrtApis::GetModelEditorApi, + + &OrtApis::CreateTensorWithDataAndDeleterAsOrtValue, }; // OrtApiBase can never change as there is no way to know what version of OrtApiBase is returned by OrtGetApiBase. diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h index 52d3c98d526dc..9d8aeb18a782f 100644 --- a/onnxruntime/core/session/ort_apis.h +++ b/onnxruntime/core/session/ort_apis.h @@ -20,6 +20,10 @@ ORT_API(void, ReleaseCustomOpDomain, _Frees_ptr_opt_ OrtCustomOpDomain*); ORT_API(void, ReleaseMapTypeInfo, _Frees_ptr_opt_ OrtMapTypeInfo*); ORT_API(void, ReleaseSequenceTypeInfo, _Frees_ptr_opt_ OrtSequenceTypeInfo*); ORT_API(void, ReleaseModelMetadata, _Frees_ptr_opt_ OrtModelMetadata*); +ORT_API(void, ReleaseValueInfo, _Frees_ptr_opt_ OrtValueInfo*); +ORT_API(void, ReleaseNode, _Frees_ptr_opt_ OrtNode*); +ORT_API(void, ReleaseGraph, _Frees_ptr_opt_ OrtGraph*); +ORT_API(void, ReleaseModel, _Frees_ptr_opt_ OrtModel*); _Check_return_ _Ret_notnull_ [[nodiscard]] OrtStatus* ORT_API_CALL CreateStatus(OrtErrorCode code, _In_z_ const char* msg) NO_EXCEPTION; @@ -533,4 +537,16 @@ ORT_API_STATUS_IMPL(RunOptionsAddActiveLoraAdapter, _Inout_ OrtRunOptions* optio ORT_API_STATUS_IMPL(SetEpDynamicOptions, _Inout_ OrtSession* sess, _In_reads_(kv_len) const char* const* keys, _In_reads_(kv_len) const char* const* values, _In_ size_t kv_len); + +ORT_API_STATUS_IMPL(GetValueInfoName, _In_ const OrtValueInfo* value_info, _Out_ const char** name); +ORT_API_STATUS_IMPL(GetValueInfoTypeInfo, _In_ const OrtValueInfo* value_info, _Outptr_ const OrtTypeInfo** type_info); + +ORT_API(const OrtModelEditorApi*, GetModelEditorApi); + +ORT_API_STATUS_IMPL(CreateTensorWithDataAndDeleterAsOrtValue, _In_ OrtAllocator* deleter, + _In_ void* p_data, size_t p_data_len, + _In_ const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type, + _Outptr_ OrtValue** out); + } // namespace OrtApis diff --git a/onnxruntime/core/session/utils.cc b/onnxruntime/core/session/utils.cc new file mode 100644 index 0000000000000..afb1ed2696c9f --- /dev/null +++ b/onnxruntime/core/session/utils.cc @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/session/utils.h" + +#include "core/framework/error_code_helper.h" +#include "core/framework/execution_provider.h" +#include "core/session/abi_session_options_impl.h" +// #include "core/session/environment.h" +#include "core/session/inference_session.h" +#include "core/session/inference_session_utils.h" +#include "core/session/onnxruntime_c_api.h" +#include "core/session/ort_apis.h" +#include "core/session/ort_env.h" + +using namespace onnxruntime; + +common::Status CopyStringToOutputArg(std::string_view str, const char* err_msg, char* out, size_t* size) { + const size_t str_len = str.size(); + const size_t req_size = str_len + 1; + + if (out == nullptr) { // User is querying the total output buffer size + *size = req_size; + return onnxruntime::common::Status::OK(); + } + + if (*size >= req_size) { // User provided a buffer of sufficient size + std::memcpy(out, str.data(), str_len); + out[str_len] = '\0'; + *size = req_size; + return onnxruntime::common::Status::OK(); + } + + // User has provided a buffer that is not large enough + *size = req_size; + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, err_msg); +} + +// provider either model_path, or modal_data + model_data_length. +OrtStatus* CreateSessionAndLoadModel(_In_ const OrtSessionOptions* options, + _In_ const OrtEnv* env, + _In_opt_z_ const ORTCHAR_T* model_path, + _In_opt_ const void* model_data, + size_t model_data_length, + std::unique_ptr& sess) { + // quick check here to decide load path. InferenceSession will provide error message for invalid values. + // TODO: Could move to a helper + const Env& os_env = Env::Default(); // OS environment (!= ORT environment) + bool load_config_from_model = + os_env.GetEnvironmentVar(inference_session_utils::kOrtLoadConfigFromModelEnvVar) == "1"; + + if (load_config_from_model) { +#if !defined(ORT_MINIMAL_BUILD) + if (model_path != nullptr) { + sess = std::make_unique( + options == nullptr ? onnxruntime::SessionOptions() : options->value, + env->GetEnvironment(), + model_path); + } else { + sess = std::make_unique( + options == nullptr ? onnxruntime::SessionOptions() : options->value, + env->GetEnvironment(), + model_data, static_cast(model_data_length)); + } +#else + return OrtApis::CreateStatus(ORT_FAIL, "Loading config from ONNX models is not supported in this build."); +#endif + } else { + sess = std::make_unique( + options == nullptr ? onnxruntime::SessionOptions() : options->value, + env->GetEnvironment()); + } + +#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_MINIMAL_BUILD_CUSTOM_OPS) + // Add custom domains + if (options && !options->custom_op_domains_.empty()) { + ORT_API_RETURN_IF_STATUS_NOT_OK(sess->AddCustomOpDomains(options->custom_op_domains_)); + } +#endif + + // Finish load + if (load_config_from_model) { +#if !defined(ORT_MINIMAL_BUILD) + ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load()); +#endif + } else { + if (model_path != nullptr) { + ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load(model_path)); + } else { + ORT_API_RETURN_IF_STATUS_NOT_OK(sess->Load(model_data, static_cast(model_data_length))); + } + } + + return nullptr; +} + +OrtStatus* InitializeSession(_In_ const OrtSessionOptions* options, + _In_ onnxruntime::InferenceSession& sess, + _Inout_opt_ OrtPrepackedWeightsContainer* prepacked_weights_container) { + // we need to disable mem pattern if DML is one of the providers since DML doesn't have the concept of + // byte addressable memory + std::vector> provider_list; + if (options) { + for (auto& factory : options->provider_factories) { + auto provider = factory->CreateProvider(); + provider_list.push_back(std::move(provider)); + } + } + + // register the providers + for (auto& provider : provider_list) { + if (provider) { + ORT_API_RETURN_IF_STATUS_NOT_OK(sess.RegisterExecutionProvider(std::move(provider))); + } + } + + if (prepacked_weights_container != nullptr) { + ORT_API_RETURN_IF_STATUS_NOT_OK(sess.AddPrePackedWeightsContainer( + reinterpret_cast(prepacked_weights_container))); + } + + ORT_API_RETURN_IF_STATUS_NOT_OK(sess.Initialize()); + + return nullptr; +} diff --git a/onnxruntime/core/session/utils.h b/onnxruntime/core/session/utils.h new file mode 100644 index 0000000000000..ac8ad60758b5b --- /dev/null +++ b/onnxruntime/core/session/utils.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include "core/common/common.h" +#include "core/session/onnxruntime_c_api.h" + +onnxruntime::common::Status CopyStringToOutputArg(std::string_view str, const char* err_msg, char* out, size_t* size); + +struct OrtSessionOptions; +struct OrtStatus; +struct OrtPrepackedWeightsContainer; +namespace onnxruntime { +class InferenceSession; +} + +OrtStatus* CreateSessionAndLoadModel(_In_ const OrtSessionOptions* options, + _In_ const OrtEnv* env, + _In_opt_z_ const ORTCHAR_T* model_path, + _In_opt_ const void* model_data, + size_t model_data_length, + std::unique_ptr& sess); + +OrtStatus* InitializeSession(_In_ const OrtSessionOptions* options, + _In_ onnxruntime::InferenceSession& sess, + _Inout_opt_ OrtPrepackedWeightsContainer* prepacked_weights_container = nullptr); diff --git a/onnxruntime/test/framework/type_info_test.cc b/onnxruntime/test/framework/type_info_test.cc index ee787fb071d97..d8ef668bf1c7e 100644 --- a/onnxruntime/test/framework/type_info_test.cc +++ b/onnxruntime/test/framework/type_info_test.cc @@ -22,9 +22,9 @@ TEST(TypeInfoTests, TensorProto) { auto tensor_type_info = OrtTypeInfo::FromTypeProto(tensor_type.value); ASSERT_EQ(ONNX_TYPE_TENSOR, tensor_type_info->type); - ASSERT_NE(nullptr, tensor_type_info->data); - ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, tensor_type_info->data->type); - ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), tensor_type_info->data->shape.GetDims())); + ASSERT_NE(nullptr, tensor_type_info->tensor_type_info); + ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, tensor_type_info->tensor_type_info->type); + ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), tensor_type_info->tensor_type_info->shape.GetDims())); } TEST(TypeInfoTests, SequenceWithTensorElement) { @@ -37,9 +37,9 @@ TEST(TypeInfoTests, SequenceWithTensorElement) { const auto& tensor_type_info = *seq_type_info->sequence_type_info->sequence_key_type_; ASSERT_EQ(ONNX_TYPE_TENSOR, tensor_type_info.type); - ASSERT_NE(nullptr, tensor_type_info.data); - ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, tensor_type_info.data->type); - ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), tensor_type_info.data->shape.GetDims())); + ASSERT_NE(nullptr, tensor_type_info.tensor_type_info); + ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, tensor_type_info.tensor_type_info->type); + ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), tensor_type_info.tensor_type_info->shape.GetDims())); } TEST(TypeInfoTests, OptionalWithTensorProto) { @@ -54,9 +54,9 @@ TEST(TypeInfoTests, OptionalWithTensorProto) { const auto& contained_type = *optional_type_info->optional_type_info->contained_type_; ASSERT_EQ(ONNX_TYPE_TENSOR, contained_type.type); - ASSERT_NE(nullptr, contained_type.data); - ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, contained_type.data->type); - ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), contained_type.data->shape.GetDims())); + ASSERT_NE(nullptr, contained_type.tensor_type_info); + ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, contained_type.tensor_type_info->type); + ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), contained_type.tensor_type_info->shape.GetDims())); } #if !defined(DISABLE_ML_OPS) @@ -74,11 +74,11 @@ TEST(TypeInfoTests, MapWithTensorValue) { const auto& tensor_type_info = *map_info.map_value_type_; ASSERT_EQ(ONNX_TYPE_TENSOR, tensor_type_info.type); - ASSERT_NE(nullptr, tensor_type_info.data); - ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, tensor_type_info.data->type); - ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), tensor_type_info.data->shape.GetDims())); + ASSERT_NE(nullptr, tensor_type_info.tensor_type_info); + ASSERT_EQ(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, tensor_type_info.tensor_type_info->type); + ASSERT_TRUE(SpanEq(AsSpan({1, 2, 3, 4}), tensor_type_info.tensor_type_info->shape.GetDims())); } #endif } // namespace test -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/test/shared_lib/custom_op_utils.h b/onnxruntime/test/shared_lib/custom_op_utils.h index e11540aaa5691..ea2a5f2771342 100644 --- a/onnxruntime/test/shared_lib/custom_op_utils.h +++ b/onnxruntime/test/shared_lib/custom_op_utils.h @@ -8,12 +8,6 @@ #include #endif -struct Input { - const char* name = nullptr; - std::vector dims; - std::vector values; -}; - struct MyCustomKernel { MyCustomKernel(const OrtApi& ort_api, const OrtKernelInfo* /*info*/) : ort_(ort_api) { diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc index ca9ca0f82a25a..4216efdfdfdb8 100644 --- a/onnxruntime/test/shared_lib/test_inference.cc +++ b/onnxruntime/test/shared_lib/test_inference.cc @@ -1,17 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include -#include -#include -#include -#include +#include #include +#include +#include +#include #include -#include +#include #include +#include #include +#include + #include "gtest/gtest.h" #include "gmock/gmock.h" @@ -25,13 +27,13 @@ #include "core/session/onnxruntime_run_options_config_keys.h" #include "core/util/thread_utils.h" -#include "onnxruntime_config.h" -#include "providers.h" -#include "test_allocator.h" -#include "test_fixture.h" -#include "utils.h" -#include "custom_op_utils.h" -#include +#include "test/shared_lib/custom_op_utils.h" +#include "test/shared_lib/test_fixture.h" +#include "test/shared_lib/utils.h" +#include "test/util/include/providers.h" +#include "test/util/include/test_allocator.h" + +#include "onnxruntime_config.h" // generated file in build output dir #ifdef _WIN32 #include @@ -63,48 +65,6 @@ constexpr size_t countof(T (&)[N]) { return N; } extern std::unique_ptr ort_env; -template -void RunSession(OrtAllocator* allocator, Ort::Session& session_object, - const std::vector& inputs, - const char* output_name, - const std::vector& dims_y, - const std::vector& values_y, - Ort::Value* output_tensor) { - std::vector ort_inputs; - std::vector input_names; - for (size_t i = 0; i < inputs.size(); i++) { - input_names.emplace_back(inputs[i].name); - ort_inputs.emplace_back( - Ort::Value::CreateTensor(allocator->Info(allocator), const_cast(inputs[i].values.data()), - inputs[i].values.size(), inputs[i].dims.data(), inputs[i].dims.size())); - } - - std::vector ort_outputs; - if (output_tensor) - session_object.Run(Ort::RunOptions{nullptr}, input_names.data(), ort_inputs.data(), ort_inputs.size(), - &output_name, output_tensor, 1); - else { - ort_outputs = session_object.Run(Ort::RunOptions{}, input_names.data(), ort_inputs.data(), ort_inputs.size(), - &output_name, 1); - ASSERT_EQ(ort_outputs.size(), 1u); - output_tensor = &ort_outputs[0]; - } - - auto type_info = output_tensor->GetTensorTypeAndShapeInfo(); - ASSERT_EQ(type_info.GetShape(), dims_y); - size_t total_len = type_info.GetElementCount(); - ASSERT_EQ(values_y.size(), total_len); - - OutT* f = output_tensor->GetTensorMutableData(); - for (size_t i = 0; i != total_len; ++i) { - if constexpr (std::is_same::value || std::is_same::value) { - ASSERT_NEAR(values_y[i], f[i], 1e-3); - } else { - ASSERT_EQ(values_y[i], f[i]); - } - } -} - #ifdef USE_DML struct DmlObjects { ComPtr d3d12_device; @@ -300,12 +260,12 @@ Ort::Value CreateTensorValueFromExistingD3DResource( #endif -template +template > static void TestInference(Ort::Env& env, const std::basic_string& model_uri, const std::vector& inputs, const char* output_name, const std::vector& expected_dims_y, - const std::vector& expected_values_y, + const std::vector& expected_values_y, int provider_type, OrtCustomOpDomain* custom_op_domain_ptr, const ORTCHAR_T* custom_op_library_filename, @@ -362,26 +322,26 @@ static void TestInference(Ort::Env& env, const std::basic_string& mod auto default_allocator = std::make_unique(); // without preallocated output tensor - RunSession(default_allocator.get(), - session, - inputs, - output_name, - expected_dims_y, - expected_values_y, - nullptr); + RunSession(default_allocator.get(), + session, + inputs, + output_name, + expected_dims_y, + expected_values_y, + nullptr); // with preallocated output tensor - Ort::Value value_y = Ort::Value::CreateTensor(default_allocator.get(), - expected_dims_y.data(), expected_dims_y.size()); + Ort::Value value_y = Ort::Value::CreateTensor(default_allocator.get(), + expected_dims_y.data(), expected_dims_y.size()); // test it twice for (int i = 0; i != 2; ++i) - RunSession(default_allocator.get(), - session, - inputs, - output_name, - expected_dims_y, - expected_values_y, - &value_y); + RunSession(default_allocator.get(), + session, + inputs, + output_name, + expected_dims_y, + expected_values_y, + &value_y); } } @@ -450,8 +410,8 @@ class CApiTestWithProvider : public testing::Test, public ::testing::WithParamIn TEST_P(CApiTestWithProvider, simple) { // simple inference test // prepare inputs - std::vector inputs(1); - Input& input = inputs.back(); + std::vector> inputs(1); + auto& input = inputs.back(); input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -621,8 +581,8 @@ TEST(CApiTest, SparseInputModel) { TEST(CApiTest, custom_op_handler) { std::cout << "Running custom op inference" << std::endl; - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -657,8 +617,8 @@ TEST(CApiTest, custom_op_handler) { TEST(CApiTest, custom_op_set_input_memory_type) { std::cout << "Running custom op inference" << std::endl; - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -687,8 +647,8 @@ TEST(CApiTest, custom_op_set_input_memory_type) { #if !defined(ORT_MINIMAL_BUILD) TEST(CApiTest, StandaloneOpHandler) { - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -811,7 +771,7 @@ TEST(CApiTest, test_enable_ort_customops_stringlower) { // test custom op which accepts float and double as inputs TEST(CApiTest, varied_input_custom_op_handler) { - std::vector inputs(2); + std::vector> inputs(2); inputs[0].name = "X"; inputs[0].dims = {3}; inputs[0].values = {2.0f, 3.0f, 4.0f}; @@ -1422,8 +1382,8 @@ TEST(CApiTest, custom_op_with_attributes_handler) { TEST(CApiTest, RegisterCustomOpForCPUAndCUDA) { std::cout << "Tests registration of a custom op of the same name for both CPU and CUDA EPs" << std::endl; - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -1531,7 +1491,7 @@ TEST(CApiTest, test_custom_op_openvino_wrapper_library) { // The custom op extracts the serialized .xml/.bin bytes and creates an in-memory OpenVINO model // during kernel creation. The custom op is passed an image of a hand-drawn "1" as an input during computation, which // is then inferenced using OpenVINO C++ APIs. - std::vector inputs(1); + std::vector> inputs(1); inputs[0].name = "Input3"; inputs[0].dims = {1, 1, 28, 28}; @@ -1630,7 +1590,7 @@ TEST(CApiTest, test_custom_op_library) { #endif std::cout << "Running inference using custom op shared library" << std::endl; - std::vector inputs(2); + std::vector> inputs(2); inputs[0].name = "input_1"; inputs[0].dims = {3, 5}; inputs[0].values = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f, @@ -1682,7 +1642,7 @@ TEST(CApiTest, DISABLED_test_custom_op_shape_infer_attr) { #else TEST(CApiTest, test_custom_op_shape_infer_attr) { #endif - std::vector inputs(1); + std::vector> inputs(1); inputs[0].name = "input_0"; inputs[0].dims = {5}; inputs[0].values = {1.f, 2.f, 3.f, 4.f, 5.f}; @@ -1715,7 +1675,7 @@ TEST(CApiTest, test_custom_op_library_copy_variadic) { #endif std::cout << "Running inference using custom op shared library" << std::endl; - std::vector inputs(2); + std::vector> inputs(2); inputs[0].name = "input_0"; inputs[0].dims = {15}; inputs[0].values = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f, @@ -1869,8 +1829,8 @@ void PrepareModule() { TEST(CApiTest, test_pyop) { std::call_once(my_module_flag, PrepareModule); - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {2, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f}; @@ -1882,8 +1842,8 @@ TEST(CApiTest, test_pyop) { TEST(CApiTest, test_pyop_multi) { std::call_once(my_module_flag, PrepareModule); - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {2, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f}; @@ -1895,8 +1855,8 @@ TEST(CApiTest, test_pyop_multi) { TEST(CApiTest, test_pyop_kwarg) { std::call_once(my_module_flag, PrepareModule); - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {2, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f}; @@ -1920,7 +1880,7 @@ TEST(ReducedOpsBuildTest, test_excluded_ops) { // In reduced ops build, test a model containing ops not included in required_ops.config cannot be loaded. // See onnxruntime/test/testdata/reduced_build_test.readme.txt for more details of the setup constexpr PATH_TYPE model_uri = TSTR("testdata/reduced_build_test.onnx_model_with_excluded_ops"); - std::vector inputs = {{"X", {3}, {-1.0f, 2.0f, -3.0f}}}; + std::vector> inputs = {{"X", {3}, {-1.0f, 2.0f, -3.0f}}}; std::vector expected_dims_y = {3}; std::vector expected_values_y = {0.1f, 0.1f, 0.1f}; bool failed = false; @@ -3322,8 +3282,8 @@ TEST(CApiTest, TestSharedAllocators) { OrtEnv* env_ptr = (OrtEnv*)(*ort_env); // prepare inputs - std::vector inputs(1); - Input& input = inputs.back(); + std::vector> inputs(1); + auto& input = inputs.back(); input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -3509,8 +3469,8 @@ TEST(CApiTest, TestSharedAllocators) { TEST(CApiTest, TestSharingOfInitializerAndItsPrepackedVersion) { // simple inference test // prepare inputs - std::vector inputs(1); - Input& input = inputs.back(); + std::vector> inputs(1); + auto& input = inputs.back(); input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -3905,8 +3865,8 @@ TEST_P(CApiTensorRTTest, TestConfigureTensorRTProviderOptions) { // simple inference test // prepare inputs - std::vector inputs(1); - Input& input = inputs.back(); + std::vector> inputs(1); + auto& input = inputs.back(); input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; diff --git a/onnxruntime/test/shared_lib/test_model_builder_api.cc b/onnxruntime/test/shared_lib/test_model_builder_api.cc new file mode 100644 index 0000000000000..9807fcca06ed4 --- /dev/null +++ b/onnxruntime/test/shared_lib/test_model_builder_api.cc @@ -0,0 +1,701 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "core/common/narrow.h" +#include "core/graph/constants.h" +#include "core/session/onnxruntime_c_api.h" +#include "core/session/onnxruntime_cxx_api.h" +#include "core/session/onnxruntime_lite_custom_op.h" +#include "core/session/onnxruntime_session_options_config_keys.h" + +#include "test/shared_lib/test_fixture.h" +#include "test/shared_lib/utils.h" +#include "test/util/include/test_allocator.h" + +#include "onnxruntime_config.h" // generated file in build output dir + +extern std::unique_ptr ort_env; + +using namespace Ort; + +namespace { + +Ort::Session CreateSession(Ort::Env& env, + Model& graph_api_model, + Ort::SessionOptions* session_options_for_test = nullptr) { + Ort::SessionOptions default_session_options; + Ort::SessionOptions& session_options = session_options_for_test ? *session_options_for_test + : default_session_options; + + // Set this to save the model if you want to debug. + // session_options.SetOptimizedModelFilePath(ORT_TSTR("model_builder_output.onnx")); + + Ort::Session session(env, graph_api_model, session_options); + + // Session should not require the model to stay alive so free it now to validate. + graph_api_model = Model(nullptr); + + return session; +} + +template +void TestInference(Ort::Session& session, + const std::vector>& inputs, + const char* output_name, + const std::vector& expected_dims, + const std::vector& expected_values) { + auto default_allocator = std::make_unique(); + + // without preallocated output tensor + RunSession(default_allocator.get(), + session, + inputs, + output_name, + expected_dims, + expected_values, + nullptr); +} + +// Create OrtNode using the C API +OrtNode* CreateNode(const OrtModelEditorApi& api, + const char* operator_name, const char* node_name, + const gsl::span input_names, + const gsl::span output_names, + const gsl::span attributes = {}, + const char* domain_name = onnxruntime::kOnnxDomain) { + OrtNode* node = nullptr; + Ort::ThrowOnError(api.CreateNode(operator_name, domain_name, node_name, + input_names.data(), input_names.size(), + output_names.data(), output_names.size(), + attributes.data(), attributes.size(), + &node)); + return node; +} + +// convenience func to convert initalizer lists to gsl::span +OrtNode* CreateNode(const OrtModelEditorApi& api, + const char* operator_name, const char* node_name, + const std::initializer_list input_names, + const std::initializer_list output_names, + const std::initializer_list attributes = {}, + const char* domain_name = onnxruntime::kOnnxDomain) { + std::vector inputs(input_names); + std::vector outputs(output_names); + std::vector attrs(attributes); + return CreateNode(api, operator_name, node_name, inputs, outputs, attrs, domain_name); +} +} // namespace + +struct TestAllocator : public OrtAllocator { + TestAllocator() { + version = ORT_API_VERSION; + Info = [](const struct OrtAllocator* this_ptr) -> const struct OrtMemoryInfo* { + auto* test_allocator = static_cast(this_ptr); + return test_allocator->memory_info; + }; + + Free = [](struct OrtAllocator* allocator, void* p) -> void { + auto* test_allocator = static_cast(allocator); + // find the matching pointer and remove it + auto it = std::find_if(test_allocator->weights.begin(), test_allocator->weights.end(), + [p](const std::unique_ptr>& v) { return v->data() == p; }); + if (it == test_allocator->weights.end()) { + throw std::runtime_error("Free called with unknown pointer"); + } + + test_allocator->weights.erase(it); + }; + + Alloc = [](struct OrtAllocator* /*this*/, size_t /*size*/) -> void* { + throw std::runtime_error("This should not be used"); + }; + + Reserve = [](struct OrtAllocator* /*this*/, size_t /*size*/) -> void* { + throw std::runtime_error("This should not be used"); + }; + } + + // initializers that are used directly by the model. as there's no copy they must remain valid. + // we store them in the test allocator so we can validate that Free is called + std::vector>> weights; + Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtDeviceAllocator, + OrtMemType::OrtMemTypeDefault); +}; + +// Test the ModelEditorAPI C api +// Uses the ORT C++ api for the rest for simplicity +TEST(ModelEditorAPITest, Basic_CApi) { + const auto& api = Ort::GetApi(); + const auto& model_editor_api = Ort::GetModelEditorApi(); + + TestAllocator deleter; + + // return void so we can use ASSERT_* in the lambda + const auto build_model = [&](bool use_constant_node, OrtModel*& model) -> void { + OrtGraph* graph = nullptr; + Ort::ThrowOnError(model_editor_api.CreateGraph(&graph)); + + // + // Create OrtModel with a Gemm. X input is 3x4, Y input is 4x8, Z output is 3x8. + // X is model input. Y is initializer. + // Set the alpha attribute of the Gemm node to 2.0 to test attribute handling. + // + + // model input + OrtTensorTypeAndShapeInfo* tensor_type_info = nullptr; + std::vector input_dims = {3, 4}; + // can use api.SetSymbolicDimensions to set symbolic dimensions. + // the input array should have the same rank as the call to SetDimensions. + // e.g. call SetDimensions with {-1, 3, 2} and SetSymbolicDimensions with {"N", nullptr, nullptr} to create + // a shape of {"N", 3, 2} + + Ort::ThrowOnError(api.CreateTensorTypeAndShapeInfo(&tensor_type_info)); + Ort::ThrowOnError(api.SetTensorElementType(tensor_type_info, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT)); + Ort::ThrowOnError(api.SetDimensions(tensor_type_info, input_dims.data(), input_dims.size())); + + OrtTypeInfo* input_type_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateTensorTypeInfo(tensor_type_info, &input_type_info)); + api.ReleaseTensorTypeAndShapeInfo(tensor_type_info); // input_type_info took a copy + + // create ValueInfo and release the type info as CreateValueInfo takes a copy. + OrtValueInfo* input_value_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateValueInfo("X", input_type_info, &input_value_info)); + api.ReleaseTypeInfo(input_type_info); // input_value_info took a copy + tensor_type_info = nullptr; + + // model outputs + OrtTypeInfo* output_type_info = nullptr; + std::vector output_dims = {3, 8}; + + Ort::ThrowOnError(api.CreateTensorTypeAndShapeInfo(&tensor_type_info)); + Ort::ThrowOnError(api.SetTensorElementType(tensor_type_info, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT)); + Ort::ThrowOnError(api.SetDimensions(tensor_type_info, output_dims.data(), output_dims.size())); + + Ort::ThrowOnError(model_editor_api.CreateTensorTypeInfo(tensor_type_info, &output_type_info)); + api.ReleaseTensorTypeAndShapeInfo(tensor_type_info); // input_type_info took a copy + + OrtValueInfo* output_value_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateValueInfo("Z", output_type_info, &output_value_info)); + api.ReleaseTypeInfo(output_type_info); + + std::vector graph_inputs = {input_value_info}; + std::vector graph_outputs = {output_value_info}; + Ort::ThrowOnError(model_editor_api.SetGraphInputs(graph, graph_inputs.data(), graph_inputs.size())); + Ort::ThrowOnError(model_editor_api.SetGraphOutputs(graph, graph_outputs.data(), graph_outputs.size())); + input_value_info = nullptr; // graph now owns the input/output values + output_value_info = nullptr; + + // + // Gemm node + // + + OrtOpAttr* alpha_attr = nullptr; + float alpha_value = 2.0; + Ort::ThrowOnError(api.CreateOpAttr("alpha", &alpha_value, 1, OrtOpAttrType::ORT_OP_ATTR_FLOAT, &alpha_attr)); + + std::vector node_input_names = {"X", "Y"}; + const std::string gemm_output_name = use_constant_node ? "Z_temp" : "Z"; + std::vector node_output_names = {gemm_output_name.c_str()}; + std::vector node_attributes{alpha_attr}; + OrtNode* node = CreateNode(model_editor_api, "Gemm", "Gemm1", node_input_names, node_output_names, node_attributes); + alpha_attr = nullptr; // Node now owns + + Ort::ThrowOnError(model_editor_api.AddNodeToGraph(graph, node)); + node = nullptr; // graph now owns node + + // Y input + // As it's 128 bytes it could either be allocated using CreateTensorAsOrtValue or use existing memory. + // Under 128 bytes must use CreateTensorAsOrtValue. + std::vector y_dims = {4, 8}; + + deleter.weights.emplace_back(std::make_unique>(32)); + auto& y_values = *deleter.weights.back(); + std::iota(y_values.begin(), y_values.end(), 1.0f); + + // create an initializer for the Y input. add to `weights` so the memory remains valid. + OrtValue* y_tensor = nullptr; + Ort::ThrowOnError( + api.CreateTensorWithDataAndDeleterAsOrtValue(&deleter, + y_values.data(), y_values.size() * sizeof(y_values[0]), + y_dims.data(), y_dims.size(), + ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, + &y_tensor)); + + Ort::ThrowOnError(model_editor_api.AddInitializerToGraph(graph, "Y", y_tensor, /*data is external*/ true)); + y_tensor = nullptr; // graph now owns + + if (use_constant_node) { + // Test that a Constant node is converted to an initializer + + // create Constant nodes for min/max to limit output range + OrtOpAttr* min_attr = nullptr; + float min = 400.0f; + Ort::ThrowOnError(api.CreateOpAttr("value", &min, sizeof(min), ORT_OP_ATTR_FLOAT, &min_attr)); + node = CreateNode(model_editor_api, "Constant", "clip_min", {}, {"min"}, {min_attr}); + Ort::ThrowOnError(model_editor_api.AddNodeToGraph(graph, node)); + node = nullptr; // graph now owns node + + OrtOpAttr* max_attr = nullptr; + float max = 900.0f; + Ort::ThrowOnError(api.CreateOpAttr("value", &max, sizeof(max), ORT_OP_ATTR_FLOAT, &max_attr)); + node = CreateNode(model_editor_api, "Constant", "clip_max", {}, {"max"}, {max_attr}); + Ort::ThrowOnError(model_editor_api.AddNodeToGraph(graph, node)); + node = nullptr; // graph now owns node + + node = CreateNode(model_editor_api, "Clip", "Clip1", {gemm_output_name.c_str(), "min", "max"}, {"Z"}); + Ort::ThrowOnError(model_editor_api.AddNodeToGraph(graph, node)); + node = nullptr; // graph now owns node + } + + std::vector domain_names = {onnxruntime::kOnnxDomain}; + std::vector opset_versions = {18}; + Ort::ThrowOnError(model_editor_api.CreateModel(domain_names.data(), opset_versions.data(), domain_names.size(), + &model)); + Ort::ThrowOnError(model_editor_api.AddGraphToModel(model, graph)); + graph = nullptr; // model now owns + }; + + auto run_test = [&](bool use_constant_node) -> void { + OrtModel* model = nullptr; + build_model(use_constant_node, model); + + ASSERT_NE(model, nullptr) << "build_model should have created a model"; + + std::vector> inputs(1); + auto& input = inputs[0]; + input.name = "X"; + input.dims = {3, 4}; + input.values = {1.0f, 2.0f, 3.0f, 4.0f, + 8.0f, 7.0f, 6.0f, 5.0f, + 9.0f, 3.0f, 5.0f, 7.0f}; + + std::vector expected_dims = {3, 8}; + Model cxx_model(model); + auto session = CreateSession(*ort_env, cxx_model); + + std::vector expected_output; + if (use_constant_node) { + // clipped with min 400 and max 900 + expected_output = {400.0f, 400.0f, 400.0f, 400.0f, 420.0f, 440.0f, 460.0f, 480.0f, + 596.0f, 648.0f, 700.0f, 752.0f, 804.0f, 856.0f, 900.0f, 900.0f, + 592.0f, 640.0f, 688.0f, 736.0f, 784.0f, 832.0f, 880.0f, 900.0f}; + } else { + expected_output = {340.0f, 360.0f, 380.0f, 400.0f, 420.0f, 440.0f, 460.0f, 480.0f, + 596.0f, 648.0f, 700.0f, 752.0f, 804.0f, 856.0f, 908.0f, 960.0f, + 592.0f, 640.0f, 688.0f, 736.0f, 784.0f, 832.0f, 880.0f, 928.0f}; + } + + TestInference(session, inputs, "Z", expected_dims, expected_output); + + api.ReleaseSession(session.release()); + + ASSERT_EQ(deleter.weights.size(), size_t(0)) << "All weights should have been freed"; + }; + + run_test(false); + run_test(true); // use Constant node for initializer +} + +TEST(ModelEditorAPITest, Basic_CxxApi) { + // initializers that are used directly by the model. as there's no copy they must remain valid + std::vector>> weights; + + Ort::Graph graph; + + // + // Create OrtModel with a Gemm. X input is 3x4, Y input is 4x8, Z output is 3x8. + // X is model input. Y is initializer. + // Set the alpha attribute of the Gemm node to 2.0 to test attribute handling. + // + + std::vector graph_inputs; + std::vector graph_outputs; + + // model input. it's {3, 4} but use a symbolic dim to test that works. + std::vector input_dims({-1, 4}); + std::vector input_symbolic_dims({"multiple_of_3", ""}); + TensorTypeAndShapeInfo input_tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, + input_dims, + &input_symbolic_dims); + auto input_type_info = TypeInfo::CreateTensorInfo(input_tensor_info.GetConst()); + graph_inputs.emplace_back("X", input_type_info.GetConst()); + + // model outputs + std::vector output_dims = {-1, 8}; + std::vector output_symbolic_dims({"multiple_of_3", ""}); + TensorTypeAndShapeInfo output_tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, + output_dims, + &output_symbolic_dims); + auto output_type_info = TypeInfo::CreateTensorInfo(output_tensor_info.GetConst()); + graph_outputs.emplace_back("Z", output_type_info.GetConst()); + + graph.SetInputs(graph_inputs); + graph.SetOutputs(graph_outputs); + + // + // Gemm node + // + + std::vector attributes; + float alpha_value = 2.0; + attributes.push_back(OpAttr("alpha", &alpha_value, 1, OrtOpAttrType::ORT_OP_ATTR_FLOAT)); + + Node node("Gemm", onnxruntime::kOnnxDomain, "Gemm1", {"X", "Y"}, {"Z"}, attributes); + + graph.AddNode(node); + + // create an initializer for the Y input. + // add to `weights` so it remains valid for the lifetime of the session and we can avoid copying the data. + // As it's 128 bytes it could either be allocated using CreateTensorAsOrtValue or use existing memory. + // Under 128 bytes must use CreateTensorAsOrtValue. + std::vector y_dims = {4, 8}; + + weights.emplace_back(std::make_unique>(32)); + auto& y_values = *weights.back(); + std::iota(y_values.begin(), y_values.end(), 1.0f); + + auto info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeDefault); + + // if you use this API the initializer data MUST remain valid for the lifetime of the InferenceSession + auto y_tensor = Value::CreateTensor(info, y_values.data(), y_values.size(), y_dims.data(), y_dims.size()); + graph.AddInitializer("Y", y_tensor, /*data is external*/ true); + + std::vector opsets{{onnxruntime::kOnnxDomain, 18}}; + Model model(opsets); + model.AddGraph(graph); + + std::vector> inputs(1); + auto& input = inputs[0]; + input.name = "X"; + input.dims = {3, 4}; + input.values = {1.0f, 2.0f, 3.0f, 4.0f, + 8.0f, 7.0f, 6.0f, 5.0f, + 9.0f, 3.0f, 5.0f, 7.0f}; + + std::vector expected_dims = {3, 8}; + + auto session = CreateSession(*ort_env, model); + TestInference(session, inputs, "Z", expected_dims, + {340.0f, 360.0f, 380.0f, 400.0f, 420.0f, 440.0f, 460.0f, 480.0f, + 596.0f, 648.0f, 700.0f, 752.0f, 804.0f, 856.0f, 908.0f, 960.0f, + 592.0f, 640.0f, 688.0f, 736.0f, 784.0f, 832.0f, 880.0f, 928.0f}); +} + +TEST(ModelEditorAPITest, BasicModelEdit_CxxApi) { + // + // Load existing model + // Add Cast to change the model input from float to int64 + // Update model inputs to match + // Run + // + + SessionOptions so; + + // Set this to save the model if you want to debug. + // so.SetOptimizedModelFilePath(ORT_TSTR("model_builder_edited.onnx")); + + Session session = Session::CreateModelEditorSession(*ort_env, TSTR("testdata/mnist.onnx"), so); + + ASSERT_EQ(session.GetOpset(""), 8); // ONNX domain is empty string + + // we augment the original model with nodes, initializers and the updated model inputs/outputs from this model. + // the original graph is unchanged. nodes can be added before/after it. initializers can be added. + // new nodes must conform to the original domain:opset of the model. + // additional operator domain:opset pairs can be added. + std::vector opsets; // no additional opsets required + Model model(opsets); + + std::vector graph_inputs = session.GetInputs(); + ASSERT_EQ(graph_inputs.size(), size_t(1)); + ASSERT_EQ(graph_inputs[0].TypeInfo().GetTensorTypeAndShapeInfo().GetElementType(), + ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); + + // typically this isn't needed. we replace this input but need to read info from it later on in the test + // validation so we save the info locally to keep it accessible. + auto orig_input_name = graph_inputs[0].Name(); + auto input_shape = graph_inputs[0].TypeInfo().GetTensorTypeAndShapeInfo().GetShape(); + const std::string new_input_name = "Int64Input"; + + // Add Cast node to convert input from float to int64 + std::vector attributes; + int64_t to = ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT; + attributes.push_back(OpAttr("to", &to, 1, OrtOpAttrType::ORT_OP_ATTR_INT)); + + Ort::Node node("Cast", onnxruntime::kOnnxDomain, new_input_name, {"Int64Input"}, + // the existing node will now consume the output from the Cast instead of a graph input + {orig_input_name}, + attributes); + + // we're replacing the only input. the shape is the same but the name and data type change. + TensorTypeAndShapeInfo input_tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, + input_shape); + auto input_type_info = TypeInfo::CreateTensorInfo(input_tensor_info.GetConst()); + graph_inputs[0] = ValueInfo(new_input_name, input_type_info.GetConst()); + + Graph graph; // new info to augment the model with + + graph.AddNode(node); + graph.SetInputs(graph_inputs); + + // the node we added does not require any new opsets. + model.AddGraph(graph); + session.FinalizeModelEditorSession(model, so); + + std::vector> inputs(1); + auto& input = inputs[0]; + input.name = new_input_name.c_str(); + input.dims = input_shape; + + auto num_values = std::accumulate(input.dims.begin(), input.dims.end(), int64_t(1), std::multiplies()); + input.values.resize(size_t(num_values)); + std::iota(input.values.begin(), input.values.end(), 1); + + std::vector expected_dims = {1, 10}; + std::vector expected_output = {-48.5088f, -1040.2948f, -347.0959f, 101.7392f, 421.3352f, + 750.92145f, 231.5060f, -1694.4152f, 681.5623f, 378.1689f}; + + TestInference(session, inputs, session.GetOutputNames()[0].c_str(), expected_dims, expected_output); + + // double check with original model + { + SessionOptions expected_so; + Session expected_session = Session(*ort_env, TSTR("testdata/mnist.onnx"), expected_so); + std::vector> expected_inputs(1); + auto& expected_input = expected_inputs[0]; + expected_input.name = orig_input_name.c_str(); + expected_input.dims = input_shape; + expected_input.values.reserve(size_t(num_values)); + std::transform(input.values.begin(), input.values.end(), std::back_inserter(expected_input.values), + [&](int64_t value) { return float(value); }); + + TestInference(expected_session, expected_inputs, session.GetOutputNames()[0].c_str(), + expected_dims, expected_output); + } +} + +TEST(ModelEditorAPITest, InvalidDimension) { + try { + std::vector input_dims = {-2, 2}; + TensorTypeAndShapeInfo tensor_type_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, + input_dims); + // invalid dim of -2 should cause exception + TypeInfo::CreateTensorInfo(tensor_type_info.GetConst()); + FAIL() << "Expected exception for invalid dimension"; + } catch (const Ort::Exception& e) { + ASSERT_STREQ(e.what(), "dim_values must be -1 (symbolic dimension) or larger."); + } +} + +TEST(ModelEditorAPITest, CreateInvalidModel_NoOpsets) { + Ort::Graph graph; + std::vector graph_inputs; + std::vector graph_outputs; + + std::vector dims({4}); + TensorTypeAndShapeInfo tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, dims); + auto type_info = TypeInfo::CreateTensorInfo(tensor_info.GetConst()); + graph_inputs.emplace_back("X", type_info.GetConst()); + graph_outputs.emplace_back("Z", type_info.GetConst()); + + graph.SetInputs(graph_inputs); + graph.SetOutputs(graph_outputs); + + Ort::Node node("Add", onnxruntime::kOnnxDomain, "Add1", {"X", "X"}, {"Z"}); + + graph.AddNode(node); + + std::vector opsets; + Model model(opsets); + model.AddGraph(graph); + + try { + auto session = CreateSession(*ort_env, model); + FAIL(); + } catch (const Ort::Exception& e) { + ASSERT_THAT(e.what(), ::testing::HasSubstr("Error No opset import for domain")); + } +} + +TEST(ModelEditorAPITest, CreateInvalidModel_MissingValue) { + Ort::Graph graph; + + std::vector graph_inputs; + std::vector graph_outputs; + + std::vector dims({4}); + TensorTypeAndShapeInfo tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, dims); + auto type_info = TypeInfo::CreateTensorInfo(tensor_info.GetConst()); + graph_inputs.emplace_back("X", type_info.GetConst()); + graph_outputs.emplace_back("Z", type_info.GetConst()); + + graph.SetInputs(graph_inputs); + graph.SetOutputs(graph_outputs); + + Ort::Node node("Add", onnxruntime::kOnnxDomain, "Add1", {"X", "missing"}, {"Z"}); + graph.AddNode(node); + + std::vector opsets{{onnxruntime::kOnnxDomain, 18}}; + Model model(opsets); + model.AddGraph(graph); + + try { + auto session = CreateSession(*ort_env, model); + FAIL(); + } catch (const Ort::Exception& e) { + ASSERT_THAT(e.what(), ::testing::HasSubstr("Node input 'missing' is not a graph input, " + "initializer, or output of a previous node.")); + } +} + +TEST(ModelEditorAPITest, InvalidModelEdit) { + // Add a node but make the edit invalid in various ways + // - add node but don't update graph inputs + // - add node with invalid domain + const auto edit_model = [](bool invalid_domain) { + SessionOptions so; + + // Set this to save the model if you want to debug. + // so.SetOptimizedModelFilePath(ORT_TSTR("model_builder_edited.onnx")); + + Session session = Session::CreateModelEditorSession(*ort_env, TSTR("testdata/mnist.onnx"), so); + + ASSERT_EQ(session.GetOpset(""), 8); // ONNX domain is empty string + + std::vector opsets; // no additional opsets required + Model model(opsets); + Graph graph; // new info to augment the model with + + const char* domain = invalid_domain ? "invalid_domain" : onnxruntime::kOnnxDomain; + + std::vector graph_inputs = session.GetInputs(); + ASSERT_EQ(graph_inputs.size(), size_t(1)); + ASSERT_EQ(graph_inputs[0].TypeInfo().GetTensorTypeAndShapeInfo().GetElementType(), + ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); + + const std::string new_input_name = "Int64Input"; + + // Add Cast node to convert input from float to int64 + std::vector attributes; + int64_t to = ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT; + attributes.push_back(OpAttr("to", &to, 1, OrtOpAttrType::ORT_OP_ATTR_INT)); + + Node node("Cast", domain, "NewInputNode", {new_input_name}, + // the existing node will now consume the output from the Cast instead of a graph input + {graph_inputs[0].Name()}, + attributes); + graph.AddNode(node); + + if (invalid_domain) { + // we're replacing the only input. the shape is the same but the name and data type change. + TensorTypeAndShapeInfo input_tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, + graph_inputs[0].TypeInfo().GetTensorTypeAndShapeInfo().GetShape()); + auto input_type_info = TypeInfo::CreateTensorInfo(input_tensor_info.GetConst()); + graph_inputs[0] = ValueInfo(new_input_name, input_type_info.GetConst()); + graph.SetInputs(graph_inputs); + } else { + // model should be invalid as we didn't connect the new node up to the graph inputs + } + + // the node we added does not require any new opsets. + model.AddGraph(graph); + + try { + session.FinalizeModelEditorSession(model, so); + FAIL() << "Should have failed to resolve graph due to invalid edits."; + } catch (const Ort::Exception& e) { + if (invalid_domain) { + ASSERT_THAT(e.what(), ::testing::HasSubstr("Error No opset import for domain 'invalid_domain'")); + } else { + ASSERT_THAT(e.what(), ::testing::HasSubstr("This is an invalid model")); + } + } + }; + + edit_model(false); + edit_model(true); // add node with invalid domain +} + +TEST(ModelEditorAPITest, CreateTypeInfo) { + const auto& api = Ort::GetApi(); + const auto& model_editor_api = Ort::GetModelEditorApi(); + + TensorTypeAndShapeInfo base_tensor_info(ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, + {2, 4}); + + OrtTypeInfo* base_tensor_type_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateTensorTypeInfo(base_tensor_info, &base_tensor_type_info)); + + ONNXType onnx_type = ONNX_TYPE_UNKNOWN; + const OrtTensorTypeAndShapeInfo* tensor_info = nullptr; + ONNXTensorElementDataType onnx_element_type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + + // sparse tensor + OrtTypeInfo* sparse_tensor_type_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateSparseTensorTypeInfo(base_tensor_info, &sparse_tensor_type_info)); + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(sparse_tensor_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_SPARSETENSOR); + Ort::ThrowOnError(api.CastTypeInfoToTensorInfo(sparse_tensor_type_info, &tensor_info)); + Ort::ThrowOnError(api.GetTensorElementType(tensor_info, &onnx_element_type)); + ASSERT_EQ(onnx_element_type, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); + api.ReleaseTypeInfo(sparse_tensor_type_info); + + // sequence + OrtTypeInfo* sequence_type_info = nullptr; + const OrtSequenceTypeInfo* sequence_info = nullptr; + OrtTypeInfo* sequence_element_type_info = nullptr; + + Ort::ThrowOnError(model_editor_api.CreateSequenceTypeInfo(base_tensor_type_info, &sequence_type_info)); + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(sequence_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_SEQUENCE); + Ort::ThrowOnError(api.CastTypeInfoToSequenceTypeInfo(sequence_type_info, &sequence_info)); + Ort::ThrowOnError(api.GetSequenceElementType(sequence_info, &sequence_element_type_info)); + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(sequence_element_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_TENSOR); + Ort::ThrowOnError(api.CastTypeInfoToTensorInfo(sequence_element_type_info, &tensor_info)); + Ort::ThrowOnError(api.GetTensorElementType(tensor_info, &onnx_element_type)); + ASSERT_EQ(onnx_element_type, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); + api.ReleaseTypeInfo(sequence_element_type_info); + api.ReleaseTypeInfo(sequence_type_info); + + // map + OrtTypeInfo* map_type_info = nullptr; + const OrtMapTypeInfo* map_info = nullptr; + ONNXTensorElementDataType map_key_type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + OrtTypeInfo* map_value_type_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateMapTypeInfo(ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, base_tensor_type_info, + &map_type_info)); // clones map_type_info + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(map_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_MAP); + Ort::ThrowOnError(api.CastTypeInfoToMapTypeInfo(map_type_info, &map_info)); + Ort::ThrowOnError(api.GetMapKeyType(map_info, &map_key_type)); + ASSERT_EQ(map_key_type, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64); + Ort::ThrowOnError(api.GetMapValueType(map_info, &map_value_type_info)); + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(map_value_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_TENSOR); + Ort::ThrowOnError(api.CastTypeInfoToTensorInfo(map_value_type_info, &tensor_info)); + Ort::ThrowOnError(api.GetTensorElementType(tensor_info, &onnx_element_type)); + ASSERT_EQ(onnx_element_type, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); + api.ReleaseTypeInfo(map_value_type_info); + api.ReleaseTypeInfo(map_type_info); + + // optional + OrtTypeInfo* optional_type_info = nullptr; + const OrtOptionalTypeInfo* optional_info = nullptr; + OrtTypeInfo* optional_contained_type_info = nullptr; + Ort::ThrowOnError(model_editor_api.CreateOptionalTypeInfo(base_tensor_type_info, &optional_type_info)); + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(optional_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_OPTIONAL); + Ort::ThrowOnError(api.CastTypeInfoToOptionalTypeInfo(optional_type_info, &optional_info)); + Ort::ThrowOnError(api.GetOptionalContainedTypeInfo(optional_info, &optional_contained_type_info)); + Ort::ThrowOnError(api.GetOnnxTypeFromTypeInfo(optional_contained_type_info, &onnx_type)); + ASSERT_EQ(onnx_type, ONNXType::ONNX_TYPE_TENSOR); + api.ReleaseTypeInfo(optional_contained_type_info); + api.ReleaseTypeInfo(optional_type_info); + + api.ReleaseTypeInfo(base_tensor_type_info); +} diff --git a/onnxruntime/test/shared_lib/test_ort_format_models.cc b/onnxruntime/test/shared_lib/test_ort_format_models.cc index 99a9ebc3362ae..b3491e3476f23 100644 --- a/onnxruntime/test/shared_lib/test_ort_format_models.cc +++ b/onnxruntime/test/shared_lib/test_ort_format_models.cc @@ -17,7 +17,7 @@ extern std::unique_ptr ort_env; [[maybe_unused]] static void TestInference(Ort::Env& env, const std::basic_string& model_uri, - const std::vector& inputs, const char* output_name, + const std::vector>& inputs, const char* output_name, const std::vector& expected_dims_y, const std::vector& expected_values_y, Ort::CustomOpDomain& custom_op_domain, void* cuda_compute_stream = nullptr) { Ort::SessionOptions session_options; @@ -100,8 +100,8 @@ TEST(OrtFormatCustomOpTests, ConvertOnnxModelToOrt) { } // now load the ORT format model and execute it - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; @@ -130,8 +130,8 @@ TEST(OrtFormatCustomOpTests, LoadOrtModel) { custom_op_domain.Add(&custom_op); // load the ORT format model and execute it - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f}; @@ -151,8 +151,8 @@ TEST(OrtFormatCustomOpTests, LoadOrtModelStandaloneCustomOpImplementation) { custom_op_domain.Add(&standalone_op); // load the ORT format model and execute it - std::vector inputs(1); - Input& input = inputs[0]; + std::vector> inputs(1); + auto& input = inputs[0]; input.name = "X"; input.dims = {3, 2}; input.values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; diff --git a/onnxruntime/test/shared_lib/utils.h b/onnxruntime/test/shared_lib/utils.h index 483753f2ae6b2..5d15582b86cb9 100644 --- a/onnxruntime/test/shared_lib/utils.h +++ b/onnxruntime/test/shared_lib/utils.h @@ -5,4 +5,56 @@ #include "core/session/onnxruntime_cxx_api.h" +#include "gtest/gtest.h" + OrtCUDAProviderOptions CreateDefaultOrtCudaProviderOptionsWithCustomStream(void* cuda_compute_stream = nullptr); + +template +struct Input { + const char* name = nullptr; + std::vector dims; + std::vector values; +}; + +template > +void RunSession(OrtAllocator* allocator, + Ort::Session& session_object, + const std::vector& inputs, + const char* output_name, + const std::vector& output_dims, + const std::vector& expected_output, + Ort::Value* output_tensor) { + std::vector ort_inputs; + std::vector input_names; + for (size_t i = 0; i < inputs.size(); i++) { + input_names.emplace_back(inputs[i].name); + ort_inputs.emplace_back( + Ort::Value::CreateTensor(allocator->Info(allocator), const_cast(inputs[i].values.data()), + inputs[i].values.size(), inputs[i].dims.data(), inputs[i].dims.size())); + } + + std::vector ort_outputs; + if (output_tensor) + session_object.Run(Ort::RunOptions{nullptr}, input_names.data(), ort_inputs.data(), ort_inputs.size(), + &output_name, output_tensor, 1); + else { + ort_outputs = session_object.Run(Ort::RunOptions{}, input_names.data(), ort_inputs.data(), ort_inputs.size(), + &output_name, 1); + ASSERT_EQ(ort_outputs.size(), 1u); + output_tensor = &ort_outputs[0]; + } + + auto type_info = output_tensor->GetTensorTypeAndShapeInfo(); + ASSERT_EQ(type_info.GetShape(), output_dims); + size_t total_len = type_info.GetElementCount(); + ASSERT_EQ(expected_output.size(), total_len); + + auto* actual = output_tensor->GetTensorMutableData(); + for (size_t i = 0; i != total_len; ++i) { + if constexpr (std::is_same::value || std::is_same::value) { + EXPECT_NEAR(expected_output[i], actual[i], 1e-3) << "i=" << i; + } else { + EXPECT_EQ(expected_output[i], actual[i]) << "i=" << i; + } + } +} diff --git a/winml/adapter/winml_adapter_model.cpp b/winml/adapter/winml_adapter_model.cpp index 195bf6e5f0ffd..cf02c6fa2328b 100644 --- a/winml/adapter/winml_adapter_model.cpp +++ b/winml/adapter/winml_adapter_model.cpp @@ -593,13 +593,13 @@ ORT_API_STATUS_IMPL( input.set_name(input_name); if (info->type == ONNXType::ONNX_TYPE_TENSOR) { - auto num_dims = info->data->shape.NumDimensions(); + auto num_dims = info->tensor_type_info->shape.NumDimensions(); CreateTypeProto_Tensor( input.mutable_type()->mutable_tensor_type(), input_name, - (num_dims == 0) ? nullptr : &info->data->shape[0], + (num_dims == 0) ? nullptr : &info->tensor_type_info->shape[0], num_dims, - ONNXTensorElementDataTypeToTensorProto_DataType(info->data->type) + ONNXTensorElementDataTypeToTensorProto_DataType(info->tensor_type_info->type) ); } return nullptr; @@ -619,12 +619,12 @@ ORT_API_STATUS_IMPL( ONNX_NAMESPACE::TensorProto& input = *graph.add_initializer(); input.set_name(input_name); - auto num_dims = info->data->shape.NumDimensions(); + auto num_dims = info->tensor_type_info->shape.NumDimensions(); for (size_t i = 0; i < num_dims; i++) { - input.add_dims(info->data->shape[i]); + input.add_dims(info->tensor_type_info->shape[i]); } - input.set_data_type(ONNXTensorElementDataTypeToTensorProto_DataType(info->data->type)); + input.set_data_type(ONNXTensorElementDataTypeToTensorProto_DataType(info->tensor_type_info->type)); auto tensor = value->GetMutable(); input.set_raw_data(tensor->DataRaw(), tensor->SizeInBytes()); @@ -645,9 +645,9 @@ ORT_API_STATUS_IMPL( CreateTypeProto_Tensor( output.mutable_type()->mutable_tensor_type(), output_name, - &info->data->shape[0], - info->data->shape.NumDimensions(), - ONNXTensorElementDataTypeToTensorProto_DataType(info->data->type) + &info->tensor_type_info->shape[0], + info->tensor_type_info->shape.NumDimensions(), + ONNXTensorElementDataTypeToTensorProto_DataType(info->tensor_type_info->type) ); } return nullptr; From 1ffe793a834cf347b13845c15aa9cd008ec23b23 Mon Sep 17 00:00:00 2001 From: Seungtaek Kim Date: Sat, 1 Mar 2025 15:25:04 +0900 Subject: [PATCH 025/266] Fix typo: change `Upample` to `Upsample`. (#23838) ### Description Fixed a typo in function names related to the Upsample CUDA kernel. Changed incorrect spelling Upample to Upsample across relevant functions. ### Motivation and Context This change is necessary to maintain consistency and prevent potential confusion caused by incorrect function names. --- .../core/providers/cuda/tensor/upsample.cc | 20 ++-- .../providers/cuda/tensor/upsample_impl.cu | 94 +++++++++---------- .../providers/cuda/tensor/upsample_impl.h | 20 ++-- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/onnxruntime/core/providers/cuda/tensor/upsample.cc b/onnxruntime/core/providers/cuda/tensor/upsample.cc index cbf745d3c7b4f..a38fe1efad540 100644 --- a/onnxruntime/core/providers/cuda/tensor/upsample.cc +++ b/onnxruntime/core/providers/cuda/tensor/upsample.cc @@ -290,16 +290,16 @@ Status Upsample::BaseCompute(OpKernelContext* context, scales_div[i] = fast_divmod(gsl::narrow_cast(ceil(scales[i]))); } - UpampleImpl(Stream(context), - mode_, - rank, - (UpsampleMode::LINEAR == mode_) ? (rank == 2 ? X_dims[0] : X_dims[2]) : 0, - input_strides, - output_div_pitches, - scales_div, - reinterpret_cast(X->Data()), - reinterpret_cast(Y->MutableData()), - output_count); + UpsampleImpl(Stream(context), + mode_, + rank, + (UpsampleMode::LINEAR == mode_) ? (rank == 2 ? X_dims[0] : X_dims[2]) : 0, + input_strides, + output_div_pitches, + scales_div, + reinterpret_cast(X->Data()), + reinterpret_cast(Y->MutableData()), + output_count); } return Status::OK(); diff --git a/onnxruntime/core/providers/cuda/tensor/upsample_impl.cu b/onnxruntime/core/providers/cuda/tensor/upsample_impl.cu index d1c2ae6332994..24aeada559979 100644 --- a/onnxruntime/core/providers/cuda/tensor/upsample_impl.cu +++ b/onnxruntime/core/providers/cuda/tensor/upsample_impl.cu @@ -8,12 +8,12 @@ namespace onnxruntime { namespace cuda { template -__global__ void _UpampleNearestKernel(const TArray input_pitches, - const TArray output_div_pitches, - const TArray scales_div, - const T* __restrict__ input_data, - T* __restrict__ output_data, - const size_t N) { +__global__ void _UpsampleNearestKernel(const TArray input_pitches, + const TArray output_div_pitches, + const TArray scales_div, + const T* __restrict__ input_data, + T* __restrict__ output_data, + const size_t N) { CALCULATE_ELEMENTWISE_INDEX_OR_EXIT(id, N); CUDA_LONG input_index = 0; CUDA_LONG output_index = id; @@ -36,13 +36,13 @@ __global__ void _UpampleNearestKernel(const TArray input_pitches, // This is the common use-case where the 4-D input (batched multi-channel images) // is usually of shape [N, C, H, W] and the scales are [1.0, 1.0, height_scale, width_scale] template -__global__ void _UpampleBilinear4DInputKernel(const int64_t input_dim2, - const TArray input_pitches, - const TArray output_div_pitches, - const TArray scales_div, - const T* __restrict__ input_data, - T* __restrict__ output_data, - const size_t N) { +__global__ void _UpsampleBilinear4DInputKernel(const int64_t input_dim2, + const TArray input_pitches, + const TArray output_div_pitches, + const TArray scales_div, + const T* __restrict__ input_data, + T* __restrict__ output_data, + const size_t N) { CALCULATE_ELEMENTWISE_INDEX_OR_EXIT(id, N); CUDA_LONG input_index = 0; @@ -95,13 +95,13 @@ __global__ void _UpampleBilinear4DInputKernel(const int64_t input_dim2, // The following method supports a 2-D input in 'Linear mode' template -__global__ void _UpampleBilinear2DInputKernel(const int64_t input_dim0, - const TArray input_pitches, - const TArray output_div_pitches, - const TArray scales_div, - const T* __restrict__ input_data, - T* __restrict__ output_data, - const size_t N) { +__global__ void _UpsampleBilinear2DInputKernel(const int64_t input_dim0, + const TArray input_pitches, + const TArray output_div_pitches, + const TArray scales_div, + const T* __restrict__ input_data, + T* __restrict__ output_data, + const size_t N) { CALCULATE_ELEMENTWISE_INDEX_OR_EXIT(id, N); CUDA_LONG input_index = 0; @@ -147,32 +147,32 @@ __global__ void _UpampleBilinear2DInputKernel(const int64_t input_dim0, } template -void UpampleImpl(cudaStream_t stream, - const onnxruntime::UpsampleMode upsample_mode, - const size_t rank, - const int64_t input_dim2, - const TArray& input_pitches, - const TArray& output_div_pitches, - const TArray& scales_div, - const T* input_data, - T* output_data, - const size_t N) { +void UpsampleImpl(cudaStream_t stream, + const onnxruntime::UpsampleMode upsample_mode, + const size_t rank, + const int64_t input_dim2, + const TArray& input_pitches, + const TArray& output_div_pitches, + const TArray& scales_div, + const T* input_data, + T* output_data, + const size_t N) { int blocksPerGrid = (int)(ceil(static_cast(N) / GridDim::maxThreadsPerBlock)); if (onnxruntime::UpsampleMode::NN == upsample_mode) { if (rank == 4) { - _UpampleNearestKernel<<>>( + _UpsampleNearestKernel<<>>( input_pitches, output_div_pitches, scales_div, input_data, output_data, N); } else if (rank == 3) { - _UpampleNearestKernel<<>>( + _UpsampleNearestKernel<<>>( input_pitches, output_div_pitches, scales_div, input_data, output_data, N); } else if (rank == 2) { - _UpampleNearestKernel<<>>( + _UpsampleNearestKernel<<>>( input_pitches, output_div_pitches, scales_div, input_data, output_data, N); } else if (rank == 1) { - _UpampleNearestKernel<<>>( + _UpsampleNearestKernel<<>>( input_pitches, output_div_pitches, scales_div, input_data, output_data, N); } else { @@ -180,11 +180,11 @@ void UpampleImpl(cudaStream_t stream, } } else if (onnxruntime::UpsampleMode::LINEAR == upsample_mode) { if (rank == 4) { - _UpampleBilinear4DInputKernel<<>>( + _UpsampleBilinear4DInputKernel<<>>( input_dim2, input_pitches, output_div_pitches, scales_div, input_data, output_data, N); } else if (rank == 2) { - _UpampleBilinear2DInputKernel<<>>( + _UpsampleBilinear2DInputKernel<<>>( input_dim2, input_pitches, output_div_pitches, scales_div, input_data, output_data, N); } else { @@ -197,17 +197,17 @@ void UpampleImpl(cudaStream_t stream, } } -#define SPECIALIZED_IMPL(T) \ - template void UpampleImpl(cudaStream_t stream, \ - const onnxruntime::UpsampleMode upsample_mode, \ - const size_t rank, \ - const int64_t input_dim2, \ - const TArray& input_pitches, \ - const TArray& output_div_pitches, \ - const TArray& scales_div, \ - const T* input_data, \ - T* output_data, \ - const size_t N); +#define SPECIALIZED_IMPL(T) \ + template void UpsampleImpl(cudaStream_t stream, \ + const onnxruntime::UpsampleMode upsample_mode, \ + const size_t rank, \ + const int64_t input_dim2, \ + const TArray& input_pitches, \ + const TArray& output_div_pitches, \ + const TArray& scales_div, \ + const T* input_data, \ + T* output_data, \ + const size_t N); SPECIALIZED_IMPL(float) SPECIALIZED_IMPL(double) diff --git a/onnxruntime/core/providers/cuda/tensor/upsample_impl.h b/onnxruntime/core/providers/cuda/tensor/upsample_impl.h index 250ec6b272e34..fb47ad8301615 100644 --- a/onnxruntime/core/providers/cuda/tensor/upsample_impl.h +++ b/onnxruntime/core/providers/cuda/tensor/upsample_impl.h @@ -11,16 +11,16 @@ namespace onnxruntime { namespace cuda { template -void UpampleImpl(cudaStream_t stream, - const onnxruntime::UpsampleMode upsample_mode, - const size_t rank, - const int64_t input_dim2, - const TArray& input_pitches, - const TArray& output_div_pitches, - const TArray& scales_div, - const T* input_data, - T* output_data, - const size_t N); +void UpsampleImpl(cudaStream_t stream, + const onnxruntime::UpsampleMode upsample_mode, + const size_t rank, + const int64_t input_dim2, + const TArray& input_pitches, + const TArray& output_div_pitches, + const TArray& scales_div, + const T* input_data, + T* output_data, + const size_t N); } // namespace cuda } // namespace onnxruntime From 0a6b05fb2dda82e2e18a1755f83bfaa3a0a7f5eb Mon Sep 17 00:00:00 2001 From: co63oc Date: Sat, 1 Mar 2025 16:54:58 +0800 Subject: [PATCH 026/266] [doc] Fix typos in csharp/src/Microsoft.ML.OnnxRuntime/ (#23848) ### Description Fix typos in csharp/src/Microsoft.ML.OnnxRuntime/ ### Motivation and Context --- .../src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs | 3 +-- csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs index 13117f23e8ef9..8916f11919cfe 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs @@ -25,7 +25,7 @@ internal class ManagedTypeProjection /// /// /// - /// OrtValye created accoding to the metadata + /// OrtValue created according to the metadata internal static OrtValue CreateProjection(NamedOnnxValue namedOnnxValue, NodeMetadata metadata) { OrtValue result; @@ -191,4 +191,3 @@ private static OrtValue CreateTensorProjection(NamedOnnxValue node, NodeMetadata } } } - diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs index d628b065ceaa7..b64a5c3e5a4a2 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs @@ -847,7 +847,7 @@ internal class NativeLib /// Creates an instance of OrtSession with provided parameters /// /// Native OrtEnv instance - /// Byte array correspoonding to the model + /// Byte array corresponding to the model /// Size of the model in bytes /// Native SessionOptions instance /// Native OrtPrepackedWeightsContainer instance @@ -1258,7 +1258,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// /// Native SessionOptions instance /// Name of the initializer - /// Native OrtValue instnce + /// Native OrtValue instance [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtAddInitializer(IntPtr /*(OrtSessionOptions*)*/ options, byte[] /*(const char*)*/ name, From daf9565d1b550fd0d8149e8314bfce61d8df1d54 Mon Sep 17 00:00:00 2001 From: Jambay Kinley Date: Sat, 1 Mar 2025 20:16:10 -0800 Subject: [PATCH 027/266] Quant tool: Consistent `get_qdq_config` and `get_qnn_qdq_config` behavior (#23856) --- .../execution_providers/qnn/quant_config.py | 6 +- .../python/tools/quantization/quantize.py | 32 +++++++---- .../quantization/test_get_qdq_config.py | 56 +++++++++++++++++++ 3 files changed, 81 insertions(+), 13 deletions(-) diff --git a/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py b/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py index ea995d4707ba3..50da0025752aa 100644 --- a/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py +++ b/onnxruntime/python/tools/quantization/execution_providers/qnn/quant_config.py @@ -204,9 +204,9 @@ def get_qnn_qdq_config( calibrate_method=calibrate_method, activation_type=activation_type, weight_type=weight_type, - op_types_to_quantize=op_types_to_quantize - if op_types_to_quantize - else list(op_types.difference(OP_TYPES_TO_EXCLUDE)), + op_types_to_quantize=( + op_types_to_quantize if op_types_to_quantize else list(op_types.difference(OP_TYPES_TO_EXCLUDE)) + ), nodes_to_exclude=nodes_to_exclude, per_channel=per_channel, use_external_data_format=(model_has_external_data or model.ByteSize() >= MODEL_SIZE_THRESHOLD), diff --git a/onnxruntime/python/tools/quantization/quantize.py b/onnxruntime/python/tools/quantization/quantize.py index fa468a9676a65..d19bebad8a12c 100644 --- a/onnxruntime/python/tools/quantization/quantize.py +++ b/onnxruntime/python/tools/quantization/quantize.py @@ -240,6 +240,8 @@ def get_qdq_config( keep_removable_activations: bool = False, min_real_range: float | None = None, tensor_quant_overrides: dict[str, list[dict[str, Any]]] | None = None, + calibration_providers: list[str] | None = None, + op_types_to_quantize: list[str] | None = None, nodes_to_exclude: list[str] | Callable[[onnx.ModelProto, onnx.NodeProto], bool] | None = None, extra_options: dict | None = None, ) -> StaticQuantConfig: @@ -294,6 +296,10 @@ def get_qdq_config( 'convert["recv_nodes"] = Set : Set of node names that consume the converted activation, other nodes get the original type. If not specified, assume all consumer nodes get the converted type. + calibration_providers: Execution providers to run the session during calibration. Default is None which uses + [ "CPUExecutionProvider" ]. + op_types_to_quantize: List of operator types to quantize. If None, all operators other than Cast, DequantizeLinear, + and QuantizeLinear are quantized. nodes_to_exclude: List of nodes names to exclude from quantization. Alternatively, can provide a function that accepts an onnx.ModelProto and onnx.NodeProto as arguments and returns true if the give onnx.NodeProto should be excluded from quantization. @@ -324,17 +330,20 @@ def get_qdq_config( if onnx.external_data_helper.uses_external_data(initializer): model_has_external_data = True - final_nodes_to_exclude = [] - if nodes_to_exclude is not None and isinstance(nodes_to_exclude, list): - final_nodes_to_exclude.extend(nodes_to_exclude) + op_types_to_quantize_set = set(op_types_to_quantize) if op_types_to_quantize else None + nodes_to_exclude_set = set(nodes_to_exclude) if isinstance(nodes_to_exclude, list) else set() # Iterate through nodes to get all operator types in the model and # call user's function to filter out nodes from quantization. for node in model.graph.node: - op_types.add(node.op_type) - if nodes_to_exclude is not None and callable(nodes_to_exclude): - if nodes_to_exclude(model, node): - final_nodes_to_exclude.append(node.name) + if op_types_to_quantize_set and node.op_type not in op_types_to_quantize_set: + continue + if node.name in nodes_to_exclude_set: + continue + if callable(nodes_to_exclude) and nodes_to_exclude(model, node): + nodes_to_exclude_set.add(node.name) + else: + op_types.add(node.op_type) final_extra_options = { "MinimumRealRange": min_real_range, @@ -378,11 +387,14 @@ def get_qdq_config( quant_format=QuantFormat.QDQ, activation_type=activation_type, weight_type=weight_type, - op_types_to_quantize=list(op_types.difference(op_types_to_exclude)), - nodes_to_exclude=final_nodes_to_exclude, + op_types_to_quantize=( + op_types_to_quantize if op_types_to_quantize else list(op_types.difference(op_types_to_exclude)) + ), + nodes_to_exclude=list(nodes_to_exclude_set), per_channel=per_channel, reduce_range=reduce_range, use_external_data_format=(model_has_external_data or model.ByteSize() >= MODEL_SIZE_THRESHOLD), + calibration_providers=calibration_providers, extra_options=final_extra_options, ) @@ -442,7 +454,7 @@ def check_static_quant_arguments(quant_format: QuantFormat, activation_type: Qua if activation_type != QuantType.QFLOAT8E4M3FN and weight_type == QuantType.QFLOAT8E4M3FN: raise ValueError( f"ONNXRuntime quantization doesn't support data format: activation_type={activation_type} " - f"!=QuantType.QFLOAT8E4M3FN, weight_type=QuantType.QFLOAT8E4M3FN." + "!=QuantType.QFLOAT8E4M3FN, weight_type=QuantType.QFLOAT8E4M3FN." ) if activation_type == QuantType.QFLOAT8E4M3FN and weight_type != QuantType.QFLOAT8E4M3FN: diff --git a/onnxruntime/test/python/quantization/test_get_qdq_config.py b/onnxruntime/test/python/quantization/test_get_qdq_config.py index 25f058d8f6eac..4a71b3694822c 100644 --- a/onnxruntime/test/python/quantization/test_get_qdq_config.py +++ b/onnxruntime/test/python/quantization/test_get_qdq_config.py @@ -156,6 +156,62 @@ def should_exclude_node_(model: onnx.ModelProto, node: onnx.NodeProto) -> bool: self.assertTrue(bool(expected_excluded_nodes)) self.assertEqual(set(qdq_config.nodes_to_exclude), expected_excluded_nodes) + def test_op_types_to_quantize(self): + """ + Test that get_qdq_config() returns a config that sets the op_types_to_quantize arg. + """ + shape = [1, 8, 8] + tensor_type = onnx.TensorProto.FLOAT + np_dtype = onnx.helper.tensor_dtype_to_np_dtype(tensor_type) + weight = onnx.numpy_helper.from_array(np.ones(shape, dtype=np_dtype), "weight") + float_model = self.build_add_model(shape, tensor_type, weight) + + input_data_list = [ + {"input_0": np.ones(shape, dtype=np_dtype) * np.array(-2, dtype=np_dtype)}, + {"input_0": np.ones(shape, dtype=np_dtype) * np.array(2, dtype=np_dtype)}, + ] + data_reader = TestDataFeeds(input_data_list) + + # No op_types_to_quantize arg means all ops are quantized. + qdq_config = get_qdq_config(float_model, data_reader, op_types_to_quantize=None) + self.assertEqual(set(qdq_config.op_types_to_quantize), {"Add"}) + + # specify custom op_types_to_quantize arg. + qdq_config = get_qdq_config(float_model, data_reader, op_types_to_quantize=["Mul"]) + self.assertEqual(set(qdq_config.op_types_to_quantize), {"Mul"}) + + # exclude op_type indirectly by specifying nodes_to_exclude arg. + qdq_config = get_qdq_config( + float_model, + data_reader, + nodes_to_exclude=[node.name for node in float_model.graph.node if node.op_type == "Add"], + ) + self.assertEqual(set(qdq_config.op_types_to_quantize), set()) + + def test_calibration_providers(self): + """ + Test that get_qdq_config() returns a config that sets the calibration providers arg. + """ + + shape = [1, 8, 8] + tensor_type = onnx.TensorProto.FLOAT + np_dtype = onnx.helper.tensor_dtype_to_np_dtype(tensor_type) + weight = onnx.numpy_helper.from_array(np.ones(shape, dtype=np_dtype), "weight") + float_model = self.build_add_model(shape, tensor_type, weight) + + input_data_list = [ + {"input_0": np.ones(shape, dtype=np_dtype) * np.array(-2, dtype=np_dtype)}, + {"input_0": np.ones(shape, dtype=np_dtype) * np.array(2, dtype=np_dtype)}, + ] + data_reader = TestDataFeeds(input_data_list) + + qdq_config = get_qdq_config( + float_model, + data_reader, + calibration_providers=["CPUExecutionProvider"], + ) + self.assertEqual(qdq_config.calibration_providers, ["CPUExecutionProvider"]) + def test_external_data(self): """ Test that get_qdq_config() returns a config that enables external data From 99c51a326e0ff54a56e7b194204d459932084408 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Sun, 2 Mar 2025 20:57:01 -0800 Subject: [PATCH 028/266] Change the logic to generate the default ep context file name (#23788) Change the logic to generate the default ep context file name ### Description Applies to all EPs: replace the .onnx to _ctx.onnx, instead of directly append extra string _ctx.onnx to existing model path. In QNN EP, also make the context binary .bin file shorter by removing QNNExecutionProvider_ from the file name. --- .../core/framework/graph_partitioner.cc | 28 +++++----- .../qnn/builder/onnx_ctx_model_helper.cc | 38 +++++-------- .../qnn/builder/onnx_ctx_model_helper.h | 7 +-- .../providers/qnn/qnn_execution_provider.cc | 30 +++++++---- .../test/providers/qnn/qnn_ep_context_test.cc | 53 +++++++++++++------ 5 files changed, 84 insertions(+), 72 deletions(-) diff --git a/onnxruntime/core/framework/graph_partitioner.cc b/onnxruntime/core/framework/graph_partitioner.cc index 111f8e0a5fc34..b79d0327c3ef5 100644 --- a/onnxruntime/core/framework/graph_partitioner.cc +++ b/onnxruntime/core/framework/graph_partitioner.cc @@ -667,23 +667,28 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide } // Validate the ep_context_path to make sure it is file path and check whether the file exist already -static Status EpContextFilePathCheck(const std::string& ep_context_path, - const std::filesystem::path& model_path) { - std::filesystem::path context_cache_path; +static Status GetValidatedEpContextPath(const std::filesystem::path& ep_context_path, + const std::filesystem::path& model_path, + std::filesystem::path& context_cache_path) { if (!ep_context_path.empty()) { context_cache_path = ep_context_path; if (!context_cache_path.has_filename()) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "context_file_path should not point to a folder."); } } else if (!model_path.empty()) { - context_cache_path = model_path.native() + ORT_TSTR("_ctx.onnx"); + auto pos = model_path.native().find_last_of(ORT_TSTR(".")); + if (pos != std::string::npos) { + context_cache_path = model_path.native().substr(0, pos) + ORT_TSTR("_ctx.onnx"); + } else { + context_cache_path = model_path.native() + ORT_TSTR("_ctx.onnx"); + } } else { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Both ep_context_path and model_path are empty."); } if (std::filesystem::exists(context_cache_path)) { return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to generate EP context model since the file '", - context_cache_path, "' exist already."); + context_cache_path, "' exist already. Please remove the EP context model if you want to re-generate it."); } return Status::OK(); @@ -714,15 +719,7 @@ static Status CreateEpContextModel(const ExecutionProviders& execution_providers }; std::filesystem::path context_cache_path; - const std::filesystem::path& model_path = graph.ModelPath(); - - if (!ep_context_path.empty()) { - context_cache_path = ep_context_path; - } else if (!model_path.empty()) { - context_cache_path = model_path.native() + ORT_TSTR("_ctx.onnx"); - } else { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Both ep_context_path and model_path are empty"); - } + ORT_RETURN_IF_ERROR(GetValidatedEpContextPath(ep_context_path, graph.ModelPath(), context_cache_path)); Model ep_context_model(graph.Name(), false, graph.GetModel().MetaData(), graph.GetModel().ModelPath(), // use source model path so that external initializers can find the data file path @@ -1068,7 +1065,8 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, if (ep_context_enabled) { std::string ep_context_path = config_options.GetConfigOrDefault(kOrtSessionOptionEpContextFilePath, ""); // Check before EP compile graphs - ORT_RETURN_IF_ERROR(EpContextFilePathCheck(ep_context_path, graph.ModelPath())); + std::filesystem::path context_cache_path; + ORT_RETURN_IF_ERROR(GetValidatedEpContextPath(ep_context_path, graph.ModelPath(), context_cache_path)); } // We use this only if Resource Aware Partitioning is enabled for any of the EPs diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc index 3df231e53e7c0..d85277627a3de 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc @@ -198,35 +198,13 @@ Status LoadQnnCtxFromOnnxGraph(const onnxruntime::GraphViewer& graph_viewer, return Status::OK(); } -// Figure out the real context cache file path -// return true if context cache file exists -bool ValidateContextCacheFilePath(bool is_qnn_ctx_model, - const std::string& customer_context_cache_path, - const onnxruntime::PathString& model_pathstring, - onnxruntime::PathString& context_cache_path) { - // always try the path set by user first, it's the only way to set it if load model from memory - if (!customer_context_cache_path.empty()) { - context_cache_path = ToPathString(customer_context_cache_path); - } else if (!model_pathstring.empty()) { // model loaded from file - if (is_qnn_ctx_model) { - // it's a context cache model, just use the model path - context_cache_path = model_pathstring; - } else if (!model_pathstring.empty()) { - // this is not a normal Onnx model, no customer path, create a default path for generation: model_path + _ctx.onnx - context_cache_path = model_pathstring + ToPathString("_ctx.onnx"); - } - } - - return std::filesystem::is_regular_file(context_cache_path) && std::filesystem::exists(context_cache_path); -} - Status CreateEPContextNodes(Model* model, unsigned char* buffer, uint64_t buffer_size, const std::string& sdk_build_version, const std::vector& fused_nodes_and_graphs, const QnnModelLookupTable& qnn_models, - const onnxruntime::PathString& context_cache_path, + const onnxruntime::PathString& context_model_path, bool qnn_context_embed_mode, uint64_t max_spill_fill_buffer_size, const logging::Logger& logger) { @@ -262,7 +240,19 @@ Status CreateEPContextNodes(Model* model, std::string cache_payload(buffer, buffer + buffer_size); ep_node.AddAttribute(EP_CACHE_CONTEXT, cache_payload); } else { - onnxruntime::PathString context_bin_path = context_cache_path + ToPathString("_" + graph_name + ".bin"); + onnxruntime::PathString context_bin_path; + auto pos = context_model_path.find_last_of(ORT_TSTR(".")); + if (pos != std::string::npos) { + context_bin_path = context_model_path.substr(0, pos); + } else { + context_bin_path = context_model_path; + } + std::string graph_name_in_file(graph_name); + auto name_pos = graph_name_in_file.find_first_of(kQnnExecutionProvider); + if (name_pos != std::string::npos) { + graph_name_in_file.replace(name_pos, strlen(kQnnExecutionProvider), ""); + } + context_bin_path = context_bin_path + ToPathString(graph_name_in_file + ".bin"); std::string context_cache_name(std::filesystem::path(context_bin_path).filename().string()); std::ofstream of_stream(context_bin_path.c_str(), std::ofstream::binary); if (!of_stream) { diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h index 3dfa0ae21001b..c54cd3ca6e90c 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h @@ -38,11 +38,6 @@ Status CreateNodeArgs(const std::vector& names, std::vector& node_args, onnxruntime::Graph& graph); -bool ValidateContextCacheFilePath(bool is_qnn_ctx_model, - const std::string& customer_context_cache_path, - const onnxruntime::PathString& model_pathstring, - onnxruntime::PathString& context_cache_path); - Status GetEpContextFromMainNode(const onnxruntime::Node& main_context_node, const onnxruntime::PathString& ctx_onnx_model_path, QnnBackendManager* qnn_backend_manager, @@ -67,7 +62,7 @@ Status CreateEPContextNodes(Model* model, const std::string& sdk_build_version, const std::vector& fused_nodes_and_graphs, const std::unordered_map>& qnn_models, - const onnxruntime::PathString& context_cache_path, + const onnxruntime::PathString& context_model_path, bool qnn_context_embed_mode, uint64_t max_spill_fill_buffer_size, const logging::Logger& logger); diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index 3fc537066ae0b..99a6f51f6f712 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -904,25 +904,33 @@ Status QNNExecutionProvider::CompileFromOrtGraph(const std::vector& fused_nodes_and_graphs, std::vector& node_compute_funcs) { const auto& logger = *GetLogger(); bool is_qnn_ctx_model = qnn::IsFusedGraphHasCtxNode(fused_nodes_and_graphs); - onnxruntime::PathString context_cache_path; + onnxruntime::PathString context_model_path; bool is_ctx_file_exist = false; if (is_qnn_ctx_model || context_cache_enabled_) { const onnxruntime::GraphViewer& graph_viewer_0(fused_nodes_and_graphs[0].filtered_graph); - is_ctx_file_exist = qnn::ValidateContextCacheFilePath(is_qnn_ctx_model, - context_cache_path_cfg_, - graph_viewer_0.ModelPath().native(), - context_cache_path); + // Figure out the EP context model path from model path or session option + GetContextOnnxModelFilePath(context_cache_path_cfg_, + graph_viewer_0.ModelPath().native(), + context_model_path); } - ORT_RETURN_IF(is_ctx_file_exist && !is_qnn_ctx_model && context_cache_enabled_, - "The inference session is created from normal ONNX model. And an EP context model file is provided and existed. ", - "Please remove the EP context model manually if you want to re-generate it."); - if (is_qnn_ctx_model) { // Get QnnModel from EP shared contexts if (share_ep_contexts_ && SharedContext::GetInstance().HasSharedQnnModels()) { @@ -965,7 +973,7 @@ Status QNNExecutionProvider::Compile(const std::vector& fused const onnxruntime::GraphViewer& main_ctx_graph_viewer(fused_nodes_and_graphs[main_context_pos].filtered_graph); // Create QNN context from the cached binary, deserialize the QNN graph from the binary ORT_RETURN_IF_ERROR(qnn::LoadQnnCtxFromOnnxGraph(main_ctx_graph_viewer, - context_cache_path, + context_model_path, qnn_backend_manager_.get(), qnn_models, logger, @@ -1025,7 +1033,7 @@ Status QNNExecutionProvider::Compile(const std::vector& fused qnn_backend_manager_->GetSdkVersion(), fused_nodes_and_graphs, qnn_models_, - context_cache_path, + context_model_path, qnn_context_embed_mode_, max_spill_fill_buffer_size, logger)); diff --git a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc index 07843c30a61df..e50dd7c214240 100644 --- a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc @@ -333,7 +333,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryGenerationNoOverWrite) { const auto model_data_span = AsByteSpan(model_data.data(), model_data.size()); const std::string ep_context_onnx_file = "./ep_context_no_over_write.onnx"; - const std::string ep_context_binary_file = "./ep_context_no_over_write.onnx_QNNExecutionProvider_QNN_10880527342279992768_1_0.bin"; + const std::string ep_context_binary_file = "./ep_context_no_over_write_QNN_10880527342279992768_1_0.bin"; std::remove(ep_context_onnx_file.c_str()); Ort::SessionOptions so; @@ -580,6 +580,8 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCacheEmbedModeTest) { EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); // 2nd run directly loads and run from Qnn context cache model + std::unordered_map session_option_pairs2; + session_option_pairs2.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); TestQDQModelAccuracy(BuildOpTestCase(op_type, {input_def}, {}, {}), BuildQDQOpTestCase(op_type, {input_def}, {}, {}), provider_options, @@ -587,7 +589,8 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCacheEmbedModeTest) { ExpectedEPNodeAssignment::All, QDQTolerance(), logging::Severity::kERROR, - context_binary_file); + context_binary_file, + session_option_pairs2); // Clean up ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); } @@ -604,7 +607,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCacheNonEmbedModeTest) { #endif provider_options["offload_graph_io_quantization"] = "0"; const std::string context_binary_file = "./testdata/qnn_context_cache_non_embed.onnx"; - std::string qnn_ctx_bin = "./testdata/qnn_context_cache_non_embed.onnx_QNNExecutionProvider_QNN_8283143575221199085_1_0.bin"; + std::string qnn_ctx_bin = "./testdata/qnn_context_cache_non_embed_QNN_8283143575221199085_1_0.bin"; std::unordered_map session_option_pairs; session_option_pairs.emplace(kOrtSessionOptionEpContextEnable, "1"); @@ -686,7 +689,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCache_InvalidGraph) { #endif provider_options["offload_graph_io_quantization"] = "0"; const std::string context_binary_file = "./qnn_context_cache_non_embed.onnx"; - std::filesystem::path context_bin = "qnn_context_cache_non_embed.onnx_QNNExecutionProvider_QNN_8283143575221199085_1_0.bin"; + std::filesystem::path context_bin = "qnn_context_cache_non_embed_QNN_8283143575221199085_1_0.bin"; std::remove(context_binary_file.c_str()); std::remove(context_bin.string().c_str()); @@ -828,6 +831,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryFileNotExistTest) { SessionOptions so; so.session_logid = "qnn_ctx_model_logger"; + ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextFilePath, "./qnn_context_not_exist.onnx")); RunOptions run_options; run_options.run_tag = so.session_logid; @@ -841,7 +845,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryFileNotExistTest) { #endif provider_options["offload_graph_io_quantization"] = "0"; - ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(QnnExecutionProviderWithOptions(provider_options))); + ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(QnnExecutionProviderWithOptions(provider_options, &so))); ASSERT_STATUS_OK(session_object.Load(model_data.data(), static_cast(model_data.size()))); // Verify the return status with code INVALID_GRAPH ASSERT_TRUE(session_object.Initialize().Code() == common::StatusCode::INVALID_GRAPH); @@ -854,6 +858,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryFileEmptyStringTest) { SessionOptions so; so.session_logid = "qnn_ctx_model_logger"; + ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextFilePath, "./test_ctx.onnx")); RunOptions run_options; run_options.run_tag = so.session_logid; @@ -867,7 +872,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryFileEmptyStringTest) { #endif provider_options["offload_graph_io_quantization"] = "0"; - ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(QnnExecutionProviderWithOptions(provider_options))); + ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(QnnExecutionProviderWithOptions(provider_options, &so))); ASSERT_STATUS_OK(session_object.Load(model_data.data(), static_cast(model_data.size()))); // Verify the return status with code INVALID_GRAPH ASSERT_TRUE(session_object.Initialize().Code() == common::StatusCode::INVALID_GRAPH); @@ -911,6 +916,8 @@ TEST_F(QnnHTPBackendTests, QnnContextBinary2InputsTest) { EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); // 2nd run directly loads and run from Qnn context cache model + std::unordered_map session_option_pairs2; + session_option_pairs2.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); TestQDQModelAccuracy(BuildOpTestCase(op_type, {input_def1, input_def2}, {}, {}), BuildQDQOpTestCase(op_type, {input_def1, input_def2}, {}, {}), provider_options, @@ -918,7 +925,8 @@ TEST_F(QnnHTPBackendTests, QnnContextBinary2InputsTest) { ExpectedEPNodeAssignment::All, QDQTolerance(), logging::Severity::kERROR, - context_binary_file); + context_binary_file, + session_option_pairs2); // Clean up ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); } @@ -936,14 +944,14 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCache_SingleNodeNameNotMatchGraphName provider_options["backend_path"] = "libQnnHtp.so"; #endif provider_options["offload_graph_io_quantization"] = "0"; - const std::string context_binary_file = "./qnn_context_cache_non_embed.onnx"; - std::filesystem::path context_bin = "qnn_context_cache_non_embed.onnx_QNNExecutionProvider_QNN_8283143575221199085_1_0.bin"; - std::remove(context_binary_file.c_str()); + const std::string context_model_file = "./qnn_context_cache_non_embed.onnx"; + std::filesystem::path context_bin = "qnn_context_cache_non_embed_QNN_8283143575221199085_1_0.bin"; + std::remove(context_model_file.c_str()); std::remove(context_bin.string().c_str()); std::unordered_map session_option_pairs; session_option_pairs.emplace(kOrtSessionOptionEpContextEnable, "1"); - session_option_pairs.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); + session_option_pairs.emplace(kOrtSessionOptionEpContextFilePath, context_model_file); session_option_pairs.emplace(kOrtSessionOptionEpContextEmbedMode, "0"); const TestInputDef input_def({1, 2, 3}, false, -10.0f, 10.0f); @@ -962,7 +970,7 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCache_SingleNodeNameNotMatchGraphName session_option_pairs); // Check the Onnx skeleton file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); // Check the Qnn context cache binary file is generated EXPECT_TRUE(std::filesystem::exists(context_bin)); @@ -990,18 +998,19 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCache_SingleNodeNameNotMatchGraphName SessionOptions so; so.session_logid = "qnn_ctx_model_logger"; + ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_model_file.c_str())); RunOptions run_options; run_options.run_tag = so.session_logid; InferenceSessionWrapper session_object{so, GetEnvironment()}; - ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(QnnExecutionProviderWithOptions(provider_options))); + ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(QnnExecutionProviderWithOptions(provider_options, &so))); ASSERT_STATUS_OK(session_object.Load(model_data.data(), static_cast(model_data.size()))); // Verify the return status with code INVALID_GRAPH ASSERT_TRUE(session_object.Initialize().Code() == common::StatusCode::OK); // Clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + ASSERT_EQ(std::remove(context_model_file.c_str()), 0); ASSERT_EQ(std::remove(context_bin.string().c_str()), 0); } @@ -1167,7 +1176,13 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { for (auto model_path : onnx_model_paths) { CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); EXPECT_TRUE(std::filesystem::exists(model_path.c_str())); - ctx_model_paths.push_back(model_path + "_ctx.onnx"); + auto pos = model_path.find_last_of("."); + if (pos != std::string::npos) { + model_path = model_path.substr(0, pos) + "_ctx.onnx"; + } else { + model_path = model_path + "_ctx.onnx"; + } + ctx_model_paths.push_back(model_path); } DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); @@ -1265,7 +1280,13 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions2) { for (auto model_path : onnx_model_paths) { CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); EXPECT_TRUE(std::filesystem::exists(model_path.c_str())); - ctx_model_paths.push_back(model_path + "_ctx.onnx"); + auto pos = model_path.find_last_of("."); + if (pos != std::string::npos) { + model_path = model_path.substr(0, pos) + "_ctx.onnx"; + } else { + model_path = model_path + "_ctx.onnx"; + } + ctx_model_paths.push_back(model_path); } DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); From 7f0c2c644c83a5175d92c9b2fdf20399a6faad1d Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Mon, 3 Mar 2025 13:14:04 -0500 Subject: [PATCH 029/266] Make Nuget QNN package pipeline 1ES compliant (#23805) ### Description Make [QNN_Nuget_Windows](https://aiinfra.visualstudio.com/Lotus/_build?definitionId=1234)1ES compliant ### Motivation and Context --- .../qnn-ep-nuget-packaging-pipeline.yml | 148 ++++------ .../stages/nuget-qnn-packaging-stage.yml | 76 +++++ .../azure-pipelines/templates/qnn-ep-win.yml | 259 +++++++++--------- 3 files changed, 255 insertions(+), 228 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/stages/nuget-qnn-packaging-stage.yml diff --git a/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml index 055ef58e4524a..cfca998e0f06c 100644 --- a/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml @@ -29,108 +29,58 @@ parameters: displayName: Pipeline BuildId, you could find it in the URL type: string default: '0' - -stages: - -- template: templates/qnn-ep-win.yml - parameters: - qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' - QnnSdk: ${{ parameters.QnnSdk }} - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - DoEsrp: ${{ parameters.DoEsrp }} - ArtifactName: 'drop-nuget-qnn-x64' - StageName: 'OnnxRuntime_QNN_Nuget_Win_x64' - build_config: ${{ parameters.build_config }} - -- template: templates/qnn-ep-win.yml +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: - qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' - QnnSdk: ${{ parameters.QnnSdk }} - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - DoEsrp: ${{ parameters.DoEsrp }} - ArtifactName: 'drop-nuget-qnn-arm64' - buildParameter: '--arm64' - buildPlatform: 'ARM64' - buildArch: 'ARM64' - StageName: 'OnnxRuntime_QNN_Nuget_Win_Arm64' - build_config: ${{ parameters.build_config }} - -- stage: NuGet_Packaging_QNN - pool: 'Onnxruntime-QNNEP-Windows-2022-CPU' - dependsOn: - - OnnxRuntime_QNN_Nuget_Win_x64 - - OnnxRuntime_QNN_Nuget_Win_Arm64 - condition: succeeded() - jobs: - - job: NuGet_Packaging_QNN - workspace: - clean: all - steps: - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - QNN NuGet x64' - inputs: - artifactName: 'drop-nuget-qnn-x64' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-x64' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - QNN NuGet arm64' - inputs: - artifactName: 'drop-nuget-qnn-arm64' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-arm64' - - - task: PowerShell@2 - displayName: 'Bundle NuGet' - inputs: - targetType: 'inline' - script: | - - $x64_nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/nuget-artifact-x64 -Filter Microsoft.ML.OnnxRuntime.QNN*.nupkg -Recurse) - $nuget_package_name = $x64_nupkgs[0].Name - $x64_nuget_package = $x64_nupkgs[0].FullName - - $nupkg_unzipped_directory = [System.IO.Path]::Combine($Env:BUILD_ARTIFACTSTAGINGDIRECTORY, 'nuget_unzip_merged', [System.IO.Path]::GetFileNameWithoutExtension($nuget_package_name)) - - $x64_unzip_cmd = "7z.exe x $x64_nuget_package -y -o$nupkg_unzipped_directory" - Invoke-Expression -Command $x64_unzip_cmd - - $arm64_nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/nuget-artifact-arm64 -Filter Microsoft.ML.OnnxRuntime.QNN*.nupkg -Recurse) - $arm64_nuget_package = $arm64_nupkgs[0].FullName + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: - $arm64_unzip_cmd = "7z.exe x $arm64_nuget_package -y -o$nupkg_unzipped_directory" - Invoke-Expression -Command $arm64_unzip_cmd - - $merged_nuget_path = [System.IO.Path]::Combine($Env:BUILD_ARTIFACTSTAGINGDIRECTORY, 'nuget-artifact-merged') - if (!(Test-Path $merged_nuget_path)) { - New-Item -Path $merged_nuget_path -ItemType Directory - } - - $merged_zip = [System.IO.Path]::Combine($merged_nuget_path, 'qnn_nuget.zip') - $zip_cmd = "7z.exe a -r $merged_zip $nupkg_unzipped_directory/*" - Invoke-Expression -Command $zip_cmd - - $merged_nuget = [System.IO.Path]::Combine($merged_nuget_path, $nuget_package_name) - move $merged_zip $merged_nuget - workingDirectory: $(Build.BinariesDirectory) - - - template: templates/esrp_nuget.yml + - template: templates/qnn-ep-win.yml parameters: - DisplayName: 'ESRP - sign NuGet package' - FolderPath: '$(Build.ArtifactStagingDirectory)/nuget-artifact-merged' + qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' + QnnSdk: ${{ parameters.QnnSdk }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} DoEsrp: ${{ parameters.DoEsrp }} + ArtifactName: 'drop-nuget-qnn-x64' + StageName: 'OnnxRuntime_QNN_Nuget_Win_x64' + build_config: ${{ parameters.build_config }} - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline NuGet Artifact' - inputs: - artifactName: 'drop-signed-nuget-qnn' - targetPath: '$(Build.ArtifactStagingDirectory)/nuget-artifact-merged' + - template: templates/qnn-ep-win.yml + parameters: + qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' + QnnSdk: ${{ parameters.QnnSdk }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + DoEsrp: ${{ parameters.DoEsrp }} + ArtifactName: 'drop-nuget-qnn-arm64' + buildParameter: '--arm64' + buildPlatform: 'ARM64' + buildArch: 'ARM64' + StageName: 'OnnxRuntime_QNN_Nuget_Win_Arm64' + build_config: ${{ parameters.build_config }} + + - template: stages/nuget-qnn-packaging-stage.yml + parameters: + DoEsrp: ${{ parameters.DoEsrp }} -- template: templates/publish-nuget-steps.yml - parameters: - download_artifacts_steps: - - template: templates/flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline Artifact - Signed NuGet Qnn Package' - ArtifactName: 'drop-signed-nuget-qnn' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact/final-package' - SpecificArtifact: ${{ parameters.specificArtifact }} - BuildId: ${{ parameters.BuildId }} + - template: templates/publish-nuget-steps.yml + parameters: + download_artifacts_steps: + - template: templates/flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline Artifact - Signed NuGet Qnn Package' + ArtifactName: 'drop-signed-nuget-qnn' + targetPath: '$(Build.BinariesDirectory)/nuget-artifact/final-package' + SpecificArtifact: ${{ parameters.specificArtifact }} + BuildId: ${{ parameters.BuildId }} diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-qnn-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-qnn-packaging-stage.yml new file mode 100644 index 0000000000000..03802746cec3d --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-qnn-packaging-stage.yml @@ -0,0 +1,76 @@ +parameters: +- name: DoEsrp + displayName: Run code sign tasks? Must be true if you are doing an Onnx Runtime release. + type: boolean + default: true + +stages: +- stage: NuGet_Packaging_QNN + pool: + name: 'Onnxruntime-QNNEP-Windows-2022-CPU' + dependsOn: + - OnnxRuntime_QNN_Nuget_Win_x64 + - OnnxRuntime_QNN_Nuget_Win_Arm64 + condition: succeeded() + jobs: + - job: NuGet_Packaging_QNN + workspace: + clean: all + steps: + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - QNN NuGet x64' + inputs: + artifactName: 'drop-nuget-qnn-x64' + targetPath: '$(Build.BinariesDirectory)/nuget-artifact-x64' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - QNN NuGet arm64' + inputs: + artifactName: 'drop-nuget-qnn-arm64' + targetPath: '$(Build.BinariesDirectory)/nuget-artifact-arm64' + + - task: PowerShell@2 + displayName: 'Bundle NuGet' + inputs: + targetType: 'inline' + script: | + + $x64_nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/nuget-artifact-x64 -Filter Microsoft.ML.OnnxRuntime.QNN*.nupkg -Recurse) + $nuget_package_name = $x64_nupkgs[0].Name + $x64_nuget_package = $x64_nupkgs[0].FullName + + $nupkg_unzipped_directory = [System.IO.Path]::Combine($Env:BUILD_ARTIFACTSTAGINGDIRECTORY, 'nuget_unzip_merged', [System.IO.Path]::GetFileNameWithoutExtension($nuget_package_name)) + + $x64_unzip_cmd = "7z.exe x $x64_nuget_package -y -o$nupkg_unzipped_directory" + Invoke-Expression -Command $x64_unzip_cmd + + $arm64_nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/nuget-artifact-arm64 -Filter Microsoft.ML.OnnxRuntime.QNN*.nupkg -Recurse) + $arm64_nuget_package = $arm64_nupkgs[0].FullName + + $arm64_unzip_cmd = "7z.exe x $arm64_nuget_package -y -o$nupkg_unzipped_directory" + Invoke-Expression -Command $arm64_unzip_cmd + + $merged_nuget_path = [System.IO.Path]::Combine($Env:BUILD_ARTIFACTSTAGINGDIRECTORY, 'nuget-artifact-merged') + if (!(Test-Path $merged_nuget_path)) { + New-Item -Path $merged_nuget_path -ItemType Directory + } + + $merged_zip = [System.IO.Path]::Combine($merged_nuget_path, 'qnn_nuget.zip') + $zip_cmd = "7z.exe a -r $merged_zip $nupkg_unzipped_directory/*" + Invoke-Expression -Command $zip_cmd + + $merged_nuget = [System.IO.Path]::Combine($merged_nuget_path, $nuget_package_name) + move $merged_zip $merged_nuget + workingDirectory: $(Build.BinariesDirectory) + + - template: ../templates/esrp_nuget.yml + parameters: + DisplayName: 'ESRP - sign NuGet package' + FolderPath: '$(Build.ArtifactStagingDirectory)/nuget-artifact-merged' + DoEsrp: ${{ parameters.DoEsrp }} + + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline NuGet Artifact' + inputs: + artifactName: 'drop-signed-nuget-qnn' + targetPath: '$(Build.ArtifactStagingDirectory)/nuget-artifact-merged' diff --git a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml index a93d6b5ff8419..b591a3e3e121b 100644 --- a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml +++ b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml @@ -18,7 +18,8 @@ stages: - job: ${{ parameters.StageName }} timeoutInMinutes: 120 - pool: ${{ parameters.qnn_ep_build_pool_name }} + pool: + name: ${{ parameters.qnn_ep_build_pool_name }} variables: ${{ if eq(parameters.buildArch, 'ARM64') }}: targetArchitecture: 'arm64' @@ -28,134 +29,134 @@ stages: commonBuildArgs: '--update --compile_no_warning_as_error --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --cmake_generator "Visual Studio 17 2022" --config ${{ parameters.build_config }} --parallel --use_binskim_compliant_compile_flags ${{ parameters.buildParameter }} ' steps: - - template: set-version-number-variables-step.yml - - - task: UsePythonVersion@0 - inputs: - versionSpec: '3.12' - addToPath: true - - - template: jobs/download_win_qnn_sdk.yml - parameters: - QnnSDKVersion: ${{ parameters.QnnSdk }} - - - task: PythonScript@0 - displayName: 'Generate project' - inputs: - scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: '--use_qnn --qnn_home $(QnnSDKRootDir) $(commonBuildArgs)' - - - task: VSBuild@1 - displayName: 'Build onnxruntime' - inputs: - solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnxruntime.vcxproj' - platform: ${{ parameters.buildPlatform }} - configuration: ${{ parameters.build_config }} - msbuildArchitecture: ${{ parameters.buildArch }} - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' - createLogFile: true - - - task: VSBuild@1 - displayName: 'Build onnx_test_runner' - inputs: - solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnx_test_runner.vcxproj' - platform: ${{ parameters.buildPlatform }} - configuration: ${{ parameters.build_config }} - msbuildArchitecture: ${{ parameters.buildArch }} - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' - createLogFile: true - - - task: VSBuild@1 - displayName: 'Build onnxruntime_perf_test' - inputs: - solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnxruntime_perf_test.vcxproj' - platform: ${{ parameters.buildPlatform }} - configuration: ${{ parameters.build_config }} - msbuildArchitecture: ${{ parameters.buildArch }} - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' - createLogFile: true - - - task: VSBuild@1 - displayName: 'Build onnxruntime_test_all (to copy Qnn libs)' - inputs: - solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnxruntime_test_all.vcxproj' - platform: ${{ parameters.buildPlatform }} - configuration: ${{ parameters.build_config }} - msbuildArchitecture: ${{ parameters.buildArch }} - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' - createLogFile: true - - - task: CmdLine@2 - displayName: 'Print contents of binaries directory' - inputs: - script: | - dir $(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }} - + - template: set-version-number-variables-step.yml + + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + addToPath: true + + - template: jobs/download_win_qnn_sdk.yml + parameters: + QnnSDKVersion: ${{ parameters.QnnSdk }} + + - task: PythonScript@0 + displayName: 'Generate project' + inputs: + scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' + arguments: '--use_qnn --qnn_home $(QnnSDKRootDir) $(commonBuildArgs)' + + - task: VSBuild@1 + displayName: 'Build onnxruntime' + inputs: + solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnxruntime.vcxproj' + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.build_config }} + msbuildArchitecture: ${{ parameters.buildArch }} + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' + createLogFile: true + + - task: VSBuild@1 + displayName: 'Build onnx_test_runner' + inputs: + solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnx_test_runner.vcxproj' + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.build_config }} + msbuildArchitecture: ${{ parameters.buildArch }} + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' + createLogFile: true + + - task: VSBuild@1 + displayName: 'Build onnxruntime_perf_test' + inputs: + solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnxruntime_perf_test.vcxproj' + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.build_config }} + msbuildArchitecture: ${{ parameters.buildArch }} + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' + createLogFile: true + + - task: VSBuild@1 + displayName: 'Build onnxruntime_test_all (to copy Qnn libs)' + inputs: + solution: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\onnxruntime_test_all.vcxproj' + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.build_config }} + msbuildArchitecture: ${{ parameters.buildArch }} + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}' + createLogFile: true + + - task: CmdLine@2 + displayName: 'Print contents of binaries directory' + inputs: + script: | + dir $(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }} + + - template: win-esrp-dll.yml + parameters: + FolderPath: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }}' + DisplayName: 'ESRP - Sign dlls' + DoEsrp: ${{ parameters.DoEsrp }} + Pattern: 'onnxruntime*.dll' + + - task: MSBuild@1 + displayName: 'Restore NuGet Packages and create project.assets.json' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' + platform: 'Any CPU' + configuration: ${{ parameters.build_config }} + msbuildArguments: '-t:restore -p:OrtPackageId=$(OrtPackageId)' + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - task: MSBuild@1 + displayName: 'Build C# bindings' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' + platform: 'Any CPU' + configuration: ${{ parameters.build_config }} + msbuildArguments: '-p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=$(OrtPackageId) -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }}' + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - ${{ if eq(parameters.DoEsrp, true) }}: - template: win-esrp-dll.yml parameters: - FolderPath: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }}' - DisplayName: 'ESRP - Sign dlls' + FolderPath: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\${{ parameters.build_config }}' + DisplayName: 'ESRP - Sign C# dlls' DoEsrp: ${{ parameters.DoEsrp }} - Pattern: 'onnxruntime*.dll' - - - task: MSBuild@1 - displayName: 'Restore NuGet Packages and create project.assets.json' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: ${{ parameters.build_config }} - msbuildArguments: '-t:restore -p:OrtPackageId=$(OrtPackageId)' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - task: MSBuild@1 - displayName: 'Build C# bindings' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: ${{ parameters.build_config }} - msbuildArguments: '-p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=$(OrtPackageId) -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }}' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - ${{ if eq(parameters.DoEsrp, true) }}: - - template: win-esrp-dll.yml - parameters: - FolderPath: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\${{ parameters.build_config }}' - DisplayName: 'ESRP - Sign C# dlls' - DoEsrp: ${{ parameters.DoEsrp }} - - - task: MSBuild@1 - displayName: 'Build Nuget Packages' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj' - platform: 'Any CPU' - configuration: ${{ parameters.build_config }} - msbuildArguments: '-t:CreatePackage -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=$(OrtPackageId) -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} -p:TargetArchitecture=$(targetArchitecture)' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - task: CopyFiles@2 - displayName: 'Copy native nuget package to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }}' - Contents: '*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: CopyFiles@2 - displayName: 'Copy native nuget symbols package to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }}' - Contents: '*.snupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline x64 NuGet Artifact' - inputs: - artifactName: ${{ parameters.ArtifactName }} - targetPath: '$(Build.ArtifactStagingDirectory)' + + - task: MSBuild@1 + displayName: 'Build Nuget Packages' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj' + platform: 'Any CPU' + configuration: ${{ parameters.build_config }} + msbuildArguments: '-t:CreatePackage -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=$(OrtPackageId) -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} -p:TargetArchitecture=$(targetArchitecture)' + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - task: CopyFiles@2 + displayName: 'Copy native nuget package to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }}' + Contents: '*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - task: CopyFiles@2 + displayName: 'Copy native nuget symbols package to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\${{ parameters.build_config }}\${{ parameters.build_config }}' + Contents: '*.snupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline x64 NuGet Artifact' + inputs: + artifactName: ${{ parameters.ArtifactName }} + targetPath: '$(Build.ArtifactStagingDirectory)' From 18725277e3a54cb23f096eba50ff3d8da3d528ab Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 3 Mar 2025 13:49:17 -0800 Subject: [PATCH 030/266] [js/common] allows using Uint16Array as data for float16 tensor (#23827) ### Description Resolve #23817 ### Motivation and Context --- js/common/lib/tensor-impl-type-mapping.ts | 9 +-- js/common/lib/tensor-impl.ts | 7 +++ js/common/package.json | 3 +- js/common/test/unit-tests/common.ts | 5 +- .../test/unit-tests/tensor/constructor-f16.ts | 62 +++++++++++++++++++ .../unit-tests/tensor/constructor-type.ts | 8 --- .../templates/linux-web-init-and-check.yml | 8 +++ .../azure-pipelines/templates/web-ci.yml | 3 - 8 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 js/common/test/unit-tests/tensor/constructor-f16.ts diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index 14dbdca707220..58f4cc6281b09 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -44,12 +44,6 @@ export const NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = new Map { isTypedArrayChecked = true; const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && BigInt64Array.from; const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && BigUint64Array.from; + + // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any + const Float16Array = (globalThis as any).Float16Array; const isFloat16ArrayAvailable = typeof Float16Array !== 'undefined' && Float16Array.from; if (isBigInt64ArrayAvailable) { diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 8feb8d7205fa1..2c54bdbfb6874 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -261,6 +261,13 @@ export class Tensor implements TensorInterface { } else { throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`); } + } else if (arg0 === 'float16' && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) { + // when Float16Array is available and data is of type Uint16Array. + // We allow Uint16Array to be passed in as data for 'float16' tensor until Float16Array is generally + // supported in JavaScript environment. + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data = new (globalThis as any).Float16Array(arg1.buffer, arg1.byteOffset, arg1.length); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } diff --git a/js/common/package.json b/js/common/package.json index 3d8d3f6533cfe..2d331bb42e4c7 100644 --- a/js/common/package.json +++ b/js/common/package.json @@ -15,7 +15,8 @@ "build": "node ./build.js", "prepare": "npm run build", "pretest": "tsc --build ./test", - "test": "mocha ./test/**/*.js --timeout 30000" + "test": "mocha \"./test/**/*.js\" --timeout 30000", + "test:f16": "mocha -n js-float16array \"./test/**/*.js\" --timeout 30000" }, "devDependencies": { "typedoc": "^0.25.7" diff --git a/js/common/test/unit-tests/common.ts b/js/common/test/unit-tests/common.ts index 0a6e4e5dd6ebd..bbbceed605bd4 100644 --- a/js/common/test/unit-tests/common.ts +++ b/js/common/test/unit-tests/common.ts @@ -29,9 +29,10 @@ export const NUMBER_COMPATIBLE_NUMERICAL_TYPES = [ export const BIGINT_TYPES = [['int64', BigInt64Array, true] as const, ['uint64', BigUint64Array, true] as const]; /** - * float16 type, data represented by Uint16Array + * float16 type, data represented by Uint16Array/Float16Array */ -export const FLOAT16_TYPE = ['float16', Uint16Array, false] as const; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const FLOAT16_TYPE = ['float16', (globalThis as any).Float16Array ?? Uint16Array, false] as const; /** * A list of all numerical types. diff --git a/js/common/test/unit-tests/tensor/constructor-f16.ts b/js/common/test/unit-tests/tensor/constructor-f16.ts new file mode 100644 index 0000000000000..38c6ac037c5f9 --- /dev/null +++ b/js/common/test/unit-tests/tensor/constructor-f16.ts @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import assert from 'assert/strict'; +import { Tensor } from 'onnxruntime-common'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const globalF16 = (globalThis as any).Float16Array; + +(globalF16 ? describe : describe.skip)('Tensor Constructor Tests - check type float16 (Float16Array available)', () => { + it("[float16] new Tensor('float16', numbers, dims): allow number array when Float16Array is available", () => { + const tensor = new Tensor('float16', [1, 2, 3, 4], [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof globalF16, "tensor.data should be an instance of 'Float16Array'"); + assert.equal(tensor.data[0], 1, 'tensor.data[0] should be 1'); + assert.equal(tensor.data[1], 2, 'tensor.data[1] should be 2'); + assert.equal(tensor.data[2], 3, 'tensor.data[2] should be 3'); + assert.equal(tensor.data[3], 4, 'tensor.data[3] should be 4'); + assert.equal(tensor.data.length, 4, 'tensor.data.length should be 4'); + }); + + it("[float16] new Tensor('float16', float16array, dims): allow Float16Array when Float16Array is available", () => { + const tensor = new Tensor('float16', new globalF16([1, 2, 3, 4]), [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof globalF16, "tensor.data should be an instance of 'Float16Array'"); + assert.equal(tensor.data[0], 1, 'tensor.data[0] should be 1'); + assert.equal(tensor.data[1], 2, 'tensor.data[1] should be 2'); + assert.equal(tensor.data[2], 3, 'tensor.data[2] should be 3'); + assert.equal(tensor.data[3], 4, 'tensor.data[3] should be 4'); + assert.equal(tensor.data.length, 4, 'tensor.data.length should be 4'); + }); + + it("[float16] new Tensor('float16', uint16array, dims): allow Uint16Array when Float16Array is available", () => { + const tensor = new Tensor('float16', new Uint16Array([15360, 16384, 16896, 17408]), [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof globalF16, "tensor.data should be an instance of 'Float16Array'"); + assert.equal(tensor.data[0], 1, 'tensor.data[0] should be 1'); + assert.equal(tensor.data[1], 2, 'tensor.data[1] should be 2'); + assert.equal(tensor.data[2], 3, 'tensor.data[2] should be 3'); + assert.equal(tensor.data[3], 4, 'tensor.data[3] should be 4'); + assert.equal(tensor.data.length, 4, 'tensor.data.length should be 4'); + }); +}); + +(globalF16 ? describe.skip : describe)( + 'Tensor Constructor Tests - check type float16 (Float16Array not available)', + () => { + it( + "[float16] new Tensor('float16', numbers, dims): " + + "expect to throw because it's not allowed to construct 'float16' tensor from number array", + () => { + assert.throws(() => new Tensor('float16', [1, 2, 3, 4], [2, 2]), TypeError); + }, + ); + + it("[float16] new Tensor('float16', uint16array, dims): allow Uint16Array", () => { + const tensor = new Tensor('float16', new Uint16Array([15360, 16384, 16896, 17408]), [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof Uint16Array, "tensor.data should be an instance of 'Uint16Array'"); + }); + }, +); diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 02390800e8611..d86e18ba744b8 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -105,14 +105,6 @@ describe('Tensor Constructor Tests - check types', () => { assert(tensor.data instanceof Uint8Array, "tensor.data should be an instance of 'Uint8Array'"); }); - it( - "[float16] new Tensor('float16', numbers, dims): " + - "expect to throw because it's not allowed to construct 'float16' tensor from number array", - () => { - assert.throws(() => new Tensor('float16', [1, 2, 3, 4], [2, 2]), TypeError); - }, - ); - it("[badtype] new Tensor('a', numbers, dims): expect to throw because 'a' is an invalid type", () => { assert.throws(() => new TensorAny('a', [1, 2, 3, 4], [2, 2]), TypeError); }); diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-web-init-and-check.yml b/tools/ci_build/github/azure-pipelines/templates/linux-web-init-and-check.yml index a4d5a73118ea2..2b73f82615bba 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-web-init-and-check.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-web-init-and-check.yml @@ -1,4 +1,8 @@ steps: +- task: NodeTool@0 + inputs: + # requires Node.js v22 for float16 testing (the V8 flag "--js-float16array") + versionSpec: '22.x' - script: | npm ci workingDirectory: '$(Build.SourcesDirectory)/js' @@ -11,6 +15,10 @@ steps: npm test workingDirectory: '$(Build.SourcesDirectory)/js/common' displayName: 'run onnxruntime-common tests' +- script: | + npm run test:f16 + workingDirectory: '$(Build.SourcesDirectory)/js/common' + displayName: 'run onnxruntime-common tests (enable Float16Array)' - script: | npm ci workingDirectory: '$(Build.SourcesDirectory)/js/web' diff --git a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml index 87836880cbdb8..2e3589ee87c29 100644 --- a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml @@ -83,9 +83,6 @@ stages: git submodule update --init -- cmake/external/onnx workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Checkout submodule onnx' - - task: NodeTool@0 - inputs: - versionSpec: '20.x' - template: linux-web-init-and-check.yml - task: Bash@3 displayName: 'Extract commit SHA and save to __commit.txt' From 325ee30916fef0ce56c5fcaa45e43b27673cb950 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Tue, 4 Mar 2025 08:50:14 +0800 Subject: [PATCH 031/266] [js/webgpu] Reland the optimization of ConvTranspose (#23858) This PR fixes the errors in the ConvTranspose optimization and adds tests to ensure the correctness of the implementation. --- .../ops/3rd-party/conv_backprop_webgpu.ts | 96 +++++++++++--- js/web/test/data/ops/conv-transpose.jsonc | 122 ++++++++++++++++++ 2 files changed, 199 insertions(+), 19 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts index ad1de42106d6d..50620cea33863 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts @@ -46,6 +46,11 @@ export const createConvTranspose2DProgramInfo = ( const inputChannelsPerGroup = wShape[2] / group; const outputChannelsPerGroup = wShape[3]; const aComponents = isChannelsLast ? getMaxComponents(inputChannelsPerGroup) : 1; + const packInputAs4 = isChannelsLast && outputChannelsPerGroup === 1 && inputChannelsPerGroup >= 4; + const inputChannelsPerGroupInt = packInputAs4 + ? Math.floor(inputChannelsPerGroup / 4) * 4 + : Math.floor(inputChannelsPerGroup / aComponents) * aComponents; + const inputChannelsRemainder = inputChannelsPerGroup - inputChannelsPerGroupInt; const components = isChannelsLast ? getMaxComponents(outputChannelsPerGroup) : 1; const bComponents = isChannelsLast ? (outputChannelsPerGroup === 1 ? aComponents : components) : 1; const outputSize = ShapeUtil.size(outputShape) / components; @@ -78,6 +83,7 @@ export const createConvTranspose2DProgramInfo = ( { type: DataType.uint32, data: dilations }, { type: DataType.uint32, data: effectiveFilterDims }, { type: DataType.int32, data: pads }, + { type: DataType.uint32, data: inputChannelsPerGroupInt }, { type: DataType.uint32, data: inputChannelsPerGroup }, { type: DataType.uint32, data: outputChannelsPerGroup }, ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims), @@ -96,6 +102,7 @@ export const createConvTranspose2DProgramInfo = ( { name: 'dilations', type: 'u32', length: filterDims.length }, { name: 'effective_filter_dims', type: 'u32', length: effectiveFilterDims.length }, { name: 'pads', type: 'i32', length: pads.length }, + { name: 'input_channels_per_group_int', type: 'u32' }, { name: 'input_channels_per_group', type: 'u32' }, { name: 'output_channels_per_group', type: 'u32' }, ]; @@ -114,16 +121,40 @@ export const createConvTranspose2DProgramInfo = ( const calculateResult = (): string => { let calcStr = ''; - if (aComponents === 1) { - calcStr += ` - let w_offset = ${w.indicesToOffset(`${w.type.indices}(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)`)}; - let wValue = ${w.getByOffset(`w_offset / ${bComponents}`)}; - dotProd = dotProd + xValue * wValue;`; + if (packInputAs4) { + if (aComponents === 4) { + calcStr += ` + let xValue = ${dy.getByOffset('x_offset')}; + let wValue = ${w.getByOffset('w_offset')}; + dotProd = dotProd + dot(xValue, wValue); + x_offset += 1u; + w_offset += 1u;`; + } else if (aComponents === 2) { + calcStr += ` + dotProd = dotProd + dot(vec4<${dataType}>(${dy.getByOffset('x_offset')}, ${dy.getByOffset('x_offset + 1u')}), vec4<${dataType}>(${w.getByOffset('w_offset')}, ${w.getByOffset('w_offset + 1u')})); + x_offset += 2u; + w_offset += 2u;`; + } else if (aComponents === 1) { + calcStr += ` + dotProd = dotProd + dot(vec4<${dataType}>(${dy.getByOffset('x_offset')}, ${dy.getByOffset('x_offset + 1u')}, ${dy.getByOffset('x_offset + 2u')}, ${dy.getByOffset('x_offset + 3u')}), vec4<${dataType}>(${w.getByOffset('w_offset')}, ${w.getByOffset('w_offset + 1u')}, ${w.getByOffset('w_offset + 2u')}, ${w.getByOffset('w_offset + 3u')})); + x_offset += 4u; + w_offset += 4u;`; + } } else { - if (outputChannelsPerGroup === 1) { + calcStr += ` + let xValue = ${ + isChannelsLast + ? dy.getByOffset( + `${dy.indicesToOffset(`${dy.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${aComponents}`, + ) + : dy.get('batch', 'inputChannel', 'idyR', 'idyC') + }; + `; + if (aComponents === 1) { calcStr += ` - let wValue = ${w.getByOffset(`${w.indicesToOffset(`${w.type.indices}(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)`)} / ${bComponents}`)}; - dotProd = dotProd + dot(xValue, wValue);`; + let w_offset = ${w.indicesToOffset(`${w.type.indices}(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)`)}; + let wValue = ${w.getByOffset(`w_offset / ${bComponents}`)}; + dotProd = dotProd + xValue * wValue;`; } else { for (let c = 0; c < aComponents; c++) { calcStr += ` @@ -134,6 +165,32 @@ export const createConvTranspose2DProgramInfo = ( } return calcStr; }; + const calculateRemainder = (): string => { + if (inputChannelsRemainder === 0) { + return ''; + } + if (!packInputAs4) { + throw new Error(`packInputAs4 ${packInputAs4} is not true.`); + } + let calcStr = ''; + if (aComponents === 1) { + calcStr += 'dotProd = dotProd'; + for (let i = 0; i < inputChannelsRemainder; i++) { + calcStr += ` + + ${dy.getByOffset(`x_offset + ${i}`)} * ${w.getByOffset(`w_offset + ${i}`)}`; + } + calcStr += ';'; + } else if (aComponents === 2) { + if (inputChannelsRemainder !== 2) { + throw new Error(`Invalid inputChannelsRemainder ${inputChannelsRemainder}.`); + } + calcStr += ` + let xValue = ${dy.getByOffset('x_offset')}; + let wValue = ${w.getByOffset('w_offset')}; + dotProd = dotProd + dot(xValue, wValue);`; + } + return calcStr; + }; const codeSnippet = ` let outputIndices = ${output.offsetToIndices(`global_idx * ${components}`)}; let batch = ${output.indicesGet('outputIndices', 0)}; @@ -169,7 +226,6 @@ export const createConvTranspose2DProgramInfo = ( // Minimum wC >= 0 that satisfies (dyCCorner + wC) % (uniforms.strides.y) == 0 wC = u32(((dyCCorner + i32(uniforms.strides.y) - 1) / i32(uniforms.strides.y)) * i32(uniforms.strides.y) - dyCCorner); } - for (; wC < uniforms.effective_filter_dims.y; wC = wC + 1) { if (wC % uniforms.dilations.y != 0) { continue; @@ -182,17 +238,19 @@ export const createConvTranspose2DProgramInfo = ( } let idyC: u32 = u32(dyC); var inputChannel = groupId * uniforms.input_channels_per_group; - for (var d2: u32 = 0; d2 < uniforms.input_channels_per_group; d2 = d2 + ${aComponents}) { - let xValue = ${ - isChannelsLast - ? dy.getByOffset( - `${dy.indicesToOffset(`${dy.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${aComponents}`, - ) - : dy.get('batch', 'inputChannel', 'idyR', 'idyC') - }; + ${ + packInputAs4 + ? ` + var x_offset = ${dy.indicesToOffset(`${dy.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${aComponents}; + var w_offset = ${w.indicesToOffset(`${w.type.indices}(wRPerm, wCPerm, inputChannel, wOutChannel)`)} / ${bComponents}; + ` + : '' + } + for (var d2: u32 = 0; d2 < uniforms.input_channels_per_group_int; d2 = d2 + ${packInputAs4 ? 4 : aComponents}) { ${calculateResult()} - inputChannel = inputChannel + ${aComponents}; + inputChannel = inputChannel + ${packInputAs4 ? 4 : aComponents}; } + ${calculateRemainder()} wC = wC + uniforms.strides.y - 1; } wR = wR + uniforms.strides[0] - 1; @@ -211,7 +269,7 @@ export const createConvTranspose2DProgramInfo = ( return { name: 'ConvTranspose2D', shaderCache: { - hint: `${attributes.cacheKey};${aComponents}${bComponents}${components}${outputChannelsPerGroup === 1}`, + hint: `${attributes.cacheKey};${aComponents}${bComponents}${components}${packInputAs4}${inputChannelsRemainder}`, inputDependencies, }, getRunData: () => ({ diff --git a/js/web/test/data/ops/conv-transpose.jsonc b/js/web/test/data/ops/conv-transpose.jsonc index 6429845d23df9..008d58530ee36 100644 --- a/js/web/test/data/ops/conv-transpose.jsonc +++ b/js/web/test/data/ops/conv-transpose.jsonc @@ -348,6 +348,128 @@ } ] }, + { + "name": "ConvTranspose NHWC- group - A", + "operator": "ConvTranspose", + "inputShapeDefinitions": "rankOnly", + "opset": { "domain": "", "version": 17 }, + "attributes": [ + { "name": "kernel_shape", "data": [1, 1], "type": "ints" }, + { "name": "group", "data": 2, "type": "int" } + ], + "cases": [ + { + "name": "T[0]", + "inputs": [ + { + "data": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0, 32.0, 34.0], + "dims": [1, 2, 3, 3], + "type": "float32" + }, + { + "data": [1.0, 2.0], + "dims": [2, 1, 1, 1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0, 1, 2, 3, 4, 5, 6, 7, 8, 36, 40, 44, 48, 52, 56, 60, 64, 68], + "dims": [1, 2, 3, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "ConvTranspose NHWC- group - B", + "operator": "ConvTranspose", + "inputShapeDefinitions": "rankOnly", + "opset": { "domain": "", "version": 17 }, + "attributes": [ + { "name": "kernel_shape", "data": [2, 2], "type": "ints" }, + { "name": "group", "data": 3, "type": "int" } + ], + "cases": [ + { + "name": "T[0]", + "inputs": [ + { + "data": [ + 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, + 19.0, 20.0, 21.0, 22.0, 23.0, 0, 0, 0 + ], + "dims": [1, 3, 3, 3], + "type": "float32" + }, + { + "data": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0], + "dims": [3, 1, 2, 2], + "type": "float32" + }, + { + "data": [0.125, 0.25, 0.375], + "dims": [3], + "type": "float32" + } + ], + "outputs": [ + { + "data": [ + 0.125, 1.125, 4.125, 4.125, 3.125, 13.125, 23.125, 18.125, 15.125, 43.125, 53.125, 36.125, 18.125, 45.125, + 52.125, 32.125, 45.25, 104.25, 115.25, 66.25, 123.25, 279.25, 305.25, 172.25, 159.25, 357.25, 383.25, + 214.25, 105.25, 232.25, 247.25, 136.25, 162.375, 351.375, 370.375, 200.375, 387.375, 833.375, 875.375, + 470.375, 231.375, 494.375, 517.375, 276.375, 0.375, 0.375, 0.375, 0.375 + ], + "dims": [1, 3, 4, 4], + "type": "float32" + } + ] + } + ] + }, + { + "name": "ConvTranspose NHWC- group - C", + "operator": "ConvTranspose", + "inputShapeDefinitions": "rankOnly", + "opset": { "domain": "", "version": 17 }, + "attributes": [ + { "name": "kernel_shape", "data": [2, 2], "type": "ints" }, + { "name": "group", "data": 3, "type": "int" } + ], + "cases": [ + { + "name": "T[0]", + "inputs": [ + { + "data": [ + 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, + 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0 + ], + "dims": [1, 3, 3, 4], + "type": "float32" + }, + { + "data": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0], + "dims": [3, 1, 2, 2], + "type": "float32" + } + ], + "outputs": [ + { + "data": [ + 0, 1, 4, 7, 6, 4, 16, 26, 36, 26, 20, 56, 66, 76, 50, 24, 59, 66, 73, 44, 60, 137, 148, 159, 90, 164, 368, + 394, 420, 234, 212, 472, 498, 524, 290, 140, 307, 322, 337, 184, 216, 465, 484, 503, 270, 516, 1104, 1146, + 1188, 634, 596, 1272, 1314, 1356, 722, 352, 747, 770, 793, 420 + ], + "dims": [1, 3, 4, 5], + "type": "float32" + } + ] + } + ] + }, { "name": "ConvTranspose with bias addition C", "operator": "ConvTranspose", From 30c682547bdae3e09523614f8e38526e49ca8fbc Mon Sep 17 00:00:00 2001 From: Alessio Soldano Date: Tue, 4 Mar 2025 04:12:22 +0100 Subject: [PATCH 032/266] [OpenVINO] Fix a build warning (#23877) ### Description Fix a warning with std::move usage ### Motivation and Context Possibly allow building without --compile_no_warning_as_error flag --- onnxruntime/core/providers/openvino/backends/basic_backend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 3ac4d22f5453c..44b811e6af2c0 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -653,7 +653,7 @@ void BasicBackend::CompleteAsyncInference(Ort::KernelContext& context, OVInferRe const auto& out_name = item.first; auto node = item.second; Ort::UnownedValue output_tensor = GetOutputTensor(context, - std::move(out_name), + out_name, subgraph_context_.output_names, node); auto mem_info = output_tensor.GetTensorMemoryInfo(); From bde4fbec9707f542f0b67540b051f7646ef5ab71 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Tue, 4 Mar 2025 09:37:00 -0800 Subject: [PATCH 033/266] Change gsl::byte to std::byte (#23872) To be compatible with the latest GSL library. Without this fix we will get: ``` onnxruntime\core\providers\cpu\controlflow\loop.cc(247): error C4996: 'gsl::byte': Use std::byte instead. ``` --- onnxruntime/core/providers/cpu/controlflow/loop.cc | 4 ++-- onnxruntime/core/providers/cuda/controlflow/loop.cc | 4 ++-- onnxruntime/test/providers/base_tester.cc | 6 +++--- onnxruntime/test/providers/base_tester.h | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/onnxruntime/core/providers/cpu/controlflow/loop.cc b/onnxruntime/core/providers/cpu/controlflow/loop.cc index c65dd2a04bf55..b33b1f189594b 100644 --- a/onnxruntime/core/providers/cpu/controlflow/loop.cc +++ b/onnxruntime/core/providers/cpu/controlflow/loop.cc @@ -244,7 +244,7 @@ static Status ConcatenateCpuOutput(void* /*stream*/, // we can't easily use a C++ template for the tensor element type, // so use a span for some protection but work in bytes - gsl::span output_span = gsl::make_span(static_cast(output), + gsl::span output_span = gsl::make_span(static_cast(output), output_size_in_bytes); for (size_t i = 0, num_iterations = per_iteration_output.size(); i < num_iterations; ++i) { @@ -257,7 +257,7 @@ static Status ConcatenateCpuOutput(void* /*stream*/, " Expected:", per_iteration_shape, " Got:", iteration_data.Shape()); } - auto src = gsl::make_span(static_cast(iteration_data.DataRaw()), + auto src = gsl::make_span(static_cast(iteration_data.DataRaw()), bytes_per_iteration); auto dst = output_span.subspan(i * bytes_per_iteration, bytes_per_iteration); gsl::copy(src, dst); diff --git a/onnxruntime/core/providers/cuda/controlflow/loop.cc b/onnxruntime/core/providers/cuda/controlflow/loop.cc index 3295b73a800c9..d66de7c74e647 100644 --- a/onnxruntime/core/providers/cuda/controlflow/loop.cc +++ b/onnxruntime/core/providers/cuda/controlflow/loop.cc @@ -84,10 +84,10 @@ static Status ConcatenateGpuOutput(void* stream, std::vector& per_iter CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(cur_output, iteration_data.DataRaw(), bytes_per_iteration, cudaMemcpyDeviceToDevice, static_cast(stream))); - cur_output = static_cast((static_cast(cur_output) + bytes_per_iteration)); + cur_output = static_cast((static_cast(cur_output) + bytes_per_iteration)); } - ORT_ENFORCE(static_cast(cur_output) - static_cast(output) == output_size_in_bytes, + ORT_ENFORCE(static_cast(cur_output) - static_cast(output) == output_size_in_bytes, "Concatenation did not fill output buffer as expected."); return Status::OK(); diff --git a/onnxruntime/test/providers/base_tester.cc b/onnxruntime/test/providers/base_tester.cc index 6bfe7bc3856ba..eecff3fa4d8ff 100644 --- a/onnxruntime/test/providers/base_tester.cc +++ b/onnxruntime/test/providers/base_tester.cc @@ -174,7 +174,7 @@ static std::unique_ptr MakeSparseTensor(MLDataType data_type, cons return p_tensor; } -void BaseTester::CopyDataToTensor(gsl::span data, Tensor& dst) { +void BaseTester::CopyDataToTensor(gsl::span data, Tensor& dst) { ORT_ENFORCE(dst.SizeInBytes() >= data.size_bytes(), "Not enough space in the destination tensor"); memcpy(dst.MutableDataRaw(), data.data(), data.size_bytes()); } @@ -203,7 +203,7 @@ void BaseTester::AddSparseCooTensorData(std::vector& data, MLDataType data_type, const char* name, gsl::span dims, - gsl::span values, + gsl::span values, gsl::span indices, const ValidateOutputParams& check_params, const std::vector* dim_params) { @@ -247,7 +247,7 @@ void BaseTester::AddSparseCsrTensorData(std::vector& data, MLDataType data_type, const char* name, gsl::span dims, - gsl::span values, + gsl::span values, gsl::span inner_indices, gsl::span outer_indices, const ValidateOutputParams& check_params, diff --git a/onnxruntime/test/providers/base_tester.h b/onnxruntime/test/providers/base_tester.h index 512b3402c5986..d39cc3c750dec 100644 --- a/onnxruntime/test/providers/base_tester.h +++ b/onnxruntime/test/providers/base_tester.h @@ -868,7 +868,7 @@ class BaseTester { void AddShapeToTensorData(NodeArg& node_arg, gsl::span dims, const std::vector* dim_params); - void CopyDataToTensor(gsl::span data, Tensor& dst); + void CopyDataToTensor(gsl::span data, Tensor& dst); #if !defined(DISABLE_SPARSE_TENSORS) NodeArg MakeSparseNodeArg(int32_t dtype, const char* name, @@ -879,7 +879,7 @@ class BaseTester { MLDataType data_type, const char* name, gsl::span dims, - gsl::span values, + gsl::span values, gsl::span indices, const ValidateOutputParams& check_params, const std::vector* dim_params = nullptr); @@ -895,7 +895,7 @@ class BaseTester { MLDataType data_type, const char* name, gsl::span dims, - gsl::span values, + gsl::span values, gsl::span inner_indices, gsl::span outer_indices, const ValidateOutputParams& check_params, From 17dcea7a662bf21725c754719952ae54e51d6d23 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 4 Mar 2025 10:06:36 -0800 Subject: [PATCH 034/266] Allow using extended minimal build for several EPs (#23834) ### Description #### Background From code search, the following EPs use `onnxruntime::GetCpuPreferredNodes()` in their `GetCapabilities()` methods: - CANN - CUDA - DML - JS - ROCM - WebGPU However, the source file that implements `onnxruntime::GetCpuPreferredNodes()` is excluded when minimal build is ON: https://github.com/microsoft/onnxruntime/blob/6df0973e58ba5399fcaa98686f70ed9a9e59aaef/cmake/onnxruntime_framework.cmake#L38-L42 This means that all EPs mentioned above is not able to compile with minimal build. #### Solution The excluded file `core/framework/fallback_cpu_capability.cc` cannot build in minimal build because some of its dependencies are not included in the minimal build. However, in extended minimal build mode, all dependencies are available. This PR looses the restrict and allows to compile this file when it is extended minimal build. After this change, those EPs are able to compile in extended minimal build. --- cmake/onnxruntime_framework.cmake | 5 +---- cmake/onnxruntime_providers_js.cmake | 6 +++++- onnxruntime/core/framework/fallback_cpu_capability.cc | 4 ++++ onnxruntime/core/framework/fallback_cpu_capability.h | 4 ++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cmake/onnxruntime_framework.cmake b/cmake/onnxruntime_framework.cmake index b1e98a9e0411c..9c9a25f8ee77e 100644 --- a/cmake/onnxruntime_framework.cmake +++ b/cmake/onnxruntime_framework.cmake @@ -36,10 +36,7 @@ elseif(onnxruntime_ENABLE_TRITON) endif() if (onnxruntime_MINIMAL_BUILD) - set(onnxruntime_framework_src_exclude - "${ONNXRUNTIME_ROOT}/core/framework/fallback_cpu_capability.h" - "${ONNXRUNTIME_ROOT}/core/framework/fallback_cpu_capability.cc" - ) + set(onnxruntime_framework_src_exclude) # custom ops support must be explicitly enabled in a minimal build. exclude if not. if (NOT onnxruntime_MINIMAL_BUILD_CUSTOM_OPS) diff --git a/cmake/onnxruntime_providers_js.cmake b/cmake/onnxruntime_providers_js.cmake index 9811eae611463..fefbab5082da4 100644 --- a/cmake/onnxruntime_providers_js.cmake +++ b/cmake/onnxruntime_providers_js.cmake @@ -1,6 +1,10 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. + if (onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD) + message(FATAL_ERROR "JSEP can not be used in a basic minimal build. Please build with '--minimal_build extended'") + endif() + add_compile_definitions(USE_JSEP=1) file(GLOB_RECURSE onnxruntime_providers_js_cc_srcs @@ -18,4 +22,4 @@ onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers Boost::mp11 Eigen3::Eigen ) - add_dependencies(onnxruntime_providers_js ${onnxruntime_EXTERNAL_DEPENDENCIES}) \ No newline at end of file + add_dependencies(onnxruntime_providers_js ${onnxruntime_EXTERNAL_DEPENDENCIES}) diff --git a/onnxruntime/core/framework/fallback_cpu_capability.cc b/onnxruntime/core/framework/fallback_cpu_capability.cc index 1eb7420b44d2c..d3e435c0341b0 100644 --- a/onnxruntime/core/framework/fallback_cpu_capability.cc +++ b/onnxruntime/core/framework/fallback_cpu_capability.cc @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) + #include "core/framework/fallback_cpu_capability.h" #include "core/common/inlined_containers.h" @@ -176,3 +178,5 @@ std::unordered_set GetCpuPreferredNodes(const onnxruntime::GraphViewe } } // namespace onnxruntime + +#endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) diff --git a/onnxruntime/core/framework/fallback_cpu_capability.h b/onnxruntime/core/framework/fallback_cpu_capability.h index bca75adbfd5a7..ddcc1de96d2af 100644 --- a/onnxruntime/core/framework/fallback_cpu_capability.h +++ b/onnxruntime/core/framework/fallback_cpu_capability.h @@ -3,6 +3,8 @@ #pragma once +#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) + #include #include "core/common/inlined_containers_fwd.h" #include "core/framework/execution_provider.h" // for IExecutionProvider::IKernelLookup @@ -26,3 +28,5 @@ std::unordered_set GetCpuPreferredNodes(const GraphViewer& graph, const logging::Logger& logger); } // namespace onnxruntime + +#endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) From 813bdaab8d13ec029a32545e28d05aebdceb610e Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 4 Mar 2025 10:08:18 -0800 Subject: [PATCH 035/266] Add dawn to ThirdPartyNotices (#23876) ### Description Add `dawn` to ThirdPartyNotices. --- ThirdPartyNotices.txt | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 26084ab42ec1c..a449e42f6bf19 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -6045,3 +6045,38 @@ https://github.com/intel/neural-speed terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "THIRD-PARTY-PROGRAMS" file. + +_____ + +dawn + +https://dawn.googlesource.com/dawn + + BSD 3-Clause License + + Copyright 2017-2023 The Dawn & Tint Authors + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 9d0dc9f062fa496422c3679204ecb62c65430758 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Tue, 4 Mar 2025 16:20:06 -0800 Subject: [PATCH 036/266] Enable QNN EP weight sharing generation using public API (#23702) ### Description Enable QNN EP weight sharing generation using public API instead of internal interfaces, so that user can integrate into their own toolchain. The change is to share the QnnBackendManager across ORT sessions if ep.share_ep_contexts is enabled. And there is extra option to end the share so that we know when to remove the shared QnnBackendManager from the singleton. Change the tool name from onnxruntime_qnn_ctx_gen to ep_weight_sharing_ctx_gen, so that it can be shared for other EPs. --- cmake/onnxruntime_python.cmake | 2 +- cmake/onnxruntime_unittests.cmake | 33 +-- .../onnxruntime_session_options_config_keys.h | 5 +- .../qnn/builder/qnn_backend_manager.cc | 2 + .../providers/qnn/qnn_execution_provider.cc | 42 ++- .../providers/qnn/qnn_execution_provider.h | 1 + .../core/providers/qnn/shared_context.h | 26 ++ .../README.md | 10 +- .../command_args_parser.cc | 47 ++-- .../command_args_parser.h | 0 .../test/ep_weight_sharing_ctx_gen/main.cc | 247 +++++++++++++++++ .../test_configuration.h | 7 +- .../test/providers/qnn/qnn_ep_context_test.cc | 222 ++++++++++------ onnxruntime/test/qnn_ctx_gen/main.cc | 250 ------------------ setup.py | 2 +- 15 files changed, 519 insertions(+), 377 deletions(-) rename onnxruntime/test/{qnn_ctx_gen => ep_weight_sharing_ctx_gen}/README.md (82%) rename onnxruntime/test/{qnn_ctx_gen => ep_weight_sharing_ctx_gen}/command_args_parser.cc (68%) rename onnxruntime/test/{qnn_ctx_gen => ep_weight_sharing_ctx_gen}/command_args_parser.h (100%) create mode 100644 onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc rename onnxruntime/test/{qnn_ctx_gen => ep_weight_sharing_ctx_gen}/test_configuration.h (75%) delete mode 100644 onnxruntime/test/qnn_ctx_gen/main.cc diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index aee6d2ff7655c..64b53c2912be0 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -1029,7 +1029,7 @@ if (onnxruntime_USE_QNN) add_custom_command( TARGET onnxruntime_pybind11_state POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy - $ + $ $/onnxruntime/capi/ ) if (EXISTS "${onnxruntime_QNN_HOME}/Qualcomm AI Hub Proprietary License.pdf") diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index cb5a28f82de66..2ed7923941643 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -1289,31 +1289,34 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) if(onnxruntime_USE_QNN) #qnn ctx generator - set(onnxruntime_qnn_ctx_gen_src_dir ${TEST_SRC_DIR}/qnn_ctx_gen) - set(onnxruntime_qnn_ctx_gen_src_patterns - "${onnxruntime_qnn_ctx_gen_src_dir}/*.cc" - "${onnxruntime_qnn_ctx_gen_src_dir}/*.h") + set(ep_weight_sharing_ctx_gen_src_dir ${TEST_SRC_DIR}/ep_weight_sharing_ctx_gen) + set(ep_weight_sharing_ctx_gen_src_patterns + "${ep_weight_sharing_ctx_gen_src_dir}/*.cc" + "${ep_weight_sharing_ctx_gen_src_dir}/*.h") - file(GLOB onnxruntime_qnn_ctx_gen_src CONFIGURE_DEPENDS - ${onnxruntime_qnn_ctx_gen_src_patterns} + file(GLOB ep_weight_sharing_ctx_gen_src CONFIGURE_DEPENDS + ${ep_weight_sharing_ctx_gen_src_patterns} ) - onnxruntime_add_executable(onnxruntime_qnn_ctx_gen ${onnxruntime_qnn_ctx_gen_src}) - target_include_directories(onnxruntime_qnn_ctx_gen PRIVATE ${onnx_test_runner_src_dir} ${ONNXRUNTIME_ROOT} - ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} - ${CMAKE_CURRENT_BINARY_DIR}) + onnxruntime_add_executable(ep_weight_sharing_ctx_gen ${ep_weight_sharing_ctx_gen_src}) + target_include_directories(ep_weight_sharing_ctx_gen PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}) if (WIN32) - target_compile_options(onnxruntime_qnn_ctx_gen PRIVATE ${disabled_warnings}) + target_compile_options(ep_weight_sharing_ctx_gen PRIVATE ${disabled_warnings}) if (NOT DEFINED SYS_PATH_LIB) set(SYS_PATH_LIB shlwapi) endif() endif() - if(WIN32) - target_link_libraries(onnxruntime_qnn_ctx_gen PRIVATE debug dbghelp advapi32) + if (onnxruntime_BUILD_SHARED_LIB) + set(ep_weight_sharing_ctx_gen_libs onnxruntime_common onnxruntime ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE}) + target_link_libraries(ep_weight_sharing_ctx_gen PRIVATE ${ep_weight_sharing_ctx_gen_libs}) + if (WIN32) + target_link_libraries(ep_weight_sharing_ctx_gen PRIVATE debug dbghelp advapi32) + endif() + else() + target_link_libraries(ep_weight_sharing_ctx_gen PRIVATE onnxruntime_session ${onnxruntime_test_providers_libs} ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE}) endif() - target_link_libraries(onnxruntime_qnn_ctx_gen PRIVATE onnx_test_runner_common onnxruntime_test_utils onnxruntime_common onnxruntime_graph onnxruntime_session onnxruntime_providers onnxruntime_framework onnxruntime_util onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers onnx_test_data_proto ${onnxruntime_test_providers_libs} ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE} ${SYS_PATH_LIB} ${CMAKE_DL_LIBS}) - set_target_properties(onnxruntime_qnn_ctx_gen PROPERTIES FOLDER "ONNXRuntimeTest") + set_target_properties(ep_weight_sharing_ctx_gen PROPERTIES FOLDER "ONNXRuntimeTest") endif() # shared lib diff --git a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h index 117a2cdabca2f..af1f9c04b2831 100644 --- a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h @@ -315,9 +315,12 @@ static const char* const kOrtSessionOptionEpContextEmbedMode = "ep.context_embed // in case user need to merge/connect multiple EPContext nodes in one model static const char* const kOrtSessionOptionEpContextNodeNamePrefix = "ep.context_node_name_prefix"; -// Share EP related resources across EPs +// Share EP related resources across sessions static const char* const kOrtSessionOptionShareEpContexts = "ep.share_ep_contexts"; +// Stop to share EP related resources across sessions from then on +static const char* const kOrtSessionOptionStopShareEpContexts = "ep.stop_share_ep_contexts"; + // Use this config when dumping EP context model with an external initializers file // All initializers will be inside the external data file if specified, otherwise all in Onnx file static const char* const kOrtSessionOptionsEpContextModelExternalInitializersFileName = diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc index bcde69beceef7..26d792c008edc 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc @@ -470,8 +470,10 @@ Status QnnBackendManager::InitializeProfiling() { QnnProfile_Level_t qnn_profile_level = QNN_PROFILE_LEVEL_BASIC; if (ProfilingLevel::BASIC == profiling_level_merge_) { qnn_profile_level = QNN_PROFILE_LEVEL_BASIC; + LOGS_DEFAULT(VERBOSE) << "Profiling level set to basic."; } else if (ProfilingLevel::DETAILED == profiling_level_merge_) { qnn_profile_level = QNN_PROFILE_LEVEL_DETAILED; + LOGS_DEFAULT(VERBOSE) << "Profiling level set to detailed."; } Qnn_ErrorHandle_t result = qnn_interface_.profileCreate(backend_handle_, qnn_profile_level, &profile_backend_handle_); ORT_RETURN_IF(QNN_PROFILE_NO_ERROR != result, "Failed to create QNN profile! Error: ", QnnErrorHandleToString(result)); diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index 99a6f51f6f712..1ad17d96e9322 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -195,6 +195,10 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio share_ep_contexts_ = config_options->GetConfigOrDefault(kOrtSessionOptionShareEpContexts, "0") == "1"; LOGS_DEFAULT(VERBOSE) << "User specified option - share EP contexts across sessions: " << share_ep_contexts_; + + stop_share_ep_contexts_ = + config_options->GetConfigOrDefault(kOrtSessionOptionStopShareEpContexts, "0") == "1"; + LOGS_DEFAULT(VERBOSE) << "User specified option - stop share EP contexts across sessions: " << stop_share_ep_contexts_; } static const std::string BACKEND_PATH = "backend_path"; @@ -384,17 +388,27 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio } } - qnn_backend_manager_ = qnn::QnnBackendManager::Create( - qnn::QnnBackendManagerConfig{backend_path, - profiling_level_etw, - profiling_level, - profiling_file_path, - context_priority, - qnn_saver_path, - device_id_, - htp_arch, - soc_model, - enable_htp_weight_sharing}); + // For context binary generation with weight sharing enabled, use the QnnBackendManager from the shared context if it exits + // So that all graphs from later sessions will be compiled into the same QNN context + if (context_cache_enabled_ && share_ep_contexts_ && SharedContext::GetInstance().GetSharedQnnBackendManager()) { + qnn_backend_manager_ = SharedContext::GetInstance().GetSharedQnnBackendManager(); + // Clear the QnnBackendManager from singleton to stop the resource share + if (stop_share_ep_contexts_) { + SharedContext::GetInstance().ResetSharedQnnBackendManager(); + } + } else { + qnn_backend_manager_ = qnn::QnnBackendManager::Create( + qnn::QnnBackendManagerConfig{backend_path, + profiling_level_etw, + profiling_level, + profiling_file_path, + context_priority, + qnn_saver_path, + device_id_, + htp_arch, + soc_model, + enable_htp_weight_sharing}); + } #if defined(_WIN32) if (onnxruntime::logging::EtwRegistrationManager::SupportsETW()) { @@ -1037,6 +1051,12 @@ Status QNNExecutionProvider::Compile(const std::vector& fused qnn_context_embed_mode_, max_spill_fill_buffer_size, logger)); + + if (share_ep_contexts_ && !stop_share_ep_contexts_ && + nullptr == SharedContext::GetInstance().GetSharedQnnBackendManager()) { + ORT_RETURN_IF_NOT(SharedContext::GetInstance().SetSharedQnnBackendManager(qnn_backend_manager_), + "Failed to set shared QnnBackendManager."); + } } return Status::OK(); } diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.h b/onnxruntime/core/providers/qnn/qnn_execution_provider.h index 31c34855ca4c0..0f40e40c2fa36 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.h +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.h @@ -90,6 +90,7 @@ class QNNExecutionProvider : public IExecutionProvider { uint32_t default_rpc_control_latency_ = 0; bool enable_HTP_FP16_precision_ = true; bool share_ep_contexts_ = false; + bool stop_share_ep_contexts_ = false; bool enable_spill_fill_buffer_ = false; #if defined(_WIN32) onnxruntime::logging::EtwRegistrationManager::EtwInternalCallback callback_ETWSink_provider_ = nullptr; diff --git a/onnxruntime/core/providers/qnn/shared_context.h b/onnxruntime/core/providers/qnn/shared_context.h index 81de357dbe677..277a484ad8528 100644 --- a/onnxruntime/core/providers/qnn/shared_context.h +++ b/onnxruntime/core/providers/qnn/shared_context.h @@ -61,13 +61,39 @@ class SharedContext { return graph_exist; } + bool SetSharedQnnBackendManager(std::shared_ptr& qnn_backend_manager) { + const std::lock_guard lock(mtx_); + + if (qnn_backend_manager_ != nullptr) { + if (qnn_backend_manager_ == qnn_backend_manager) { + return true; + } + return false; + } + qnn_backend_manager_ = qnn_backend_manager; + return true; + } + + std::shared_ptr GetSharedQnnBackendManager() { + const std::lock_guard lock(mtx_); + return qnn_backend_manager_; + } + + void ResetSharedQnnBackendManager() { + const std::lock_guard lock(mtx_); + qnn_backend_manager_.reset(); + } + private: SharedContext() = default; ~SharedContext() = default; ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(SharedContext); + // Used for passing through QNN models (deserialized from context binary) across sessions std::vector> shared_qnn_models_; + // Used for compiling multiple models into same QNN context binary + std::shared_ptr qnn_backend_manager_; // Producer sessions can be in parallel // Consumer sessions have to be after producer sessions initialized std::mutex mtx_; diff --git a/onnxruntime/test/qnn_ctx_gen/README.md b/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md similarity index 82% rename from onnxruntime/test/qnn_ctx_gen/README.md rename to onnxruntime/test/ep_weight_sharing_ctx_gen/README.md index 97ab89d79cbd2..be1a1fe039366 100644 --- a/onnxruntime/test/qnn_ctx_gen/README.md +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md @@ -2,17 +2,19 @@ This tool provides the way to generate Onnx models that wraps QNN context binary warpt with weight sharing enabled. The options to use with the tool are listed below: -`onnxruntime_qnn_ctx_gen [options...] model_path,model_path` +`ep_weight_sharing_ctx_gen [options...] model_1_path,model_2_path` -./onnxruntime_qnn_ctx_gen -v -i "soc_model|60 htp_graph_finalization_optimization_mode|3" -C "ep.context_enable|1 ep.context_embed_mode|0" /mnt/c/model1.onnx,/mnt/c/model2.onnx +./ep_weight_sharing_ctx_gen -e qnn -v -i "soc_model|60 htp_graph_finalization_optimization_mode|3" /mnt/c/model1.onnx,/mnt/c/model2.onnx Options: - + + -e [qnn|tensorrt|openvino|vitisai]: Specifies the compile based provider qnn, tensorrt, openvino, vitisai. Default is qnn. + -v: Show verbose information. -C: [session_config_entries]: Specify session configuration entries as key-value pairs: -C "| |" Refer to onnxruntime_session_options_config_keys.h for valid keys and values. - [Example] -C "ep.context_enable|1 ep.context_embed_mode|0" + [Example] -C "ep.context_enable|1 ep.context_embed_mode|0". These are set as default so can be ignored. -i: [provider_options]: Specify QNN EP specific runtime options as key value pairs. Different runtime options available are: [Usage]: -i '| |' diff --git a/onnxruntime/test/qnn_ctx_gen/command_args_parser.cc b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc similarity index 68% rename from onnxruntime/test/qnn_ctx_gen/command_args_parser.cc rename to onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc index 24c343c7b9541..bf21d54ccde41 100644 --- a/onnxruntime/test/qnn_ctx_gen/command_args_parser.cc +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc @@ -1,5 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. -// Copyright (c) 2023 NVIDIA Corporation. // Licensed under the MIT License. #include "command_args_parser.h" @@ -29,28 +28,30 @@ namespace qnnctxgen { /*static*/ void CommandLineParser::ShowUsage() { printf( - "onnxruntime_qnn_ctx_gen [options...] model1_path,model2_path\n" - "Example: ./onnxruntime_qnn_ctx_gen -i \"soc_model|60 htp_graph_finalization_optimization_mode|3\" -C \"ep.context_node_name_prefix|_part1\" ./model1.onnx,./model2.onnx\n" + "ep_weight_sharing_ctx_gen [options...] model1_path,model2_path\n" + "Example: ./ep_weight_sharing_ctx_gen -i \"soc_model|60 htp_graph_finalization_optimization_mode|3\" -C \"ep.context_node_name_prefix|_part1\" ./model1.onnx,./model2.onnx\n" "Options:\n" + "\t-e [qnn|tensorrt|openvino|vitisai]: Specifies the compile based provider 'qnn','tensorrt','openvino', 'vitisai'. " + "Default:'qnn'.\n" "\t-v: Show verbose information.\n" "\t-C: Specify session configuration entries as key-value pairs: -C \"| |\" \n" "\t Refer to onnxruntime_session_options_config_keys.h for valid keys and values. \n" "\t Force ep.context_enable to 1 and ep.context_embed_mode to 0. Change ep.context_file_path is not allowed." "\t [Example] -C \"ep.context_node_name_prefix|_part1\" \n" - "\t-i: Specify QNN EP specific runtime options as key value pairs. Different runtime options available are: \n" + "\t-i: Specify EP specific runtime options as key value pairs. Different runtime options available are: \n" "\t [Usage]: -i '| |'\n" "\n" - "\t [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. default to HTP backend\n" - "\t [vtcm_mb]: QNN VTCM size in MB. default to 0(not set).\n" - "\t [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'.\n" - "\t [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). \n" - "\t [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). \n" - "\t [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. \n" + "\t [QNN only] [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. default to HTP backend\n" + "\t [QNN only] [vtcm_mb]: QNN VTCM size in MB. default to 0(not set).\n" + "\t [QNN only] [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'.\n" + "\t [QNN only] [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). \n" + "\t [QNN only] [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). \n" + "\t [QNN only] [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. \n" "\t Otherwise, it will be fp32 precision. Works for float32 model for HTP backend. Defaults to '1' (with FP16 precision.). \n" - "\t [enable_htp_weight_sharing]: Allows common weights across graphs to be shared and stored in a single context binary. Defaults to '1' (enabled).\n" - "\t [offload_graph_io_quantization]: Offload graph input quantization and graph output dequantization to another EP (typically CPU EP). \n" - "\t Defaults to '0' (QNN EP handles the graph I/O quantization and dequantization). \n" - "\t [enable_htp_spill_fill_buffer]: Enable HTP spill file buffer, used while generating QNN context binary." + "\t [QNN only] [enable_htp_weight_sharing]: Allows common weights across graphs to be shared and stored in a single context binary. Defaults to '1' (enabled).\n" + "\t [QNN only] [offload_graph_io_quantization]: Offload graph input quantization and graph output dequantization to another EP (typically CPU EP). \n" + "\t Defaults to '1' (QNN EP handles the graph I/O quantization and dequantization). \n" + "\t [QNN only] [enable_htp_spill_fill_buffer]: Enable HTP spill file buffer, used while generating QNN context binary." "\t [Example] -i \"vtcm_mb|8 htp_arch|73\" \n" "\n" "\t-h: help\n"); @@ -109,8 +110,22 @@ static bool ParseSessionConfigs(const std::string& configs_string, /*static*/ bool CommandLineParser::ParseArguments(TestConfig& test_config, int argc, ORTCHAR_T* argv[]) { int ch; - while ((ch = getopt(argc, argv, ORT_TSTR("o:u:i:C:vh"))) != -1) { + while ((ch = getopt(argc, argv, ORT_TSTR("e:o:u:i:C:vh"))) != -1) { switch (ch) { + case 'e': + if (!CompareCString(optarg, ORT_TSTR("qnn"))) { + test_config.machine_config.provider_type_name = onnxruntime::kQnnExecutionProvider; + } else if (!CompareCString(optarg, ORT_TSTR("openvino"))) { + test_config.machine_config.provider_type_name = onnxruntime::kOpenVINOExecutionProvider; + } else if (!CompareCString(optarg, ORT_TSTR("tensorrt"))) { + test_config.machine_config.provider_type_name = onnxruntime::kTensorrtExecutionProvider; + } else if (!CompareCString(optarg, ORT_TSTR("vitisai"))) { + test_config.machine_config.provider_type_name = onnxruntime::kVitisAIExecutionProvider; + } else { + fprintf(stderr, "The execution provider is not included in this tool.\n"); + return false; + } + break; case 'v': test_config.run_config.f_verbose = true; break; @@ -162,7 +177,7 @@ static bool ParseSessionConfigs(const std::string& configs_string, 'offload_graph_io_quantization', 'enable_htp_spill_fill_buffer'])"); } - test_config.run_config.qnn_options[key] = value; + test_config.run_config.provider_options[key] = value; } break; } diff --git a/onnxruntime/test/qnn_ctx_gen/command_args_parser.h b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.h similarity index 100% rename from onnxruntime/test/qnn_ctx_gen/command_args_parser.h rename to onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.h diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc b/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc new file mode 100644 index 0000000000000..104cdbdfd5abc --- /dev/null +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "test_configuration.h" +#include "command_args_parser.h" + +// onnxruntime dependencies +#include "core/session/onnxruntime_cxx_api.h" +#include "core/session/onnxruntime_session_options_config_keys.h" + +// onnx dependencies +#include "onnx/onnx_pb.h" +#include + +using namespace onnxruntime; +using ProviderOptions = std::unordered_map; + +// from the last context cache Onnx model, find the EPContext node with main_context=1, +// and get the QNN context binary file name, this context binary contains all graphs from all Onnx models +// get the max spill fill buffer size +static void GetLastContextBinaryFileName(const std::basic_string last_onnx_ctx_file, + std::string& last_ctx_bin_file, + int64_t& max_size) { + max_size = 0; + + onnx::ModelProto model; + std::ifstream onnx_file_stream(last_onnx_ctx_file, std::ios_base::binary); + model.ParseFromIstream(&onnx_file_stream); + + for (auto& node : model.graph().node()) { + if (node.op_type() == "EPContext") { + int64_t is_main_context = 0; + for (auto& attr : node.attribute()) { + if (attr.name() == "main_context") { + is_main_context = attr.i(); + } + if (attr.name() == "max_size") { + max_size = attr.i(); + } + if (attr.name() == "ep_cache_context") { + last_ctx_bin_file = attr.s(); + } + } + if (is_main_context) { + return; + } + } + } + + onnx_file_stream.close(); +} + +// Update generated context cache Onnx model to make the main EPContext node point to +// the last QNN context binary file +// Remove not used QNN context binary file, only keep the last one which contains all graphs +static void UpdateEpContextModel(const std::vector>& ep_ctx_files, + const std::string& last_qnn_ctx_binary_file_name, + int64_t max_size) { + for (auto ep_ctx_file : ep_ctx_files) { + onnx::ModelProto model; + std::ifstream onnx_file_stream(ep_ctx_file, std::ios_base::binary); + model.ParseFromIstream(&onnx_file_stream); + onnx_file_stream.close(); + + for (auto& node : *(model.mutable_graph()->mutable_node())) { + if (node.op_type() == "EPContext") { + int64_t is_main_context = 0; + std::string old_qnn_ctx_binary_file_name; + int max_size_index = 0; + int ep_context_index = 0; + for (auto i = 0; i < node.attribute_size(); ++i) { + auto& attr = node.attribute()[i]; + if (attr.name() == "main_context") { + is_main_context = attr.i(); + } + if (attr.name() == "max_size") { + max_size = attr.i(); + max_size_index = i; + } + if (attr.name() == "ep_cache_context") { + old_qnn_ctx_binary_file_name = attr.s(); + ep_context_index = 0; + } + } + if (is_main_context) { + auto path_str = ToPathString(ep_ctx_file); + auto path = std::filesystem::path(path_str); + auto file_path = path.replace_filename(old_qnn_ctx_binary_file_name); + std::remove(file_path.string().c_str()); + + node.mutable_attribute(max_size_index)->set_i(max_size); + node.mutable_attribute(ep_context_index)->set_s(last_qnn_ctx_binary_file_name); + } + } + } + + // re-write the onnx ctx file + std::ofstream onnx_file_ostream(ep_ctx_file, std::ios_base::binary); + model.SerializeToOstream(&onnx_file_ostream); + onnx_file_ostream.close(); + } +} + +#ifdef _WIN32 +int real_main(int argc, wchar_t* argv[]) { +#else +int real_main(int argc, char* argv[]) { +#endif + qnnctxgen::TestConfig test_config; + if (!qnnctxgen::CommandLineParser::ParseArguments(test_config, argc, argv)) { + qnnctxgen::CommandLineParser::ShowUsage(); + return -1; + } + + OrtLoggingLevel logging_level = test_config.run_config.f_verbose + ? ORT_LOGGING_LEVEL_VERBOSE + : ORT_LOGGING_LEVEL_ERROR; + Ort::Env env(logging_level, "ep_weight_sharing"); + + ORT_TRY { + Ort::SessionOptions so; + so.SetLogId("ep_weight_sharing_ctx_gen_session_logger"); + // Set default session option to dump EPContext model with non-embed mode + so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); + so.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0"); + // enable ep.share_ep_contexts + so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); + + ProviderOptions provider_options; + + for (auto it : test_config.run_config.provider_options) { + provider_options[it.first] = it.second; + } + + for (auto it : test_config.run_config.session_config_entries) { + if (it.first == kOrtSessionOptionEpContextEnable && it.second != "1") { + std::cerr << "Need to enable ep context cache." << std::endl; + continue; + } + if (it.first == kOrtSessionOptionEpContextEmbedMode && it.second != "0") { + std::cerr << "Only support non-embed model for weight sharing." << std::endl; + continue; + } + if (it.first == kOrtSessionOptionEpContextFilePath) { + std::cout << "Not support to specify the generated Onnx context cache file name." << std::endl; + continue; + } + so.AddConfigEntry(it.first.c_str(), it.second.c_str()); + } + + for (auto model_path : test_config.model_file_paths) { + std::cout << "Model file path: " << ToUTF8String(model_path) << std::endl; + } + + // Generate context cache model files with QNN context binary files + // The context binary file generated later includes all graphs from previous models + { + std::string provider_name_ = test_config.machine_config.provider_type_name; + if (provider_name_ == onnxruntime::kQnnExecutionProvider) { +#ifdef USE_QNN +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + + // set default QNN EP option to enable weight sharing if not set by user + const std::string enable_htp_weight_sharing = "enable_htp_weight_sharing"; + if (provider_options.find(enable_htp_weight_sharing) == provider_options.end()) { + provider_options[enable_htp_weight_sharing] = "1"; + } + so.AppendExecutionProvider("QNN", provider_options); +#else + ORT_THROW("QNN is not supported in this build\n"); +#endif + } else if (!provider_name_.empty()) { + ORT_THROW("This execution provider is not included in this tool.\n"); + } + + size_t total_file_count = test_config.model_file_paths.size(); + for (size_t i = 0; i < total_file_count; ++i) { + auto model_path = test_config.model_file_paths[i]; + std::cout << "Generating context cache model for: " << ToUTF8String(model_path) << std::endl; + if (i == total_file_count - 1) { + so.AddConfigEntry(kOrtSessionOptionStopShareEpContexts, "1"); + } + Ort::Session session(env, model_path.c_str(), so); + } + } + + std::cout << "Start to update the generated Onnx model." << std::endl; + std::vector> ep_ctx_files; + ep_ctx_files.reserve(test_config.model_file_paths.size()); + for (auto model_path : test_config.model_file_paths) { + auto pos = model_path.find_last_of(ORT_TSTR(".")); + if (pos != std::string::npos) { + model_path = model_path.substr(0, pos) + ORT_TSTR("_ctx.onnx"); + } else { + model_path = model_path + ORT_TSTR("_ctx.onnx"); + } + ep_ctx_files.push_back(model_path); + } + + // Get the last context binary file name + std::string last_qnn_ctx_binary_file_name; + int64_t max_size = 0; + GetLastContextBinaryFileName(ep_ctx_files.back(), last_qnn_ctx_binary_file_name, max_size); + std::cout << "The last context binary file: " << last_qnn_ctx_binary_file_name << std::endl; + if (last_qnn_ctx_binary_file_name.empty()) { + throw Ort::Exception("Can't find QNN context binary file from the Onnx model.", OrtErrorCode::ORT_FAIL); + } + ep_ctx_files.pop_back(); + + // Update generated context cache Onnx model to make the main EPContext node point to + // the last QNN context binary file + // Remove not used QNN context binary file, only keep the last one only which contains all graphs + UpdateEpContextModel(ep_ctx_files, last_qnn_ctx_binary_file_name, max_size); + } + ORT_CATCH(const Ort::Exception& e) { + std::cerr << "Failed to generate context cache file: " << e.what(); + return -1; + } + + std::cout << "Generation done!"; + return 0; +} + +#ifdef _WIN32 +int wmain(int argc, wchar_t* argv[]) { +#else +int main(int argc, char* argv[]) { +#endif + int retval = -1; + ORT_TRY { + retval = real_main(argc, argv); + } + ORT_CATCH(const std::exception& ex) { + ORT_HANDLE_EXCEPTION([&]() { + fprintf(stderr, "%s\n", ex.what()); + retval = -1; + }); + } + + ::google::protobuf::ShutdownProtobufLibrary(); + + return retval; +} diff --git a/onnxruntime/test/qnn_ctx_gen/test_configuration.h b/onnxruntime/test/ep_weight_sharing_ctx_gen/test_configuration.h similarity index 75% rename from onnxruntime/test/qnn_ctx_gen/test_configuration.h rename to onnxruntime/test/ep_weight_sharing_ctx_gen/test_configuration.h index bf4c7061a3484..198d03211f561 100644 --- a/onnxruntime/test/qnn_ctx_gen/test_configuration.h +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/test_configuration.h @@ -14,15 +14,20 @@ namespace onnxruntime { namespace qnnctxgen { +struct MachineConfig { + std::string provider_type_name{onnxruntime::kQnnExecutionProvider}; +}; + struct RunConfig { bool f_verbose{false}; std::unordered_map session_config_entries; - std::unordered_map qnn_options; + std::unordered_map provider_options; }; struct TestConfig { std::vector> model_file_paths; RunConfig run_config; + MachineConfig machine_config; }; } // namespace qnnctxgen diff --git a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc index e50dd7c214240..3dec74599abdf 100644 --- a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc @@ -43,6 +43,35 @@ static const std::string& GetNodeAttr(const Node& node, const std::string& attr_ return default_val; } +// from the context cache Onnx model, find the EPContext node with main_context=1, +// and get the QNN context binary file name +static void GetContextBinaryFileName(const std::string onnx_ctx_file, + std::string& last_ctx_bin_file, + const Logger& logger) { + std::shared_ptr ctx_model; + ASSERT_STATUS_OK(Model::Load(ToPathString(onnx_ctx_file), ctx_model, nullptr, logger)); + auto& ctx_graph = ctx_model->MainGraph(); + for (auto& node : ctx_graph.Nodes()) { + if (node.OpType() == "EPContext") { + int64_t is_main_context = GetNodeAttr(node, "main_context", static_cast(0)); + if (1 == is_main_context) { + last_ctx_bin_file = GetNodeAttr(node, "ep_cache_context", ""); + return; + } + } + } +} + +// Get context binary file name from Context model file and remove it with the context model file +void CleanUpCtxFile(std::string context_file_path) { + std::string qnn_ctx_binary_file_name; + GetContextBinaryFileName(context_file_path, qnn_ctx_binary_file_name, + DefaultLoggingManager().DefaultLogger()); + + ASSERT_EQ(std::remove(qnn_ctx_binary_file_name.c_str()), 0); + ASSERT_EQ(std::remove(context_file_path.c_str()), 0); +} + // Create a model with FusedMatMul + Add (quantized) // input1 -> Add -> Q -> DQ ---- // | @@ -123,22 +152,22 @@ void QnnContextBinaryMultiPartitionTestBody(bool single_ep_node = true) { const auto model_data_span = AsByteSpan(model_data.data(), model_data.size()); - const std::string context_binary_file = "./qnn_context_binary_multi_partition_test.onnx"; - std::remove(context_binary_file.c_str()); + const std::string context_model_file = "./qnn_context_binary_multi_partition_test.onnx"; + std::remove(context_model_file.c_str()); Ort::SessionOptions so; so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); - so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_binary_file.c_str()); + so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_model_file.c_str()); so.AppendExecutionProvider("QNN", provider_options); Ort::Session session(*ort_env, model_data_span.data(), model_data_span.size(), so); // Make sure the Qnn context cache binary file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); int ep_context_node_count = 0; int non_ep_context_node_count = 0; std::shared_ptr ctx_model; - ASSERT_STATUS_OK(Model::Load(ToPathString(context_binary_file), ctx_model, nullptr, DefaultLoggingManager().DefaultLogger())); + ASSERT_STATUS_OK(Model::Load(ToPathString(context_model_file), ctx_model, nullptr, DefaultLoggingManager().DefaultLogger())); auto& ctx_graph = ctx_model->MainGraph(); for (auto& node : ctx_graph.Nodes()) { if (node.OpType() == "EPContext") { @@ -156,7 +185,7 @@ void QnnContextBinaryMultiPartitionTestBody(bool single_ep_node = true) { Ort::SessionOptions so2; // context file path is required if it's non-embed mode and the model is loaded from memory - so2.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_binary_file.c_str()); + so2.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_model_file.c_str()); so2.AppendExecutionProvider("QNN", provider_options); std::string ctx_model_data; @@ -164,7 +193,7 @@ void QnnContextBinaryMultiPartitionTestBody(bool single_ep_node = true) { Ort::Session session2(*ort_env, ctx_model_data.data(), ctx_model_data.size(), so2); // clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + CleanUpCtxFile(context_model_file); } // Test that models with 1 non-quantized FusedMatMul node and 1 quantized Add node can still generate the context binary @@ -237,7 +266,7 @@ void EpCtxCpuNodeWithExternalIniFileTestBody(bool expect_external_ini_file) { // clean up ASSERT_EQ(std::remove(model_with_ext.c_str()), 0); ASSERT_EQ(std::remove(model_ext_file_full_path.c_str()), 0); - ASSERT_EQ(std::remove(ep_context_model_file.c_str()), 0); + CleanUpCtxFile(ep_context_model_file); } // Set the external initializer size threshold to 1024 so FusedMatMul (which fallback on CPU) @@ -444,21 +473,21 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryGeneration2InputTypes) { const auto model_data_span = AsByteSpan(model_data.data(), model_data.size()); - const std::string context_binary_file = "./qnn_context_binary_int32_fp32_inputs_test.onnx"; - std::remove(context_binary_file.c_str()); + const std::string context_model_file = "./qnn_context_binary_int32_fp32_inputs_test.onnx"; + std::remove(context_model_file.c_str()); Ort::SessionOptions so; so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); - so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_binary_file.c_str()); + so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_model_file.c_str()); so.AppendExecutionProvider("QNN", provider_options); Ort::Session session(*ort_env, model_data_span.data(), model_data_span.size(), so); // Make sure the Qnn context cache binary file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); // clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + CleanUpCtxFile(context_model_file); } // Generate context cache model from the ONNX models with 2 inputs. @@ -481,26 +510,26 @@ TEST_F(QnnHTPBackendTests, QnnContextGeneration2InputsOrderIssue) { auto& logging_manager = DefaultLoggingManager(); logging_manager.SetDefaultLoggerSeverity(logging::Severity::kERROR); - const std::string context_binary_file = "./qnn_ctx_2_inputs_order_test_gen.onnx"; + const std::string context_model_file = "./qnn_ctx_2_inputs_order_test_gen.onnx"; Ort::SessionOptions so; so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); - so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_binary_file.c_str()); + so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_model_file.c_str()); so.AppendExecutionProvider("QNN", provider_options); Ort::Session session(*ort_env, ORT_TSTR("testdata/qnn_ctx_2_inputs_order_test.onnx"), so); // Make sure the Qnn context cache binary file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); std::shared_ptr model; - ASSERT_STATUS_OK(Model::Load(ToPathString(context_binary_file), model, nullptr, DefaultLoggingManager().DefaultLogger())); + ASSERT_STATUS_OK(Model::Load(ToPathString(context_model_file), model, nullptr, DefaultLoggingManager().DefaultLogger())); auto inputs = model->MainGraph().GetInputs(); EXPECT_TRUE(inputs.size() == 2); EXPECT_TRUE(inputs[0]->Name() == "attention_mask"); EXPECT_TRUE(inputs[1]->Name() == "Add_input_0"); // clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + CleanUpCtxFile(context_model_file); } TEST_F(QnnHTPBackendTests, QnnContextGenerationNodeNamePrefix) { @@ -519,20 +548,20 @@ TEST_F(QnnHTPBackendTests, QnnContextGenerationNodeNamePrefix) { auto& logging_manager = DefaultLoggingManager(); logging_manager.SetDefaultLoggerSeverity(logging::Severity::kERROR); - const std::string context_binary_file = "./qnn_ctx_2_inputs_order_test_gen.onnx"; + const std::string context_model_file = "./qnn_ctx_2_inputs_order_test_gen.onnx"; Ort::SessionOptions so; so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); - so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_binary_file.c_str()); + so.AddConfigEntry(kOrtSessionOptionEpContextFilePath, context_model_file.c_str()); so.AddConfigEntry(kOrtSessionOptionEpContextNodeNamePrefix, node_name_prefix.c_str()); so.AppendExecutionProvider("QNN", provider_options); Ort::Session session(*ort_env, ORT_TSTR("testdata/qnn_ctx_2_inputs_order_test.onnx"), so); // Make sure the Qnn context cache binary file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); std::shared_ptr model; - ASSERT_STATUS_OK(Model::Load(ToPathString(context_binary_file), model, nullptr, DefaultLoggingManager().DefaultLogger())); + ASSERT_STATUS_OK(Model::Load(ToPathString(context_model_file), model, nullptr, DefaultLoggingManager().DefaultLogger())); for (auto& node : model->MainGraph().Nodes()) { if (node.OpType() == "EPContext") { EXPECT_TRUE(node.Name().find(node_name_prefix) != std::string::npos); @@ -540,7 +569,7 @@ TEST_F(QnnHTPBackendTests, QnnContextGenerationNodeNamePrefix) { } // clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + CleanUpCtxFile(context_model_file); } // Run QDQ model on HTP 3 times @@ -554,12 +583,12 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCacheEmbedModeTest) { provider_options["backend_path"] = "libQnnHtp.so"; #endif provider_options["offload_graph_io_quantization"] = "0"; - const std::string context_binary_file = "./qnn_context_binary_test.onnx"; - std::remove(context_binary_file.c_str()); + const std::string context_model_file = "./qnn_context_binary_test.onnx"; + std::remove(context_model_file.c_str()); std::unordered_map session_option_pairs; session_option_pairs.emplace(kOrtSessionOptionEpContextEnable, "1"); - session_option_pairs.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); + session_option_pairs.emplace(kOrtSessionOptionEpContextFilePath, context_model_file); const TestInputDef input_def({1, 2, 3}, false, -10.0f, 10.0f); const std::string op_type = "Atan"; @@ -577,11 +606,11 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCacheEmbedModeTest) { session_option_pairs); // Make sure the Qnn context cache binary file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); // 2nd run directly loads and run from Qnn context cache model std::unordered_map session_option_pairs2; - session_option_pairs2.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); + session_option_pairs2.emplace(kOrtSessionOptionEpContextFilePath, context_model_file); TestQDQModelAccuracy(BuildOpTestCase(op_type, {input_def}, {}, {}), BuildQDQOpTestCase(op_type, {input_def}, {}, {}), provider_options, @@ -589,10 +618,10 @@ TEST_F(QnnHTPBackendTests, QnnContextBinaryCacheEmbedModeTest) { ExpectedEPNodeAssignment::All, QDQTolerance(), logging::Severity::kERROR, - context_binary_file, + context_model_file, session_option_pairs2); // Clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + CleanUpCtxFile(context_model_file); } // Run QDQ model on HTP 3 times @@ -889,12 +918,12 @@ TEST_F(QnnHTPBackendTests, QnnContextBinary2InputsTest) { provider_options["backend_path"] = "libQnnHtp.so"; #endif provider_options["offload_graph_io_quantization"] = "0"; - const std::string context_binary_file = "./qnn_context_binary_2inputs_test.onnx"; - std::remove(context_binary_file.c_str()); + const std::string context_model_file = "./qnn_context_binary_2inputs_test.onnx"; + std::remove(context_model_file.c_str()); std::unordered_map session_option_pairs; session_option_pairs.emplace(kOrtSessionOptionEpContextEnable, "1"); - session_option_pairs.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); + session_option_pairs.emplace(kOrtSessionOptionEpContextFilePath, context_model_file); const TestInputDef input_def1({1, 2, 3}, false, -10.0f, 10.0f); const TestInputDef input_def2({1, 2, 3}, false, -10.0f, 10.0f); @@ -913,11 +942,11 @@ TEST_F(QnnHTPBackendTests, QnnContextBinary2InputsTest) { session_option_pairs); // Make sure the Qnn context cache binary file is generated - EXPECT_TRUE(std::filesystem::exists(context_binary_file.c_str())); + EXPECT_TRUE(std::filesystem::exists(context_model_file.c_str())); // 2nd run directly loads and run from Qnn context cache model std::unordered_map session_option_pairs2; - session_option_pairs2.emplace(kOrtSessionOptionEpContextFilePath, context_binary_file); + session_option_pairs2.emplace(kOrtSessionOptionEpContextFilePath, context_model_file); TestQDQModelAccuracy(BuildOpTestCase(op_type, {input_def1, input_def2}, {}, {}), BuildQDQOpTestCase(op_type, {input_def1, input_def2}, {}, {}), provider_options, @@ -925,10 +954,10 @@ TEST_F(QnnHTPBackendTests, QnnContextBinary2InputsTest) { ExpectedEPNodeAssignment::All, QDQTolerance(), logging::Severity::kERROR, - context_binary_file, + context_model_file, session_option_pairs2); // Clean up - ASSERT_EQ(std::remove(context_binary_file.c_str()), 0); + CleanUpCtxFile(context_model_file); } // Context binary only contains a single QNN graph, generated context cache model (detached mode) only has 1 EPContext node @@ -1062,44 +1091,20 @@ static void CreateQdqModel(const std::string& model_file_name, const Logger& log static void DumpModelWithSharedCtx(const ProviderOptions& provider_options, const std::string& onnx_model_path1, const std::string& onnx_model_path2) { - SessionOptions so; - so.session_logid = "qnn_ctx_model_logger"; - ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1")); - ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0")); - RunOptions run_options; - run_options.run_tag = so.session_logid; - - auto qnn_ep = QnnExecutionProviderWithOptions(provider_options, &so); - std::shared_ptr qnn_ep_shared(std::move(qnn_ep)); + Ort::SessionOptions so; + so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); + so.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0"); + // enable ep.share_ep_contexts so that QNNEP share the QnnBackendManager across sessions + so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); - InferenceSessionWrapper session_object1{so, GetEnvironment()}; - ASSERT_STATUS_OK(session_object1.RegisterExecutionProvider(qnn_ep_shared)); - ASSERT_STATUS_OK(session_object1.Load(ToPathString(onnx_model_path1))); - ASSERT_STATUS_OK(session_object1.Initialize()); + so.AppendExecutionProvider("QNN", provider_options); - InferenceSessionWrapper session_object2{so, GetEnvironment()}; - ASSERT_STATUS_OK(session_object2.RegisterExecutionProvider(qnn_ep_shared)); - ASSERT_STATUS_OK(session_object2.Load(ToPathString(onnx_model_path2))); - ASSERT_STATUS_OK(session_object2.Initialize()); -} + // Create 2 sessions to generate context binary models, the 1st session will share the QnnBackendManager + // to the 2nd session, so graphs from these 2 models are all included in the 2nd context binary + Ort::Session session1(*ort_env, ToPathString(onnx_model_path1).c_str(), so); -// from the last context ache Onnx model, find the EPContext node with main_context=1, -// and get the QNN context binary file name, thie context binary contains all graphs from all Onnx models -static void GetLastContextBinaryFileName(const std::string last_onnx_ctx_file, - std::string& last_ctx_bin_file, - const Logger& logger) { - std::shared_ptr ctx_model; - ASSERT_STATUS_OK(Model::Load(ToPathString(last_onnx_ctx_file), ctx_model, nullptr, logger)); - auto& ctx_graph = ctx_model->MainGraph(); - for (auto& node : ctx_graph.Nodes()) { - if (node.OpType() == "EPContext") { - int64_t is_main_context = GetNodeAttr(node, "main_context", static_cast(0)); - if (1 == is_main_context) { - last_ctx_bin_file = GetNodeAttr(node, "ep_cache_context", ""); - return; - } - } - } + so.AddConfigEntry(kOrtSessionOptionStopShareEpContexts, "1"); + Ort::Session session2(*ort_env, ToPathString(onnx_model_path2).c_str(), so); } // Update generated context cache Onnx model to make the main EPContext node point to @@ -1187,10 +1192,10 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); - // Get the last context binary file name + // Get the last context binary file name, the latest context binary file holds all graphs generated from all models std::string last_qnn_ctx_binary_file_name; - GetLastContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, - DefaultLoggingManager().DefaultLogger()); + GetContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, + DefaultLoggingManager().DefaultLogger()); EXPECT_TRUE(!last_qnn_ctx_binary_file_name.empty()); // Update generated context cache Onnx model to make the main EPContext node point to @@ -1293,8 +1298,8 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions2) { // Get the last context binary file name std::string last_qnn_ctx_binary_file_name; - GetLastContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, - DefaultLoggingManager().DefaultLogger()); + GetContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, + DefaultLoggingManager().DefaultLogger()); EXPECT_TRUE(!last_qnn_ctx_binary_file_name.empty()); // Update generated context cache Onnx model to make the main EPContext node point to @@ -1357,6 +1362,69 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions2) { } std::remove(last_qnn_ctx_binary_file_name.c_str()); } + +// For Ort sessions to generate the context binary, with session option ep.share_ep_contexts enabled +// Ort sessions will share the QnnBackendManager, so that all graphs from all models compile into the same Qnn context +TEST_F(QnnHTPBackendTests, QnnContextGenWeightSharingSessionAPI) { + ProviderOptions provider_options; +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + provider_options["offload_graph_io_quantization"] = "0"; + + // Create QDQ models + std::vector onnx_model_paths{"./weight_share1.onnx", "./weight_share2.onnx"}; + std::vector ctx_model_paths; + for (auto model_path : onnx_model_paths) { + CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(std::filesystem::exists(model_path.c_str())); + auto pos = model_path.find_last_of("."); + if (pos != std::string::npos) { + model_path = model_path.substr(0, pos) + "_ctx.onnx"; + } else { + model_path = model_path + "_ctx.onnx"; + } + ctx_model_paths.push_back(model_path); + } + + Ort::SessionOptions so; + so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); + so.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0"); + // enable ep.share_ep_contexts so that QNNEP share the QnnBackendManager across sessions + so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); + + so.AppendExecutionProvider("QNN", provider_options); + + Ort::Session session1(*ort_env, ToPathString(onnx_model_paths[0]).c_str(), so); + std::string qnn_ctx_binary_file_name1; + GetContextBinaryFileName(ctx_model_paths[0], qnn_ctx_binary_file_name1, + DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(!qnn_ctx_binary_file_name1.empty()); + + // Tell the EP stop share the QnnBackendManager from this session then on + so.AddConfigEntry(kOrtSessionOptionStopShareEpContexts, "1"); + Ort::Session session2(*ort_env, ToPathString(onnx_model_paths[1]).c_str(), so); + std::string qnn_ctx_binary_file_name2; + GetContextBinaryFileName(ctx_model_paths[1], qnn_ctx_binary_file_name2, + DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(!qnn_ctx_binary_file_name2.empty()); + + auto file_size_1 = std::filesystem::file_size(qnn_ctx_binary_file_name1); + auto file_size_2 = std::filesystem::file_size(qnn_ctx_binary_file_name2); + EXPECT_TRUE(file_size_2 > file_size_1); + + // clean up + for (auto model_path : onnx_model_paths) { + ASSERT_EQ(std::remove(model_path.c_str()), 0); + } + for (auto ctx_model_path : ctx_model_paths) { + ASSERT_EQ(std::remove(ctx_model_path.c_str()), 0); + } + ASSERT_EQ(std::remove(qnn_ctx_binary_file_name1.c_str()), 0); + ASSERT_EQ(std::remove(qnn_ctx_binary_file_name2.c_str()), 0); +} #endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__) } // namespace test diff --git a/onnxruntime/test/qnn_ctx_gen/main.cc b/onnxruntime/test/qnn_ctx_gen/main.cc deleted file mode 100644 index bb5007b40b072..0000000000000 --- a/onnxruntime/test/qnn_ctx_gen/main.cc +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// onnxruntime dependencies -#include "test_configuration.h" -#include -#include -#include -#include "command_args_parser.h" -#include - -#include "core/session/onnxruntime_session_options_config_keys.h" -#include "core/session/inference_session.h" -#include "core/session/ort_env.h" -#include "core/providers/provider_factory_creators.h" -#include "core/common/logging/sinks/clog_sink.h" - -#include "core/graph/model.h" -#include "core/session/environment.h" -#include "core/common/logging/logging.h" - -using namespace onnxruntime; -const OrtApi* g_ort = NULL; -std::unique_ptr ort_env; - -static void CheckStatus(const Status& status) { - if (status.Code() != common::StatusCode::OK) { - std::string msg = status.ErrorMessage(); - throw Ort::Exception(std::move(msg), OrtErrorCode::ORT_FAIL); - } -} - -static int64_t GetNodeAttr(const Node& node, const std::string& attr_name, int64_t default_val) { - const auto& attributes = node.GetAttributes(); - if (auto entry = attributes.find(attr_name); entry != attributes.end()) { - return entry->second.i(); - } - - return default_val; -} - -static const std::string& GetNodeAttr(const Node& node, const std::string& attr_name, const std::string& default_val) { - const auto& attributes = node.GetAttributes(); - if (auto entry = attributes.find(attr_name); entry != attributes.end()) { - return entry->second.s(); - } - - return default_val; -} - -// from the last context cache Onnx model, find the EPContext node with main_context=1, -// and get the QNN context binary file name, this context binary contains all graphs from all Onnx models -// get the max spill fill buffer size -static void GetLastContextBinaryFileName(const std::basic_string last_onnx_ctx_file, - std::string& last_ctx_bin_file, - int64_t& max_size) { - max_size = 0; - std::shared_ptr ctx_model; - CheckStatus(Model::Load(ToPathString(last_onnx_ctx_file), ctx_model, nullptr, - (*((OrtEnv*)*ort_env.get())->GetEnvironment().GetLoggingManager()).DefaultLogger())); - auto& ctx_graph = ctx_model->MainGraph(); - for (auto& node : ctx_graph.Nodes()) { - if (node.OpType() == "EPContext") { - int64_t is_main_context = GetNodeAttr(node, "main_context", static_cast(0)); - max_size = GetNodeAttr(node, "max_size", static_cast(0)); - if (1 == is_main_context) { - last_ctx_bin_file = GetNodeAttr(node, "ep_cache_context", ""); - return; - } - } - } -} - -// Update generated context cache Onnx model to make the main EPContext node point to -// the last QNN context binary file -// Remove not used QNN context binary file, only keep the last one which contains all graphs -static void UpdateEpContextModel(const std::vector>& ep_ctx_files, - const std::string& last_qnn_ctx_binary_file_name, - int64_t max_size) { - for (auto ep_ctx_file : ep_ctx_files) { - std::shared_ptr ctx_model; - auto path_str = ToPathString(ep_ctx_file); - CheckStatus(Model::Load(path_str, ctx_model, nullptr, - (*((OrtEnv*)*ort_env.get())->GetEnvironment().GetLoggingManager()).DefaultLogger())); - auto& ctx_graph = ctx_model->MainGraph(); - GraphViewer graph_viewer(ctx_graph); - auto path = std::filesystem::path(path_str); - - for (auto& node : ctx_graph.Nodes()) { - if (node.OpType() == "EPContext") { - int64_t is_main_context = GetNodeAttr(node, "main_context", static_cast(0)); - if (1 == is_main_context) { - std::string old_qnn_ctx_binary_file_name = GetNodeAttr(node, "ep_cache_context", ""); - auto file_path = path.replace_filename(old_qnn_ctx_binary_file_name); - std::remove(file_path.string().c_str()); - node.ClearAttribute("ep_cache_context"); - node.AddAttribute("ep_cache_context", last_qnn_ctx_binary_file_name); - node.ClearAttribute("max_size"); - node.AddAttribute("max_size", max_size); - } - } - } - std::remove(ToUTF8String(ep_ctx_file).c_str()); - CheckStatus(Model::Save(*ctx_model.get(), ToPathString(ep_ctx_file))); - } -} - -#ifdef _WIN32 -int real_main(int argc, wchar_t* argv[]) { -#else -int real_main(int argc, char* argv[]) { -#endif - g_ort = OrtGetApiBase()->GetApi(ORT_API_VERSION); - qnnctxgen::TestConfig test_config; - if (!qnnctxgen::CommandLineParser::ParseArguments(test_config, argc, argv)) { - qnnctxgen::CommandLineParser::ShowUsage(); - return -1; - } - - { - bool failed = false; - ORT_TRY { - OrtLoggingLevel logging_level = test_config.run_config.f_verbose - ? ORT_LOGGING_LEVEL_VERBOSE - : ORT_LOGGING_LEVEL_WARNING; - - ort_env = std::make_unique(logging_level, "Default"); - } - ORT_CATCH(const Ort::Exception& e) { - ORT_HANDLE_EXCEPTION([&]() { - fprintf(stderr, "Error creating environment. Error-> %s \n", e.what()); - failed = true; - }); - } - - if (failed) - return -1; - } - - ORT_TRY { - SessionOptions so; - so.session_logid = "qnn_ctx_gen_session_logger"; - // Set default session option to dump QNN context model with non-embed mode - CheckStatus(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1")); - CheckStatus(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0")); - RunOptions run_options; - run_options.run_tag = so.session_logid; - - ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif - // set default QNN EP option to enable weight sharing - provider_options["enable_htp_weight_sharing"] = "1"; - - for (auto it : test_config.run_config.qnn_options) { - provider_options[it.first] = it.second; - } - - for (auto it : test_config.run_config.session_config_entries) { - if (it.first == kOrtSessionOptionEpContextEnable && it.second != "1") { - std::cerr << "Need to enable ep context cache." << std::endl; - continue; - } - if (it.first == kOrtSessionOptionEpContextEmbedMode && it.second != "0") { - std::cerr << "Only support non-embed model for weight sharing." << std::endl; - continue; - } - if (it.first == kOrtSessionOptionEpContextFilePath) { - std::cout << "Not support to specify the generated Onnx context cache file name." << std::endl; - continue; - } - CheckStatus(so.config_options.AddConfigEntry(it.first.c_str(), it.second.c_str())); - } - - for (auto model_path : test_config.model_file_paths) { - std::cout << "Model file path: " << ToUTF8String(model_path) << std::endl; - } - - // Generate context cache model files with QNN context binary files - // The context binary file generated later includes all graphs from previous models - { - auto ep = QNNProviderFactoryCreator::Create(provider_options, &so)->CreateProvider(); - std::shared_ptr qnn_ep(std::move(ep)); - - for (auto model_path : test_config.model_file_paths) { - std::cout << "Generate context cache model for: " << ToUTF8String(model_path) << std::endl; - InferenceSession session_object{so, ((OrtEnv*)*ort_env.get())->GetEnvironment()}; - CheckStatus(session_object.RegisterExecutionProvider(qnn_ep)); - CheckStatus(session_object.Load(ToPathString(model_path))); - CheckStatus(session_object.Initialize()); - } - } - - std::cout << "Start to update the generated Onnx model." << std::endl; - std::vector> ep_ctx_files; - ep_ctx_files.reserve(test_config.model_file_paths.size()); - for (auto model_path : test_config.model_file_paths) { - ep_ctx_files.push_back(model_path + ORT_TSTR("_ctx.onnx")); - } - - // Get the last context binary file name - std::string last_qnn_ctx_binary_file_name; - int64_t max_size = 0; - GetLastContextBinaryFileName(ep_ctx_files.back(), last_qnn_ctx_binary_file_name, max_size); - std::cout << "The last context binary file: " << last_qnn_ctx_binary_file_name << std::endl; - if (last_qnn_ctx_binary_file_name.empty()) { - throw Ort::Exception("Can't find QNN context binary file from the Onnx model.", OrtErrorCode::ORT_FAIL); - } - ep_ctx_files.pop_back(); - - // Update generated context cache Onnx model to make the main EPContext node point to - // the last QNN context binary file - // Remove not used QNN context binary file, only keep the last one which contains all graphs - UpdateEpContextModel(ep_ctx_files, last_qnn_ctx_binary_file_name, max_size); - } - ORT_CATCH(const Ort::Exception& e) { - fprintf(stderr, "Failed to generate context cache file: %s \n", e.what()); - - ort_env.reset(); - return -1; - } - - ort_env.reset(); - - return 0; -} - -#ifdef _WIN32 -int wmain(int argc, wchar_t* argv[]) { -#else -int main(int argc, char* argv[]) { -#endif - int retval = -1; - ORT_TRY { - retval = real_main(argc, argv); - } - ORT_CATCH(const std::exception& ex) { - ORT_HANDLE_EXCEPTION([&]() { - fprintf(stderr, "%s\n", ex.what()); - retval = -1; - }); - } - - ::google::protobuf::ShutdownProtobufLibrary(); - - return retval; -} diff --git a/setup.py b/setup.py index ced2f28e38778..53e533050b245 100644 --- a/setup.py +++ b/setup.py @@ -356,7 +356,7 @@ def finalize_options(self): "libQnnSaver.so", "libQnnSystem.so", "libHtpPrepare.so", - "onnxruntime_qnn_ctx_gen", + "ep_weight_sharing_ctx_gen", ] dl_libs.extend(qnn_deps) if nightly_build: From 788ca51b044bf1c7379a065213ec1b56c978c55f Mon Sep 17 00:00:00 2001 From: Ashish Garg Date: Tue, 4 Mar 2025 23:02:58 -0800 Subject: [PATCH 037/266] [QNN-EP]: Fix inference failures while running with htp_shared_memory (#23892) ### Description When using the enable_htp_shared_memory feature, we see that the address of the buffer passed to rpcmem_free is incorrect. So the rpc buffers are not freed leading to memory exhaustion. ### Motivation and Context When using the enable_htp_shared_memory_allocator feature for QNN in GenAI extensions, it leads to inference failures during the second prompt. As GenAI memory asks are higher, it surfaces sooner in gen AI use cases. Co-authored-by: Ashish Garg --- onnxruntime/core/providers/qnn/qnn_allocator.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/qnn/qnn_allocator.cc b/onnxruntime/core/providers/qnn/qnn_allocator.cc index 1fb8742f724cd..cb92e927ff65a 100644 --- a/onnxruntime/core/providers/qnn/qnn_allocator.cc +++ b/onnxruntime/core/providers/qnn/qnn_allocator.cc @@ -181,7 +181,9 @@ void HtpSharedMemoryAllocator::Free(void* allocation_address) { // Avoid throwing exceptions as this may be running from a destructor. try { // take ownership of shared memory and free at end of scope - auto shared_memory = WrapSharedMemoryWithUniquePtr(allocation_address, rpcmem_lib_->Api()); + const size_t allocation_offset = AllocationOffsetFromStartOfHeader(); + void* raw_allocation_address = (void*)((std::byte*)allocation_address - allocation_offset); + auto shared_memory = WrapSharedMemoryWithUniquePtr(raw_allocation_address, rpcmem_lib_->Api()); // destroy header allocation_header.~AllocationHeader(); From 8aed9208d28131b2b0dc022092250c39ae58768e Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Thu, 6 Mar 2025 01:59:50 +0800 Subject: [PATCH 038/266] Fix enable_pix_capture build for WebGPU (#23857) The build option --enable_pix_capture is broken. This fixes the problem. --------- Co-authored-by: wp --- cmake/external/onnxruntime_external_deps.cmake | 9 +-------- onnxruntime/core/providers/webgpu/webgpu_context.cc | 1 - .../core/providers/webgpu/webgpu_pix_frame_generator.cc | 4 ++-- .../core/providers/webgpu/webgpu_pix_frame_generator.h | 2 +- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index ebf20ab21bbd2..a579badee666c 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -304,7 +304,7 @@ if(NOT TARGET Boost::mp11) EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES Boost ) - onnxruntime_fetchcontent_makeavailable(mp11) + onnxruntime_fetchcontent_makeavailable(mp11) if(NOT TARGET Boost::mp11) add_library(Boost::mp11 ALIAS Boost::headers) endif() @@ -672,17 +672,10 @@ if (onnxruntime_USE_WEBGPU) # disable things we don't use set(DAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG OFF) - set(DAWN_ENABLE_DESKTOP_GL OFF CACHE BOOL "" FORCE) - set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE) - set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING OFF CACHE BOOL "" FORCE) - set(DAWN_USE_GLFW OFF CACHE BOOL "" FORCE) - set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE) set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE) set(TINT_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(TINT_BUILD_CMD_TOOLS OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_GLSL_WRITER OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_GLSL_VALIDATOR OFF CACHE BOOL "" FORCE) set(TINT_BUILD_IR_BINARY OFF CACHE BOOL "" FORCE) set(TINT_BUILD_SPV_READER OFF CACHE BOOL "" FORCE) # don't need. disabling is a large binary size saving set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "" FORCE) # needed to create cache key. runtime error if not enabled. diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 163dd691b7f16..2bd547f406226 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -165,7 +165,6 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi #if defined(ENABLE_PIX_FOR_WEBGPU_EP) // set pix frame generator pix_frame_generator_ = std::make_unique(instance_, - Adapter(), Device()); #else ORT_THROW("Support PIX capture requires extra build flags (--enable_pix_capture)"); diff --git a/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.cc b/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.cc index 90b99b7b38bb1..9b287b7b7df99 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.cc @@ -11,7 +11,7 @@ namespace onnxruntime { namespace webgpu { -WebGpuPIXFrameGenerator::WebGpuPIXFrameGenerator(wgpu::Instance instance, wgpu::Adapter adapter, wgpu::Device device) { +WebGpuPIXFrameGenerator::WebGpuPIXFrameGenerator(wgpu::Instance instance, wgpu::Device device) { // Trivial window size for surface texture creation and provide frame concept for PIX. static constexpr uint32_t kWidth = 512u; static constexpr uint32_t kHeight = 512u; @@ -32,7 +32,7 @@ WebGpuPIXFrameGenerator::WebGpuPIXFrameGenerator(wgpu::Instance instance, wgpu:: wgpu::TextureFormat format; wgpu::SurfaceCapabilities capabilities; - surface_.GetCapabilities(adapter, &capabilities); + surface_.GetCapabilities(device.GetAdapter(), &capabilities); format = capabilities.formats[0]; wgpu::SurfaceConfiguration config; diff --git a/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h b/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h index 52a7459a81eba..0d9393321284d 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h +++ b/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h @@ -41,7 +41,7 @@ namespace webgpu { // WebGpuContext destruction. class WebGpuPIXFrameGenerator { public: - WebGpuPIXFrameGenerator(wgpu::Instance instance, wgpu::Adapter adapter, wgpu::Device device); + WebGpuPIXFrameGenerator(wgpu::Instance instance, wgpu::Device device); ~WebGpuPIXFrameGenerator(); void GeneratePIXFrame(); From 834adde81a4f4cadc8c9e29bcb96c6479c19b42c Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Wed, 5 Mar 2025 13:40:40 -0800 Subject: [PATCH 039/266] [WebGPU-EP Native] Add ReduceMean (#23860) ### Description ### Motivation and Context --- .../webgpu/reduction/reduction_ops.cc | 168 ++++++++++++++++++ .../webgpu/reduction/reduction_ops.h | 62 +++++++ .../webgpu/webgpu_execution_provider.cc | 8 +- 3 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc create mode 100644 onnxruntime/core/providers/webgpu/reduction/reduction_ops.h diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc new file mode 100644 index 0000000000000..eb7903e7903b6 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/reduction/reduction_ops.h" +#include +#include "core/framework/data_transfer_manager.h" +#include "core/providers/webgpu/data_transfer.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +namespace onnxruntime { +namespace webgpu { + +#define REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceOp, begin, end) \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX( \ + ReduceOp, \ + kOnnxDomain, \ + begin, end, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedNumberTypes()), \ + ReduceOp); + +#define REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceOp, version) \ + ONNX_OPERATOR_KERNEL_EX( \ + ReduceOp, \ + kOnnxDomain, \ + version, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedNumberTypes()).InputMemoryType(OrtMemTypeCPUInput, 1), \ + ReduceOp); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMean, 18); + +Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& input = shader.AddInput("input", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + bool reduce_on_all_axes = no_op_with_empty_axes_ == false && axes_.empty(); + std::string loop_header = code_[0]; + std::string loop_body = "let current_element: input_value_t = " + input.GetByIndices("input_indices") + ";\n" + code_[1]; + std::string loop_footer = code_[2]; + const auto input_rank = input.Rank(); + for (int i = 0, l = 0; i < input_rank; ++i) { + if (reduce_on_all_axes || std::find(axes_.begin(), axes_.end(), i) != axes_.end()) { + if (keepdims_) { + l++; + } + std::stringstream ss; + std::string index = "i" + std::to_string(i); + ss << "for (var " << index << " : u32 = 0; " << index << " < " << input.IndicesGet("uniforms.input_shape", i) << "; " << index << "++) {\n"; + ss << input.IndicesSet("input_indices", i, index) << ";\n"; + ss << loop_body << "\n"; + ss << "}\n"; + loop_body = ss.str(); + } else { + std::stringstream ss; + ss << loop_header << "\n"; + std::string index = "i" + std::to_string(i); + ss << "let " << index << " = " << output.IndicesGet("output_indices", l) << ";\n"; + ss << input.IndicesSet("input_indices", i, index) << ";\n"; + loop_header = ss.str(); + l++; + } + } + std::stringstream input_indices_init_value; + for (int i = 0; i < input_rank - 1; ++i) { + input_indices_init_value << "0, "; + } + input_indices_init_value << "0"; + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "let output_indices: output_indices_t = " << output.OffsetToIndices("global_idx") << ";\n" + << "var input_indices: input_indices_t = input_indices_t(" << input_indices_init_value.str() << ");\n" + << loop_header << loop_body << loop_footer; + shader.MainFunctionBody() << output.SetByOffset("global_idx", "output_value"); + return Status::OK(); +} + +template +Status ReduceKernel::ComputeInternal(ComputeContext& context) const { + const auto* input_tensor = context.Input(0); + InlinedVector input_axes; + auto rank = input_tensor->Shape().NumDimensions(); + auto transform_axis = [rank](int64_t axis) { + if (axis < 0) { + axis += rank; + } + if (axis < 0 || static_cast(axis) >= rank) { + ORT_THROW("Axes values must be in the range [-rank, rank-1]. Got: ", axis); + } + return static_cast(axis); + }; + // Check if axes input is provided and copy the axes values to input_axes + if (context.InputCount() > 1) { + ORT_ENFORCE(axes_.empty(), "Axes attribute may not be specified when axes input is also provided."); + const Tensor* axes_tensor = context.Input(1); + auto size = static_cast(axes_tensor->Shape()[0]); + const auto* data = axes_tensor->Data(); + input_axes.reserve(size); + std::transform(data, data + size, std::back_inserter(input_axes), transform_axis); + } else { + input_axes.reserve(axes_.size()); + std::transform(axes_.begin(), axes_.end(), std::back_inserter(input_axes), transform_axis); + } + if (input_axes.empty()) { + if (noop_with_empty_axes_ || rank == 0) { + // If axes is empty and noop_with_empty_axes_ is true, it is a no-op according to the spec + // If input tensor is a scalar, return the input tensor as is. + // This is not correct for ReduceLogSum and ReduceSumSquare + // TODO handle these cases separately. + auto output = context.Output(0, input_tensor->Shape()); + if (output->DataRaw() != input_tensor->DataRaw()) { + ORT_RETURN_IF_ERROR(Info().GetDataTransferManager().CopyTensor(*input_tensor, *output)); + } + return Status::OK(); + } else { + // If axes is empty and noop_with_empty_axes_ is false, it is a reduction over all axes + input_axes.resize(rank); + std::iota(input_axes.begin(), input_axes.end(), 0); + } + } + const auto code = GetOpSpecificCode(input_tensor, input_axes.size()); + // Compute output shape + std::vector output_shape; + for (size_t i = 0; i < input_tensor->Shape().NumDimensions(); ++i) { + if (std::find(input_axes.begin(), input_axes.end(), i) != input_axes.end()) { + if (keepdims_) { + output_shape.push_back(1); + } + } else { + output_shape.push_back(input_tensor->Shape()[i]); + } + } + TensorShape output_tensor_shape(output_shape); + int64_t output_size = output_tensor_shape.Size(); + ReduceKernelProgram program("ReduceMean", keepdims_, noop_with_empty_axes_, input_axes, code); + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .AddOutput({context.Output(0, output_shape), ProgramTensorMetadataDependency::TypeAndRank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({{static_cast(output_size)}, + {static_cast(noop_with_empty_axes_ ? 1 : 0)}, + {input_axes}, + {static_cast(input_axes.size())}}); + + return context.RunProgram(program); +} + +ReduceOpSpecificCode ReduceMean::GetOpSpecificCode(const Tensor* input_tensor, size_t axes_size) const { + const TensorShape& input_shape = input_tensor->Shape(); + size_t input_rank = input_shape.NumDimensions(); + std::stringstream ss; + ss << "var size: u32 = 1;\n" + << "for (var i: u32 = 0; i < uniforms.axes_size; i += 1) { \n" + << " let index = " << GetElementAt("uniforms.axes", "i", axes_size) << ";\n" + << " size = size * " << GetElementAt("uniforms.input_shape", "index", input_rank) << ";\n" + << "}\n" + << "let output_value = output_value_t(sum / f32(size));"; + ReduceOpSpecificCode code({"var sum = f32(0);", "sum += f32(current_element);", ss.str()}); + return code; +} + +Status ReduceMean::ComputeInternal(ComputeContext& ctx) const { + return ReduceKernel::ComputeInternal(ctx); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h new file mode 100644 index 0000000000000..e93eb06f20886 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include "core/common/optional.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/cpu/reduction/reduction_kernel_base.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/shader_helper.h" +namespace onnxruntime { +namespace webgpu { +// reduceOpSpecificCode is a 3-element array of strings that represent the op specific code for the reduce operation. +// The first element is the loop header, the second element is the loop body, and the third element is the loop footer. +// The loop header is the code that is executed before the loop starts. The loop body is the code that is executed for each element in the loop. +// The loop footer is the code that is executed after the loop ends. +typedef std::array ReduceOpSpecificCode; +class ReduceKernelProgram final : public Program { + public: + ReduceKernelProgram(std::string name, bool keepdims, bool no_op_with_empty_axes, const InlinedVector& axes, ReduceOpSpecificCode code) : Program{name}, keepdims_(keepdims), no_op_with_empty_axes_(no_op_with_empty_axes), axes_(axes.begin(), axes.end()), code_(code) {} + Status GenerateShaderCode(ShaderHelper& wgpuShaderModuleAddRef) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, + {"no_op_with_empty_axes", ProgramUniformVariableDataType::Uint32}, + {"axes", ProgramUniformVariableDataType::Uint32}, + {"axes_size", ProgramUniformVariableDataType::Uint32}); + + private: + const bool keepdims_; + const bool no_op_with_empty_axes_; + InlinedVector axes_; + ReduceOpSpecificCode code_; +}; + +template +class ReduceKernel : public WebGpuKernel, public ReduceKernelBase { + protected: + using ReduceKernelBase::axes_; + using ReduceKernelBase::noop_with_empty_axes_; + using ReduceKernelBase::keepdims_; + using ReduceKernelBase::select_last_index_; + + ReduceKernel(const OpKernelInfo& info, std::string name, optional keepdims_override = {}) + : WebGpuKernel(info), + ReduceKernelBase(info, keepdims_override), + name_(name) { + } + Status ComputeInternal(ComputeContext& ctx) const; + virtual ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor, size_t axes_size) const = 0; + + private: + std::string name_; +}; + +class ReduceMean final : public ReduceKernel { + public: + ReduceMean(const OpKernelInfo& info) : ReduceKernel(info, "ReduceMean") {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor, size_t axes_size) const override; + Status ComputeInternal(ComputeContext& ctx) const override; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index d44cf4674d8a3..4950d94dea4c4 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -516,10 +516,10 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, From cfb0a72feb93a59722c55e69b1415d47c80df7bc Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 5 Mar 2025 14:44:32 -0800 Subject: [PATCH 040/266] [WebGPU EP] introduce BiasAdd contrib op (#23861) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../contrib_ops/webgpu/bert/bias_add.cc | 80 +++++++++++++++++++ .../contrib_ops/webgpu/bert/bias_add.h | 32 ++++++++ .../webgpu/webgpu_contrib_kernels.cc | 4 +- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 onnxruntime/contrib_ops/webgpu/bert/bias_add.cc create mode 100644 onnxruntime/contrib_ops/webgpu/bert/bias_add.h diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc new file mode 100644 index 0000000000000..65c14e8cb0bdd --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "contrib_ops/webgpu/bert/bias_add.h" +#include "contrib_ops/webgpu/webgpu_contrib_kernels.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +ONNX_OPERATOR_KERNEL_EX( + BiasAdd, + kMSDomain, + 1, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()), + BiasAdd); + +Status BiasAddProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input"); + const ShaderVariableHelper& bias = shader.AddInput("bias"); + const ShaderVariableHelper& residual = shader.AddInput("residual"); + const ShaderVariableHelper& output = shader.AddOutput("output"); + + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "let value = " << input.GetByOffset("global_idx") + << " + " << bias.GetByOffset("global_idx % uniforms.channels") + << " + " << residual.GetByOffset("global_idx") << ";\n" + << output.SetByOffset("global_idx", "value"); + + return Status::OK(); +} + +static int64_t GetMaxComponents(int64_t size) { + if (size % 4 == 0) { + return 4; + } else if (size % 2 == 0) { + return 2; + } + return 1; +} + +Status BiasAdd::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) const { + const auto* input = context.Input(0); + const auto* bias = context.Input(1); + const auto* residual = context.Input(2); + + TensorShape input_shape = input->Shape(); + + if (input_shape.NumDimensions() != 3) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "BiasAdd input should have 3 dimensions."); + } + + int64_t channels = input_shape[2]; + int64_t components = GetMaxComponents(channels); + channels /= components; + + TensorShape bias_shape = bias->Shape(); + if (bias_shape.NumDimensions() != 1 || bias_shape[0] != channels) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "BiasAdd bias should have 1 dimension with size equal to the number of channels."); + } + + auto* output = context.Output(0, input_shape); + int64_t output_size = output->Shape().Size() / components; + + BiasAddProgram program{}; + program.AddInputs({{input}, {bias}, {residual}}) + .AddOutput({output}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({{static_cast(output_size)}, + {static_cast(channels)}}); + return context.RunProgram(program); +} + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_add.h b/onnxruntime/contrib_ops/webgpu/bert/bias_add.h new file mode 100644 index 0000000000000..58cc5f09f8003 --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_add.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/webgpu_kernel.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +using namespace onnxruntime::webgpu; +using onnxruntime::webgpu::ComputeContext; + +class BiasAddProgram final : public Program { + public: + BiasAddProgram() : Program{"BiasAdd"} {} + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, + {"channels", ProgramUniformVariableDataType::Uint32}); +}; + +class BiasAdd final : public WebGpuKernel { + public: + BiasAdd(const OpKernelInfo& info) : WebGpuKernel(info) {} + Status ComputeInternal(ComputeContext& context) const override; +}; + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc b/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc index 2e7ed5a16a2f0..068a94c7390e2 100644 --- a/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc @@ -37,8 +37,8 @@ Status RegisterWebGpuContribKernels(KernelRegistry& kernel_registry) { static const BuildKernelCreateInfoFn function_table[] = { BuildKernelCreateInfo, // default entry to avoid the list become empty after ops-reducing // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + // BuildKernelCreateInfo, BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, From 5e636a676bdbf36907681171ab1d87430cab3b4e Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Wed, 5 Mar 2025 15:13:23 -0800 Subject: [PATCH 041/266] Dynamo export and improve benchmark script for SAM2 encoder (#23887) ### Description * Add dynamo export for Sam2 image encoder * Verify fp32 onnx model with CPU EP (to avoid error message from TRT EP). * Update benchmark script: - output ORT profiling - output torch compiled code and unique kernel name for compiled kernel - add an option for nightly package installation - uninstall existing ort packages before installing The node metadata of dynamo exported model can help mapping node in onnx model back to pytorch modeling script. Currently, the graph optimization is not done on dynamo exported model, so it is experimental right now. ### Motivation and Context To support profiling of torch compiled CUDA kernel. --- .../tools/transformers/models/sam2/README.md | 31 +- .../models/sam2/benchmark_sam2.py | 15 +- .../models/sam2/benchmark_sam2.sh | 310 ++++++++++++------ .../models/sam2/convert_to_onnx.py | 14 +- .../transformers/models/sam2/image_decoder.py | 2 +- .../transformers/models/sam2/image_encoder.py | 74 ++++- .../transformers/models/sam2/mask_decoder.py | 2 +- .../models/sam2/prompt_encoder.py | 2 +- 8 files changed, 315 insertions(+), 135 deletions(-) diff --git a/onnxruntime/python/tools/transformers/models/sam2/README.md b/onnxruntime/python/tools/transformers/models/sam2/README.md index e7cafeffc6231..463d154525f8f 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/README.md +++ b/onnxruntime/python/tools/transformers/models/sam2/README.md @@ -96,8 +96,7 @@ We can create a conda environment then run GPU benchmark like the following: conda create -n sam2_gpu python=3.11 -y conda activate sam2_gpu install_dir=$HOME -profiling=true -bash benchmark_sam2.sh $install_dir gpu $profiling +bash benchmark_sam2.sh $install_dir gpu ``` or create a new conda environment for CPU benchmark: @@ -107,16 +106,28 @@ conda activate sam2_cpu bash benchmark_sam2.sh $HOME cpu ``` -The first parameter is a directory to clone git repositories or install CUDA/cuDNN for benchmark. -The second parameter can be either "gpu" or "cpu", which indicates the device to run benchmark. -The third parameter is optional. Value "true" will enable profiling after running benchmarking on GPU. +The usage of the script like the following: +``` +bash benchmark_sam2.sh [profiling] [benchmarking] [nightly] [dynamo] +``` + +| Parameter| Default | Description | +|----------|----------| ------------| +| install_dir | $HOME | a directory to clone git repositories or install CUDA/cuDNN for benchmark | +| cpu_or_gpu | gpu | the device to run benchmark. The value can be either "gpu" or "cpu" | +| profiling | false | run gpu profiling | +| benchmarking | true | run benchmark | +| nightly | false | install onnxruntime nightly or official release package | +| dynamo | false | export image encoder using dynamo or not. | -The script will automatically install required packages in current conda environment, download checkpoints, export onnx, -and run demo, benchmark and optionally run profiling. +The dynamo export is experimental since graph optimization still need extra works for this model. -* The performance test result is in sam2_gpu.csv or sam2_cpu.csv, which can be loaded into Excel. -* The demo output is sam2_demo_fp16_gpu.png or sam2_demo_fp32_cpu.png. -* The profiling results are in *.nsys-rep or *.json files in current directory. Use Nvidia NSight System to view the *.nsys-rep file. +Output files: +* sam2_cpu_[timestamp].csv or sam2_gpu_[timestamp].csv has benchmark results. Use Excel to load the file to view it. +* onnxruntime_image_[encoder|decoder].json has ONNX Runtime profiling results. Use `chrome://tracing` in Chrome browser to view it. +* torch_image_[encoder|decoder].json has PyTorch profiling results. Use `chrome://tracing` in Chrome browser to view it. +* sam2_fp16_profile_image_[encoder|decoder]_[ort|torch]_gpu.[nsys-rep|sqlite] has NVTX profiling. Use Nvidia NSight System to view it. +* torch_image_encoder_compiled_code.txt has the compiled kernel code from Pytorch. ## Limitations - The exported image_decoder model does not support batch mode for now. diff --git a/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.py b/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.py index 16d71d5057b02..3fc24d157b0cf 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.py +++ b/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.py @@ -46,6 +46,7 @@ def __init__( prefer_nhwc: bool = False, warm_up: int = 5, enable_nvtx_profile: bool = False, + enable_ort_profile: bool = False, enable_torch_profile: bool = False, repeats: int = 1000, verbose: bool = False, @@ -74,6 +75,7 @@ def __init__( self.prefer_nhwc = prefer_nhwc self.warm_up = warm_up self.enable_nvtx_profile = enable_nvtx_profile + self.enable_ort_profile = enable_ort_profile self.enable_torch_profile = enable_torch_profile self.repeats = repeats self.verbose = verbose @@ -317,6 +319,7 @@ def run_test( repeats=args.repeats, warm_up=args.warm_up, enable_nvtx_profile=args.enable_nvtx_profile, + enable_ort_profile=args.enable_ort_profile, enable_torch_profile=args.enable_torch_profile, torch_compile_mode=args.torch_compile_mode, verbose=False, @@ -325,7 +328,7 @@ def run_test( if args.engine == "ort": sess_options = SessionOptions() sess_options.intra_op_num_threads = args.intra_op_num_threads - if config.enable_nvtx_profile: + if config.enable_ort_profile: sess_options.enable_profiling = True sess_options.log_severity_level = 4 sess_options.log_verbosity_level = 0 @@ -349,6 +352,8 @@ def run_test( with nvtx.annotate("one_run"): _ = session.infer(input_dict) cudart.cudaProfilerStop() + + if config.enable_ort_profile: session.ort_session.end_profiling() if repeats == 0: @@ -554,6 +559,14 @@ def _parse_arguments(): help="Enable nvtx profiling. It will add an extra run for profiling before performance test.", ) + parser.add_argument( + "--enable_ort_profile", + required=False, + default=False, + action="store_true", + help="Enable ORT profiling.", + ) + parser.add_argument( "--enable_torch_profile", required=False, diff --git a/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.sh b/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.sh index 9e97867657ab9..c82b1ed31796e 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.sh +++ b/onnxruntime/python/tools/transformers/models/sam2/benchmark_sam2.sh @@ -5,7 +5,17 @@ # ------------------------------------------------------------------------- # Please refer to README.md for the prerequisites and usage of this script. -# bash benchmark_sam2.sh [profiling] +# bash benchmark_sam2.sh [profiling] [benchmarking] [nightly] [dynamo] +# Note that dynamo need onnxruntime 1.21 or later, or nightly build. +# Example: +# bash benchmark_sam2.sh $HOME gpu true true true false + +install_dir="${1:-$HOME}" +cpu_or_gpu="${2:-gpu}" +profiling="${3:-false}" +benchmarking="${4:-true}" +nightly="${5:-false}" +dynamo="${6:-false}" python="$CONDA_PREFIX/bin/python3" @@ -13,9 +23,6 @@ python="$CONDA_PREFIX/bin/python3" dir="$(cd "$(dirname "$0")" && pwd)" onnx_dir="$dir/sam2_onnx_models" -# Installation directory (default: $HOME) -install_dir="${1:-$HOME}" - if [ ! -d "$install_dir" ]; then echo "Error: install_dir '$install_dir' does not exist." exit 1 @@ -26,7 +33,6 @@ sam2_dir="$install_dir/segment-anything-2" model="sam2_hiera_large" # Default to GPU, switch to CPU if specified -cpu_or_gpu="${2:-gpu}" if [ "$cpu_or_gpu" != "gpu" ] && [ "$cpu_or_gpu" != "cpu" ]; then echo "Invalid option: $2. Please specify 'cpu' or 'gpu'." exit 1 @@ -35,52 +41,97 @@ fi echo "install_dir: $install_dir" echo "cpu_or_gpu: $cpu_or_gpu" -install_cuda_12() -{ - pushd $install_dir - wget https://developer.download.nvidia.com/compute/cuda/12.6.2/local_installers/cuda_12.6.2_560.35.03_linux.run - sh cuda_12.6.2_560.35.03_linux.run --toolkit --toolkitpath=$install_dir/cuda12.6 --silent --override --no-man-page +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Ensure necessary tools are installed +if ! command_exists wget; then + echo "wget is not installed. Please install it and try again." + exit 1 +fi + +if ! command_exists git; then + echo "git is not installed. Please install it and try again." + exit 1 +fi + +if ! command_exists pip; then + echo "pip is not installed. Please install it and try again." + exit 1 +fi + +cuda_version=12.6 +cudnn_version=9.5 - export PATH="$install_dir/cuda12.6/bin:$PATH" - export LD_LIBRARY_PATH="$install_dir/cuda12.6/lib64:$LD_LIBRARY_PATH" - popd +# Install CUDA 12.6 +install_cuda_12() { + if ! [ -d "$install_dir/cuda${cuda_version}" ]; then + pushd "$install_dir" || exit + wget https://developer.download.nvidia.com/compute/cuda/12.6.2/local_installers/cuda_12.6.2_560.35.03_linux.run + sh cuda_12.6.2_560.35.03_linux.run --toolkit --toolkitpath="$install_dir/cuda${cuda_version}" --silent --override --no-man-page + popd || exit + fi + export PATH="$install_dir/cuda${cuda_version}/bin:$PATH" + export LD_LIBRARY_PATH="$install_dir/cuda${cuda_version}/lib64:$LD_LIBRARY_PATH" } -# Function to install cuDNN 9.4 +# Install cuDNN 9.5 install_cudnn_9() { - pushd "$install_dir" - wget -q https://developer.download.nvidia.com/compute/cudnn/redist/cudnn/linux-x86_64/cudnn-linux-x86_64-9.5.0.50_cuda12-archive.tar.xz - mkdir -p "$install_dir/cudnn9.5" - tar -Jxvf cudnn-linux-x86_64-9.5.0.50_cuda12-archive.tar.xz -C "$install_dir/cudnn9.5" --strip=1 - export LD_LIBRARY_PATH="$install_dir/cudnn9.5/lib:$LD_LIBRARY_PATH" - popd + if ! [ -d "$install_dir/cudnn${cudnn_version}" ]; then + pushd "$install_dir" || exit + wget -q https://developer.download.nvidia.com/compute/cudnn/redist/cudnn/linux-x86_64/cudnn-linux-x86_64-9.5.0.50_cuda12-archive.tar.xz + mkdir -p "$install_dir/cudnn${cudnn_version}" + tar -Jxvf cudnn-linux-x86_64-9.5.0.50_cuda12-archive.tar.xz -C "$install_dir/cudnn${cudnn_version}" --strip=1 + popd || exit + fi + export LD_LIBRARY_PATH="$install_dir/cudnn${cudnn_version}/lib:$LD_LIBRARY_PATH" +} + +install_ort() { + local ort="$1" + pip uninstall onnxruntime onnxruntime-gpu -y + + if [ "$nightly" = "true" ]; then + pip install flatbuffers numpy packaging protobuf sympy + pip install --pre --index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/ORT-Nightly/pypi/simple/ "$ort" + else + pip install "$ort" + fi + + pip install onnx onnxscript opencv-python matplotlib } # Install GPU dependencies install_gpu() { - [ ! -d "$install_dir/cuda12.6" ] && install_cuda_12 - [ ! -d "$install_dir/cudnn9.5" ] && install_cudnn_9 + install_cuda_12 + install_cudnn_9 + echo "PATH: $PATH" + echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH" + + # The dynamo export need torch 2.6.0 or later. Use the latest one. + pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124 --upgrade - pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124 - pip install onnxruntime-gpu onnx opencv-python matplotlib + install_ort "onnxruntime-gpu" } # Install CPU dependencies install_cpu() { pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu - pip install onnxruntime onnx opencv-python matplotlib + install_ort "onnxruntime" } # Clone and install SAM2 if not already installed install_sam2() { - pushd "$install_dir" + pushd "$install_dir" || exit if [ ! -d "$sam2_dir" ]; then git clone https://github.com/facebookresearch/segment-anything-2.git fi - cd "$sam2_dir" + cd "$sam2_dir" || exit pip show SAM-2 > /dev/null 2>&1 || pip install -e . [ ! -f checkpoints/sam2_hiera_large.pt ] && (cd checkpoints && sh ./download_ckpts.sh) - popd + popd || exit } # Download test image if not available @@ -90,7 +141,12 @@ download_test_image() { run_cpu_benchmark() { local repeats="$1" - $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --demo + + if [ "$dynamo" = "true" ]; then + $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --demo --dynamo + else + $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --demo + fi for component in image_encoder image_decoder; do $python benchmark_sam2.py --model_type "$model" --engine torch --sam2_dir "$sam2_dir" --repeats "$repeats" --dtype fp32 --component "$component" @@ -103,65 +159,75 @@ run_cpu_benchmark() { done } -run_gpu_benchmark() { +run_ort_gpu_benchmark() { local repeats="$1" - $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --use_gpu --dtype fp32 - $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --use_gpu --dtype fp16 --demo - for component in image_encoder image_decoder; do - for dtype in bf16 fp32 fp16; do - $python benchmark_sam2.py --model_type "$model" --engine torch --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype $dtype --component "$component" - done - done + if [ "$dynamo" = "true" ]; then + $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --use_gpu --dtype fp32 --dynamo + $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --use_gpu --dtype fp16 --demo --dynamo + else + $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --use_gpu --dtype fp32 + $python convert_to_onnx.py --sam2_dir "$sam2_dir" --optimize --use_gpu --dtype fp16 --demo + fi component="image_encoder" for dtype in fp32 fp16; do - #TODO: --prefer_nhwc does not help with performance - $python benchmark_sam2.py --model_type "$model" --engine ort --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype $dtype --component "$component" --onnx_path "${onnx_dir}/${model}_${component}_${dtype}_gpu.onnx" --use_cuda_graph + $python benchmark_sam2.py --model_type "$model" --engine ort --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype "$dtype" --component "$component" --onnx_path "${onnx_dir}/${model}_${component}_${dtype}_gpu.onnx" --use_cuda_graph done + # Test prefer_nhwc. + $python benchmark_sam2.py --model_type "$model" --engine ort --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype fp16 --component "$component" --onnx_path "${onnx_dir}/${model}_${component}_${dtype}_gpu.onnx" --use_cuda_graph --prefer_nhwc component="image_decoder" for dtype in fp32 fp16; do # TODO: decoder does not work with cuda graph - $python benchmark_sam2.py --model_type "$model" --engine ort --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype $dtype --component "$component" --onnx_path "${onnx_dir}/${model}_${component}_${dtype}_gpu.onnx" + $python benchmark_sam2.py --model_type "$model" --engine ort --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype "$dtype" --component "$component" --onnx_path "${onnx_dir}/${model}_${component}_${dtype}_gpu.onnx" done + # Test prefer_nhwc. + $python benchmark_sam2.py --model_type "$model" --engine ort --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype fp16 --component "$component" --onnx_path "${onnx_dir}/${model}_${component}_${dtype}_gpu.onnx" --prefer_nhwc } -run_torch_compile_gpu_benchmark() { +run_torch_gpu_benchmark() { local repeats="$1" + # Test PyTorch eager mode. + for component in image_encoder image_decoder; do + for dtype in bf16 fp32 fp16; do + $python benchmark_sam2.py --model_type "$model" --engine torch --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype "$dtype" --component "$component" + done + done + # Test different torch compile modes on image encoder for torch_compile_mode in none max-autotune reduce-overhead max-autotune-no-cudagraphs do - $python benchmark_sam2.py --model_type $model --engine torch --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype fp16 --component image_encoder --torch_compile_mode $torch_compile_mode + $python benchmark_sam2.py --model_type "$model" --engine torch --sam2_dir "$sam2_dir" --repeats "$repeats" --use_gpu --dtype fp16 --component image_encoder --torch_compile_mode $torch_compile_mode done } - -# Main script -run_benchmarks() { - if [ ! -v CONDA_PREFIX ]; then - echo "Please activate conda environment before running this script." - exit 1 +install_all() { + if [ "$cpu_or_gpu" = "gpu" ]; then + install_gpu + else + install_cpu fi - - # Install dependencies - [ "$cpu_or_gpu" = "gpu" ] && install_gpu || install_cpu install_sam2 download_test_image +} - # Run benchmarks - output_csv="sam2_${cpu_or_gpu}.csv" +run_benchmarks() { + suffix=$(date +"%Y_%m_%d_%H_%M_%S") + [ "$dynamo" = "true" ] && suffix="${suffix}_dynamo" + output_csv="sam2_${cpu_or_gpu}_${suffix}.csv" if [ ! -f "$output_csv" ]; then echo "Running $cpu_or_gpu benchmark..." if [ "$cpu_or_gpu" = "gpu" ]; then - run_gpu_benchmark 1000 - run_torch_compile_gpu_benchmark 1000 + run_ort_gpu_benchmark 1000 + run_torch_gpu_benchmark 1000 else run_cpu_benchmark 100 fi cat benchmark*.csv > combined_csv awk '!x[$0]++' combined_csv > "$output_csv" + rm benchmark*.csv rm combined_csv echo "Benchmark results saved in $output_csv" else @@ -169,7 +235,16 @@ run_benchmarks() { fi } -run_benchmarks +if [ ! -v CONDA_PREFIX ]; then + echo "Please activate conda environment before running this script." + exit 1 +fi + +install_all + +if [ "$benchmarking" = "true" ]; then + run_benchmarks +fi #-------------------------------------------------------------------------- # Below are for profiling @@ -177,79 +252,100 @@ run_benchmarks # Build onnxruntime-gpu from source for profiling build_onnxruntime_gpu_for_profiling() { - pushd "$install_dir" + pushd "$install_dir" || exit if ! [ -d onnxruntime ]; then git clone https://github.com/microsoft/onnxruntime fi - cd onnxruntime - CUDA_ARCH=$(python3 -c "import torch; cc = torch.cuda.get_device_capability(); print(f'{cc[0]}{cc[1]}')") - if [ -n "$CUDA_ARCH" ]; then - pip install --upgrade pip cmake psutil setuptools wheel packaging ninja numpy==1.26.4 - sh build.sh --config Release --build_dir build/cuda12 --build_shared_lib --parallel \ - --use_cuda --cuda_version 12.6 --cuda_home $install_dir/cuda12.6 \ - --cudnn_home $install_dir/cudnn9.5 \ - --build_wheel --skip_tests \ - --cmake_generator Ninja \ - --compile_no_warning_as_error \ - --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=$CUDA_ARCH \ - --cmake_extra_defines onnxruntime_ENABLE_NVTX_PROFILE=ON \ - --enable_cuda_line_info - - pip install build/cuda12/Release/dist/onnxruntime_gpu-*-linux_x86_64.whl numpy==1.26.4 - else - echo "No CUDA device found." - exit 1 - fi - popd + cd onnxruntime || exit + pip install --upgrade pip cmake psutil setuptools wheel packaging ninja numpy + build_dir=build/cuda${cuda_version} + rm -rf ${build_dir}/Release/dist + sh build.sh --config Release --build_dir "${build_dir}" --build_shared_lib --parallel \ + --use_cuda --cuda_version ${cuda_version} --cuda_home "$install_dir/cuda${cuda_version}" \ + --cudnn_home "$install_dir/cudnn${cudnn_version}" \ + --build_wheel --skip_tests \ + --cmake_generator Ninja \ + --compile_no_warning_as_error \ + --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=native \ + --cmake_extra_defines onnxruntime_ENABLE_NVTX_PROFILE=ON \ + --enable_cuda_line_info + pip uninstall onnxruntime-gpu -y + pip install "${build_dir}/Release/dist/onnxruntime_gpu-*-linux_x86_64.whl" + popd || exit } # Run profiling with NVTX. -run_nvtx_profile() -{ - pip install nvtx cuda-python==12.6.0 - +run_nvtx_profile() { + local engine="$1" # Only trace one device to avoid huge output file size. device_id=0 - envs="CUDA_VISIBLE_DEVICES=$device_id,ORT_ENABLE_CUDNN_FLASH_ATTENTION=1,LD_LIBRARY_PATH=$LD_LIBRARY_PATH" + envs="CUDA_VISIBLE_DEVICES=$device_id,ORT_ENABLE_CUDNN_FLASH_ATTENTION=1,LD_LIBRARY_PATH=$LD_LIBRARY_PATH,TORCHINDUCTOR_UNIQUE_KERNEL_NAMES=1" cuda_graph_trace=node - for engine in ort torch; do - for component in image_encoder image_decoder; do - sudo $install_dir/cuda12.6/bin/nsys profile --capture-range=nvtx --nvtx-capture='one_run' \ - --gpu-metrics-device $device_id --force-overwrite true \ - --sample process-tree --backtrace fp --stats true \ - -t cuda,cudnn,cublas,osrt,nvtx --cuda-memory-usage true --cudabacktrace all \ - --cuda-graph-trace $cuda_graph_trace \ - -e $envs,NSYS_NVTX_PROFILER_REGISTER_ONLY=0 \ - -o sam2_fp16_profile_${component}_${engine}_${cpu_or_gpu} \ - $python benchmark_sam2.py --model_type $model --engine $engine \ - --sam2_dir $sam2_dir --warm_up 1 --repeats 0 \ - --onnx_path ${onnx_dir}/${model}_${component}_fp16_gpu.onnx \ - --component $component \ - --use_gpu --dtype fp16 --enable_nvtx_profile - done + for component in image_encoder image_decoder; do + sudo "$install_dir/cuda${cuda_version}/bin/nsys" profile --capture-range=nvtx --nvtx-capture='one_run' \ + --gpu-metrics-devices $device_id --force-overwrite true \ + --sample process-tree --backtrace fp --stats true \ + -t cuda,cudnn,cublas,osrt,nvtx --cuda-memory-usage true --cudabacktrace all \ + --cuda-graph-trace "$cuda_graph_trace" \ + -e "$envs,NSYS_NVTX_PROFILER_REGISTER_ONLY=0" \ + -o "sam2_fp16_profile_${component}_${engine}_${cpu_or_gpu}" \ + $python benchmark_sam2.py --model_type "$model" --engine "$engine" \ + --sam2_dir "$sam2_dir" --warm_up 1 --repeats 0 \ + --onnx_path "${onnx_dir}/${model}_${component}_fp16_gpu.onnx" \ + --component "$component" \ + --use_gpu --dtype fp16 --enable_nvtx_profile done } -# Run profiling with PyTorch -run_torch_profile() { +run_ort_profile() { + export ORT_ENABLE_CUDNN_FLASH_ATTENTION=1 + rm -f onnxruntime_*.json for component in image_encoder image_decoder; do - $python benchmark_sam2.py --model_type $model --engine torch \ - --sam2_dir $sam2_dir --warm_up 1 --repeats 0 \ - --component $component \ - --use_gpu --dtype fp16 --enable_torch_profile + $python benchmark_sam2.py --model_type "$model" --engine ort \ + --sam2_dir "$sam2_dir" --warm_up 1 --repeats 0 \ + --onnx_path "${onnx_dir}/${model}_${component}_fp16_gpu.onnx" \ + --component "$component" \ + --use_gpu --dtype fp16 --enable_ort_profile + mv onnxruntime_profile*.json onnxruntime_$component.json done } -run_profilings() { - build_onnxruntime_gpu_for_profiling +# Run profiling with PyTorch +run_torch_profile() { + # Enable logging might could help get the code of compiled kernels. You can turn it off to reduce overhead. + export TORCH_LOGS="+inductor,+output_code" + export TORCHINDUCTOR_UNIQUE_KERNEL_NAMES=1 + component=image_encoder + $python benchmark_sam2.py --model_type "$model" --engine torch \ + --sam2_dir "$sam2_dir" --warm_up 1 --repeats 0 \ + --component "$component" \ + --torch_compile_mode max-autotune \ + --use_gpu --dtype fp16 --enable_torch_profile > "torch_${component}_compiled_code.txt" + + component=image_decoder + $python benchmark_sam2.py --model_type "$model" --engine torch \ + --sam2_dir "$sam2_dir" --warm_up 1 --repeats 0 \ + --component "$component" \ + --torch_compile_mode none \ + --use_gpu --dtype fp16 --enable_torch_profile +} +run_nvtx_profilings() { + build_onnxruntime_gpu_for_profiling rm -f *.nsys-rep *.sqlite - run_nvtx_profile + run_nvtx_profile ort + run_nvtx_profile torch +} +run_profilings() { + pip install nvtx cuda-python==${cuda_version}.0 + run_ort_profile run_torch_profile + + # NVTX profiling need to build onnxruntime-gpu from source so it is put as the last step. + run_nvtx_profilings } -profiling="${3:-false}" if [ "$profiling" = "true" ] && [ "$cpu_or_gpu" = "gpu" ]; then run_profilings fi diff --git a/onnxruntime/python/tools/transformers/models/sam2/convert_to_onnx.py b/onnxruntime/python/tools/transformers/models/sam2/convert_to_onnx.py index cacad717faf9c..3533a274b9972 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/convert_to_onnx.py +++ b/onnxruntime/python/tools/transformers/models/sam2/convert_to_onnx.py @@ -113,6 +113,14 @@ def parse_arguments(): help="Optimize onnx models for GPU", ) + parser.add_argument( + "--dynamo", + required=False, + default=False, + action="store_true", + help="Use dynamo for exporting onnx model. Only image_encoder supports dynamo right now.", + ) + parser.add_argument( "--verbose", required=False, @@ -151,8 +159,10 @@ def main(): onnx_model_path = sam2_onnx_path(args.output_dir, args.model_type, component, args.multimask_output) if component == "image_encoder": if args.overwrite or not os.path.exists(onnx_model_path): - export_image_encoder_onnx(sam2_model, onnx_model_path, args.dynamic_batch_axes, args.verbose) - test_image_encoder_onnx(sam2_model, onnx_model_path, dynamic_batch_axes=False) + export_image_encoder_onnx( + sam2_model, onnx_model_path, args.dynamic_batch_axes, args.verbose, args.dynamo + ) + test_image_encoder_onnx(sam2_model, onnx_model_path, dynamic_batch_axes=args.dynamic_batch_axes) elif component == "mask_decoder": if args.overwrite or not os.path.exists(onnx_model_path): diff --git a/onnxruntime/python/tools/transformers/models/sam2/image_decoder.py b/onnxruntime/python/tools/transformers/models/sam2/image_decoder.py index 07ed150631f50..376e6ba7d802c 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/image_decoder.py +++ b/onnxruntime/python/tools/transformers/models/sam2/image_decoder.py @@ -246,7 +246,7 @@ def test_decoder_onnx( import onnxruntime - ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=onnxruntime.get_available_providers()) + ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=["CPUExecutionProvider"]) model_inputs = ort_session.get_inputs() input_names = [model_inputs[i].name for i in range(len(model_inputs))] diff --git a/onnxruntime/python/tools/transformers/models/sam2/image_encoder.py b/onnxruntime/python/tools/transformers/models/sam2/image_encoder.py index c5ce339732063..79e9297788c36 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/image_encoder.py +++ b/onnxruntime/python/tools/transformers/models/sam2/image_encoder.py @@ -90,6 +90,8 @@ def export_image_encoder_onnx( onnx_model_path: str, dynamic_batch_axes: bool = False, verbose: bool = False, + dynamo: bool = False, + clear_dynamo_metadata: bool = False, ): image = random_sam2_input_image() @@ -113,17 +115,65 @@ def export_image_encoder_onnx( if not verbose: warnings.filterwarnings("ignore", category=torch.jit.TracerWarning) warnings.filterwarnings("ignore", category=UserWarning) - torch.onnx.export( - sam2_encoder, - image, - onnx_model_path, - export_params=True, - opset_version=17, - do_constant_folding=True, - input_names=["image"], - output_names=["image_features_0", "image_features_1", "image_embeddings"], - dynamic_axes=dynamic_axes, - ) + + if not dynamo: + torch.onnx.export( + sam2_encoder, + image, + onnx_model_path, + export_params=True, + opset_version=17, + do_constant_folding=True, + input_names=["image"], + output_names=["image_features_0", "image_features_1", "image_embeddings"], + dynamic_axes=dynamic_axes, + ) + else: + torch._dynamo.config.capture_scalar_outputs = True + ep = torch.export.export( + sam2_encoder, + args=(image,), + strict=False, + dynamic_shapes=[ + {0: torch.export.Dim.AUTO}, + ], + ) + + onnx_program = torch.onnx.export( + ep, + (), + opset_version=17, + input_names=["image"], + output_names=["image_features_0", "image_features_1", "image_embeddings"], + dynamo=True, + ) + onnx_program.optimize() + onnx_program.save(onnx_model_path + ".dynamo.onnx", external_data=False) + import onnx + + from onnxruntime.transformers.dynamo_onnx_helper import DynamoOnnxHelper + + onnx_model = onnx.load_model(onnx_model_path + ".dynamo.onnx", load_external_data=True) + if dynamic_batch_axes: + # Fix labels of dynamic axes since they can't be specified during Dynamo export currently + onnx_model.graph.input[0].type.tensor_type.shape.dim[0].dim_param = "batch_size" + for i in range(3): + onnx_model.graph.output[i].type.tensor_type.shape.dim[0].dim_param = "batch_size" + + onnx_model_helper = DynamoOnnxHelper(onnx_model) + onnx_model_helper.convert_constants_to_initializers() + if clear_dynamo_metadata: + onnx_model_helper.clear_metadata() + + import os + + if os.path.exists(onnx_model_path): + os.remove(onnx_model_path) + if os.path.exists(onnx_model_path + ".data"): + os.remove(onnx_model_path + ".data") + onnx_model_helper.model.save_model_to_file( + onnx_model_path, use_external_data_format=True, all_tensors_to_one_file=True, convert_attribute=True + ) print("encoder onnx model saved to", onnx_model_path) @@ -133,7 +183,7 @@ def test_image_encoder_onnx( onnx_model_path: str, dynamic_batch_axes=False, ): - ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=onnxruntime.get_available_providers()) + ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=["CPUExecutionProvider"]) model_inputs = ort_session.get_inputs() input_names = [model_inputs[i].name for i in range(len(model_inputs))] diff --git a/onnxruntime/python/tools/transformers/models/sam2/mask_decoder.py b/onnxruntime/python/tools/transformers/models/sam2/mask_decoder.py index 56473c002d4ae..fa83e2f666d06 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/mask_decoder.py +++ b/onnxruntime/python/tools/transformers/models/sam2/mask_decoder.py @@ -177,7 +177,7 @@ def test_mask_decoder_onnx( import onnxruntime - ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=onnxruntime.get_available_providers()) + ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=["CPUExecutionProvider"]) model_inputs = ort_session.get_inputs() input_names = [model_inputs[i].name for i in range(len(model_inputs))] diff --git a/onnxruntime/python/tools/transformers/models/sam2/prompt_encoder.py b/onnxruntime/python/tools/transformers/models/sam2/prompt_encoder.py index 883c51858346c..f25e6ff23324b 100644 --- a/onnxruntime/python/tools/transformers/models/sam2/prompt_encoder.py +++ b/onnxruntime/python/tools/transformers/models/sam2/prompt_encoder.py @@ -146,7 +146,7 @@ def test_prompt_encoder_onnx( import onnxruntime - ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=onnxruntime.get_available_providers()) + ort_session = onnxruntime.InferenceSession(onnx_model_path, providers=["CPUExecutionProvider"]) model_inputs = ort_session.get_inputs() input_names = [model_inputs[i].name for i in range(len(model_inputs))] From aafa8d170a134e0b807ce852ea6294444ba4fb06 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:03:21 -0800 Subject: [PATCH 042/266] [js/web] improve workaround for bundlers (#23902) ### Description This PR improves the workaround for bundlers in onnxruntime-web. Specifically, the following changes have been made: - Use [this workaround](https://github.com/xenova/onnxruntime/commit/9c50aa2c63bad4cb73ad77ff1c43e0c43da0907f) as suggested by @xenova in https://github.com/huggingface/transformers.js/pull/1161#issuecomment-2695785730 - Use `url > "file:" && url < "file;"` instead of `url.startsWith("file:")` to allow minifiers to remove dead code correctly. This change allows to remove unnecessary dependencies of file parsed from `new URL("ort.bundle.min.js", import.meta.url)` in Vite, and optimize code like `if("file://filepath.js".startsWith("file:")) {do_sth1(); } else {do_sth2();}` into `do_sth1()` for webpack/terser usages. Resolves https://github.com/huggingface/transformers.js/pull/1161 --- js/web/lib/wasm/proxy-wrapper.ts | 8 +++-- js/web/lib/wasm/wasm-utils-import.ts | 50 ++++++++++++++++++++++++++-- js/web/script/build.ts | 19 ++++++++--- js/web/test/e2e/exports/main.js | 11 +++++- js/web/test/e2e/exports/test.js | 22 ++++++++++++ 5 files changed, 100 insertions(+), 10 deletions(-) diff --git a/js/web/lib/wasm/proxy-wrapper.ts b/js/web/lib/wasm/proxy-wrapper.ts index 5d97bb83e3475..30b1f5101e5f2 100644 --- a/js/web/lib/wasm/proxy-wrapper.ts +++ b/js/web/lib/wasm/proxy-wrapper.ts @@ -12,7 +12,11 @@ import { } from './proxy-messages'; import * as core from './wasm-core-impl'; import { initializeWebAssembly } from './wasm-factory'; -import { importProxyWorker, inferWasmPathPrefixFromScriptSrc } from './wasm-utils-import'; +import { + importProxyWorker, + inferWasmPathPrefixFromScriptSrc, + isEsmImportMetaUrlHardcodedAsFileUri, +} from './wasm-utils-import'; const isProxy = (): boolean => !!env.wasm.proxy && typeof document !== 'undefined'; let proxyWorker: Worker | undefined; @@ -116,7 +120,7 @@ export const initializeWebAssemblyAndOrtRuntime = async (): Promise => { BUILD_DEFS.IS_ESM && BUILD_DEFS.ENABLE_BUNDLE_WASM_JS && !message.in!.wasm.wasmPaths && - (objectUrl || BUILD_DEFS.ESM_IMPORT_META_URL?.startsWith('file:')) + (objectUrl || isEsmImportMetaUrlHardcodedAsFileUri) ) { // for a build bundled the wasm JS, if either of the following conditions is met: // - the proxy worker is loaded from a blob URL diff --git a/js/web/lib/wasm/wasm-utils-import.ts b/js/web/lib/wasm/wasm-utils-import.ts index 871b575d71edc..a8e27f6f334bc 100644 --- a/js/web/lib/wasm/wasm-utils-import.ts +++ b/js/web/lib/wasm/wasm-utils-import.ts @@ -11,6 +11,39 @@ import { isNode } from './wasm-utils-env'; */ const origin = isNode || typeof location === 'undefined' ? undefined : location.origin; +/** + * Some bundlers (eg. Webpack) will rewrite `import.meta.url` to a file URL at compile time. + * + * This function checks if `import.meta.url` starts with `file:`, but using the `>` and `<` operators instead of + * `startsWith` function so that code minimizers can remove the dead code correctly. + * + * For example, if we use terser to minify the following code: + * ```js + * if ("file://hard-coded-filename".startsWith("file:")) { + * console.log(1) + * } else { + * console.log(2) + * } + * + * if ("file://hard-coded-filename" > "file:" && "file://hard-coded-filename" < "file;") { + * console.log(3) + * } else { + * console.log(4) + * } + * ``` + * + * The minified code will be: + * ```js + * "file://hard-coded-filename".startsWith("file:")?console.log(1):console.log(2),console.log(3); + * ``` + * + * (use Terser 5.39.0 with default options, https://try.terser.org/) + * + * @returns true if the import.meta.url is hardcoded as a file URI. + */ +export const isEsmImportMetaUrlHardcodedAsFileUri = + BUILD_DEFS.IS_ESM && BUILD_DEFS.ESM_IMPORT_META_URL! > 'file:' && BUILD_DEFS.ESM_IMPORT_META_URL! < 'file;'; + const getScriptSrc = (): string | undefined => { // if Nodejs, return undefined if (isNode) { @@ -26,9 +59,22 @@ const getScriptSrc = (): string | undefined => { // new URL('actual-bundle-name.js', import.meta.url).href // ``` // So that bundler can preprocess the URL correctly. - if (BUILD_DEFS.ESM_IMPORT_META_URL?.startsWith('file:')) { + if (isEsmImportMetaUrlHardcodedAsFileUri) { // if the rewritten URL is a relative path, we need to use the origin to resolve the URL. - return new URL(new URL(BUILD_DEFS.BUNDLE_FILENAME, BUILD_DEFS.ESM_IMPORT_META_URL).href, origin).href; + + // The following is a workaround for Vite. + // + // Vite uses a bundler(rollup/rolldown) that does not rewrite `import.meta.url` to a file URL. So in theory, this + // code path should not be executed in Vite. However, the bundler does not know it and it still try to load the + // following pattern: + // - `return new URL('filename', import.meta.url).href` + // + // By replacing the pattern above with the following code, we can skip the resource loading behavior: + // - `const URL2 = URL; return new URL2('filename', import.meta.url).href;` + // + // And it still works in Webpack. + const URL2 = URL; + return new URL(new URL2(BUILD_DEFS.BUNDLE_FILENAME, BUILD_DEFS.ESM_IMPORT_META_URL).href, origin).href; } return BUILD_DEFS.ESM_IMPORT_META_URL; diff --git a/js/web/script/build.ts b/js/web/script/build.ts index 6006de62b41b6..7966262631bbf 100644 --- a/js/web/script/build.ts +++ b/js/web/script/build.ts @@ -123,13 +123,17 @@ async function minifyWasmModuleJsForBrowser(filepath: string): Promise { // ``` // with: // ``` - // new Worker(import.meta.url.startsWith('file:') - // ? new URL(BUILD_DEFS.BUNDLE_FILENAME, import.meta.url) - // : new URL(import.meta.url), ... + // new Worker((() => { + // const URL2 = URL; + // return import.meta.url > 'file:' && import.meta.url < 'file;' + // ? new URL2(BUILD_DEFS.BUNDLE_FILENAME, import.meta.url) + // : new URL(import.meta.url); + // })(), ... // ``` // // NOTE: this is a workaround for some bundlers that does not support runtime import.meta.url. - // TODO: in emscripten 3.1.61+, need to update this code. + // + // Check more details in the comment of `isEsmImportMetaUrlHardcodedAsFileUri()` and `getScriptSrc()` in file `lib/wasm/wasm-utils-import.ts`. // First, check if there is exactly one occurrence of "new Worker(new URL(import.meta.url)". const matches = [...contents.matchAll(/new Worker\(new URL\(import\.meta\.url\),/g)]; @@ -142,7 +146,12 @@ async function minifyWasmModuleJsForBrowser(filepath: string): Promise { // Replace the only occurrence. contents = contents.replace( /new Worker\(new URL\(import\.meta\.url\),/, - `new Worker(import.meta.url.startsWith('file:')?new URL(BUILD_DEFS.BUNDLE_FILENAME, import.meta.url):new URL(import.meta.url),`, + `new Worker((() => { + const URL2 = URL; + return (import.meta.url > 'file:' && import.meta.url < 'file;') + ? new URL2(BUILD_DEFS.BUNDLE_FILENAME, import.meta.url) + : new URL(import.meta.url); + })(),`, ); // Use terser to minify the code with special configurations: diff --git a/js/web/test/e2e/exports/main.js b/js/web/test/e2e/exports/main.js index 8ed22a6784e7c..d8c7bbf69039f 100644 --- a/js/web/test/e2e/exports/main.js +++ b/js/web/test/e2e/exports/main.js @@ -3,7 +3,7 @@ 'use strict'; -const { runDevTest, runProdTest } = require('./test'); +const { runDevTest, runProdTest, verifyAssets } = require('./test'); const { installOrtPackages } = require('./utils'); /** @@ -29,5 +29,14 @@ module.exports = async function main(PRESERVE, PACKAGES_TO_INSTALL) { await runDevTest('vite-default', '\x1b[32m➜\x1b[39m \x1b[1mLocal\x1b[22m:', 5173); await runProdTest('vite-default', '\x1b[32m➜\x1b[39m \x1b[1mLocal\x1b[22m:', 4173); + + await verifyAssets('vite-default', async (cwd) => { + const globby = await import('globby'); + + return { + test: 'File "dist/assets/**/ort.*.mjs" should not exist', + success: globby.globbySync('dist/assets/**/ort.*.mjs', { cwd }).length === 0, + }; + }); } }; diff --git a/js/web/test/e2e/exports/test.js b/js/web/test/e2e/exports/test.js index 9c5ed745ab0b5..e2bcffea97519 100644 --- a/js/web/test/e2e/exports/test.js +++ b/js/web/test/e2e/exports/test.js @@ -121,7 +121,29 @@ async function runProdTest(testCaseName, ready, port) { await runTest(testCaseName, ['prod'], ready, 'npm run start', port); } +async function verifyAssets(testCaseName, testers) { + testers = Array.isArray(testers) ? testers : [testers]; + const wd = path.join(__dirname, 'testcases', testCaseName); + + console.log(`[${testCaseName}] Verifying assets...`); + + const testResults = []; + + try { + for (const tester of testers) { + testResults.push(await tester(wd)); + } + + if (testResults.some((r) => !r.success)) { + throw new Error(`[${testCaseName}] asset verification failed.`); + } + } finally { + console.log(`[${testCaseName}] asset verification result:`, testResults); + } +} + module.exports = { runDevTest, runProdTest, + verifyAssets, }; From d35db9b8fdae986a5ac8e894607350dee551568f Mon Sep 17 00:00:00 2001 From: Jianhui Dai Date: Thu, 6 Mar 2025 09:33:03 +0800 Subject: [PATCH 043/266] [webgpu] Restore MatMulNBits workgroup size for Phi-3.5 (#23349) ### Description This change restores the MatMulNBits workgroup size from (8, 8, 1) back to (16, 8, 1) to resolve a performance regression observed on Intel iGPUs during token generation (M=1). ### Motivation and Context As above. Signed-off-by: Jianhui Dai --- onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index 28d622b2c9c33..1534fd26d3ad9 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -884,7 +884,8 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context program.CacheHint("T_M" + std::to_string(tile_m) + "Subgroup" + std::to_string(use_subgroup)); } else if (block_size == 32) { components = 1; - constexpr uint32_t workgroup_size = 64; + // TODO: Tune the workgroup size when `M=1`. + constexpr uint32_t workgroup_size = 128; const uint32_t workgroup_y = N % 8 == 0 ? 8 : 1; const uint32_t workgroup_x = workgroup_size / workgroup_y; program.SetWorkgroupSize(workgroup_x, workgroup_y, 1); From 95225dda1ea382923577b00bfdc6a4df10f32ec7 Mon Sep 17 00:00:00 2001 From: xhcao Date: Thu, 6 Mar 2025 09:43:32 +0800 Subject: [PATCH 044/266] [webgpu] support Pad operator (#23141) ### Description ### Motivation and Context --- .../core/providers/webgpu/tensor/pad.cc | 261 ++++++++++++++++++ .../core/providers/webgpu/tensor/pad.h | 40 +++ .../webgpu/webgpu_execution_provider.cc | 16 +- 3 files changed, 311 insertions(+), 6 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/tensor/pad.cc create mode 100644 onnxruntime/core/providers/webgpu/tensor/pad.h diff --git a/onnxruntime/core/providers/webgpu/tensor/pad.cc b/onnxruntime/core/providers/webgpu/tensor/pad.cc new file mode 100644 index 0000000000000..9ee13aada67fe --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/pad.cc @@ -0,0 +1,261 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +#include "core/util/math.h" +#include "core/providers/webgpu/tensor/pad.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +namespace onnxruntime { +namespace webgpu { + +Status PadProgram::GenerateShaderCode(ShaderHelper& shader) const { + if (!dim_value_zero_) { + shader.AddInput("data", ShaderUsage::UseUniform | ShaderUsage::UseShapeAndStride); + } + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseShapeAndStride | ShaderUsage::UseValueTypeAlias); + + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size"); + std::string constant_value_str = std::string("let constant_value = ") + + (is_float16_ ? "bitcast>(uniforms.constant_value)[0];\n" : "bitcast(uniforms.constant_value);\n"); + if (dim_value_zero_) { + // Only Constant mode needs fill output if the one dim value or mores dims' values of input are zero. + shader.MainFunctionBody() << constant_value_str + << "output[global_idx] = constant_value;\n"; + return Status::OK(); + } + + shader.MainFunctionBody() << " let output_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var input_index = u32(0);\n" + << " var use_pad_value = false;\n" + << " var in_coord = i32(0);\n"; + + const int rank = output.Rank(); + std::string output_indices_str = "i32(" + GetElementAt("output_indices", "dim", rank) + ")"; + std::string lower_pads_str = GetElementAt("uniforms.lower_pads", "dim", rank); + std::string data_shape_str = "i32(" + GetElementAt("uniforms.data_shape", "dim", rank) + ")"; + std::string data_stride_str = rank == 1 ? "" : " * " + GetElementAt("uniforms.data_stride", "dim", rank - 1); + std::string begin_axis_statement = "in_coord = "; + std::string end_axis_statement = "in_coord = "; + std::string in_axis_statement = "in_coord = " + output_indices_str + " - " + lower_pads_str + ";\n"; + switch (mode_) { + case Mode::Constant: + begin_axis_statement = "use_pad_value = true;\n"; + end_axis_statement = "use_pad_value = true;\n"; + break; + case Mode::Edge: + begin_axis_statement += "0;\n"; + end_axis_statement += data_shape_str + " - 1;\n"; + break; + case Mode::Reflect: + begin_axis_statement += lower_pads_str + " - " + output_indices_str + ";\n"; + end_axis_statement += data_shape_str + " - 2 - (" + output_indices_str + + " - (" + lower_pads_str + " + " + data_shape_str + "));\n"; + break; + case Mode::Wrap: + begin_axis_statement += data_shape_str + " + " + output_indices_str + " - " + lower_pads_str + ";\n"; + end_axis_statement += output_indices_str + " - " + lower_pads_str + " - " + data_shape_str + ";\n"; + break; + default: + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported mode type: ", static_cast(mode_)); + } + + shader.MainFunctionBody() << " for (var dim = 0; dim < " << rank << " && !use_pad_value; dim++) {\n" + << " if (" << output_indices_str << " < " << lower_pads_str << ") {\n" + << " " << begin_axis_statement << " }\n" + << " else if (" << output_indices_str << " >= " << lower_pads_str << " + " << data_shape_str << ") {\n" + << " " << end_axis_statement << " }\n" + << " else {\n" + << " " << in_axis_statement << " }\n" + << " input_index += select(u32(in_coord)" << data_stride_str << ", u32(in_coord), dim == " << rank - 1 << ");\n" + << " }\n" + << " " << constant_value_str + << " " << output.SetByOffset("global_idx", "select(data[input_index], constant_value, use_pad_value)"); + + return Status::OK(); +} + +Status Pad::ComputeInternal(ComputeContext& context) const { + const Tensor* input_tensor = context.Input(0); + auto const& input_shape = input_tensor->Shape(); + size_t dimension_count = input_shape.NumDimensions(); + + const PadsVector* p_pads = &pads_; + const PadsVector* p_slices = &slices_; + + PadsVector pads; + PadsVector slices; + // kOnnxDomain Pad opset >= 11 (Or) kMsDomain opset == 1 + if (is_dynamic_) { + size_t data_rank = input_tensor->Shape().NumDimensions(); + + const Tensor* pads_tensor = context.Input(1); + auto pads_tensor_dims = pads_tensor->Shape().GetDims(); + ORT_ENFORCE(pads_tensor_dims.size() == 1 || (pads_tensor_dims.size() == 2 && pads_tensor_dims[0] == 1), + "Pads tensor should be a 1D tensor of shape [2 * num_axes] " + "or a 2D tensor of shape [1, 2 * num_axes]"); + + const auto pads_data = pads_tensor->DataAsSpan(); + + // Compute Pads by applying axes if specified otherwise copy the supplied pads. + PadBase::ComputePads(context.KernelContext(), data_rank, pads_data, pads); + + // Separate out any negative pads into the slices array + PadBase::SeparateNegativeToSlices(pads, slices); + + p_pads = &pads; + p_slices = &slices; + } + + auto output_dims(input_shape.AsShapeVector()); + ORT_ENFORCE(dimension_count * 2 == p_pads->size(), "'pads' attribute has wrong number of values"); + + // Calculate output dimensions, and handle any negative padding + std::vector lower_pads(dimension_count); + for (size_t i = 0; i < dimension_count; i++) { + int64_t lower_pad = (*p_pads)[i] + (*p_slices)[i]; + int64_t upper_pad = (*p_pads)[i + dimension_count] + (*p_slices)[i + dimension_count]; + lower_pads[i] = static_cast(lower_pad); + output_dims[i] += lower_pad + upper_pad; + } + TensorShape output_shape(output_dims); + + // special case when there is a dim value of 0 in the shape. behavior depends on mode + bool dim_value_zero = input_shape.Size() == 0; + if (dim_value_zero) { + ORT_RETURN_IF_ERROR(PadBase::HandleDimValueZero(mode_, input_shape, output_shape)); + } + + auto* output_tensor = context.Output(0, output_shape); + uint32_t output_size = gsl::narrow(output_shape.Size()); + if (output_size == 0) { + // Do not need to fill output, return + return Status::OK(); + } + + // Read constant value and bitcast to uint32. + uint32_t value_uint32 = 0; + const auto data_type = input_tensor->GetElementType(); + bool is_float16 = data_type == ONNX_NAMESPACE::TensorProto_DataType_FLOAT16; + const Tensor* value_tensor = context.Input(2); + if (!is_dynamic_) { + if (is_float16) { + uint16_t value = math::floatToHalf(value_); + std::memcpy(&value_uint32, &value, sizeof(value)); + } else { + value_uint32 = *reinterpret_cast(&value_); + } + } else if (value_tensor) { + ORT_ENFORCE(value_tensor->DataType() == input_tensor->DataType() && value_tensor->Shape().Size() == 1, + "Value tensor should be a 1D tensor of size 1 with the same type as that of the input tensor"); + switch (data_type) { + case ONNX_NAMESPACE::TensorProto_DataType_INT32: { + int32_t value = value_tensor->Data()[0]; + value_uint32 = *reinterpret_cast(&value); + } break; + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: { + float value = value_tensor->Data()[0]; + value_uint32 = *reinterpret_cast(&value); + } break; + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: { + uint16_t value = value_tensor->Data()[0].val; + std::memcpy(&value_uint32, &value, sizeof(value)); + } break; + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: { + value_uint32 = value_tensor->Data()[0]; + } break; + default: + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported input type: ", static_cast(data_type)); + } + } + + PadProgram program{mode_, dim_value_zero, is_float16}; + if (!dim_value_zero) { + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}); + } + program.AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .CacheHint(std::to_string(static_cast(mode_)), dim_value_zero) + .AddUniformVariables({{gsl::span(lower_pads.data(), lower_pads.size())}, {output_size}, {value_uint32}}); + + return context.RunProgram(program); +} + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Pad, + kOnnxDomain, + 2, 10, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Pad, + kOnnxDomain, + 11, 12, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Pad, + kOnnxDomain, + 13, 17, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Pad, + kOnnxDomain, + 18, 18, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Pad, + kOnnxDomain, + 19, 20, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Pad, + kOnnxDomain, + 21, 22, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); +ONNX_OPERATOR_KERNEL_EX( + Pad, + kOnnxDomain, + 23, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 1) + .InputMemoryType(OrtMemTypeCPUInput, 2) + .InputMemoryType(OrtMemTypeCPUInput, 3) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Pad); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/pad.h b/onnxruntime/core/providers/webgpu/tensor/pad.h new file mode 100644 index 0000000000000..58049ddb0e5ce --- /dev/null +++ b/onnxruntime/core/providers/webgpu/tensor/pad.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/cpu/tensor/padbase.h" + +namespace onnxruntime { +namespace webgpu { + +class PadProgram final : public Program { + public: + PadProgram(const Mode mode, bool dim_value_zero, bool is_float16) : Program{"Pad"}, + mode_{mode}, + dim_value_zero_{dim_value_zero}, + is_float16_{is_float16} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"lower_pads", ProgramUniformVariableDataType::Int32}, + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"constant_value", ProgramUniformVariableDataType::Uint32}); + + private: + Mode mode_; + bool dim_value_zero_; + bool is_float16_; +}; + +class Pad final : public PadBase, public WebGpuKernel { + public: + Pad(const OpKernelInfo& info) : PadBase(info), WebGpuKernel(info) {} + + Status ComputeInternal(ComputeContext& context) const override; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 4950d94dea4c4..a2b8709e0e075 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -363,7 +363,9 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxD class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, Pad); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 17, Pad); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 18, 18, Pad); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, Pad); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, 20, Pad); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, 22, Pad); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 23, Pad); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, If); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, If); @@ -685,11 +687,13 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, From b5242293475c944c2abae3fd5d96e1c1788054a7 Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Thu, 6 Mar 2025 14:33:07 +0800 Subject: [PATCH 045/266] [WebNN] Accept Float16Array for float16 data type if it is available (#23894) Float16Array is now shipping and WebNN Chromium implementation has accepted it. We should allow it in WebNN EP as well. --- js/web/lib/wasm/jsep/backend-webnn.ts | 3 ++- .../builders/impl/rotaryEmbedding_op_builder.cc | 14 +++++++++++--- .../core/providers/webnn/builders/model_builder.cc | 6 ++++-- .../core/providers/webnn/builders/model_builder.h | 10 ++++++++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/js/web/lib/wasm/jsep/backend-webnn.ts b/js/web/lib/wasm/jsep/backend-webnn.ts index 2b9a9208e2e53..55784ae13ad7a 100644 --- a/js/web/lib/wasm/jsep/backend-webnn.ts +++ b/js/web/lib/wasm/jsep/backend-webnn.ts @@ -314,7 +314,8 @@ export class WebNNBackend { bufferView = new Float32Array(buffer); break; case 'float16': - bufferView = new Uint16Array(buffer); + bufferView = + typeof Float16Array !== 'undefined' && Float16Array.from ? new Float16Array(buffer) : new Uint16Array(buffer); break; case 'int32': bufferView = new Int32Array(buffer); diff --git a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc index cbaff79f4fd4f..966deb14196dd 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc @@ -219,9 +219,17 @@ Status RotaryEmbeddingOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_build sign_buffer.set(0, -1.0f); sign_buffer.set(1, 1.0f); } else if (input_data_type == ONNX_NAMESPACE::TensorProto_DataType_FLOAT16) { - sign_buffer = emscripten::val::global("Uint16Array").new_(2); - sign_buffer.set(0, PackFloat32ToUint16AsFloat16(-1.0f)); - sign_buffer.set(1, PackFloat32ToUint16AsFloat16(1.0f)); + if (model_builder.IsFloat16ArrayAvailable()) { + // Float16Array is avaliable - use Float16Array. + sign_buffer = emscripten::val::global("Float16Array").new_(2); + sign_buffer.set(0, -1.0f); + sign_buffer.set(1, 1.0f); + } else { + // Float16Array is not available - use Uint16Array instead. + sign_buffer = emscripten::val::global("Uint16Array").new_(2); + sign_buffer.set(0, PackFloat32ToUint16AsFloat16(-1.0f)); + sign_buffer.set(1, PackFloat32ToUint16AsFloat16(1.0f)); + } } else { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported input data type: ", input_data_type); } diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index ace6519a1fc11..cf4ce216ed5b3 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -197,7 +197,8 @@ Status ModelBuilder::RegisterInitializers() { // Wasm memory grow will cause all array buffers reallocation, which will be treated as detached // buffers in JS side. Simply create a copy to fix it. - operand = wnn_builder_.call("constant", desc, view.call("slice")); + view = view.call("slice"); + operand = wnn_builder_.call("constant", desc, view["buffer"]); } } else { // TODO: support other type. @@ -350,7 +351,8 @@ Status ModelBuilder::AddOperandFromPersistMemoryBuffer( emscripten::val operand = emscripten::val::object(); // Wasm memory grow will cause all array buffers reallocation, which will be treated as detached // buffers in JS side. Simply create a copy to fix it. - operand = wnn_builder_.call("constant", desc, view.call("slice")); + view = view.call("slice"); + operand = wnn_builder_.call("constant", desc, view["buffer"]); AddOperand(name, operand); mem_persist_buffers_.push_back(std::move(persist_buffer)); diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.h b/onnxruntime/core/providers/webnn/builders/model_builder.h index 4e2d84f481df0..1e5f859506d6b 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.h +++ b/onnxruntime/core/providers/webnn/builders/model_builder.h @@ -30,6 +30,7 @@ class ModelBuilder { Status Compile(std::unique_ptr& model) ORT_MUST_USE_RESULT; // Accessors for members. + bool IsFloat16ArrayAvailable() const { return is_float16array_available_; } const GraphViewer& GetGraphViewer() const { return graph_viewer_; } InitializedTensorSet GetInitializerTensors(); @@ -68,6 +69,8 @@ class ModelBuilder { private: const GraphViewer& graph_viewer_; const logging::Logger& logger_; + const bool is_float16array_available_ = !emscripten::val::global("Float16Array").isUndefined() && + emscripten::val::global("Float16Array").hasOwnProperty("from"); emscripten::val wnn_context_ = emscripten::val::undefined(); emscripten::val wnn_builder_ = emscripten::val::undefined(); @@ -172,9 +175,12 @@ const emscripten::val& ModelBuilder::CreateOrGetConstant(const int32_t& data_typ } break; case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: - buffer = emscripten::val::global("Uint16Array").new_(num_elements); + buffer = is_float16array_available_ + ? emscripten::val::global("Float16Array").new_(num_elements) + : emscripten::val::global("Uint16Array").new_(num_elements); if (value) { - buffer.call("fill", emscripten::val(PackFloat32ToUint16AsFloat16(value))); + buffer.call("fill", + emscripten::val(is_float16array_available_ ? value : PackFloat32ToUint16AsFloat16(value))); } break; case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: From 996fffbeddf8a6402a15f1db9155d083ecdd1ba1 Mon Sep 17 00:00:00 2001 From: Mark Schofield Date: Thu, 6 Mar 2025 08:51:50 -0800 Subject: [PATCH 046/266] Ensure that the 'cmake_minimum_required' is version 3.5 or greater (#23888) ### Description CMake 4.0 release candidate 2.0 is available, and it cannot compile all of OnnxRuntime out-of-the-box. There's portions of the OnnxRuntime codebase that specify a `cmake_minimum_required` version of 3.0, and CMake 4.0 has removed support for compatibility with CMake < 3.5 - the following error is reported: ``` CMake Error at winml_sdk_helpers.cmake:4 (cmake_minimum_required): Compatibility with CMake < 3.5 has been removed from CMake. Update the VERSION argument value. Or, use the ... syntax to tell CMake that the project requires at least but has been updated to work with policies introduced by or earlier. Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to try configuring anyway. ``` Since CMake 3.5 appears to have shipped in 2016, it seems reasonable to set that as a minimum version to fix the error. The root CMakeLists.txt does ask for a minimum version of 3.28, so we could snap to that, but I'm still ramping up on the build, so wanted to propose a minimally sufficient fix. ### Motivation and Context Being able to build with the latest CMake - when it ships - reduces the barrier to entry to building OnnxRuntime, and allows the OnnxRuntime to leverage the latest and greatest tooling. --- cmake/nuget_helpers.cmake | 2 +- cmake/winml_sdk_helpers.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/nuget_helpers.cmake b/cmake/nuget_helpers.cmake index 22143ac422e9f..b066d1e9fb50e 100644 --- a/cmake/nuget_helpers.cmake +++ b/cmake/nuget_helpers.cmake @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) # Determines the version of a native nuget package from the root packages.config. # diff --git a/cmake/winml_sdk_helpers.cmake b/cmake/winml_sdk_helpers.cmake index 9241fcd060caf..ca657311b7f14 100644 --- a/cmake/winml_sdk_helpers.cmake +++ b/cmake/winml_sdk_helpers.cmake @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) # utility function(convert_forward_slashes_to_back input output) From 54b2d64c525ccac20f6ebd9ca20dfea0c8b75565 Mon Sep 17 00:00:00 2001 From: jiangzhaoming Date: Fri, 7 Mar 2025 00:53:23 +0800 Subject: [PATCH 047/266] WebGPU: Remove deprecated subgroups-f16 from WebGPU native and JS EP (#23898) This PR removes the deprecated subgroups-f16 from WebGPU native and JS EP, and also remove the unused deviceInfo in WebGPU JS EP. --- js/web/lib/wasm/jsep/backend-webgpu.ts | 28 +------------------ js/web/lib/wasm/jsep/init.ts | 10 +------ .../lib/wasm/jsep/webgpu/program-manager.ts | 1 - js/web/lib/wasm/jsep/webgpu/types.ts | 10 ------- .../core/providers/webgpu/shader_helper.cc | 3 -- .../core/providers/webgpu/webgpu_context.cc | 3 +- 6 files changed, 3 insertions(+), 52 deletions(-) diff --git a/js/web/lib/wasm/jsep/backend-webgpu.ts b/js/web/lib/wasm/jsep/backend-webgpu.ts index a0010df4643a4..413e89111740e 100644 --- a/js/web/lib/wasm/jsep/backend-webgpu.ts +++ b/js/web/lib/wasm/jsep/backend-webgpu.ts @@ -13,7 +13,6 @@ import { ProgramManager } from './webgpu/program-manager'; import { AdapterInfo, ComputeContext, - DeviceInfo, GpuArchitecture, GpuData, GpuVendor, @@ -135,26 +134,6 @@ class AdapterInfoImpl implements AdapterInfo { } } -class DeviceInfoImpl implements DeviceInfo { - readonly subgroupsSupported: boolean; - readonly subgroupsF16Supported: boolean; - readonly subgroupSizeRange?: readonly [number, number]; - - constructor(device: GPUDevice) { - this.subgroupsSupported = device.features.has('subgroups' as GPUFeatureName); - this.subgroupsF16Supported = device.features.has('subgroups' as GPUFeatureName); - // Currently subgroups feature is still experimental and size attributes are not in the WebGPU IDL, so we have to - // workaround the IDL type checks. - // TODO: clean this after subgroups feature is settled in IDL. - const deviceSubgroupsLimits = device.limits as { minSubgroupSize?: number; maxSubgroupSize?: number }; - if (!this.subgroupsSupported || !deviceSubgroupsLimits.minSubgroupSize || !deviceSubgroupsLimits.maxSubgroupSize) { - this.subgroupSizeRange = undefined; - } else { - this.subgroupSizeRange = [deviceSubgroupsLimits.minSubgroupSize, deviceSubgroupsLimits.maxSubgroupSize]; - } - } -} - /** * this class is designed to store status and being used as a singleton for JSEP. It will be passed to jsepInit() as * the first parameter so that it is stored for future use. @@ -162,7 +141,6 @@ class DeviceInfoImpl implements DeviceInfo { export class WebGpuBackend { adapterInfo: AdapterInfoImpl; device: GPUDevice; - deviceInfo: DeviceInfoImpl; /** * an instance of GpuDataManager to manage a GpuDataId -> GpuBuffer mapping */ @@ -274,13 +252,9 @@ export class WebGpuBackend { } requireFeatureIfAvailable('shader-f16'); // Try subgroups - if (requireFeatureIfAvailable('subgroups' as GPUFeatureName)) { - // If subgroups feature is available, also try subgroups-f16 - requireFeatureIfAvailable('subgroups-f16' as GPUFeatureName); - } + requireFeatureIfAvailable('subgroups' as GPUFeatureName); this.device = await adapter.requestDevice(deviceDescriptor); - this.deviceInfo = new DeviceInfoImpl(this.device); this.adapterInfo = new AdapterInfoImpl(adapter.info || (await adapter.requestAdapterInfo())); this.gpuDataManager = createGpuDataManager(this); this.programManager = new ProgramManager(this); diff --git a/js/web/lib/wasm/jsep/init.ts b/js/web/lib/wasm/jsep/init.ts index b4071eae51c8f..6c2be3aa0cfe1 100644 --- a/js/web/lib/wasm/jsep/init.ts +++ b/js/web/lib/wasm/jsep/init.ts @@ -11,13 +11,7 @@ import { WebGpuBackend } from './backend-webgpu'; import { LOG_DEBUG } from './log'; import { TensorView } from './tensor-view'; import { ShapeUtil } from './util'; -import { - AdapterInfo, - ComputeContext, - ComputeContextInputsOutputsMapping, - DeviceInfo, - ProgramInfo, -} from './webgpu/types'; +import { AdapterInfo, ComputeContext, ComputeContextInputsOutputsMapping, ProgramInfo } from './webgpu/types'; import { WebNNBackend } from './backend-webnn'; /* eslint-disable no-bitwise */ @@ -76,7 +70,6 @@ class TensorViewImpl implements TensorView { class ComputeContextImpl implements ComputeContext { readonly adapterInfo: AdapterInfo; - readonly deviceInfo: DeviceInfo; readonly opKernelContext: number; readonly inputs: readonly TensorView[]; readonly outputCount: number; @@ -94,7 +87,6 @@ class ComputeContextImpl implements ComputeContext { contextDataOffset: number, ) { this.adapterInfo = backend.adapterInfo; - this.deviceInfo = backend.deviceInfo; // extract context data const ptrSize = module.PTR_SIZE; diff --git a/js/web/lib/wasm/jsep/webgpu/program-manager.ts b/js/web/lib/wasm/jsep/webgpu/program-manager.ts index 2c5180c5db3ee..18d505f57655a 100644 --- a/js/web/lib/wasm/jsep/webgpu/program-manager.ts +++ b/js/web/lib/wasm/jsep/webgpu/program-manager.ts @@ -99,7 +99,6 @@ export class ProgramManager { const extensionsInfo: Array<{ feature: GPUFeatureName; extension: string }> = [ { feature: 'shader-f16', extension: 'f16' }, { feature: 'subgroups' as GPUFeatureName, extension: 'subgroups' }, - { feature: 'subgroups-f16' as GPUFeatureName, extension: 'subgroups_f16' }, ]; extensionsInfo.forEach((info) => { if (device.features.has(info.feature)) { diff --git a/js/web/lib/wasm/jsep/webgpu/types.ts b/js/web/lib/wasm/jsep/webgpu/types.ts index 9321ac170d036..f3cfc6cb98cae 100644 --- a/js/web/lib/wasm/jsep/webgpu/types.ts +++ b/js/web/lib/wasm/jsep/webgpu/types.ts @@ -21,11 +21,6 @@ export interface AdapterInfo { isArchitecture: (architecture: GpuArchitecture) => boolean; isVendor: (vendor: GpuVendor) => boolean; } -export interface DeviceInfo { - readonly subgroupsSupported: boolean; - readonly subgroupsF16Supported: boolean; - readonly subgroupSizeRange?: readonly [number, number]; -} export interface GpuData { type: GpuDataType; @@ -165,11 +160,6 @@ export interface ComputeContext { */ readonly adapterInfo: AdapterInfo; - /** - * gpu device info - */ - readonly deviceInfo: DeviceInfo; - /** * stores the pointer to OpKernelContext */ diff --git a/onnxruntime/core/providers/webgpu/shader_helper.cc b/onnxruntime/core/providers/webgpu/shader_helper.cc index 8fccbacac903b..19cab9b178b1f 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.cc +++ b/onnxruntime/core/providers/webgpu/shader_helper.cc @@ -345,9 +345,6 @@ Status ShaderHelper::GenerateSourceCode(std::string& code, std::vector& sha })) { ORT_RETURN_IF_NOT(device_.HasFeature(wgpu::FeatureName::ShaderF16), "Program ", program_.Name(), " requires f16 but the device does not support it."); ss << "enable f16;\n"; - if (device_.HasFeature(wgpu::FeatureName::SubgroupsF16)) { - ss << "enable subgroups_f16;\n"; - } } if (device_.HasFeature(wgpu::FeatureName::Subgroups)) { ss << "enable subgroups;\n"; diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 2bd547f406226..21e5e55588a2e 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -489,8 +489,7 @@ std::vector WebGpuContext::GetAvailableRequiredFeatures(const #endif wgpu::FeatureName::TimestampQuery, wgpu::FeatureName::ShaderF16, - wgpu::FeatureName::Subgroups, - wgpu::FeatureName::SubgroupsF16}; + wgpu::FeatureName::Subgroups}; for (auto feature : features) { if (adapter.HasFeature(feature)) { required_features.push_back(feature); From ccf8fdd9ea8b0df0eb4b092323479ce8a47be161 Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Thu, 6 Mar 2025 09:09:53 -0800 Subject: [PATCH 048/266] [JSEP/WebGPU] Fixed error in softmax dispatch. (#23906) ### Description Fixed an error softmax dispatch ### Motivation and Context Produce expected results for LlaMA model --- js/web/lib/wasm/jsep/webgpu/ops/attention.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts index 6a78c8ae3b190..6a8dffb73fa08 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts @@ -433,7 +433,7 @@ const createInPlaceSoftmaxProgramInfo = ( getShaderSource, getRunData: () => ({ outputs: [], - dispatchGroup: { x: Math.ceil(totalSequenceLength / WG), y: sequenceLength, z: batchSize * numHeads }, + dispatchGroup: { x: 1, y: sequenceLength, z: batchSize * numHeads }, programUniforms, }), }; From 101353cf5e54bdab057bf759befc8440465a1339 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:23:01 -0800 Subject: [PATCH 049/266] enable WebGPU EP in WebAssembly build (#23913) ### Description This PR is the first step for migrating the webgpu backend of onnxruntime-web from JSEP based to WebGPU EP based. In this change, we enable building WebGPU EP in a wasm build (ie. `--build_wasm` `--use_webgpu` `--use_jsep`). However, the old build flags should still keep previous behavior. --- .../external/onnxruntime_external_deps.cmake | 24 +- cmake/onnxruntime_webassembly.cmake | 37 ++- cmake/patches/dawn/dawn.patch | 113 ++++++- js/build_webgpu.bat | 79 +++++ js/web/lib/build-def.d.ts | 7 + js/web/lib/wasm/jsep/init.ts | 136 ++++---- js/web/lib/wasm/session-options.ts | 116 +++++-- js/web/lib/wasm/wasm-core-impl.ts | 97 ++++-- js/web/lib/wasm/wasm-types.ts | 68 +++- js/web/script/build.ts | 17 +- .../core/framework/external_data_loader.cc | 7 +- .../core/framework/external_data_loader.h | 2 +- .../providers/webgpu/external_data_loader.cc | 40 +++ .../providers/webgpu/external_data_loader.h | 30 ++ onnxruntime/core/providers/webgpu/program.cc | 20 ++ onnxruntime/core/providers/webgpu/program.h | 1 + .../core/providers/webgpu/webgpu_context.cc | 53 +-- .../webgpu/webgpu_execution_provider.cc | 7 + .../webgpu/webgpu_execution_provider.h | 3 + .../webgpu/webgpu_provider_factory.cc | 6 + onnxruntime/wasm/api.cc | 26 +- onnxruntime/wasm/api.h | 24 +- onnxruntime/wasm/js_post_js.js | 2 - onnxruntime/wasm/js_post_js_64.js | 2 - onnxruntime/wasm/post-webgpu.js | 261 +++++++++++++++ onnxruntime/wasm/pre-async.js | 132 ++++++++ onnxruntime/wasm/pre-jsep.js | 308 ++++++------------ onnxruntime/wasm/pre.js | 15 +- tools/ci_build/build.py | 7 +- 29 files changed, 1245 insertions(+), 395 deletions(-) create mode 100644 js/build_webgpu.bat create mode 100644 onnxruntime/core/providers/webgpu/external_data_loader.cc create mode 100644 onnxruntime/core/providers/webgpu/external_data_loader.h create mode 100644 onnxruntime/wasm/post-webgpu.js create mode 100644 onnxruntime/wasm/pre-async.js diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index a579badee666c..2ab9fc129a90d 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -725,7 +725,29 @@ if (onnxruntime_USE_WEBGPU) # # if we need to apply patches in the future, we can uncomment the following line. # # The dawn.patch contains the following changes: - # - https://dawn-review.googlesource.com/c/dawn/+/225514 + # + # - (public) CMake fix to support Emscripten v4.0.3+ + # This change allows Dawn to find the file "gen_struct_info.py" in the correct location. + # https://dawn-review.googlesource.com/c/dawn/+/225514 + # + # - (public) Fix emwgpu C++ implementation for buffer destroy + # In native implementation, wgpuBufferRelease will trigger the buffer destroy (if refcount decreased to 0). But + # in emwgpu implementation, the buffer destroy won't happen. This change fixes the bug. + # https://dawn-review.googlesource.com/c/dawn/+/226315 + # + # - (private) Allow "external" buffer in emwgpu C++ implementation + # This change allows WGPUBufferImpl to destroy the buffer when the refcount decreased to 0 only for non-external + # buffer. + # "external buffer" means the GPUBuffer instance created in JavaScript and imported to C++ by `importJsBuffer`. + # + # - (private) Remove hard-coded CMAKE_OSX_DEPLOYMENT_TARGET in Dawn's CMake files + # https://github.com/microsoft/onnxruntime/pull/23729 + # + # - (private) Fix external ref count for "external" device in emwgpu C++ implementation + # This change fixes the incorrect external ref count for class WGPUDeviceImpl when used with "external" device. + # "external device" means the GPUDevice instance created in JavaScript and imported to C++ by `importJsDevice`. + # + # PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn.patch EXCLUDE_FROM_ALL ) diff --git a/cmake/onnxruntime_webassembly.cmake b/cmake/onnxruntime_webassembly.cmake index 8106e46ccf580..f3afaf7033fd1 100644 --- a/cmake/onnxruntime_webassembly.cmake +++ b/cmake/onnxruntime_webassembly.cmake @@ -211,10 +211,14 @@ else() target_link_libraries(onnxruntime_webassembly PRIVATE tensorboard) endif() + set(onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/pre.js") + + set(EXPORTED_FUNCTIONS "_malloc,_free") if (onnxruntime_USE_JSEP) - set(EXPORTED_FUNCTIONS "_malloc,_free,_JsepOutput,_JsepGetNodeName") - else() - set(EXPORTED_FUNCTIONS "_malloc,_free") + string(APPEND EXPORTED_FUNCTIONS ",_JsepOutput,_JsepGetNodeName") + endif() + if (onnxruntime_USE_WEBGPU) + string(APPEND EXPORTED_FUNCTIONS ",_wgpuBufferRelease,_wgpuCreateInstance") endif() if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) @@ -312,13 +316,15 @@ else() target_compile_options(noexcep_operators PRIVATE ${SMEMORY_FLAG} -Wno-experimental) endif() target_link_options(onnxruntime_webassembly PRIVATE - --post-js "${ONNXRUNTIME_ROOT}/wasm/js_post_js_64.js" + "SHELL:--post-js \"${ONNXRUNTIME_ROOT}/wasm/js_post_js_64.js\"" ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/js_post_js_64.js") else () set(MAXIMUM_MEMORY "4294967296") target_link_options(onnxruntime_webassembly PRIVATE - --post-js "${ONNXRUNTIME_ROOT}/wasm/js_post_js.js" + "SHELL:--post-js \"${ONNXRUNTIME_ROOT}/wasm/js_post_js.js\"" ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/js_post_js.js") endif () target_link_options(onnxruntime_webassembly PRIVATE @@ -372,7 +378,6 @@ jsepDownload:_pp_") "SHELL:-s SIGNATURE_CONVERSIONS='${SIGNATURE_CONVERSIONS}'" ) endif () - set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre.js) if (onnxruntime_USE_JSEP) # NOTE: "-s ASYNCIFY=1" is required for JSEP to work with WebGPU @@ -382,10 +387,8 @@ jsepDownload:_pp_") target_compile_definitions(onnxruntime_webassembly PRIVATE USE_JSEP=1) target_link_options(onnxruntime_webassembly PRIVATE "SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js\"" - "SHELL:-s ASYNCIFY=1" - "SHELL:-s ASYNCIFY_STACK_SIZE=65536" ) - set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js") if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) target_link_options(onnxruntime_webassembly PRIVATE @@ -397,6 +400,20 @@ jsepDownload:_pp_") if (onnxruntime_USE_WEBGPU) target_compile_definitions(onnxruntime_webassembly PRIVATE USE_WEBGPU=1) + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:--post-js \"${ONNXRUNTIME_ROOT}/wasm/post-webgpu.js\"" + ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/post-webgpu.js") + endif() + + if (onnxruntime_USE_JSEP OR onnxruntime_USE_WEBGPU OR onnxruntime_USE_WEBNN) + # if any of the above is enabled, we need to use the asyncify library + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-async.js\"" + "SHELL:-s ASYNCIFY=1" + "SHELL:-s ASYNCIFY_STACK_SIZE=65536" + ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/pre-async.js") endif() if (onnxruntime_EMSCRIPTEN_SETTINGS) @@ -458,6 +475,8 @@ jsepDownload:_pp_") ) endif() + set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS "${onnxruntime_webassembly_script_deps}") + set(target_name_list ort) if (onnxruntime_ENABLE_TRAINING_APIS) diff --git a/cmake/patches/dawn/dawn.patch b/cmake/patches/dawn/dawn.patch index 2f85d5ab473b5..b578b858eac59 100644 --- a/cmake/patches/dawn/dawn.patch +++ b/cmake/patches/dawn/dawn.patch @@ -18,7 +18,7 @@ index 6e8ae37593..633af91eef 100644 @@ -77,9 +77,17 @@ if (${DAWN_ENABLE_EMSCRIPTEN}) "${arg_UNPARSED_ARGUMENTS}") endif() - + + # since Emscripten 4.0.3, file gen_struct_info.py is moved to outside of directory maint. + if (EXISTS "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/gen_struct_info.py") + set(EM_GEN_STRUCT_INFO_SCRIPT "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/gen_struct_info.py") @@ -34,3 +34,114 @@ index 6e8ae37593..633af91eef 100644 -q "${EM_BUILD_GEN_DIR}/struct_info_webgpu.json" "-I=${EM_BUILD_GEN_DIR}/include" +diff --git a/src/emdawnwebgpu/README.md b/src/emdawnwebgpu/README.md +index efd6491cd6..8ebc5d28b6 100644 +--- a/src/emdawnwebgpu/README.md ++++ b/src/emdawnwebgpu/README.md +@@ -56,7 +56,7 @@ Set up the build directory using emcmake + mkdir out/cmake-wasm + cd out/cmake-wasm + +-# Make sure the path is to the source checkout of Emscripten, not emsdk's release. ++# If using Emscripten v4.0.2 or lower, make sure the path is to the source checkout of Emscripten, not emsdk's release. + emcmake cmake -GNinja -DDAWN_EMSCRIPTEN_TOOLCHAIN="path/to/emscripten" ../.. + + ninja +diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp +index f1c5a7d50e..16f2495712 100644 +--- a/third_party/emdawnwebgpu/webgpu.cpp ++++ b/third_party/emdawnwebgpu/webgpu.cpp +@@ -131,7 +131,6 @@ class RefCounted : NonMovable { + bool Release() { + if (mRefCount.fetch_sub(1u, std::memory_order_release) == 1u) { + std::atomic_thread_fence(std::memory_order_acquire); +- emwgpuDelete(this); + return true; + } + return false; +@@ -234,6 +233,7 @@ class Ref { + static void Release(T value) { + if (value != nullptr && value->RefCounted::Release()) { + delete value; ++ emwgpuDelete(value); + } + } + +@@ -641,7 +641,8 @@ struct WGPUAdapterImpl final : public EventSource, public RefCounted { + struct WGPUBufferImpl final : public EventSource, + public RefCountedWithExternalCount { + public: +- WGPUBufferImpl(const EventSource* source, bool mappedAtCreation); ++ WGPUBufferImpl(const EventSource* source, bool mappedAtCreation, bool isExternal); ++ ~WGPUBufferImpl(); + + void Destroy(); + const void* GetConstMappedRange(size_t offset, size_t size); +@@ -671,6 +672,7 @@ struct WGPUBufferImpl final : public EventSource, + }; + MapRequest mPendingMapRequest; + WGPUBufferMapState mMapState; ++ bool mIsExternal; + }; + + struct WGPUQueueImpl final : public EventSource, public RefCounted { +@@ -1164,11 +1166,15 @@ WGPUAdapter emwgpuCreateAdapter(const EventSource* source) { + + WGPUBuffer emwgpuCreateBuffer(const EventSource* source, + bool mappedAtCreation = false) { +- return new WGPUBufferImpl(source, mappedAtCreation); ++ return new WGPUBufferImpl(source, mappedAtCreation, true); + } + + WGPUDevice emwgpuCreateDevice(const EventSource* source, WGPUQueue queue) { +- return new WGPUDeviceImpl(source, queue); ++ // This function is only called from JS via `importJsDevice()`, which ++ // needs to increment the external ref count to fix the behavior. ++ WGPUDeviceImpl* device = new WGPUDeviceImpl(source, queue); ++ device->AddExternalRef(); ++ return device; + } + + WGPUQueue emwgpuCreateQueue(const EventSource* source) { +@@ -1275,15 +1281,22 @@ WGPUAdapterImpl::WGPUAdapterImpl(const EventSource* source) + // WGPUBuffer implementations. + // ---------------------------------------------------------------------------- + +-WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, bool mappedAtCreation) ++WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, bool mappedAtCreation, bool isExternal) + : EventSource(source), + mMapState(mappedAtCreation ? WGPUBufferMapState_Mapped +- : WGPUBufferMapState_Unmapped) { ++ : WGPUBufferMapState_Unmapped), ++ mIsExternal(isExternal) { + if (mappedAtCreation) { + mPendingMapRequest = {kNullFutureId, WGPUMapMode_Write}; + } + } + ++WGPUBufferImpl::~WGPUBufferImpl() { ++ if (!mIsExternal) { ++ Destroy(); ++ } ++} ++ + void WGPUBufferImpl::Destroy() { + emwgpuBufferDestroy(this); + AbortPendingMap("Buffer was destroyed before mapping was resolved."); +@@ -1504,6 +1517,7 @@ WGPUFuture WGPUShaderModuleImpl::GetCompilationInfo( + void wgpu##Name##Release(WGPU##Name o) { \ + if (o->Release()) { \ + delete o; \ ++ emwgpuDelete(o); \ + } \ + } + WGPU_OBJECTS(DEFINE_WGPU_DEFAULT_ADDREF_RELEASE) +@@ -1638,7 +1652,7 @@ void wgpuBufferUnmap(WGPUBuffer buffer) { + + WGPUBuffer wgpuDeviceCreateBuffer(WGPUDevice device, + const WGPUBufferDescriptor* descriptor) { +- WGPUBuffer buffer = new WGPUBufferImpl(device, descriptor->mappedAtCreation); ++ WGPUBuffer buffer = new WGPUBufferImpl(device, descriptor->mappedAtCreation, false); + emwgpuDeviceCreateBuffer(device, descriptor, buffer); + return buffer; + } diff --git a/js/build_webgpu.bat b/js/build_webgpu.bat new file mode 100644 index 0000000000000..95413509e701d --- /dev/null +++ b/js/build_webgpu.bat @@ -0,0 +1,79 @@ +@echo off + +rem build_webgpu.bat --- build onnxruntime-web with WebGPU EP +rem +rem Usage: +rem build_webgpu.bat config [clean] +rem +rem Options: +rem config Build configuration, "d" or "r" +rem clean Perform a clean build, "clean" or empty + +setlocal enabledelayedexpansion + +set ROOT=%~dp0..\ +set BUILD_DIR=%ROOT%build_webgpu + +:arg1 +if ["%~1"]==["d"] ( + set CONFIG=Debug + set CONFIG_EXTRA_FLAG= + @rem --enable_wasm_profiling --wasm_run_tests_in_browser + @rem --cmake_extra_defines onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL=1 + @rem --enable_wasm_debug_info + goto :arg2 +) +if ["%~1"]==["r"] ( + set CONFIG=Release + set CONFIG_EXTRA_FLAG= + @rem --enable_wasm_api_exception_catching --disable_rtti + goto :arg2 +) +echo Invalid configuration "%~1", must be "d"(Debug) or "r"(Release) +exit /b 1 + +:arg2 +if ["%~2"]==["clean"] ( + goto :clean +) +if not exist "%ROOT%js\web\dist" ( + goto :npm_ci +) + +goto :build_wasm + +:clean +if exist "%BUILD_DIR%" ( + rd /s /q %BUILD_DIR% +) + +pushd %ROOT% +git submodule sync --recursive +git submodule update --init --recursive +popd + +:npm_ci +pushd %ROOT%js +call npm ci +popd +pushd %ROOT%js\common +call npm ci +popd +pushd %ROOT%js\web +call npm ci +call npm run pull:wasm +popd + +:build_wasm + +set PATH=C:\Program Files\Git\usr\bin;%PATH% + +call %ROOT%build.bat --config %CONFIG% %CONFIG_EXTRA_FLAG% --skip_submodule_sync --build_wasm --target onnxruntime_webassembly --skip_tests^ + --enable_wasm_simd --enable_wasm_threads --use_jsep --use_webnn --use_webgpu --build_dir %BUILD_DIR% + +IF NOT "%ERRORLEVEL%" == "0" ( + exit /b %ERRORLEVEL% +) + +copy /Y %BUILD_DIR%\%CONFIG%\ort-wasm-simd-threaded.jsep.wasm %ROOT%js\web\dist\ +copy /Y %BUILD_DIR%\%CONFIG%\ort-wasm-simd-threaded.jsep.mjs %ROOT%js\web\dist\ diff --git a/js/web/lib/build-def.d.ts b/js/web/lib/build-def.d.ts index 59f64a3179605..83a52ebaefe05 100644 --- a/js/web/lib/build-def.d.ts +++ b/js/web/lib/build-def.d.ts @@ -40,6 +40,13 @@ interface BuildDefinitions { */ readonly ENABLE_BUNDLE_WASM_JS: boolean; + /** + * defines whether to use WebGPU EP instead of JSEP for WebGPU backend. + * + * This flag requires the corresponding WebAssembly artifact to be built with `--use_webgpu` flag. + */ + readonly USE_WEBGPU_EP: boolean; + // #endregion // #region Build definitions for ESM diff --git a/js/web/lib/wasm/jsep/init.ts b/js/web/lib/wasm/jsep/init.ts index 6c2be3aa0cfe1..8ab6b054bf8a7 100644 --- a/js/web/lib/wasm/jsep/init.ts +++ b/js/web/lib/wasm/jsep/init.ts @@ -1,17 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { Env } from 'onnxruntime-common'; +import type { Env } from 'onnxruntime-common'; import { calculateTensorSizeInBytes, DataType } from '../wasm-common'; import type { OrtWasmModule } from '../wasm-types'; -import { WebGpuBackend } from './backend-webgpu'; +import type { WebGpuBackend } from './backend-webgpu'; import { LOG_DEBUG } from './log'; -import { TensorView } from './tensor-view'; +import type { TensorView } from './tensor-view'; import { ShapeUtil } from './util'; -import { AdapterInfo, ComputeContext, ComputeContextInputsOutputsMapping, ProgramInfo } from './webgpu/types'; +import type { AdapterInfo, ComputeContext, ComputeContextInputsOutputsMapping, ProgramInfo } from './webgpu/types'; import { WebNNBackend } from './backend-webnn'; /* eslint-disable no-bitwise */ @@ -197,79 +197,83 @@ export const init = async ( } if (name === 'webgpu') { - const backend = new WebGpuBackend(); - await backend.initialize(env, gpuAdapter!); + if (!BUILD_DEFS.USE_WEBGPU_EP) { + // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires + const webGpuBackendImpl = require('./backend-webgpu').WebGpuBackend; + const backend = new webGpuBackendImpl(); + await backend.initialize(env, gpuAdapter!); - jsepInit('webgpu', [ - // backend - backend, + jsepInit('webgpu', [ + // backend + backend, + + // jsepAlloc() + (size: number) => backend.alloc(Number(size)), - // jsepAlloc() - (size: number) => backend.alloc(Number(size)), + // jsepFree() + (ptr: number) => backend.free(ptr), - // jsepFree() - (ptr: number) => backend.free(ptr), + // jsepCopy(src, dst, size, isSourceGpu) + (src: number, dst: number, size: number, isSourceGpu = false) => { + if (isSourceGpu) { + LOG_DEBUG( + 'verbose', + () => `[WebGPU] jsepCopyGpuToGpu: src=${Number(src)}, dst=${Number(dst)}, size=${Number(size)}`, + ); + backend.memcpy(Number(src), Number(dst)); + } else { + LOG_DEBUG( + 'verbose', + () => + `[WebGPU] jsepCopyCpuToGpu: dataOffset=${Number(src)}, gpuDataId=${Number(dst)}, size=${Number(size)}`, + ); + const data = module.HEAPU8.subarray(Number(src >>> 0), Number(src >>> 0) + Number(size)); + backend.upload(Number(dst), data); + } + }, - // jsepCopy(src, dst, size, isSourceGpu) - (src: number, dst: number, size: number, isSourceGpu = false) => { - if (isSourceGpu) { + // jsepCopyAsync(src, dst, size) + async (gpuDataId: number, dataOffset: number, size: number): Promise => { LOG_DEBUG( 'verbose', - () => `[WebGPU] jsepCopyGpuToGpu: src=${Number(src)}, dst=${Number(dst)}, size=${Number(size)}`, + () => `[WebGPU] jsepCopyGpuToCpu: gpuDataId=${gpuDataId}, dataOffset=${dataOffset}, size=${size}`, ); - backend.memcpy(Number(src), Number(dst)); - } else { - LOG_DEBUG( - 'verbose', - () => - `[WebGPU] jsepCopyCpuToGpu: dataOffset=${Number(src)}, gpuDataId=${Number(dst)}, size=${Number(size)}`, - ); - const data = module.HEAPU8.subarray(Number(src >>> 0), Number(src >>> 0) + Number(size)); - backend.upload(Number(dst), data); - } - }, - // jsepCopyAsync(src, dst, size) - async (gpuDataId: number, dataOffset: number, size: number): Promise => { - LOG_DEBUG( - 'verbose', - () => `[WebGPU] jsepCopyGpuToCpu: gpuDataId=${gpuDataId}, dataOffset=${dataOffset}, size=${size}`, - ); - - await backend.download(Number(gpuDataId), () => - module.HEAPU8.subarray(Number(dataOffset) >>> 0, Number(dataOffset + size) >>> 0), - ); - }, + await backend.download(Number(gpuDataId), () => + module.HEAPU8.subarray(Number(dataOffset) >>> 0, Number(dataOffset + size) >>> 0), + ); + }, - // jsepCreateKernel - (kernelType: string, kernelId: number, attribute: unknown) => - backend.createKernel( - kernelType, - Number(kernelId), - attribute, - module.UTF8ToString(module._JsepGetNodeName!(Number(kernelId))), - ), + // jsepCreateKernel + (kernelType: string, kernelId: number, attribute: unknown) => + backend.createKernel( + kernelType, + Number(kernelId), + attribute, + module.UTF8ToString(module._JsepGetNodeName!(Number(kernelId))), + ), - // jsepReleaseKernel - (kernel: number) => backend.releaseKernel(kernel), + // jsepReleaseKernel + (kernel: number) => backend.releaseKernel(kernel), - // jsepRun - (kernel: number, contextDataOffset: number, sessionHandle: number, errors: Array>) => { - LOG_DEBUG( - 'verbose', - () => - `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${contextDataOffset}`, - ); - const context = new ComputeContextImpl(module, backend, Number(contextDataOffset)); - return backend.computeKernel(Number(kernel), context, errors); - }, - // jsepCaptureBegin - () => backend.captureBegin(), - // jsepCaptureEnd - () => backend.captureEnd(), - // jsepReplay - () => backend.replay(), - ]); + // jsepRun + (kernel: number, contextDataOffset: number, sessionHandle: number, errors: Array>) => { + LOG_DEBUG( + 'verbose', + () => + `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${contextDataOffset}`, + ); + const context = new ComputeContextImpl(module, backend, Number(contextDataOffset)); + return backend.computeKernel(Number(kernel), context, errors); + }, + // jsepCaptureBegin + () => backend.captureBegin(), + // jsepCaptureEnd + () => backend.captureEnd(), + // jsepReplay + () => backend.replay(), + ]); + } } else { const backend = new WebNNBackend(env); jsepInit('webnn', [ diff --git a/js/web/lib/wasm/session-options.ts b/js/web/lib/wasm/session-options.ts index 17e564247863d..89a4484e5a1c4 100644 --- a/js/web/lib/wasm/session-options.ts +++ b/js/web/lib/wasm/session-options.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { InferenceSession } from 'onnxruntime-common'; +import type { InferenceSession } from 'onnxruntime-common'; import { getInstance } from './wasm-factory'; import { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils'; @@ -54,13 +54,28 @@ const appendDefaultOptions = (options: InferenceSession.SessionOptions): void => } }; -const setExecutionProviders = ( +const appendSessionConfig = (sessionOptionsHandle: number, key: string, value: string, allocs: number[]): void => { + const keyDataOffset = allocWasmString(key, allocs); + const valueDataOffset = allocWasmString(value, allocs); + if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { + checkLastError(`Can't set a session config entry: ${key} - ${value}.`); + } +}; + +const appendEpOption = (epOptions: Array<[number, number]>, key: string, value: string, allocs: number[]): void => { + const keyDataOffset = allocWasmString(key, allocs); + const valueDataOffset = allocWasmString(value, allocs); + epOptions.push([keyDataOffset, valueDataOffset]); +}; + +const setExecutionProviders = async ( sessionOptionsHandle: number, executionProviders: readonly InferenceSession.ExecutionProviderConfig[], allocs: number[], -): void => { +): Promise => { for (const ep of executionProviders) { let epName = typeof ep === 'string' ? ep : ep.name; + const epOptions: Array<[number, number]> = []; // check EP name switch (epName) { @@ -71,26 +86,44 @@ const setExecutionProviders = ( // const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context; const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType; if (deviceType) { - const keyDataOffset = allocWasmString('deviceType', allocs); - const valueDataOffset = allocWasmString(deviceType, allocs); - if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { - checkLastError(`Can't set a session config entry: 'deviceType' - ${deviceType}.`); - } + appendSessionConfig(sessionOptionsHandle, 'deviceType', deviceType, allocs); } } break; case 'webgpu': - epName = 'JS'; - if (typeof ep !== 'string') { - const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption; - if (webgpuOptions?.preferredLayout) { - if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') { - throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`); + if (BUILD_DEFS.USE_WEBGPU_EP) { + epName = 'WebGPU'; + let customDevice: GPUDevice | undefined; + + if (typeof ep !== 'string') { + const customOptions = ep as unknown as { device: GPUDevice }; + if (customOptions.device) { + if (typeof GPUDevice !== 'undefined' && customOptions.device instanceof GPUDevice) { + customDevice = customOptions.device; + } else { + throw new Error('Invalid GPU device set in WebGPU EP options.'); + } } - const keyDataOffset = allocWasmString('preferredLayout', allocs); - const valueDataOffset = allocWasmString(webgpuOptions.preferredLayout, allocs); - if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { - checkLastError(`Can't set a session config entry: 'preferredLayout' - ${webgpuOptions.preferredLayout}.`); + + // TODO: handle more options + } + + const info = getInstance().webgpuRegisterDevice!(customDevice); + if (info) { + const [deviceId, instanceHandle, deviceHandle] = info; + appendEpOption(epOptions, 'deviceId', deviceId.toString(), allocs); + appendEpOption(epOptions, 'webgpuInstance', instanceHandle.toString(), allocs); + appendEpOption(epOptions, 'webgpuDevice', deviceHandle.toString(), allocs); + } + } else { + epName = 'JS'; + if (typeof ep !== 'string') { + const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption; + if (webgpuOptions?.preferredLayout) { + if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') { + throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`); + } + appendSessionConfig(sessionOptionsHandle, 'preferredLayout', webgpuOptions.preferredLayout, allocs); } } } @@ -103,13 +136,34 @@ const setExecutionProviders = ( } const epNameDataOffset = allocWasmString(epName, allocs); - if (getInstance()._OrtAppendExecutionProvider(sessionOptionsHandle, epNameDataOffset) !== 0) { + const epOptionsCount = epOptions.length; + let keysOffset = 0; + let valuesOffset = 0; + if (epOptionsCount > 0) { + keysOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE); + allocs.push(keysOffset); + valuesOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE); + allocs.push(valuesOffset); + for (let i = 0; i < epOptionsCount; i++) { + getInstance().setValue(keysOffset + i * getInstance().PTR_SIZE, epOptions[i][0], '*'); + getInstance().setValue(valuesOffset + i * getInstance().PTR_SIZE, epOptions[i][1], '*'); + } + } + if ( + (await getInstance()._OrtAppendExecutionProvider( + sessionOptionsHandle, + epNameDataOffset, + keysOffset, + valuesOffset, + epOptionsCount, + )) !== 0 + ) { checkLastError(`Can't append execution provider: ${epName}.`); } } }; -export const setSessionOptions = (options?: InferenceSession.SessionOptions): [number, number[]] => { +export const setSessionOptions = async (options?: InferenceSession.SessionOptions): Promise<[number, number[]]> => { const wasm = getInstance(); let sessionOptionsHandle = 0; const allocs: number[] = []; @@ -155,20 +209,19 @@ export const setSessionOptions = (options?: InferenceSession.SessionOptions): [n } if (sessionOptions.executionProviders) { - setExecutionProviders(sessionOptionsHandle, sessionOptions.executionProviders, allocs); + await setExecutionProviders(sessionOptionsHandle, sessionOptions.executionProviders, allocs); } if (sessionOptions.enableGraphCapture !== undefined) { if (typeof sessionOptions.enableGraphCapture !== 'boolean') { throw new Error(`enableGraphCapture must be a boolean value: ${sessionOptions.enableGraphCapture}`); } - const keyDataOffset = allocWasmString('enableGraphCapture', allocs); - const valueDataOffset = allocWasmString(sessionOptions.enableGraphCapture.toString(), allocs); - if (wasm._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { - checkLastError( - `Can't set a session config entry: 'enableGraphCapture' - ${sessionOptions.enableGraphCapture}.`, - ); - } + appendSessionConfig( + sessionOptionsHandle, + 'enableGraphCapture', + sessionOptions.enableGraphCapture.toString(), + allocs, + ); } if (sessionOptions.freeDimensionOverrides) { @@ -188,12 +241,7 @@ export const setSessionOptions = (options?: InferenceSession.SessionOptions): [n if (sessionOptions.extra !== undefined) { iterateExtraOptions(sessionOptions.extra, '', new WeakSet>(), (key, value) => { - const keyDataOffset = allocWasmString(key, allocs); - const valueDataOffset = allocWasmString(value, allocs); - - if (wasm._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { - checkLastError(`Can't set a session config entry: ${key} - ${value}.`); - } + appendSessionConfig(sessionOptionsHandle, key, value, allocs); }); } diff --git a/js/web/lib/wasm/wasm-core-impl.ts b/js/web/lib/wasm/wasm-core-impl.ts index 4bccfa76fdda3..dbcf80adf3552 100644 --- a/js/web/lib/wasm/wasm-core-impl.ts +++ b/js/web/lib/wasm/wasm-core-impl.ts @@ -102,11 +102,20 @@ export const initRuntime = async (env: Env): Promise => { * @param epName */ export const initEp = async (env: Env, epName: string): Promise => { + // initialize ASYNCIFY support + getInstance().asyncInit?.(); + + if (epName === 'webgpu' && BUILD_DEFS.USE_WEBGPU_EP) { + getInstance().webgpuInit!((device) => { + env.webgpu.device = device; + }); + } + if (!BUILD_DEFS.DISABLE_JSEP) { // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires const initJsep = require('./jsep/init').init; - if (epName === 'webgpu') { + if (epName === 'webgpu' && !BUILD_DEFS.USE_WEBGPU_EP) { // perform WebGPU availability check if (typeof navigator === 'undefined' || !navigator.gpu) { throw new Error('WebGPU is not supported in current environment'); @@ -270,7 +279,7 @@ export const createSession = async ( const outputNamesUTF8Encoded = []; try { - [sessionOptionsHandle, allocs] = setSessionOptions(options); + [sessionOptionsHandle, allocs] = await setSessionOptions(options); if (options?.externalData && wasm.mountExternalData) { const loadingPromises = []; @@ -278,7 +287,7 @@ export const createSession = async ( const path = typeof file === 'string' ? file : file.path; loadingPromises.push( loadFile(typeof file === 'string' ? file : file.data).then((data) => { - wasm.mountExternalData!(path, data); + wasm.mountExternalData(path, data); }), ); } @@ -312,6 +321,7 @@ export const createSession = async ( } sessionHandle = await wasm._OrtCreateSession(modelDataOffset, modelDataLength, sessionOptionsHandle); + wasm.webgpuOnCreateSession?.(sessionHandle); if (sessionHandle === 0) { checkLastError("Can't create a session."); } @@ -444,6 +454,7 @@ export const releaseSession = (sessionId: number): void => { } wasm.jsepOnReleaseSession?.(sessionId); + wasm.webgpuOnReleaseSession?.(sessionId); inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); @@ -491,11 +502,20 @@ export const prepareInputOutputTensor = async ( const gpuBuffer = tensor[2].gpuBuffer; dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!; - const registerBuffer = wasm.jsepRegisterBuffer; - if (!registerBuffer) { - throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); + if (BUILD_DEFS.USE_WEBGPU_EP) { + const registerBuffer = wasm.webgpuRegisterBuffer; + if (!registerBuffer) { + throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); + } + + rawData = registerBuffer(gpuBuffer, sessionId); + } else { + const registerBuffer = wasm.jsepRegisterBuffer; + if (!registerBuffer) { + throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); + } + rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength); } - rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength); } else if (location === 'ml-tensor') { const mlTensor = tensor[2].mlTensor as MLTensor; dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!; @@ -791,7 +811,7 @@ export const run = async ( // If a certain output's preferred location is GPU but the tensor is empty, we still need to create a CPU // tensor for it. There is no mapping GPU buffer for an empty tensor. if (preferredLocation === 'gpu-buffer' && size > 0) { - const getBuffer = wasm.jsepGetBuffer; + const getBuffer = BUILD_DEFS.USE_WEBGPU_EP ? wasm.webgpuGetBuffer : wasm.jsepGetBuffer; if (!getBuffer) { throw new Error('preferredLocation "gpu-buffer" is not supported without using WebGPU.'); } @@ -804,20 +824,43 @@ export const run = async ( // do not release the tensor right now. it will be released when user calls tensor.dispose(). keepOutputTensor = true; - output.push([ - type, - dims, - { - gpuBuffer, - download: wasm.jsepCreateDownloader!(gpuBuffer, bufferSize, type), - dispose: () => { - if (wasm._OrtReleaseTensor(tensor) !== 0) { - checkLastError("Can't release tensor."); - } + if (BUILD_DEFS.USE_WEBGPU_EP) { + wasm.webgpuRegisterBuffer!(gpuBuffer, sessionId, dataOffset); + const downloadDataFunction = wasm.webgpuCreateDownloader!(gpuBuffer, bufferSize, sessionId); + output.push([ + type, + dims, + { + gpuBuffer, + download: async () => { + const arrayBuffer = await downloadDataFunction(); + const data = new (tensorTypeToTypedArrayConstructor(type!))(arrayBuffer); + return data as Tensor.DataTypeMap[Tensor.GpuBufferDataTypes]; + }, + dispose: () => { + if (wasm._OrtReleaseTensor(tensor) !== 0) { + checkLastError("Can't release tensor."); + } + }, }, - }, - 'gpu-buffer', - ]); + 'gpu-buffer', + ]); + } else { + output.push([ + type, + dims, + { + gpuBuffer, + download: wasm.jsepCreateDownloader!(gpuBuffer, bufferSize, type), + dispose: () => { + if (wasm._OrtReleaseTensor(tensor) !== 0) { + checkLastError("Can't release tensor."); + } + }, + }, + 'gpu-buffer', + ]); + } } else if (preferredLocation === 'ml-tensor' && size > 0) { const ensureTensor = wasm.jsepEnsureTensor; if (!ensureTensor) { @@ -887,6 +930,18 @@ export const run = async ( } finally { wasm.stackRestore(beforeRunStack); + if (BUILD_DEFS.USE_WEBGPU_EP) { + inputTensors.forEach((t) => { + if (t && t[3] === 'gpu-buffer') { + wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer); + } + }); + outputTensors.forEach((t) => { + if (t && t[3] === 'gpu-buffer') { + wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer); + } + }); + } inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); inputOutputAllocs.forEach((p) => wasm._free(p)); diff --git a/js/web/lib/wasm/wasm-types.ts b/js/web/lib/wasm/wasm-types.ts index b4871e145f4d7..9b2ec71fd351d 100644 --- a/js/web/lib/wasm/wasm-types.ts +++ b/js/web/lib/wasm/wasm-types.ts @@ -41,18 +41,6 @@ export declare namespace JSEP { type DownloadTensorFunction = (tensorId: number, dstBuffer: ArrayBufferView | ArrayBuffer) => Promise; export interface Module extends WebGpuModule, WebNnModule { - /** - * Mount the external data file to an internal map, which will be used during session initialization. - * - * @param externalDataFilePath - specify the relative path of the external data file. - * @param externalDataFileData - specify the content data. - */ - mountExternalData(externalDataFilePath: string, externalDataFileData: Uint8Array): void; - /** - * Unmount all external data files from the internal map. - */ - unmountExternalData(): void; - /** * This is the entry of JSEP initialization. This function is called once when initializing ONNX Runtime per * backend. This function initializes Asyncify support. If name is 'webgpu', also initializes WebGPU backend and @@ -294,6 +282,21 @@ export declare namespace JSEP { } } +export declare namespace WebGpu { + export interface Module { + webgpuInit(setDefaultDevice: (device: GPUDevice) => void): void; + webgpuRegisterDevice( + device?: GPUDevice, + ): undefined | [deviceId: number, instanceHandle: number, deviceHandle: number]; + webgpuOnCreateSession(sessionHandle: number): void; + webgpuOnReleaseSession(sessionHandle: number): void; + webgpuRegisterBuffer(buffer: GPUBuffer, sessionHandle: number, bufferHandle?: number): number; + webgpuUnregisterBuffer(buffer: GPUBuffer): void; + webgpuGetBuffer(bufferHandle: number): GPUBuffer; + webgpuCreateDownloader(gpuBuffer: GPUBuffer, size: number, sessionHandle: number): () => Promise; + } +} + export interface OrtInferenceAPIs { _OrtInit(numThreads: number, loggingLevel: number): number; @@ -358,7 +361,13 @@ export interface OrtInferenceAPIs { logVerbosityLevel: number, optimizedModelFilePath: number, ): number; - _OrtAppendExecutionProvider(sessionOptionsHandle: number, name: number): number; + _OrtAppendExecutionProvider( + sessionOptionsHandle: number, + name: number, + providerOptionsKeys: number, + providerOptionsValues: number, + numKeys: number, + ): Promise; _OrtAddFreeDimensionOverride(sessionOptionsHandle: number, name: number, dim: number): number; _OrtAddSessionConfigEntry(sessionOptionsHandle: number, configKey: number, configValue: number): number; _OrtReleaseSessionOptions(sessionOptionsHandle: number): number; @@ -373,8 +382,11 @@ export interface OrtInferenceAPIs { /** * The interface of the WebAssembly module for ONNX Runtime, compiled from C++ source code by Emscripten. */ -export interface OrtWasmModule extends EmscriptenModule, OrtInferenceAPIs, Partial { - PTR_SIZE: number; +export interface OrtWasmModule + extends EmscriptenModule, + OrtInferenceAPIs, + Partial, + Partial { // #region emscripten functions stackSave(): number; stackRestore(stack: number): void; @@ -387,7 +399,31 @@ export interface OrtWasmModule extends EmscriptenModule, OrtInferenceAPIs, Parti stringToUTF8(str: string, offset: number, maxBytes: number): void; // #endregion + // #region ORT shared + + readonly PTR_SIZE: 4 | 8; + + /** + * Mount the external data file to an internal map, which will be used during session initialization. + * + * @param externalDataFilePath - specify the relative path of the external data file. + * @param externalDataFileData - specify the content data. + */ + mountExternalData(externalDataFilePath: string, externalDataFileData: Uint8Array): void; + /** + * Unmount all external data files from the internal map. + */ + unmountExternalData(): void; + + /** + * This function patches the WebAssembly module to support Asyncify. This function should be called at least once + * before any ORT API is called. + */ + asyncInit?(): void; + + // #endregion + // #region config - numThreads?: number; + readonly numThreads?: number; // #endregion } diff --git a/js/web/script/build.ts b/js/web/script/build.ts index 7966262631bbf..98e61c9f87fbb 100644 --- a/js/web/script/build.ts +++ b/js/web/script/build.ts @@ -27,7 +27,8 @@ const args = minimist(process.argv.slice(2)); * --bundle-mode=node * Build a single ort-web bundle for nodejs. */ -const BUNDLE_MODE: 'prod' | 'dev' | 'perf' | 'node' = args['bundle-mode'] || 'prod'; +const BUNDLE_MODE: 'prod' | 'dev' | 'perf' | 'node' = + process.env.npm_config_bundle_mode || args['bundle-mode'] || 'prod'; /** * --debug @@ -41,7 +42,18 @@ const BUNDLE_MODE: 'prod' | 'dev' | 'perf' | 'node' = args['bundle-mode'] || 'pr * Enable debug mode. In this mode, esbuild metafile feature will be enabled. Full bundle analysis will be saved to a * file as JSON. */ -const DEBUG = args.debug; // boolean|'verbose'|'save' +const DEBUG = process.env.npm_config_debug || args.debug; // boolean|'verbose'|'save' + +/** + * --webgpu-ep + * --no-webgpu-ep (default) + * + * Enable or disable the use of WebGPU EP. If enabled, the WebGPU EP will be used. If disabled, the WebGPU backend will + * be used with JSEP. + * + * (temporary) This flag is used to test the WebGPU EP integration. It will be removed in the future. + */ +const USE_WEBGPU_EP = process.env.npm_config_webgpu_ep ?? args['webgpu-ep'] ?? false; /** * Root folder of the source code: `/js/` @@ -57,6 +69,7 @@ const DEFAULT_DEFINE = { 'BUILD_DEFS.DISABLE_WASM': 'false', 'BUILD_DEFS.DISABLE_WASM_PROXY': 'false', 'BUILD_DEFS.ENABLE_BUNDLE_WASM_JS': 'false', + 'BUILD_DEFS.USE_WEBGPU_EP': JSON.stringify(!!USE_WEBGPU_EP), 'BUILD_DEFS.IS_ESM': 'false', 'BUILD_DEFS.ESM_IMPORT_META_URL': 'undefined', diff --git a/onnxruntime/core/framework/external_data_loader.cc b/onnxruntime/core/framework/external_data_loader.cc index fe73a55735631..c577805e69cc4 100644 --- a/onnxruntime/core/framework/external_data_loader.cc +++ b/onnxruntime/core/framework/external_data_loader.cc @@ -60,7 +60,12 @@ common::Status LoadWebAssemblyExternalData(const Env& env, break; case 1: // Load external data to GPU. - Module.jsepUploadExternalBuffer(dataIdOrBuffer, data); + // TODO: use a unified interface for upload external buffer. + if (Module.webgpuUploadExternalBuffer) { + Module.webgpuUploadExternalBuffer(dataIdOrBuffer, data); + } else { + Module.jsepUploadExternalBuffer(dataIdOrBuffer, data); + } break; default: return 4; // Unknown error occurred in memory copy. diff --git a/onnxruntime/core/framework/external_data_loader.h b/onnxruntime/core/framework/external_data_loader.h index 117da7d0a4afa..90d48ca800797 100644 --- a/onnxruntime/core/framework/external_data_loader.h +++ b/onnxruntime/core/framework/external_data_loader.h @@ -42,7 +42,7 @@ class IExternalDataLoader { enum class ExternalDataLoadType { CPU = 0, -#if defined(USE_JSEP) +#if defined(USE_JSEP) || defined(USE_WEBGPU) WEBGPU_BUFFER = 1, #endif }; diff --git a/onnxruntime/core/providers/webgpu/external_data_loader.cc b/onnxruntime/core/providers/webgpu/external_data_loader.cc new file mode 100644 index 0000000000000..6da9598b146f5 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/external_data_loader.cc @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#if defined(__wasm__) + +#include + +#include "core/framework/tensor.h" +#include "core/providers/webgpu/external_data_loader.h" + +namespace onnxruntime { +namespace webgpu { + +bool ExternalDataLoader::CanLoad(const OrtMemoryInfo& target_memory_info) const { + return target_memory_info.device.Type() == OrtDevice::CPU || + (target_memory_info.device.Type() == OrtDevice::GPU && target_memory_info.name == WEBGPU_BUFFER); +} + +common::Status ExternalDataLoader::LoadTensor(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + Tensor& tensor) const { + ExternalDataLoadType load_type; + if (tensor.Location().device.Type() == OrtDevice::CPU) { + load_type = ExternalDataLoadType::CPU; + } else if (tensor.Location().device.Type() == OrtDevice::GPU && + tensor.Location().name == WEBGPU_BUFFER) { + load_type = ExternalDataLoadType::WEBGPU_BUFFER; + } else { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Unsupported tensor location: ", tensor.Location().ToString()); + } + + return LoadWebAssemblyExternalData(env, data_file_path, data_offset, data_length, load_type, tensor.MutableDataRaw()); +} + +} // namespace webgpu +} // namespace onnxruntime + +#endif diff --git a/onnxruntime/core/providers/webgpu/external_data_loader.h b/onnxruntime/core/providers/webgpu/external_data_loader.h new file mode 100644 index 0000000000000..7ced4e930bf7a --- /dev/null +++ b/onnxruntime/core/providers/webgpu/external_data_loader.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if defined(__wasm__) + +#include "core/framework/external_data_loader.h" + +namespace onnxruntime { +namespace webgpu { + +class ExternalDataLoader : public IExternalDataLoader { + public: + ExternalDataLoader() {}; + ~ExternalDataLoader() {}; + + bool CanLoad(const OrtMemoryInfo& target_memory_info) const override; + + common::Status LoadTensor(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + Tensor& tensor) const override; +}; + +} // namespace webgpu +} // namespace onnxruntime + +#endif diff --git a/onnxruntime/core/providers/webgpu/program.cc b/onnxruntime/core/providers/webgpu/program.cc index d1d4c242c4697..976b7927ac3dd 100644 --- a/onnxruntime/core/providers/webgpu/program.cc +++ b/onnxruntime/core/providers/webgpu/program.cc @@ -206,6 +206,26 @@ ProgramVariableDataType ToProgramVariableDataType(int32_t element_type, int comp } } +std::ostream& operator<<(std::ostream& os, ValidationMode mode) { + switch (mode) { + case ValidationMode::Disabled: + os << "Disabled"; + break; + case ValidationMode::WGPUOnly: + os << "WGPUOnly"; + break; + case ValidationMode::Basic: + os << "Basic"; + break; + case ValidationMode::Full: + os << "Full"; + break; + default: + os << "Unknown(" << static_cast(mode) << ")"; + } + return os; +} + namespace { TensorShape GetReducedShape(const TensorShape& shape, int component /* > 1 */) { ORT_ENFORCE(shape.NumDimensions() > 0 && shape.GetDims()[shape.NumDimensions() - 1] % component == 0, diff --git a/onnxruntime/core/providers/webgpu/program.h b/onnxruntime/core/providers/webgpu/program.h index 7bfd9e8800099..95fef36144025 100644 --- a/onnxruntime/core/providers/webgpu/program.h +++ b/onnxruntime/core/providers/webgpu/program.h @@ -237,6 +237,7 @@ enum class ValidationMode { Basic, Full }; +std::ostream& operator<<(std::ostream& os, ValidationMode mode); namespace details { class ProgramWrapper; diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 21e5e55588a2e..14c12ac247080 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -134,6 +134,8 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi ORT_ENFORCE(device_ != nullptr, "Failed to get a WebGPU device."); } + LOGS_DEFAULT(VERBOSE) << "WebGPU EP Context is created for: Instance=" << instance_.Get() << ", Device=" << device_.Get() << "."; + // cache adapter info ORT_ENFORCE(Device().GetAdapterInfo(&adapter_info_)); // cache device limits @@ -706,45 +708,46 @@ WebGpuContext& WebGpuContextFactory::CreateContext(const WebGpuContextConfig& co WGPUInstance instance = config.instance; WGPUDevice device = config.device; - if (context_id == 0) { - // context ID is preserved for the default context. User cannot use context ID 0 as a custom context. - ORT_ENFORCE(instance == nullptr && device == nullptr, - "WebGPU EP default context (contextId=0) must not have custom WebGPU instance or device."); - - std::call_once(init_default_flag_, [ + std::call_once(init_default_flag_, [ #if !defined(__wasm__) - dawn_proc_table = config.dawn_proc_table + dawn_proc_table = config.dawn_proc_table #endif - ]() { - // Step.1 - setup dawn proc table (only for non-WASM build) + ]() { + // Step.1 - setup dawn proc table (only for non-WASM build) #if !defined(__wasm__) - const DawnProcTable* dawn_procs = reinterpret_cast(dawn_proc_table); + const DawnProcTable* dawn_procs = reinterpret_cast(dawn_proc_table); #if defined(BUILD_DAWN_MONOLITHIC_LIBRARY) - ORT_ENFORCE(dawn_procs == nullptr, "setting DawnProcTable is not allowed when dynamically linked to webgpu_dawn."); + ORT_ENFORCE(dawn_procs == nullptr, "setting DawnProcTable is not allowed when dynamically linked to webgpu_dawn."); #else #if !defined(USE_EXTERNAL_DAWN) - if (dawn_procs == nullptr) { - dawn_procs = &dawn::native::GetProcs(); - } + if (dawn_procs == nullptr) { + dawn_procs = &dawn::native::GetProcs(); + } #else - ORT_ENFORCE(dawn_procs != nullptr, "DawnProcTable must be provided."); + ORT_ENFORCE(dawn_procs != nullptr, "DawnProcTable must be provided."); #endif - dawnProcSetProcs(dawn_procs); + dawnProcSetProcs(dawn_procs); #endif #endif - // Step.2 - Create wgpu::Instance + // Step.2 - Create wgpu::Instance #if !defined(__wasm__) - wgpu::InstanceDescriptor instance_desc{}; - instance_desc.capabilities.timedWaitAnyEnable = true; - default_instance_ = wgpu::CreateInstance(&instance_desc); + wgpu::InstanceDescriptor instance_desc{}; + instance_desc.capabilities.timedWaitAnyEnable = true; + default_instance_ = wgpu::CreateInstance(&instance_desc); #else - default_instance_ = wgpu::CreateInstance(nullptr); + default_instance_ = wgpu::CreateInstance(nullptr); #endif - ORT_ENFORCE(default_instance_ != nullptr, "Failed to create wgpu::Instance."); - }); + ORT_ENFORCE(default_instance_ != nullptr, "Failed to create wgpu::Instance."); + }); + + if (context_id == 0) { + // context ID is preserved for the default context. User cannot use context ID 0 as a custom context. + ORT_ENFORCE(instance == nullptr && device == nullptr, + "WebGPU EP default context (contextId=0) must not have custom WebGPU instance or device."); + instance = default_instance_.Get(); } else { // for context ID > 0, user must provide custom WebGPU instance and device. @@ -798,5 +801,9 @@ void CleanupWebGpuContexts() { WebGpuContextFactory::Cleanup(); } +WGPUDevice GetDevice(int context_id) { + return WebGpuContextFactory::GetContext(context_id).Device().Get(); +} + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index a2b8709e0e075..d673f9d0717f0 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -23,6 +23,7 @@ #include "core/providers/webgpu/webgpu_context.h" #include "core/providers/webgpu/data_transfer.h" +#include "core/providers/webgpu/external_data_loader.h" #include "core/providers/webgpu/webgpu_profiler.h" namespace onnxruntime { @@ -825,6 +826,12 @@ std::unique_ptr WebGpuExecutionProvider::GetDataTran return std::make_unique(context_); } +#if defined(__wasm__) +std::unique_ptr WebGpuExecutionProvider::GetExternalDataLoader() const { + return std::make_unique(); +} +#endif + WebGpuExecutionProvider::~WebGpuExecutionProvider() { WebGpuContextFactory::ReleaseContext(context_id_); } diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h index 7a0ade97aa3df..dc25636821651 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h @@ -49,6 +49,9 @@ class WebGpuExecutionProvider : public IExecutionProvider { std::shared_ptr GetKernelRegistry() const override; std::unique_ptr GetDataTransfer() const override; +#if defined(__wasm__) + std::unique_ptr GetExternalDataLoader() const override; +#endif DataLayout GetPreferredLayout() const override { return preferred_data_layout_; } diff --git a/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc b/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc index 60c61b2ca5665..1d779152f91f3 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc @@ -151,6 +151,12 @@ std::shared_ptr WebGpuProviderFactoryCreator::Create( validation_mode, }; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP Device ID: " << context_id; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP WGPUInstance: " << webgpu_instance; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP WGPUDevice: " << webgpu_device; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP DawnProcTable: " << dawn_proc_table; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP ValidationMode: " << validation_mode; + // // STEP.3 - prepare parameters for WebGPU context initialization. // diff --git a/onnxruntime/wasm/api.cc b/onnxruntime/wasm/api.cc index 7adfc6a2b2ccb..1ad35b51bb1c1 100644 --- a/onnxruntime/wasm/api.cc +++ b/onnxruntime/wasm/api.cc @@ -8,6 +8,14 @@ #include "core/session/onnxruntime_cxx_api.h" #include "api.h" +#ifdef USE_WEBGPU +namespace onnxruntime { +namespace webgpu { +WGPUDevice GetDevice(int); +} +} // namespace onnxruntime +#endif + #include #include #include @@ -164,8 +172,12 @@ OrtSessionOptions* OrtCreateSessionOptions(size_t graph_optimization_level, return UNREGISTER_AUTO_RELEASE(session_options); } -int OrtAppendExecutionProvider(ort_session_options_handle_t session_options, const char* name) { - return CHECK_STATUS(SessionOptionsAppendExecutionProvider, session_options, name, nullptr, nullptr, 0); +int OrtAppendExecutionProvider(ort_session_options_handle_t session_options, + const char* name, + const char* const* provider_options_keys, + const char* const* provider_options_values, + size_t num_keys) { + return CHECK_STATUS(SessionOptionsAppendExecutionProvider, session_options, name, provider_options_keys, provider_options_values, num_keys); } int OrtAddFreeDimensionOverride(ort_session_options_handle_t session_options, @@ -507,6 +519,16 @@ char* OrtEndProfiling(ort_session_handle_t session) { : nullptr; } +// WebGPU API Section + +#ifdef USE_WEBGPU + +WGPUDevice OrtGetWebGpuDevice(int device_id) { + return onnxruntime::webgpu::GetDevice(device_id); +} + +#endif + // Training API Section #ifdef ENABLE_TRAINING_APIS diff --git a/onnxruntime/wasm/api.h b/onnxruntime/wasm/api.h index f44c515d98f6b..9ff1eb55ecedc 100644 --- a/onnxruntime/wasm/api.h +++ b/onnxruntime/wasm/api.h @@ -10,6 +10,10 @@ #include +#ifdef USE_WEBGPU +#include +#endif + #include struct OrtSession; @@ -85,7 +89,10 @@ ort_session_options_handle_t EMSCRIPTEN_KEEPALIVE OrtCreateSessionOptions(size_t * @returns ORT error code. If not zero, call OrtGetLastError() to get detailed error message. */ int EMSCRIPTEN_KEEPALIVE OrtAppendExecutionProvider(ort_session_options_handle_t session_options, - const char* name); + const char* name, + const char* const* provider_options_keys, + const char* const* provider_options_values, + size_t num_keys); /** * add a free dimension override for one dimension of a session's input. @@ -294,6 +301,21 @@ int EMSCRIPTEN_KEEPALIVE OrtRun(ort_session_handle_t session, */ char* EMSCRIPTEN_KEEPALIVE OrtEndProfiling(ort_session_handle_t session); +// WebGPU API Section + +#ifdef USE_WEBGPU + +/** + * get the GPU Device by device ID. + * + * This function is only available after the GPU Device is initialized in WebGpuContextFactory. + * + * @returns a WGPUDevice handle. + */ +WGPUDevice EMSCRIPTEN_KEEPALIVE OrtGetWebGpuDevice(int device_id); + +#endif + // Training API Section #ifdef ENABLE_TRAINING_APIS diff --git a/onnxruntime/wasm/js_post_js.js b/onnxruntime/wasm/js_post_js.js index b77d82fbd7d10..56d3246fd07f0 100644 --- a/onnxruntime/wasm/js_post_js.js +++ b/onnxruntime/wasm/js_post_js.js @@ -2,6 +2,4 @@ // Licensed under the MIT License. -'use strict'; - Module["PTR_SIZE"] = 4; diff --git a/onnxruntime/wasm/js_post_js_64.js b/onnxruntime/wasm/js_post_js_64.js index b140df927ebbd..cfd79523f7900 100644 --- a/onnxruntime/wasm/js_post_js_64.js +++ b/onnxruntime/wasm/js_post_js_64.js @@ -2,6 +2,4 @@ // Licensed under the MIT License. -'use strict'; - Module["PTR_SIZE"] = 8; diff --git a/onnxruntime/wasm/post-webgpu.js b/onnxruntime/wasm/post-webgpu.js new file mode 100644 index 0000000000000..146355f6a44d3 --- /dev/null +++ b/onnxruntime/wasm/post-webgpu.js @@ -0,0 +1,261 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// +// This file contains the post-run code for the ORT WebAssembly module. The code in this file will be injected into the +// final module using Emscripten's `--post-js` option. +// +// This file will only be used in build with flag `--use_webgpu`. + +/** + * This function is called only once when initializing the WebGPU backend. + * + * @param {(gpuDevice: GPUDevice) => void} setDefaultDevice A callback function to set the default device. + */ +Module["webgpuInit"] = (setDefaultDevice) => { + /** + * a map from GPUDevice to [deviceId, instanceHandle, deviceHandle] + * + * only stores custom devices (ie. devices created by the user, not the default device created by ORT) + * + * key is the GPUDevice object. + * + * value is a tuple of 3 elements: + * - deviceId: a unique ID for the device. Must be positive integer. + * - instanceHandle: the instance handle(pointer) of the device. + * - deviceHandle: the device handle(pointer) of the device. + * + * @type {WeakMap} + */ + const webgpuActiveDevices = new WeakMap(); + /** + * a number that is used to assign a unique ID to the next custom device. + */ + let webgpuNextDeviceId = 1; + /** + * a function to set the default device. + * + * @type {(gpuDevice: GPUDevice) => void} + */ + const webgpuSetDefaultDevice = setDefaultDevice; + /** + * the current device that is being used to create a WebGPU EP inference session. + * + * the value of this variable is only valid during the creation of a WebGPU EP inference session. + * + * @type {GPUDevice|undefined} + */ + let webgpuCurrentDevice = undefined; + /** + * the current device ID that is being used to create a WebGPU EP inference session. + * + * the value of this variable is only valid during the creation of a WebGPU EP inference session. + * + * @type {number|undefined} + */ + let webgpuCurrentDeviceId = undefined; + + /** + * This function is called only when a custom device is used, during preparation of session options. + * + * @param {GPUDevice} device the user provided device object. + * @returns {undefined|[number, number, number]} a tuple of device id, instance handle, and device handle. + */ + Module["webgpuRegisterDevice"] = (device) => { + if (webgpuCurrentDeviceId !== undefined) { + throw new Error("another WebGPU EP inference session is being created."); + } + + if (device) { + let deviceInfo = webgpuActiveDevices.get(device); + if (!deviceInfo) { + const instanceHandle = _wgpuCreateInstance(0); + const deviceHandle = WebGPU.importJsDevice(device, instanceHandle); + deviceInfo = [webgpuNextDeviceId++, instanceHandle, deviceHandle]; + webgpuActiveDevices.set(device, deviceInfo); + } + + // The current device ID is a temporary storage for the device ID to be used in the session that is being created. + // + // Soon after `webgpuRegisterDevice` (this function) is called, `webgpuOnCreateSession` will be called so that the + // value of `webgpuCurrentDeviceId` is used and reset then. + webgpuCurrentDevice = device; + webgpuCurrentDeviceId = deviceInfo[0]; + return deviceInfo; + } else { + webgpuCurrentDevice = undefined; + webgpuCurrentDeviceId = 0; + return undefined; + } + }; + + const webgpuActiveSessions = new Map(); + Module["webgpuOnCreateSession"] = (sessionHandle) => { + if (webgpuCurrentDeviceId === undefined) { + // do nothing if webgpuCurrentDeviceId is undefined. + // this means no WebGPU EP is being created. + return; + } + + const deviceId = webgpuCurrentDeviceId; + webgpuCurrentDeviceId = undefined; + + if (sessionHandle) { + // when session created successfully + const deviceHandle = _OrtGetWebGpuDevice(deviceId); + webgpuActiveSessions.set(sessionHandle, deviceHandle); + + if (deviceId === 0) { + const device = webgpuCurrentDevice ?? WebGPU.getJsObject(deviceHandle); + webgpuSetDefaultDevice(device); + } + } + webgpuCurrentDevice = undefined; + }; + + Module["webgpuOnReleaseSession"] = (sessionHandle) => { + webgpuActiveSessions.delete(sessionHandle); + }; + + const gpuBufferMetadataSymbol = Symbol("gpuBufferMetadata"); + + Module["webgpuRegisterBuffer"] = (buffer, sessionHandle, bufferHandle) => { + if (bufferHandle) { + // This is a buffer that was created by ORT. Metadata is [bufferHandle, NaN] + + buffer[gpuBufferMetadataSymbol] = [bufferHandle, NaN]; + return bufferHandle; + } else { + // This is a buffer that was created by the user. Metadata is [bufferHandle, refCount] + + const metadata = buffer[gpuBufferMetadataSymbol]; + if (metadata) { + metadata[1]++; + return metadata[0]; + } + + const deviceHandle = webgpuActiveSessions.get(sessionHandle); + if (deviceHandle === undefined) { + throw new Error( + "Invalid session handle passed to webgpuRegisterBuffer" + ); + } + + const bufferHandle = WebGPU.importJsBuffer(buffer, deviceHandle); + buffer[gpuBufferMetadataSymbol] = [bufferHandle, 1]; + return bufferHandle; + } + }; + + Module["webgpuUnregisterBuffer"] = (buffer) => { + const metadata = buffer[gpuBufferMetadataSymbol]; + if (!metadata) { + throw new Error("Buffer is not registered"); + } + metadata[1]--; + // For buffers created by ORT, metadata[1] will always be NaN. This function will not release the buffer. + // Instead, the buffer will be released when user calls `Tensor.dispose()` in JavaScript. + if (metadata[1] === 0) { + _wgpuBufferRelease(metadata[0]); + delete buffer[gpuBufferMetadataSymbol]; + } + }; + + Module["webgpuGetBuffer"] = (bufferHandle) => { + return WebGPU.getJsObject(bufferHandle); + }; + + Module["webgpuCreateDownloader"] = (gpuBuffer, bufferSize, sessionHandle) => { + const deviceHandle = webgpuActiveSessions.get(sessionHandle); + if (deviceHandle === undefined) { + throw new Error("Invalid session handle passed to webgpuRegisterBuffer"); + } + + const buffer = gpuBuffer; + const device = WebGPU.getJsObject(deviceHandle); + const originalSize = bufferSize; + const size = Math.ceil(Number(originalSize) / 16) * 16; + + return async () => { + // prettier-ignore + // + // the line above is used to force prettier to skip formatting the next statement. + // this is because prettier will remove the quotes around the property names, but we need to keep them + // because otherwise closure compiler may rename them and break the code. + const gpuReadBufferDescriptor = { + "size": size, + "usage": 9 /* GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ */, + }; + const gpuReadBuffer = device.createBuffer(gpuReadBufferDescriptor); + try { + const commandEncoder = device.createCommandEncoder(); + commandEncoder.copyBufferToBuffer( + buffer /* source buffer */, + 0 /* source offset */, + gpuReadBuffer /* destination buffer */, + 0 /* destination offset */, + size /* size */ + ); + device.queue.submit([commandEncoder.finish()]); + + await gpuReadBuffer.mapAsync(GPUMapMode.READ); + + const arrayBuffer = gpuReadBuffer.getMappedRange(); + return arrayBuffer.slice(0, originalSize); + } finally { + gpuReadBuffer.destroy(); + } + }; + }; + + // Setup a callback function for loading external buffers (model weights). + Module.webgpuUploadExternalBuffer = (bufferHandle, data) => { + const srcArrayBuffer = data.buffer; + const srcOffset = data.byteOffset; + const srcLength = data.byteLength; + const size = Math.ceil(Number(srcLength) / 16) * 16; + + const gpuBuffer = WebGPU.getJsObject(bufferHandle); + + // get current device + if (!webgpuCurrentDevice) { + const deviceHandle = _OrtGetWebGpuDevice(webgpuCurrentDeviceId); + webgpuCurrentDevice = WebGPU.getJsObject(deviceHandle); + } + + // create gpu buffer + + // prettier-ignore + // + // the line above is used to force prettier to skip formatting the next statement. + // this is because prettier will remove the quotes around the property names, but we need to keep them + // because otherwise closure compiler may rename them and break the code. + const gpuBufferForUploadingDescriptor = { + "mappedAtCreation": true, + "size": size, + "usage": 6 /* GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC */, + }; + const gpuBufferForUploading = webgpuCurrentDevice.createBuffer( + gpuBufferForUploadingDescriptor + ); + + // copy (upload) data + const arrayBuffer = gpuBufferForUploading.getMappedRange(); + new Uint8Array(arrayBuffer).set( + new Uint8Array(srcArrayBuffer, srcOffset, srcLength) + ); + gpuBufferForUploading.unmap(); + + // GPU copy + const commandEncoder = webgpuCurrentDevice.createCommandEncoder(); + commandEncoder.copyBufferToBuffer( + gpuBufferForUploading, + 0, + gpuBuffer, + 0, + size + ); + webgpuCurrentDevice.queue.submit([commandEncoder.finish()]); + gpuBufferForUploading.destroy(); + }; +}; diff --git a/onnxruntime/wasm/pre-async.js b/onnxruntime/wasm/pre-async.js new file mode 100644 index 0000000000000..8c75dc7c5cf1e --- /dev/null +++ b/onnxruntime/wasm/pre-async.js @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// +// This file contains the pre-run code for the ORT WebAssembly module. The code in this file will be injected into the +// final module using Emscripten's `--pre-js` option. +// +// This file will only be used in build with flag `-s ASYNCIFY=1`. + +/** + * initialize for asyncify support. + */ +let initAsyncImpl = () => { + // This is a simplified version of cwrap() with options.async === true (-sASYNCIFY=1) + // It removes some overhead in cwarp() and ccall() that we don't need. + // + // Currently in ASYNCIFY build, we only use this for the following functions: + // - OrtCreateSession() + // - OrtRun() + // - OrtRunWithBinding() + // - OrtBindInput() + // + // Note: about parameters "getFunc" and "setFunc": + // - Emscripten has different behaviors for Debug and Release builds for generating exported function wrapper. + // + // - In Debug build, it will generate a wrapper function for each exported function. For example, it generates a + // wrapper for OrtRun() like this (minified): + // ``` + // var _OrtRun = Module["_OrtRun"] = createExportWrapper("OrtRun"); + // ``` + // + // - In Release build, it will generate a lazy loading wrapper for each exported function. For example, it generates + // a wrapper for OrtRun() like this (minified): + // ``` + // d._OrtRun = (a, b, c, e, f, h, l, q) => (d._OrtRun = J.ka)(a, b, c, e, f, h, l, q); + // ``` + // + // The behavior of these two wrappers are different. The debug build will assign `Module["_OrtRun"]` only once + // because `createExportWrapper()` does not reset `Module["_OrtRun"]` inside. The release build, however, will + // reset d._OrtRun to J.ka when the first time it is called. + // + // The difference is important because we need to design the async wrapper in a way that it can handle both cases. + // + // Now, let's look at how the async wrapper is designed to work for both cases: + // + // - Debug build: + // 1. When Web assembly is being loaded, `Module["_OrtRun"]` is assigned to `createExportWrapper("OrtRun")`. + // 2. When the first time `Module["initAsync"]` is called, `Module["_OrtRun"]` is re-assigned to a new async + // wrapper function. + // Value of `Module["_OrtRun"]` will not be changed again. + // + // - Release build: + // 1. When Web assembly is being loaded, `Module["_OrtRun"]` is assigned to a lazy loading wrapper function. + // 2. When the first time `Module["initAsync"]` is called, `Module["_OrtRun"]` is re-assigned to a new async + // wrapper function. + // 3. When the first time `Module["_OrtRun"]` is called, the async wrapper will be called. It will call into this + // function: + // ``` + // (a, b, c, e, f, h, l, q) => (d._OrtRun = J.ka)(a, b, c, e, f, h, l, q); + // ``` + // This function will assign d._OrtRun (ie. the minimized `Module["_OrtRun"]`) to the real function (J.ka). + // 4. Since d._OrtRun is re-assigned, we need to update the async wrapper to re-assign its stored + // function to the updated value (J.ka), and re-assign the value of `d._OrtRun` back to the async wrapper. + // Value of `Module["_OrtRun"]` will not be changed again. + // + // The value of `Module["_OrtRun"]` will need to be assigned for 2 times for debug build and 4 times for release + // build. + // + // This is why we need this `getFunc` and `setFunc` parameters. They are used to get the current value of an + // exported function and set the new value of an exported function. + // + const wrapAsync = (func, getFunc, setFunc) => { + return (...args) => { + // cache the async data before calling the function. + const previousAsync = Asyncify.currData; + + const previousFunc = getFunc?.(); + const ret = func(...args); + const newFunc = getFunc?.(); + if (previousFunc !== newFunc) { + // The exported function has been updated. + // Set the sync function reference to the new function. + func = newFunc; + // Set the exported function back to the async wrapper. + setFunc(previousFunc); + // Remove getFunc and setFunc. They are no longer needed. + setFunc = null; + getFunc = null; + } + + // If the async data has been changed, it means that the function started an async operation. + if (Asyncify.currData != previousAsync) { + // returns the promise + return Asyncify.whenDone(); + } + // the function is synchronous. returns the result. + return ret; + }; + }; + + // replace the original functions with asyncified versions + const wrapAsyncAPIs = (funcNames) => { + for (const funcName of funcNames) { + Module[funcName] = wrapAsync( + Module[funcName], + () => Module[funcName], + (v) => (Module[funcName] = v) + ); + } + }; + + wrapAsyncAPIs([ + "_OrtAppendExecutionProvider", + "_OrtCreateSession", + "_OrtRun", + "_OrtRunWithBinding", + "_OrtBindInput", + ]); + + // If JSEP is enabled, wrap OrtRun() and OrtRunWithBinding() with asyncify. + if (typeof jsepRunAsync !== "undefined") { + Module["_OrtRun"] = jsepRunAsync(Module["_OrtRun"]); + Module["_OrtRunWithBinding"] = jsepRunAsync(Module["_OrtRunWithBinding"]); + } + + // remove this function to make sure it is called only once. + initAsyncImpl = undefined; +}; + +Module["asyncInit"] = () => { + initAsyncImpl?.(); +}; diff --git a/onnxruntime/wasm/pre-jsep.js b/onnxruntime/wasm/pre-jsep.js index 0c83e71a921cb..5b2f044d4c27b 100644 --- a/onnxruntime/wasm/pre-jsep.js +++ b/onnxruntime/wasm/pre-jsep.js @@ -1,255 +1,157 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -'use strict'; - // // This file contains the pre-run code for the ORT WebAssembly module. The code in this file will be injected into the // final module using Emscripten's `--pre-js` option. // // This file will only be used in build with flag `--use_jsep`. - -/** - * initialize JSEP for asyncify support. - */ -let jsepInitAsync = () => { - // This is a simplified version of cwrap() with options.async === true (-sASYNCIFY=1) - // It removes some overhead in cwarp() and ccall() that we don't need. - // - // Currently in JSEP build, we only use this for the following functions: - // - OrtRun() - // - OrtRunWithBinding() - // - OrtBindInput() - // - // Note: about parameters "getFunc" and "setFunc": - // - Emscripten has different behaviors for Debug and Release builds for generating exported function wrapper. - // - // - In Debug build, it will generate a wrapper function for each exported function. For example, it generates a - // wrapper for OrtRun() like this (minified): - // ``` - // var _OrtRun = Module["_OrtRun"] = createExportWrapper("OrtRun"); - // ``` - // - // - In Release build, it will generate a lazy loading wrapper for each exported function. For example, it generates - // a wrapper for OrtRun() like this (minified): - // ``` - // d._OrtRun = (a, b, c, e, f, h, l, q) => (d._OrtRun = J.ka)(a, b, c, e, f, h, l, q); - // ``` - // - // The behavior of these two wrappers are different. The debug build will assign `Module["_OrtRun"]` only once - // because `createExportWrapper()` does not reset `Module["_OrtRun"]` inside. The release build, however, will - // reset d._OrtRun to J.ka when the first time it is called. - // - // The difference is important because we need to design the async wrapper in a way that it can handle both cases. - // - // Now, let's look at how the async wrapper is designed to work for both cases: - // - // - Debug build: - // 1. When Web assembly is being loaded, `Module["_OrtRun"]` is assigned to `createExportWrapper("OrtRun")`. - // 2. When the first time `Module["jsepInit"]` is called, `Module["_OrtRun"]` is re-assigned to a new async - // wrapper function. - // Value of `Module["_OrtRun"]` will not be changed again. - // - // - Release build: - // 1. When Web assembly is being loaded, `Module["_OrtRun"]` is assigned to a lazy loading wrapper function. - // 2. When the first time `Module["jsepInit"]` is called, `Module["_OrtRun"]` is re-assigned to a new async - // wrapper function. - // 3. When the first time `Module["_OrtRun"]` is called, the async wrapper will be called. It will call into this - // function: - // ``` - // (a, b, c, e, f, h, l, q) => (d._OrtRun = J.ka)(a, b, c, e, f, h, l, q); - // ``` - // This function will assign d._OrtRun (ie. the minimized `Module["_OrtRun"]`) to the real function (J.ka). - // 4. Since d._OrtRun is re-assigned, we need to update the async wrapper to re-assign its stored - // function to the updated value (J.ka), and re-assign the value of `d._OrtRun` back to the async wrapper. - // Value of `Module["_OrtRun"]` will not be changed again. - // - // The value of `Module["_OrtRun"]` will need to be assigned for 2 times for debug build and 4 times for release - // build. - // - // This is why we need this `getFunc` and `setFunc` parameters. They are used to get the current value of an - // exported function and set the new value of an exported function. - // - const jsepWrapAsync = (func, getFunc, setFunc) => { - return (...args) => { - // cache the async data before calling the function. - const previousAsync = Asyncify.currData; - - const previousFunc = getFunc?.(); - const ret = func(...args); - const newFunc = getFunc?.(); - if (previousFunc !== newFunc) { - // The exported function has been updated. - // Set the sync function reference to the new function. - func = newFunc; - // Set the exported function back to the async wrapper. - setFunc(previousFunc); - // Remove getFunc and setFunc. They are no longer needed. - setFunc = null; - getFunc = null; +// This is a wrapper for OrtRun() and OrtRunWithBinding() to ensure that Promises are handled correctly. +const jsepRunAsync = (runAsyncFunc) => { + return async (...args) => { + try { + // Module.jsepSessionState should be null, unless we are in the middle of a session. + // If it is not null, it means that the previous session has not finished yet. + if (Module.jsepSessionState) { + throw new Error("Session already started"); } + const state = (Module.jsepSessionState = { + sessionHandle: args[0], + errors: [], + }); - // If the async data has been changed, it means that the function started an async operation. - if (Asyncify.currData != previousAsync) { - // returns the promise - return Asyncify.whenDone(); - } - // the function is synchronous. returns the result. - return ret; - }; - }; - - // This is a wrapper for OrtRun() and OrtRunWithBinding() to ensure that Promises are handled correctly. - const runAsync = (runAsyncFunc) => { - return async (...args) => { - try { - // Module.jsepSessionState should be null, unless we are in the middle of a session. - // If it is not null, it means that the previous session has not finished yet. - if (Module.jsepSessionState) { - throw new Error('Session already started'); - } - const state = Module.jsepSessionState = {sessionHandle: args[0], errors: []}; - - // Run the acyncified function: OrtRun() or OrtRunWithBinding() - const ret = await runAsyncFunc(...args); + // Run the acyncified function: OrtRun() or OrtRunWithBinding() + const ret = await runAsyncFunc(...args); - // Check if the session is still valid. this object should be the same as the one we set above. - if (Module.jsepSessionState !== state) { - throw new Error('Session mismatch'); - } + // Check if the session is still valid. this object should be the same as the one we set above. + if (Module.jsepSessionState !== state) { + throw new Error("Session mismatch"); + } - // Flush the backend. This will submit all pending commands to the GPU. - Module.jsepBackend?.['flush'](); + // Flush the backend. This will submit all pending commands to the GPU. + Module.jsepBackend?.["flush"](); - // Await all pending promises. This includes GPU validation promises for diagnostic purposes. - const errorPromises = state.errors; - if (errorPromises.length > 0) { - let errors = await Promise.all(errorPromises); - errors = errors.filter(e => e); - if (errors.length > 0) { - throw new Error(errors.join('\n')); - } + // Await all pending promises. This includes GPU validation promises for diagnostic purposes. + const errorPromises = state.errors; + if (errorPromises.length > 0) { + let errors = await Promise.all(errorPromises); + errors = errors.filter((e) => e); + if (errors.length > 0) { + throw new Error(errors.join("\n")); } - - return ret; - } finally { - Module.jsepSessionState = null; } - }; - }; - // replace the original functions with asyncified versions - Module['_OrtCreateSession'] = jsepWrapAsync( - Module['_OrtCreateSession'], - () => Module['_OrtCreateSession'], - v => Module['_OrtCreateSession'] = v); - Module['_OrtRun'] = runAsync(jsepWrapAsync( - Module['_OrtRun'], - () => Module['_OrtRun'], - v => Module['_OrtRun'] = v)); - Module['_OrtRunWithBinding'] = runAsync(jsepWrapAsync( - Module['_OrtRunWithBinding'], - () => Module['_OrtRunWithBinding'], - v => Module['_OrtRunWithBinding'] = v)); - Module['_OrtBindInput'] = jsepWrapAsync( - Module['_OrtBindInput'], - () => Module['_OrtBindInput'], - v => Module['_OrtBindInput'] = v); - - // remove this function to make sure it is called only once. - jsepInitAsync = undefined; + return ret; + } finally { + Module.jsepSessionState = null; + } + }; }; - /** - * initialize JSEP for WebGPU. + * initialize JSEP for WebGPU and WebNN. */ -Module['jsepInit'] = (name, params) => { - jsepInitAsync?.(); - - if (name === 'webgpu') { - [Module.jsepBackend, - Module.jsepAlloc, - Module.jsepFree, - Module.jsepCopy, - Module.jsepCopyAsync, - Module.jsepCreateKernel, - Module.jsepReleaseKernel, - Module.jsepRunKernel, - Module.jsepCaptureBegin, - Module.jsepCaptureEnd, - Module.jsepReplay] = params; +Module["jsepInit"] = (name, params) => { + if (name === "webgpu") { + [ + Module.jsepBackend, + Module.jsepAlloc, + Module.jsepFree, + Module.jsepCopy, + Module.jsepCopyAsync, + Module.jsepCreateKernel, + Module.jsepReleaseKernel, + Module.jsepRunKernel, + Module.jsepCaptureBegin, + Module.jsepCaptureEnd, + Module.jsepReplay, + ] = params; // expose webgpu backend functions const backend = Module.jsepBackend; - Module['jsepRegisterBuffer'] = (sessionId, index, buffer, size) => { - return backend['registerBuffer'](sessionId, index, buffer, size); + Module["jsepRegisterBuffer"] = (sessionId, index, buffer, size) => { + return backend["registerBuffer"](sessionId, index, buffer, size); }; - Module['jsepGetBuffer'] = (dataId) => { - return backend['getBuffer'](dataId); + Module["jsepGetBuffer"] = (dataId) => { + return backend["getBuffer"](dataId); }; - Module['jsepCreateDownloader'] = (gpuBuffer, size, type) => { - return backend['createDownloader'](gpuBuffer, size, type); + Module["jsepCreateDownloader"] = (gpuBuffer, size, type) => { + return backend["createDownloader"](gpuBuffer, size, type); }; - Module['jsepOnCreateSession'] = sessionId => { - backend['onCreateSession'](sessionId); + Module["jsepOnCreateSession"] = (sessionId) => { + backend["onCreateSession"](sessionId); }; - Module['jsepOnReleaseSession'] = sessionId => { - backend['onReleaseSession'](sessionId); + Module["jsepOnReleaseSession"] = (sessionId) => { + backend["onReleaseSession"](sessionId); }; - Module['jsepOnRunStart'] = sessionId => { - return backend['onRunStart'](sessionId); + Module["jsepOnRunStart"] = (sessionId) => { + return backend["onRunStart"](sessionId); }; Module.jsepUploadExternalBuffer = (dataId, buffer) => { - backend['upload'](dataId, buffer); + backend["upload"](dataId, buffer); }; - } else if (name === 'webnn') { + } else if (name === "webnn") { // Functions called from EM_ASM need to be assigned in a way that can be minified. // Functions called via emscripten::val::module_property need to be assigned by name so that the minifier doesn't // change the name. - [Module.jsepBackend, - Module.jsepReserveTensorId, - Module.jsepReleaseTensorId, - Module['jsepEnsureTensor'], - Module.jsepUploadTensor, - Module['jsepDownloadTensor'], + [ + Module.jsepBackend, + Module.jsepReserveTensorId, + Module.jsepReleaseTensorId, + Module["jsepEnsureTensor"], + Module.jsepUploadTensor, + Module["jsepDownloadTensor"], ] = params; // This function is called from both JS and an EM_ASM block, it needs both a minifiable name and an explicit name. - Module['jsepReleaseTensorId'] = Module.jsepReleaseTensorId; - Module['jsepUploadTensor'] = Module.jsepUploadTensor; + Module["jsepReleaseTensorId"] = Module.jsepReleaseTensorId; + Module["jsepUploadTensor"] = Module.jsepUploadTensor; // Functions called from JS also need to have explicit names. const backend = Module.jsepBackend; - Module['jsepOnRunStart'] = sessionId => { - return backend['onRunStart'](sessionId); + Module["jsepOnRunStart"] = (sessionId) => { + return backend["onRunStart"](sessionId); }; - Module['jsepOnRunEnd'] = backend['onRunEnd'].bind(backend); - Module['jsepRegisterMLContext'] = (sessionId, mlContext) => { - backend['registerMLContext'](sessionId, mlContext); + Module["jsepOnRunEnd"] = backend["onRunEnd"].bind(backend); + Module["jsepRegisterMLContext"] = (sessionId, mlContext) => { + backend["registerMLContext"](sessionId, mlContext); }; - Module['jsepOnReleaseSession'] = sessionId => { - backend['onReleaseSession'](sessionId); + Module["jsepOnReleaseSession"] = (sessionId) => { + backend["onReleaseSession"](sessionId); }; - Module['jsepCreateMLTensorDownloader'] = (tensorId, type) => { - return backend['createMLTensorDownloader'](tensorId, type); - } - Module['jsepRegisterMLTensor'] = (sessionId, tensor, dataType, shape) => { - return backend['registerMLTensor'](sessionId, tensor, dataType, shape); + Module["jsepCreateMLTensorDownloader"] = (tensorId, type) => { + return backend["createMLTensorDownloader"](tensorId, type); + }; + Module["jsepRegisterMLTensor"] = (sessionId, tensor, dataType, shape) => { + return backend["registerMLTensor"](sessionId, tensor, dataType, shape); }; - Module['jsepCreateMLContext'] = (optionsOrGpuDevice) => { - return backend['createMLContext'](optionsOrGpuDevice); + Module["jsepCreateMLContext"] = (optionsOrGpuDevice) => { + return backend["createMLContext"](optionsOrGpuDevice); }; - Module['jsepRegisterMLConstant'] = (externalFilePath, dataOffset, dataLength, builder, desc) => { - return backend['registerMLConstant']( - externalFilePath, dataOffset, dataLength, builder, desc, Module.MountedFiles); + Module["jsepRegisterMLConstant"] = ( + externalFilePath, + dataOffset, + dataLength, + builder, + desc + ) => { + return backend["registerMLConstant"]( + externalFilePath, + dataOffset, + dataLength, + builder, + desc, + Module.MountedFiles + ); }; - Module['jsepRegisterGraphInput'] = backend['registerGraphInput'].bind(backend); - Module['jsepIsGraphInput'] = backend['isGraphInput'].bind(backend); + Module["jsepRegisterGraphInput"] = + backend["registerGraphInput"].bind(backend); + Module["jsepIsGraphInput"] = backend["isGraphInput"].bind(backend); - Module['jsepCreateTemporaryTensor'] = backend['createTemporaryTensor'].bind(backend); + Module["jsepCreateTemporaryTensor"] = + backend["createTemporaryTensor"].bind(backend); } }; diff --git a/onnxruntime/wasm/pre.js b/onnxruntime/wasm/pre.js index 9b5f3ce545b78..636a9713519a7 100644 --- a/onnxruntime/wasm/pre.js +++ b/onnxruntime/wasm/pre.js @@ -1,21 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -'use strict'; - // // This file contains the pre-run code for the ORT WebAssembly module. The code in this file will be injected into the // final module using Emscripten's `--pre-js` option. - /** * Mount external data files of a model to an internal map, which will be used during session initialization. * * @param {string} externalDataFilesPath * @param {Uint8Array} externalDataFilesData */ -Module['mountExternalData'] = (externalDataFilePath, externalDataFileData) => { - if (externalDataFilePath.startsWith('./')) { +Module["mountExternalData"] = (externalDataFilePath, externalDataFileData) => { + if (externalDataFilePath.startsWith("./")) { externalDataFilePath = externalDataFilePath.substring(2); } const files = Module.MountedFiles || (Module.MountedFiles = new Map()); @@ -25,7 +22,7 @@ Module['mountExternalData'] = (externalDataFilePath, externalDataFileData) => { /** * Unmount external data files of a model. */ -Module['unmountExternalData'] = () => { +Module["unmountExternalData"] = () => { delete Module.MountedFiles; }; @@ -48,5 +45,7 @@ Module['unmountExternalData'] = () => { * * @suppress {checkVars} */ -var SharedArrayBuffer = globalThis.SharedArrayBuffer ?? - new WebAssembly.Memory({'initial': 0, 'maximum': 0, 'shared': true}).buffer.constructor; +var SharedArrayBuffer = + globalThis.SharedArrayBuffer ?? + new WebAssembly.Memory({ initial: 0, maximum: 0, shared: true }).buffer + .constructor; diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 8607887072347..fe20351b0e8bb 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -1592,8 +1592,11 @@ def generate_build_tree( raise BuildError("WebNN is only available for WebAssembly build.") cmake_args += ["-Donnxruntime_USE_WEBNN=ON"] - if args.use_jsep and args.use_webgpu: - raise BuildError("JSEP (--use_jsep) and WebGPU (--use_webgpu) cannot be enabled at the same time.") + # TODO: currently we allows building with both --use_jsep and --use_webgpu in this working branch. + # This situation is temporary. Eventually, those two flags will be mutually exclusive. + # + # if args.use_jsep and args.use_webgpu: + # raise BuildError("JSEP (--use_jsep) and WebGPU (--use_webgpu) cannot be enabled at the same time.") if args.use_external_dawn and not args.use_webgpu: raise BuildError("External Dawn (--use_external_dawn) must be enabled with WebGPU (--use_webgpu).") From 8f07743597f454b00317939cdb33c1e4e9d6e2a6 Mon Sep 17 00:00:00 2001 From: Yi-Hong Lyu Date: Thu, 6 Mar 2025 16:01:08 -0800 Subject: [PATCH 050/266] Adding OpenVINO Windows CI Pipeline (#23919) ### Description Enable an OpenVINO Windows CI pipeline. This includes: - Downloading the OpenVINO toolkit for Windows from an external source. - Setting up OpenVINO environment variables. - Building the ONNX Runtime OpenVINO Execution Provider. - Running unit tests. ### Motivation and Context This change is required to run checks on precommit and commit in the ONNX Runtime project. It ensures that the code is tested with the OpenVINO toolkit on Windows, improving the reliability and compatibility of the project. --- cmake/onnxruntime_unittests.cmake | 4 +- .../templates/jobs/download_win_openvino.yml | 64 ++++++++++ .../win-openvino-ci-pipeline.yml | 116 ++++++++++++++++++ tools/ci_build/set-trigger-rules.py | 3 +- 4 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/templates/jobs/download_win_openvino.yml create mode 100644 tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index 2ed7923941643..87aee2a174fab 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -236,14 +236,14 @@ function(AddTest) ) endif() # Set test timeout to 3 hours. - set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 7200) + set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 10800) else() add_test(NAME ${_UT_TARGET} COMMAND ${_UT_TARGET} ${TEST_ARGS} WORKING_DIRECTORY $ ) # Set test timeout to 3 hours. - set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 7200) + set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 10800) endif() endif() endfunction(AddTest) diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_openvino.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_openvino.yml new file mode 100644 index 0000000000000..f6956b426ddfc --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_openvino.yml @@ -0,0 +1,64 @@ +parameters: + - name: OpenVINOVersion + type: string + default: '2025.0.0' + +steps: + - powershell: | + $Url = "https://storage.openvinotoolkit.org/repositories/openvino/packages/2025.0/windows/openvino_toolkit_windows_2025.0.0.17942.1f68be9f594_x86_64.zip" + $OutputPath = "$env:Agent_TempDirectory\openvino.zip" + $ExtractPath = "$env:Agent_TempDirectory\openvino-v$env:OpenVINOVersion" + $TempExtractPath = "$env:Agent_TempDirectory\openvino_temp" + + # Ensure directories exist + if (Test-Path $ExtractPath) { + Remove-Item -Recurse -Force $ExtractPath + } + New-Item -ItemType Directory -Path $ExtractPath | Out-Null + New-Item -ItemType Directory -Path $TempExtractPath | Out-Null + + # Download OpenVINO ZIP + Write-Output "Downloading OpenVINO" + Invoke-WebRequest -Uri $Url -OutFile $OutputPath + + # Extract to temporary directory first + Write-Output "Extracting OpenVINO to a temporary directory" + Expand-Archive -Path $OutputPath -DestinationPath $TempExtractPath -Force + + # Locate the nested subdirectory + $InnerFolder = Get-ChildItem -Path $TempExtractPath -Directory | Select-Object -First 1 + + if ($InnerFolder) { + Write-Output "Moving extracted files to final destination" + Move-Item -Path "$($InnerFolder.FullName)\*" -Destination $ExtractPath -Force + } else { + Write-Error "Extraction failed: No expected subdirectory found in $TempExtractPath." + Write-Error "The archive may not have extracted correctly, or its structure is different than expected." + exit 1 + } + + # Clean up temporary files + Remove-Item -Recurse -Force $TempExtractPath + Remove-Item -Force $OutputPath + + # Confirm success + Write-Output "OpenVINO extracted to $ExtractPath" + displayName: 'Download OpenVINO Toolkit v${{ parameters.OpenVINOVersion }}' + env: + OpenVINOVersion: ${{ parameters.OpenVINOVersion }} + + - powershell: | + echo "##vso[task.setvariable variable=OpenVINORootDir]$(Agent.TempDirectory)\openvino-v${{ parameters.OpenVINOVersion }}" + displayName: 'Set OpenVINORootDir' + + - task: CmdLine@2 + inputs: + script: | + echo $(OpenVINORootDir) + displayName: 'Print OpenVINORootDir after downloading OpenVINO' + + - task: CmdLine@2 + displayName: 'Print contents of OpenVINO Toolkit' + inputs: + script: | + dir $(OpenVINORootDir) diff --git a/tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml new file mode 100644 index 0000000000000..f95ac526886fa --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml @@ -0,0 +1,116 @@ +##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### +trigger: + branches: + include: + - main + - rel-* + paths: + exclude: + - docs/** + - README.md + - CONTRIBUTING.md + - BUILD.md + - 'js/web' + - 'onnxruntime/core/providers/js' +pr: + branches: + include: + - main + - rel-* + paths: + exclude: + - docs/** + - README.md + - CONTRIBUTING.md + - BUILD.md + - 'js/web' + - 'onnxruntime/core/providers/js' +#### end trigger #### + +jobs: +- job: 'BUILD_OPENVINO_EP' + pool: 'onnxruntime-Win-CPU-2022' + variables: + MsbuildArguments: '-detailedsummary -maxcpucount -consoleloggerparameters:PerformanceSummary' + OnnxRuntimeBuildDirectory: '$(Build.BinariesDirectory)' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + buildArch: x64 + setVcvars: true + BuildConfig: 'RelWithDebInfo' + ALLOW_RELEASED_ONNX_OPSET_ONLY: '1' + TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] + timeoutInMinutes: 240 + workspace: + clean: all + steps: + + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + addToPath: true + architecture: $(buildArch) + + - template: templates/jobs/download_win_openvino.yml + + - powershell: | + Write-Output "Setting up OpenVINO environment variables" + . "$(OpenVINORootDir)\setupvars.ps1" + + Write-Output "Exporting selected environment variables to pipeline" + + $vars = @( + "INTEL_OPENVINO_DIR", + "OpenVINO_DIR", + "OpenVINOGenAI_DIR", + "OPENVINO_LIB_PATHS", + "TBB_DIR", + "PATH", + "PYTHONPATH" + ) + + foreach ($var in $vars) { + if (Test-Path "Env:$var") { + $value = [System.Environment]::GetEnvironmentVariable($var, "Process") + Write-Output "Setting $var" + Write-Output "##vso[task.setvariable variable=$var;]$value" + } else { + Write-Output "Warning: $var is not set." + } + } + + Write-Output "Selected environment variables exported successfully" + displayName: 'Set up OpenVINO environment' + + - template: templates/jobs/win-ci-build-steps.yml + parameters: + WithCache: True + Today: $(TODAY) + AdditionalKey: "win-openvino | $(BuildConfig)" + BuildPyArguments: >- + --config $(BuildConfig) + --build_dir $(Build.BinariesDirectory) + --cmake_generator "Visual Studio 17 2022" + --build_shared_lib + --use_openvino CPU + --use_binskim_compliant_compile_flags + --update --parallel + MsbuildArguments: $(MsbuildArguments) + BuildArch: $(buildArch) + Platform: 'x64' + BuildConfig: $(BuildConfig) + + - powershell: | + Write-Output "Getting CPU information" + Get-WmiObject Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors, Architecture | Format-Table -AutoSize + + Write-Output "Starting unit tests" + python "$(Build.SourcesDirectory)\tools\ci_build\build.py" ` + --config "$(BuildConfig)" ` + --build_dir "$(Build.BinariesDirectory)" ` + --cmake_generator "Visual Studio 17 2022" ` + --build_shared_lib ` + --use_openvino CPU ` + --use_binskim_compliant_compile_flags ` + --test --enable_onnx_tests + displayName: 'Run unit tests' diff --git a/tools/ci_build/set-trigger-rules.py b/tools/ci_build/set-trigger-rules.py index 78f59452d1284..899aaaa95216a 100644 --- a/tools/ci_build/set-trigger-rules.py +++ b/tools/ci_build/set-trigger-rules.py @@ -16,8 +16,6 @@ "android-x86_64-crosscompile-ci-pipeline.yml", "bigmodels-ci-pipeline.yml", "linux-ci-pipeline.yml", - "linux-cpu-aten-pipeline.yml", - "linux-cpu-eager-pipeline.yml", "linux-dnnl-ci-pipeline.yml", "linux-gpu-ci-pipeline.yml", "linux-gpu-tensorrt-ci-pipeline.yml", @@ -36,6 +34,7 @@ "win-gpu-doc-gen-ci-pipeline.yml", "win-gpu-tensorrt-ci-pipeline.yml", "win-gpu-webgpu-ci-pipeline.yml", + "win-openvino-ci-pipeline.yml", "win-qnn-arm64-ci-pipeline.yml", "win-qnn-ci-pipeline.yml", ] From 4bb79d13a06c6a02d522b736f030070bdfe752cb Mon Sep 17 00:00:00 2001 From: vraspar Date: Thu, 6 Mar 2025 16:46:56 -0800 Subject: [PATCH 051/266] [WebGPU EP] SoftMax Implementation (#23538) Increase coverage for WebGPU Op --- .../core/providers/webgpu/math/softmax.cc | 238 ++++++++++++++++++ .../core/providers/webgpu/math/softmax.h | 54 ++++ .../core/providers/webgpu/tensor/transpose.cc | 60 +++-- .../core/providers/webgpu/tensor/transpose.h | 2 + .../webgpu/webgpu_execution_provider.cc | 6 +- .../test/providers/cpu/math/softmax_test.cc | 13 +- 6 files changed, 344 insertions(+), 29 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/math/softmax.cc create mode 100644 onnxruntime/core/providers/webgpu/math/softmax.h diff --git a/onnxruntime/core/providers/webgpu/math/softmax.cc b/onnxruntime/core/providers/webgpu/math/softmax.cc new file mode 100644 index 0000000000000..d06fc5a57eb8c --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/softmax.cc @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include + +#include "core/common/inlined_containers.h" +#include "core/providers/common.h" +#include "core/providers/webgpu/math/softmax.h" +#include "core/providers/webgpu/tensor/transpose.h" +#include "core/providers/cpu/tensor/utils.h" +#include "core/providers/webgpu/shader_variable.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +namespace onnxruntime { +namespace webgpu { + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Softmax, + kOnnxDomain, + 1, 10, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Softmax); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Softmax, + kOnnxDomain, + 11, 12, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Softmax); + +ONNX_OPERATOR_KERNEL_EX( + Softmax, + kOnnxDomain, + 13, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedNumberTypes()), + Softmax); + +static std::string MaxVector(const std::string& name, int components) { + switch (components) { + case 1: + return name; + case 2: + return "max(" + name + ".x, " + name + ".y)"; + case 3: + return "max(max(" + name + ".x, " + name + ".y), " + name + ".z)"; + case 4: + return "max(max(" + name + ".x, " + name + ".y), max(" + name + ".z, " + name + ".w))"; + default: + ORT_THROW("Unsupported number of components: ", components); + } +} + +static std::string SumVector(const std::string& x, int components) { + switch (components) { + case 1: + return x; + case 2: + return "(" + x + ".x + " + x + ".y" + ")"; + case 4: + return "(" + x + ".x + " + x + ".y + " + x + ".w + " + x + ".z" + ")"; + default: + ORT_THROW("Unsupported number of components: ", components); + } +} + +static int GetMaxComponents(int64_t size) { + if (size % 4 == 0) { + return 4; + } else if (size % 2 == 0) { + return 2; + } + return 1; +} + +Status SoftmaxProgram::GenerateShaderCode(ShaderHelper& shader) const { + // Add input and output variables + const auto& input = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + shader.AddOutput("result", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias); + int components = input.NumComponents(); + + const std::string thread_max_decl = is_fp32_ + ? "var thread_max = x_value_t(-3.402823e+38f);\n" + : "var thread_max = x_value_t(-65504.0h);\n"; + + // Define shared memory for row max and row sum + shader.AdditionalImplementation() + << "var row_max_shared : x_value_t;\n" + << "var row_sum_shared : x_value_t;\n" + << "var thread_shared : array;\n"; + + // Define helper functions to get and set values + shader.AdditionalImplementation() + << "fn getValue(row: i32, col: i32, row_stride: i32) -> x_value_t {\n" + << " let index = row * row_stride + col;\n" + << " return x[index];\n" + << "}\n" + << "fn setValue(row: i32, col: i32, row_stride: i32, value: x_value_t) {\n" + << " let index = row * row_stride + col;\n" + << " result[index] = value;\n" + << "}\n"; + + // Main function body + shader.MainFunctionBody() + << " let gindex = i32(global_idx);\n" + << " let lindex = i32(local_idx);\n" + << " const wg = " << wg_ << ";\n" + << " let row = gindex / wg;\n" + << " let cols = uniforms.packedCols;\n" + << " let row_stride : i32 = uniforms.packedCols;\n" + + // Find the row's max value + << thread_max_decl + << " for (var col = lindex; col < cols; col += wg) {\n" + << " let value = getValue(row, col, row_stride);\n" + << " thread_max = max(thread_max, value);\n" + << " }\n" + << " if (lindex < cols) {\n" + << " thread_shared[lindex] = thread_max;\n" + << " }\n" + << " workgroupBarrier();\n" + + // Reduce to find the max value + << " var reduce_size = min(cols, wg);\n" + << " for (var curr_size = reduce_size >> 1; curr_size > 0; curr_size = reduce_size >> 1) {\n" + << " reduce_size = curr_size + (reduce_size & 1);\n" + << " if (lindex < curr_size) {\n" + << " thread_shared[lindex] = max(thread_shared[lindex], thread_shared[lindex + reduce_size]);\n" + << " }\n" + << " workgroupBarrier();\n" + << " }\n" + << " if (lindex == 0) {\n" + << " row_max_shared = x_value_t(" << MaxVector("thread_shared[0]", components) << ");\n" + << " }\n" + << " workgroupBarrier();\n" + + // Find the row's sum of exponentials + << " var thread_sum = x_value_t(0.0);\n" + << " for (var col = lindex; col < cols; col += wg) {\n" + << " let sub_exp = exp(getValue(row, col, row_stride) - row_max_shared);\n" + << " thread_sum += sub_exp;\n" + << " }\n" + << " thread_shared[lindex] = thread_sum;\n" + << " workgroupBarrier();\n" + + // Reduce to find the sum of exponentials + << " for (var curr_size = wg >> 1; curr_size > 0; curr_size = curr_size >> 1) {\n" + << " if (lindex < curr_size) {\n" + << " thread_shared[lindex] = thread_shared[lindex] + thread_shared[lindex + curr_size];\n" + << " }\n" + << " workgroupBarrier();\n" + << " }\n" + << " if (lindex == 0) {\n" + << " row_sum_shared = x_value_t(" << SumVector("thread_shared[0]", components) << ");\n" + << " }\n" + << " workgroupBarrier();\n" + + // Calculate the final value for each element in the row + << " for (var col = lindex; col < cols; col += wg) {\n" + << " let value = exp(getValue(row, col, row_stride) - row_max_shared) / row_sum_shared;\n" + << " setValue(row, col, row_stride, value);\n" + << " }\n"; + + return Status::OK(); +} + +Status Softmax::ComputeInternal(ComputeContext& context) const { + const auto* input_tensor = context.Input(0); + const TensorShape& input_shape = input_tensor->Shape(); + size_t input_rank = input_shape.NumDimensions(); + auto* output_tensor = context.Output(0, input_shape); + + // normalize axis + size_t axis = static_cast(HandleNegativeAxis(axis_, input_rank)); + bool is_transpose_required = axis < input_rank - 1; + + TensorShape transposed_input_shape; + Tensor transposed_input_tensor; + Tensor intermediate_output; + InlinedVector perm(input_rank); + + if (is_transpose_required) { + std::iota(std::begin(perm), std::end(perm), 0); + perm[axis] = input_rank - 1; + perm[input_rank - 1] = axis; + + TensorShapeVector transposed_input_dims; + for (auto e : perm) { + transposed_input_dims.push_back(input_shape[e]); + } + + transposed_input_shape = TensorShape(transposed_input_dims); + transposed_input_tensor = context.CreateGPUTensor(input_tensor->DataType(), transposed_input_shape); + ORT_RETURN_IF_ERROR(Transpose::DoTranspose(context, perm, *input_tensor, transposed_input_tensor)); + intermediate_output = context.CreateGPUTensor(output_tensor->DataType(), transposed_input_shape); + } + + const int64_t cols = is_transpose_required ? transposed_input_shape[input_rank - 1] : input_shape[input_rank - 1]; + const int64_t rows = input_shape.Size() / cols; + const int64_t components = GetMaxComponents(cols); + const auto packed_cols = cols / components; + uint32_t workgroup_size = rows == 1 ? 256 : 64; + // check input tensor element type is float + const bool is_fp32 = input_tensor->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT; + + SoftmaxProgram program{workgroup_size, is_fp32}; + if (is_transpose_required) { + program + .AddInputs({{&transposed_input_tensor, ProgramTensorMetadataDependency::TypeAndRank, static_cast(components)}}) + .AddOutputs({{&intermediate_output, ProgramTensorMetadataDependency::TypeAndRank, static_cast(components)}}); + } else { + program + .AddInputs({{input_tensor, ProgramTensorMetadataDependency::TypeAndRank, static_cast(components)}}) + .AddOutputs({{output_tensor, ProgramTensorMetadataDependency::TypeAndRank, static_cast(components)}}); + } + + program + .CacheHint(std::to_string(components), std::to_string(workgroup_size)) + .SetWorkgroupSize(workgroup_size) + .SetDispatchGroupSize(static_cast(rows)) + .AddUniformVariables({{static_cast(packed_cols)}}); + + ORT_RETURN_IF_ERROR(context.RunProgram(program)); + + // If transpose was required, transpose the result back + if (is_transpose_required) { + ORT_RETURN_IF_ERROR(Transpose::DoTranspose(context, perm, intermediate_output, *output_tensor)); + } + + return Status::OK(); +} +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/math/softmax.h b/onnxruntime/core/providers/webgpu/math/softmax.h new file mode 100644 index 0000000000000..cc97611dcb4bc --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/softmax.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/framework/op_kernel.h" + +namespace onnxruntime { +namespace webgpu { + +class Softmax final : public WebGpuKernel { + public: + Softmax(const OpKernelInfo& info) : WebGpuKernel{info} { + int opset_ = info.node().SinceVersion(); + int64_t axis; + Status status = info.GetAttr("axis", &axis); + + if (status.IsOK()) { + axis_ = axis; + } else { + if (opset_ < 13) { + axis_ = 1; // opset-12 and below, the default axis value is 1 + } else { + axis_ = -1; // opset-13, the default axis value is -1 + } + } + } + + Status ComputeInternal(ComputeContext& context) const override; + + private: + int64_t axis_; +}; + +class SoftmaxProgram final : public Program { + public: + SoftmaxProgram(uint32_t wg, bool is_fp32) + : Program{"Softmax"}, wg_{wg}, is_fp32_{is_fp32} { + } + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"packedCols", ProgramUniformVariableDataType::Int32}); + + private: + uint32_t wg_; + bool is_fp32_; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/transpose.cc b/onnxruntime/core/providers/webgpu/tensor/transpose.cc index c40ec43dd0009..24b98e9533d17 100644 --- a/onnxruntime/core/providers/webgpu/tensor/transpose.cc +++ b/onnxruntime/core/providers/webgpu/tensor/transpose.cc @@ -47,7 +47,10 @@ ONNX_OPERATOR_KERNEL_EX( .TypeConstraint("T", WebGpuSupportedNumberTypes()), Transpose); -auto SqueezeShape(const gsl::span& shape, const gsl::span& adjusted_perm, InlinedVector& new_shape, InlinedVector& new_perm) { +auto SqueezeShape(const gsl::span& shape, + const gsl::span& adjusted_perm, + TensorShapeVector& new_shape, + TensorShapeVector& new_perm) { for (size_t i = 0; i < shape.size(); ++i) { if (shape[i] != 1) { new_shape.push_back(shape[i]); @@ -97,26 +100,28 @@ Status TransposeProgram::GenerateShaderCode(ShaderHelper& shader) const { return Status::OK(); } -Status Transpose::ComputeInternal(ComputeContext& context) const { - const auto* input_tensor = context.Input(0); - const TensorShape& input_shape = input_tensor->Shape(); +Status Transpose::DoTranspose(onnxruntime::webgpu::ComputeContext& context, + gsl::span permutations, + const Tensor& input, Tensor& output) { + const auto& input_shape = input.Shape(); + const auto& input_dims = input_shape.GetDims(); int32_t rank = gsl::narrow_cast(input_shape.NumDimensions()); TensorShapeVector output_dims(rank); - InlinedVector default_perm(rank); - const InlinedVector* p_perm = nullptr; - ORT_RETURN_IF_ERROR(ComputeOutputShape(*input_tensor, output_dims, default_perm, p_perm)); - TensorShape output_shape(output_dims); - auto* output_tensor = context.Output(0, output_shape); - InlinedVector new_shape{}; - InlinedVector new_perm{}; - SqueezeShape(input_shape.GetDims(), *p_perm, new_shape, new_perm); - const bool channels_last = new_perm == InlinedVector({2, 3, 1}); - const bool channels_first = new_perm == InlinedVector({3, 1, 2}); + for (int32_t i = 0; i < rank; i++) { + output_dims[i] = input_dims[permutations[i]]; + } + + TensorShapeVector new_shape{}; + TensorShapeVector new_perm{}; + SqueezeShape(input_shape.GetDims(), permutations, new_shape, new_perm); + const bool channels_last = new_perm == TensorShapeVector({2, 3, 1}); + const bool channels_first = new_perm == TensorShapeVector({3, 1, 2}); const bool use_shared = (new_shape.size() == 2 && new_perm[0] > new_perm[1]) || channels_last || channels_first; auto new_input_shape = input_shape; TensorShape new_output_shape(output_dims); + if (use_shared) { new_input_shape = channels_last ? TensorShape({new_shape[0], new_shape[1] * new_shape[2]}) @@ -126,16 +131,16 @@ Status Transpose::ComputeInternal(ComputeContext& context) const { new_output_shape = TensorShape({new_input_shape[1], new_input_shape[0]}); } - uint32_t output_size = gsl::narrow_cast(input_tensor->Shape().Size()); - TransposeProgram program{*p_perm, use_shared}; + uint32_t output_size = gsl::narrow_cast(input_shape.Size()); + TransposeProgram program{permutations, use_shared}; + if (use_shared) { program.SetWorkgroupSize(TILE_SIZE, TILE_SIZE, 1); } - program - .CacheHint(absl::StrJoin(*p_perm, "-")) - .AddInputs({{input_tensor, ProgramTensorMetadataDependency::TypeAndRank, new_input_shape, 1}}) - .AddOutputs({{output_tensor, ProgramTensorMetadataDependency::None, new_output_shape, 1}}) + .CacheHint(absl::StrJoin(permutations, "-")) + .AddInputs({{&input, ProgramTensorMetadataDependency::TypeAndRank, new_input_shape, 1}}) + .AddOutputs({{&output, ProgramTensorMetadataDependency::None, new_output_shape, 1}}) .SetDispatchGroupSize(static_cast((new_output_shape[1] + TILE_SIZE - 1) / TILE_SIZE), static_cast(((new_output_shape[0] + TILE_SIZE - 1) / TILE_SIZE))) .AddUniformVariables({ @@ -148,5 +153,20 @@ Status Transpose::ComputeInternal(ComputeContext& context) const { return context.RunProgram(program); } +Status Transpose::ComputeInternal(ComputeContext& context) const { + const auto* input_tensor = context.Input(0); + const TensorShape& input_shape = input_tensor->Shape(); + int32_t rank = gsl::narrow_cast(input_shape.NumDimensions()); + + TensorShapeVector output_dims(rank); + InlinedVector default_perm(rank); + const InlinedVector* p_perm = nullptr; + ORT_RETURN_IF_ERROR(ComputeOutputShape(*input_tensor, output_dims, default_perm, p_perm)); + TensorShape output_shape(output_dims); + auto* output_tensor = context.Output(0, output_shape); + + return DoTranspose(context, *p_perm, *input_tensor, *output_tensor); +} + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/transpose.h b/onnxruntime/core/providers/webgpu/tensor/transpose.h index 7cf5c1fe0865d..b62a419fa12bc 100644 --- a/onnxruntime/core/providers/webgpu/tensor/transpose.h +++ b/onnxruntime/core/providers/webgpu/tensor/transpose.h @@ -16,6 +16,8 @@ class Transpose final : public WebGpuKernel, public TransposeBase { Transpose(const OpKernelInfo& info) : WebGpuKernel{info}, TransposeBase{info} { } Status ComputeInternal(ComputeContext& context) const override; + static Status DoTranspose(onnxruntime::webgpu::ComputeContext& context, gsl::span permutations, const Tensor& input, Tensor& output); + constexpr static uint32_t TILE_SIZE = 16; }; diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index d673f9d0717f0..f3bf2402252b7 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -628,9 +628,9 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/test/providers/cpu/math/softmax_test.cc b/onnxruntime/test/providers/cpu/math/softmax_test.cc index 6f7930f722564..1c6375ebdb0b1 100644 --- a/onnxruntime/test/providers/cpu/math/softmax_test.cc +++ b/onnxruntime/test/providers/cpu/math/softmax_test.cc @@ -170,11 +170,11 @@ TEST(SoftmaxOperator, ThreeAndFourDimsAxis0) { RunTest(input_vals_60, expected_vals, three_dimensions, /*opset*/ 7, /*axis*/ 0, // axis=0 is not supported by TensorRT - {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider}); + {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider, kWebGpuExecutionProvider}); RunTest(input_vals_60, expected_vals, four_dimensions, /*opset*/ 7, /*axis*/ 0, // axis=0 is not supported by TensorRT - {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider}); + {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider, kWebGpuExecutionProvider}); } TEST(SoftmaxOperator, ThreeAndFourDimsSecondLastAxis) { @@ -201,10 +201,10 @@ TEST(SoftmaxOperator, ThreeAndFourDimsSecondLastAxis) { 0.040478885f, 0.033857856f, 0.080346674f, 0.06199841f, 0.040481992f}; RunTest(input_vals_60, expected_vals, three_dimensions, /*opset*/ 7, /*axis*/ 1, - {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider}); + {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider, kWebGpuExecutionProvider}); RunTest(input_vals_60, expected_vals, four_dimensions, /*opset*/ 7, /*axis*/ 2, - {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider}); + {kTensorrtExecutionProvider, kOpenVINOExecutionProvider, kDnnlExecutionProvider, kWebGpuExecutionProvider}); } TEST(SoftmaxOperator, ThreeAndFourDimsSecondLastAxis_opset13) { @@ -376,8 +376,9 @@ TEST(SoftmaxOperator, DimWithZero) { RunTest(x_vals, expected_vals, dimensions, /*opset*/ -1, /*axis*/ 0, {kTensorrtExecutionProvider, - kNnapiExecutionProvider, // NNAPI softmax does not support empty input - kQnnExecutionProvider} // QNN doesn't support dim 0 + kNnapiExecutionProvider, // NNAPI softmax does not support empty input + kWebGpuExecutionProvider, // WebGPU does not support dim 0 + kQnnExecutionProvider} // QNN doesn't support dim 0 ); } From b2ab87e8b76edc67aeba5ba31093bae94efc64fb Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Fri, 7 Mar 2025 11:24:10 +1000 Subject: [PATCH 052/266] Exclude MAUI projects from GPU C# packaging builds (#23923) ### Description Use 'desktop only' solution in GPU C# packaging builds. We don't need to include any MAUI support for those builds. ### Motivation and Context --- .../rocm-nuget-packaging-pipeline.yml | 6 +++--- .../stages/nuget-cuda-packaging-stage.yml | 15 +++------------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml index f7f5c7b1494e8..286f92b36f7e4 100644 --- a/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml @@ -224,7 +224,7 @@ stages: - task: MSBuild@1 displayName: 'Restore NuGet Packages and create project.assets.json' inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.sln' + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' platform: 'Any CPU' configuration: RelWithDebInfo msbuildArguments: '-t:restore -p:OrtPackageId="Microsoft.ML.OnnxRuntime.ROCm"' @@ -233,7 +233,7 @@ stages: - task: MSBuild@1 displayName: 'Build C# bindings' inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.sln' + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' platform: 'Any CPU' configuration: RelWithDebInfo msbuildArguments: > @@ -317,7 +317,7 @@ stages: - task: MSBuild@1 displayName: 'Clean C#' inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.sln' + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' platform: 'Any CPU' configuration: RelWithDebInfo msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.ROCm' diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml index 8fabb80a73869..5ae60aac8f9b4 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml @@ -96,18 +96,10 @@ stages: inputs: versionSpec: 6.10.x - - task: PowerShell@2 - displayName: Install MAUI workloads - inputs: - targetType: 'inline' - script: | - dotnet workload install android ios maccatalyst - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - task: MSBuild@1 displayName: 'Restore NuGet Packages and create project.assets.json' inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.sln' + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' platform: 'Any CPU' configuration: RelWithDebInfo msbuildArguments: '-t:restore -p:OrtPackageId="Microsoft.ML.OnnxRuntime.Gpu"' @@ -116,7 +108,7 @@ stages: - task: MSBuild@1 displayName: 'Build C# bindings' inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.sln' + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' configuration: RelWithDebInfo platform: 'Any CPU' msbuildArguments: > @@ -208,7 +200,7 @@ stages: - task: MSBuild@1 displayName: 'Clean C#' inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.sln' + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' platform: 'Any CPU' configuration: RelWithDebInfo msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu' @@ -223,4 +215,3 @@ stages: inputs: artifactName: 'drop-signed-nuget-GPU' targetPath: '$(Build.ArtifactStagingDirectory)' - From eeaf73b3f418f829acc17f3212056959e5703cd5 Mon Sep 17 00:00:00 2001 From: Sushanth Rajasankar <44513542+sushraja-msft@users.noreply.github.com> Date: Thu, 6 Mar 2025 17:44:37 -0800 Subject: [PATCH 053/266] Support all block sizes that are multiples of 32 for DP4A (#23907) ### Description Simple change 1. The DP4A shader actually supports all block sizes that are multiples of 32, relaxing the restriction and making a small tweak to support sizes other than 32. 2. Moved the shader to a separate file for maintainability. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../webgpu/quantization/dp4a_matmul_nbits.cc | 326 ++++++++++++++++++ .../webgpu/quantization/dp4a_matmul_nbits.h | 56 +++ .../webgpu/quantization/matmul_nbits.cc | 297 +--------------- .../webgpu/quantization/matmul_nbits.h | 19 - 4 files changed, 387 insertions(+), 311 deletions(-) create mode 100644 onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc create mode 100644 onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc new file mode 100644 index 0000000000000..6720a6072f7bb --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc @@ -0,0 +1,326 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h" +#include "core/providers/webgpu/shader_helper.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +Status DP4AMatMulQuantizeProgram::GenerateShaderCode(ShaderHelper& shader) const { + shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + shader.AddOutput("output", ShaderUsage::UseUniform); + shader.AddOutput("scales", ShaderUsage::UseUniform); + shader.AdditionalImplementation() << R"ADDNL_FN( + fn readInput(offset: u32) -> input_a_value_t + { + if (offset > uniforms.input_size) { + return input_a_value_t(0); + } + return input_a[offset]; + } + )ADDNL_FN"; + shader.MainFunctionBody() << R"MAIN_FN( + var local_a : array, 32>; + var max_value:vec4 = vec4(0); + for (var idx:u32=0;idx<32;idx+=1) + { + local_a[idx] = readInput(workgroup_idx*32 + idx); + max_value = max(max_value, abs(local_a[idx])); + } + var scale = max(max_value.x, max_value.y); + scale = max(scale, max_value.z); + scale = max(scale, max_value.w); + for (var idx:u32=0;idx<32;idx+=1) + { + output[workgroup_idx*32+idx] = pack4x8snorm(vec4(local_a[idx]/scale)); + } + // 127 is the max value of signed int8 [-127,127] used by pack4x8snorm for 1.0f. + scales[workgroup_idx] = scale/127; + )MAIN_FN"; + return Status::OK(); +} + +Status DP4AMatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { + shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + shader.AddInput("scales_a", ShaderUsage::UseUniform); + shader.AddInput("input_b", ShaderUsage::UseUniform); + shader.AddInput("scales_b", ShaderUsage::UseUniform); + shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseElementTypeAlias); + + // This shader implements co-operative matrix multiply. The key idea here is to + // assume there is a primitive for medium size matrix multiply a subgroup can perform, + // using all its lanes and pooling all its registers to keep the values in registry. + // + // The entire workgroup which has N subgroups first loads a tile into shared memory, + // Then each subgroup loads a subtile from shared memory into registers and uses + // the medium size matrix multiply primitive to perform the math. + // The values for tile/subtile size are chosen to conform to the resource limits + // of an alderlake/tiger lake gpu. A tile is 64x64, workgroup is 256 threads - + // therefore there are 16 subgroups and 16 lanes in each subgroup. + // K the hidden dimension is paged in from RAM at k tile size which is 64. + // All this puts the shared memory requirement slightly above 16KB. + // WebGPU limit is 16KB, output is moved to registers instead of SHM to make + // everything fit in shared memory. + // + // Each subgroup performs a 16 x 64 x 16 multiply which is implemented with + // subgroup shuffle as a placeholder for the day the medium matrix mul primitive + // becomes available in WGSL. The registry requirements is ~2KB per subgroup, on + // Alderlake/Tigerlake subgroup has 8KB of registry space pooling the + // 512B of registry from each lane. + // + // The medium size matmul is implemented using dot4I8Packed, so the inputs for + // this shader require A to be int8 quantized with block size 64. B is regular + // matmulnbits input with block size 32. + + shader.AdditionalImplementation() << " const block_size = " << block_size_ << ";"; + + shader.AdditionalImplementation() << R"ADDNL_FN( + const tile_size = 64; + const subtile_size = 16; + const tile_size_k = 32; + const vec_factor = 4; + const u32_factor = 4; + const tile_size_k_vec = 2; + + // Shared memory + var tile_A : array, tile_size>, tile_size_k_vec>; // 64 x 32 + var scale_A : array; // 64 x 1 + var tile_B : array, tile_size>, tile_size_k_vec>; // 64 x 32 + var scale_B : array; // 64 x 1 + + fn loadSHMA(a_global_base:u32, kidx_v:u32, row: u32, col: u32) + { + let a_global = a_global_base + row; + if (a_global >= uniforms.M) + { + return; + } + tile_A[col][row] = input_a[a_global*uniforms.K16+kidx_v+col]; + if (col == 0) + { + // kidx_v - covers 16 values of k + scale_A[row] = scales_a[a_global*(uniforms.K/128) + kidx_v/8]; + } + } + + fn loadSHMB(b_global_base:u32, kidx_v:u32, row: u32, col: u32) + { + let b_global = b_global_base + row; + if (b_global >= uniforms.N) + { + return; + } + + let b_value = input_b[b_global*uniforms.K16+kidx_v+col]; + var b_value_lower = vec4(unpack4xU8(b_value[0] & 0x0F0F0F0Fu)) - vec4(8); + var b_value_upper = vec4(unpack4xU8((b_value[0] >> 4) & 0x0F0F0F0Fu)) - vec4(8); + tile_B[col][row][0] = pack4xI8(vec4(b_value_lower[0], b_value_upper[0], b_value_lower[1], b_value_upper[1])); + tile_B[col][row][1] = pack4xI8(vec4(b_value_lower[2], b_value_upper[2], b_value_lower[3], b_value_upper[3])); + b_value_lower = vec4(unpack4xU8(b_value[1] & 0x0F0F0F0Fu)) - vec4(8); + b_value_upper = vec4(unpack4xU8((b_value[1] >> 4) & 0x0F0F0F0Fu)) - vec4(8); + tile_B[col][row][2] = pack4xI8(vec4(b_value_lower[0], b_value_upper[0], b_value_lower[1], b_value_upper[1])); + tile_B[col][row][3] = pack4xI8(vec4(b_value_lower[2], b_value_upper[2], b_value_lower[3], b_value_upper[3])); + if (col == 0) + { + // kidx_v - each kidx_v covers 16 values of k + scale_B[row] = scales_b[b_global*(uniforms.K/block_size) + kidx_v/(block_size/16)]; + } + } + + // Scaled dot product of 8 packed unsigned integers. + fn SDP8AI(a1:vec4, b1:vec4, a2:vec4, b2:vec4, scale:output_element_t) -> output_element_t + { + var local_sum = dot4I8Packed(a1[0], b1[0]); + local_sum += dot4I8Packed(a1[1], b1[1]); + local_sum += dot4I8Packed(a1[2], b1[2]); + local_sum += dot4I8Packed(a1[3], b1[3]); + local_sum += dot4I8Packed(a2[0], b2[0]); + local_sum += dot4I8Packed(a2[1], b2[1]); + local_sum += dot4I8Packed(a2[2], b2[2]); + local_sum += dot4I8Packed(a2[3], b2[3]); + return output_element_t(local_sum) * scale; + } + )ADDNL_FN"; + + shader.MainFunctionBody() << R"MAIN_FN( + // During the load phase we use all 256 threads to load 64 rows of A/B. + // For each row we load tile_size_k_vec (2) vectorized elements, which are 32 elements of K. + let a_global_base = workgroup_id.x * tile_size; + let b_global_base = workgroup_id.y * tile_size; + let load_AorB = u32(local_idx/128); + let load_row = u32((local_idx%128)/2); + let load_col = u32(local_idx%2); + + // During the compute phase, we have the 64x64 tile split into + // subtiles of 16x16. We have a grid of 4x4 subtiles. + let subtile_id = u32(local_idx / subtile_size); + let subtile_idx = u32(subtile_id / 4); + let subtile_idy = u32(subtile_id % 4); + let base_A = subtile_idx * 16; + let base_B = subtile_idy * 16; + // For each subtile we have 16 threads assigned. + let a_idx = u32(local_idx % subtile_size); + + var lane_output1: vec4; + var lane_output2: vec4; + var lane_output3: vec4; + var lane_output4: vec4; + // K's vectrorization is 16 items per index. See input_a/input_b. + // tile_size_k_vec - is the k tile size in vectorized space (1/16). That is + // k tile size is 32. In vectorized space that is 32/16 = 2. + for (var kidx_v:u32 = 0; kidx_v < uniforms.K16; kidx_v+=tile_size_k_vec) + { + // Load Phase: Populate shared memory for the workgroup. + if (load_AorB == 0) + { + loadSHMA(a_global_base, kidx_v, load_row, load_col); + } + else + { + loadSHMB(b_global_base, kidx_v, load_row, load_col); + } + workgroupBarrier(); + + // Compute phase: Perform matmul for this subtile 16 x 32 x 16. + // Step 1: Load from shared memory into registers across entire subgroup. + var own_a0: vec4 = tile_A[0][base_A + a_idx]; + var own_a1: vec4 = tile_A[1][base_A + a_idx]; + var own_scale_a: output_element_t = scale_A[base_A + a_idx]; + if (sg_size == 16) + { + var own_b0: vec4 = tile_B[0][base_B + sg_id]; + var own_b1: vec4 = tile_B[1][base_B + sg_id]; + var own_scale_b: output_element_t = scale_B[base_B + sg_id]; + // Step 2: Access registers across the subgroup using subgroupShuffle and perform the matmul. + lane_output1[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 0), own_a1, subgroupShuffle(own_b1, 0), subgroupShuffle(own_scale_b, 0) * own_scale_a); + lane_output1[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 1), own_a1, subgroupShuffle(own_b1, 1), subgroupShuffle(own_scale_b, 1) * own_scale_a); + lane_output1[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 2), own_a1, subgroupShuffle(own_b1, 2), subgroupShuffle(own_scale_b, 2) * own_scale_a); + lane_output1[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 3), own_a1, subgroupShuffle(own_b1, 3), subgroupShuffle(own_scale_b, 3) * own_scale_a); + + lane_output2[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 4), own_a1, subgroupShuffle(own_b1, 4), subgroupShuffle(own_scale_b, 4) * own_scale_a); + lane_output2[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 5), own_a1, subgroupShuffle(own_b1, 5), subgroupShuffle(own_scale_b, 5) * own_scale_a); + lane_output2[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 6), own_a1, subgroupShuffle(own_b1, 6), subgroupShuffle(own_scale_b, 6) * own_scale_a); + lane_output2[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 7), own_a1, subgroupShuffle(own_b1, 7), subgroupShuffle(own_scale_b, 7) * own_scale_a); + + lane_output3[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 8), own_a1, subgroupShuffle(own_b1, 8), subgroupShuffle(own_scale_b, 8) * own_scale_a); + lane_output3[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 9), own_a1, subgroupShuffle(own_b1, 9), subgroupShuffle(own_scale_b, 9) * own_scale_a); + lane_output3[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 10), own_a1, subgroupShuffle(own_b1, 10), subgroupShuffle(own_scale_b, 10) * own_scale_a); + lane_output3[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 11), own_a1, subgroupShuffle(own_b1, 11), subgroupShuffle(own_scale_b, 11) * own_scale_a); + + lane_output4[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 12), own_a1, subgroupShuffle(own_b1, 12), subgroupShuffle(own_scale_b, 12) * own_scale_a); + lane_output4[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 13), own_a1, subgroupShuffle(own_b1, 13), subgroupShuffle(own_scale_b, 13) * own_scale_a); + lane_output4[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 14), own_a1, subgroupShuffle(own_b1, 14), subgroupShuffle(own_scale_b, 14) * own_scale_a); + lane_output4[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 15), own_a1, subgroupShuffle(own_b1, 15), subgroupShuffle(own_scale_b, 15) * own_scale_a); + } + else + { + // Code for other subgroup sizes, simply doesnt use subgroups at all. + // Relies on reads from single location tile_B[][base_B + col] by all + // being optimized by the hardware. + lane_output1[0] += SDP8AI(own_a0, tile_B[0][base_B + 0], own_a1, tile_B[1][base_B + 0], own_scale_a * scale_B[base_B + 0]); + lane_output1[1] += SDP8AI(own_a0, tile_B[0][base_B + 1], own_a1, tile_B[1][base_B + 1], own_scale_a * scale_B[base_B + 1]); + lane_output1[2] += SDP8AI(own_a0, tile_B[0][base_B + 2], own_a1, tile_B[1][base_B + 2], own_scale_a * scale_B[base_B + 2]); + lane_output1[3] += SDP8AI(own_a0, tile_B[0][base_B + 3], own_a1, tile_B[1][base_B + 3], own_scale_a * scale_B[base_B + 3]); + + lane_output2[0] += SDP8AI(own_a0, tile_B[0][base_B + 4], own_a1, tile_B[1][base_B + 4], own_scale_a * scale_B[base_B + 4]); + lane_output2[1] += SDP8AI(own_a0, tile_B[0][base_B + 5], own_a1, tile_B[1][base_B + 5], own_scale_a * scale_B[base_B + 5]); + lane_output2[2] += SDP8AI(own_a0, tile_B[0][base_B + 6], own_a1, tile_B[1][base_B + 6], own_scale_a * scale_B[base_B + 6]); + lane_output2[3] += SDP8AI(own_a0, tile_B[0][base_B + 7], own_a1, tile_B[1][base_B + 7], own_scale_a * scale_B[base_B + 7]); + + lane_output3[0] += SDP8AI(own_a0, tile_B[0][base_B + 8], own_a1, tile_B[1][base_B + 8], own_scale_a * scale_B[base_B + 8]); + lane_output3[1] += SDP8AI(own_a0, tile_B[0][base_B + 9], own_a1, tile_B[1][base_B + 9], own_scale_a * scale_B[base_B + 9]); + lane_output3[2] += SDP8AI(own_a0, tile_B[0][base_B + 10], own_a1, tile_B[1][base_B + 10], own_scale_a * scale_B[base_B + 10]); + lane_output3[3] += SDP8AI(own_a0, tile_B[0][base_B + 11], own_a1, tile_B[1][base_B + 11], own_scale_a * scale_B[base_B + 11]); + + lane_output4[0] += SDP8AI(own_a0, tile_B[0][base_B + 12], own_a1, tile_B[1][base_B + 12], own_scale_a * scale_B[base_B + 12]); + lane_output4[1] += SDP8AI(own_a0, tile_B[0][base_B + 13], own_a1, tile_B[1][base_B + 13], own_scale_a * scale_B[base_B + 13]); + lane_output4[2] += SDP8AI(own_a0, tile_B[0][base_B + 14], own_a1, tile_B[1][base_B + 14], own_scale_a * scale_B[base_B + 14]); + lane_output4[3] += SDP8AI(own_a0, tile_B[0][base_B + 15], own_a1, tile_B[1][base_B + 15], own_scale_a * scale_B[base_B + 15]); + } + workgroupBarrier(); + } + + let a_global = a_global_base + base_A + a_idx; + let b_global = b_global_base + base_B; + let output_idx = ((a_global) * uniforms.N + b_global)/4; + // This creates a shader requirement that uniforms.N % 16 == 0 + if (a_global < uniforms.M && b_global < uniforms.N) + { + output[output_idx] = lane_output1; + output[output_idx+1] = lane_output2; + output[output_idx+2] = lane_output3; + output[output_idx+3] = lane_output4; + } + )MAIN_FN"; + + return Status::OK(); +} + +Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor* scales, + uint32_t M, + uint32_t N, + uint32_t K, + uint32_t block_size, + onnxruntime::webgpu::ComputeContext& context, + Tensor* y) { + constexpr uint32_t kVec4Components = 4; + constexpr uint32_t kVec2Components = 2; + constexpr uint32_t kU32Components = 4; + + constexpr uint32_t kBlockSizeA = 128; + DP4AMatMulQuantizeProgram quantize_program; + quantize_program.SetWorkgroupSize(1); + quantize_program.SetDispatchGroupSize(M * K / kBlockSizeA, 1, 1); + TensorShape a_quant_shape{1, M, K / kU32Components}; + Tensor a_quant = context.CreateGPUTensor(DataTypeImpl::GetType(), a_quant_shape); + TensorShapeVector a_scales_dims({1, 1, M, K / kBlockSizeA}); + Tensor a_scale = context.CreateGPUTensor(a->DataType(), a_scales_dims); + quantize_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec4Components)}}) + .AddOutputs({{&a_quant, ProgramTensorMetadataDependency::Rank, a_quant.Shape(), gsl::narrow(1)}, + {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), gsl::narrow(1)}}) + .AddUniformVariable({static_cast(M * K / kVec4Components)}); + ORT_RETURN_IF_ERROR(context.RunProgram(quantize_program)); + + constexpr uint32_t kTileSize = 64; + TensorShape reshaped_y_shape{1, M, N / kVec4Components}; + DP4AMatMulNBitsProgram mul_program{block_size}; + mul_program.SetWorkgroupSize(256); + mul_program.SetDispatchGroupSize( + (M + kTileSize - 1) / kTileSize, + (N + kTileSize - 1) / kTileSize, 1); + mul_program.AddInputs({{&a_quant, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec4Components)}, + {&a_scale, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}, + {b, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec2Components * kU32Components)}, + {scales, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}}) + .AddUniformVariables({{static_cast(M)}, + {static_cast(N)}, + {static_cast(K)}, + {static_cast(K / 8)}, + {static_cast(K / 16)}}) + .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, gsl::narrow(kVec4Components)}) + .CacheHint("Block" + std::to_string(block_size)); + return context.RunProgram(mul_program); +} + +bool CanApplyDP4AMatrixMatMulNBits(onnxruntime::webgpu::ComputeContext& context, + uint64_t accuracy_level, + uint32_t block_size, + uint32_t batch_count, + uint32_t N, + uint32_t K, + uint32_t components_k, + bool has_zero_points) { + // macOS - Avoid using dp4a on Metal, as it does not appear to have native dp4a support. + // https://github.com/gpuweb/gpuweb/issues/2677#issuecomment-1713292226 + bool use_dp4a = context.Device().HasFeature(wgpu::FeatureName::Subgroups) && + context.AdapterInfo().backendType != wgpu::BackendType::Metal; + return (accuracy_level == 4 && block_size % 32 == 0 && + batch_count == 1 && components_k == 4 && K % 64 == 0 && N % 16 == 0 && + !has_zero_points && use_dp4a); +} + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h new file mode 100644 index 0000000000000..15b86d78301ad --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/webgpu_kernel.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +using namespace onnxruntime::webgpu; + +class DP4AMatMulQuantizeProgram final : public Program { + public: + DP4AMatMulQuantizeProgram() : Program{"DP4AMatMulQuantize"} {} + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"input_size", ProgramUniformVariableDataType::Uint32}); +}; + +class DP4AMatMulNBitsProgram final : public Program { + public: + DP4AMatMulNBitsProgram(uint32_t block_size) : Program{"DP4AMatMulNBits"}, block_size_(block_size) {} + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( + {"M", ProgramUniformVariableDataType::Uint32}, + {"N", ProgramUniformVariableDataType::Uint32}, + {"K", ProgramUniformVariableDataType::Uint32}, + {"K8", ProgramUniformVariableDataType::Uint32}, + {"K16", ProgramUniformVariableDataType::Uint32}); + + private: + uint32_t block_size_; +}; + +Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor* scales, + uint32_t M, + uint32_t N, + uint32_t K, + uint32_t block_size, + onnxruntime::webgpu::ComputeContext& context, + Tensor* y); + +bool CanApplyDP4AMatrixMatMulNBits(onnxruntime::webgpu::ComputeContext& context, + uint64_t accuracy_level, + uint32_t block_size, + uint32_t batch_count, + uint32_t N, + uint32_t K, + uint32_t components_k, + bool has_zero_points); + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index 1534fd26d3ad9..e10a7f551eec9 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -5,6 +5,7 @@ #include "contrib_ops/webgpu/quantization/matmul_nbits.h" #include "contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.h" +#include "contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h" #include "contrib_ops/webgpu/webgpu_contrib_kernels.h" #include "core/providers/cpu/math/matmul_helper.h" #include "core/providers/webgpu/shader_helper.h" @@ -532,255 +533,6 @@ Status MatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { return Status::OK(); } -Status DP4AMatMulQuantizeProgram::GenerateShaderCode(ShaderHelper& shader) const { - shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); - shader.AddOutput("output", ShaderUsage::UseUniform); - shader.AddOutput("scales", ShaderUsage::UseUniform); - shader.AdditionalImplementation() << R"ADDNL_FN( - fn readInput(offset: u32) -> input_a_value_t - { - if (offset > uniforms.input_size) { - return input_a_value_t(0); - } - return input_a[offset]; - } -)ADDNL_FN"; - shader.MainFunctionBody() << R"MAIN_FN( - var local_a : array, 32>; - var max_value:vec4 = vec4(0); - for (var idx:u32=0;idx<32;idx+=1) - { - local_a[idx] = readInput(workgroup_idx*32 + idx); - max_value = max(max_value, abs(local_a[idx])); - } - var scale = max(max_value.x, max_value.y); - scale = max(scale, max_value.z); - scale = max(scale, max_value.w); - for (var idx:u32=0;idx<32;idx+=1) - { - output[workgroup_idx*32+idx] = pack4x8snorm(vec4(local_a[idx]/scale)); - } - // 127 is the max value of signed int8 [-127,127] used by pack4x8snorm for 1.0f. - scales[workgroup_idx] = scale/127; -)MAIN_FN"; - return Status::OK(); -} - -Status DP4AMatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { - shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); - shader.AddInput("scales_a", ShaderUsage::UseUniform); - shader.AddInput("input_b", ShaderUsage::UseUniform); - shader.AddInput("scales_b", ShaderUsage::UseUniform); - shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseElementTypeAlias); - - // This shader implements co-operative matrix multiply. The key idea here is to - // assume there is a primitive for medium size matrix multiply a subgroup can perform, - // using all its lanes and pooling all its registers to keep the values in registry. - // - // The entire workgroup which has N subgroups first loads a tile into shared memory, - // Then each subgroup loads a subtile from shared memory into registers and uses - // the medium size matrix multiply primitive to perform the math. - // The values for tile/subtile size are chosen to conform to the resource limits - // of an alderlake/tiger lake gpu. A tile is 64x64, workgroup is 256 threads - - // therefore there are 16 subgroups and 16 lanes in each subgroup. - // K the hidden dimension is paged in from RAM at k tile size which is 64. - // All this puts the shared memory requirement slightly above 16KB. - // WebGPU limit is 16KB, output is moved to registers instead of SHM to make - // everything fit in shared memory. - // - // Each subgroup performs a 16 x 64 x 16 multiply which is implemented with - // subgroup shuffle as a placeholder for the day the medium matrix mul primitive - // becomes available in WGSL. The registry requirements is ~2KB per subgroup, on - // Alderlake/Tigerlake subgroup has 8KB of registry space pooling the - // 512B of registry from each lane. - // - // The medium size matmul is implemented using dot4I8Packed, so the inputs for - // this shader require A to be int8 quantized with block size 64. B is regular - // matmulnbits input with block size 32. - - shader.AdditionalImplementation() << R"ADDNL_FN( - const tile_size = 64; - const subtile_size = 16; - const tile_size_k = 32; - const vec_factor = 4; - const u32_factor = 4; - const tile_size_k_vec = 2; - const block_size = 32; - - // Shared memory - var tile_A : array, tile_size>, tile_size_k_vec>; // 64 x 32 - var scale_A : array; // 64 x 1 - var tile_B : array, tile_size>, tile_size_k_vec>; // 64 x 32 - var scale_B : array; // 64 x 1 - - fn loadSHMA(a_global_base:u32, kidx_v:u32, row: u32, col: u32) - { - let a_global = a_global_base + row; - if (a_global >= uniforms.M) - { - return; - } - tile_A[col][row] = input_a[a_global*uniforms.K16+kidx_v+col]; - if (col == 0) - { - // kidx_v - covers 16 values of k - scale_A[row] = scales_a[a_global*(uniforms.K/128) + kidx_v/8]; - } - } - - fn loadSHMB(b_global_base:u32, kidx_v:u32, row: u32, col: u32) - { - let b_global = b_global_base + row; - if (b_global >= uniforms.N) - { - return; - } - - let b_value = input_b[b_global*uniforms.K16+kidx_v+col]; - var b_value_lower = vec4(unpack4xU8(b_value[0] & 0x0F0F0F0Fu)) - vec4(8); - var b_value_upper = vec4(unpack4xU8((b_value[0] >> 4) & 0x0F0F0F0Fu)) - vec4(8); - tile_B[col][row][0] = pack4xI8(vec4(b_value_lower[0], b_value_upper[0], b_value_lower[1], b_value_upper[1])); - tile_B[col][row][1] = pack4xI8(vec4(b_value_lower[2], b_value_upper[2], b_value_lower[3], b_value_upper[3])); - b_value_lower = vec4(unpack4xU8(b_value[1] & 0x0F0F0F0Fu)) - vec4(8); - b_value_upper = vec4(unpack4xU8((b_value[1] >> 4) & 0x0F0F0F0Fu)) - vec4(8); - tile_B[col][row][2] = pack4xI8(vec4(b_value_lower[0], b_value_upper[0], b_value_lower[1], b_value_upper[1])); - tile_B[col][row][3] = pack4xI8(vec4(b_value_lower[2], b_value_upper[2], b_value_lower[3], b_value_upper[3])); - if (col == 0) - { - // kidx_v - each kidx_v covers 16 values of k - scale_B[row] = scales_b[b_global*(uniforms.K/32) + kidx_v/2]; - } - } - - // Scaled dot product of 8 packed unsigned integers. - fn SDP8AI(a1:vec4, b1:vec4, a2:vec4, b2:vec4, scale:output_element_t) -> output_element_t - { - var local_sum = dot4I8Packed(a1[0], b1[0]); - local_sum += dot4I8Packed(a1[1], b1[1]); - local_sum += dot4I8Packed(a1[2], b1[2]); - local_sum += dot4I8Packed(a1[3], b1[3]); - local_sum += dot4I8Packed(a2[0], b2[0]); - local_sum += dot4I8Packed(a2[1], b2[1]); - local_sum += dot4I8Packed(a2[2], b2[2]); - local_sum += dot4I8Packed(a2[3], b2[3]); - return output_element_t(local_sum) * scale; - } -)ADDNL_FN"; - - shader.MainFunctionBody() << R"MAIN_FN( - // During the load phase we use all 256 threads to load 64 rows of A/B. - // For each row we load tile_size_k_vec (2) vectorized elements, which are 32 elements of K. - let a_global_base = workgroup_id.x * tile_size; - let b_global_base = workgroup_id.y * tile_size; - let load_AorB = u32(local_idx/128); - let load_row = u32((local_idx%128)/2); - let load_col = u32(local_idx%2); - - // During the compute phase, we have the 64x64 tile split into - // subtiles of 16x16. We have a grid of 4x4 subtiles. - let subtile_id = u32(local_idx / subtile_size); - let subtile_idx = u32(subtile_id / 4); - let subtile_idy = u32(subtile_id % 4); - let base_A = subtile_idx * 16; - let base_B = subtile_idy * 16; - // For each subtile we have 16 threads assigned. - let a_idx = u32(local_idx % subtile_size); - - var lane_output1: vec4; - var lane_output2: vec4; - var lane_output3: vec4; - var lane_output4: vec4; - // K's vectrorization is 16 items per index. See input_a/input_b. - // tile_size_k_vec - is the k tile size in vectorized space (1/16). That is - // k tile size is 32. In vectorized space that is 32/16 = 2. - for (var kidx_v:u32 = 0; kidx_v < uniforms.K16; kidx_v+=tile_size_k_vec) - { - // Load Phase: Populate shared memory for the workgroup. - if (load_AorB == 0) - { - loadSHMA(a_global_base, kidx_v, load_row, load_col); - } - else - { - loadSHMB(b_global_base, kidx_v, load_row, load_col); - } - workgroupBarrier(); - - // Compute phase: Perform matmul for this subtile 16 x 32 x 16. - // Step 1: Load from shared memory into registers across entire subgroup. - var own_a0: vec4 = tile_A[0][base_A + a_idx]; - var own_a1: vec4 = tile_A[1][base_A + a_idx]; - var own_scale_a: output_element_t = scale_A[base_A + a_idx]; - if (sg_size == 16) - { - var own_b0: vec4 = tile_B[0][base_B + sg_id]; - var own_b1: vec4 = tile_B[1][base_B + sg_id]; - var own_scale_b: output_element_t = scale_B[base_B + sg_id]; - // Step 2: Access registers across the subgroup using subgroupShuffle and perform the matmul. - lane_output1[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 0), own_a1, subgroupShuffle(own_b1, 0), subgroupShuffle(own_scale_b, 0) * own_scale_a); - lane_output1[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 1), own_a1, subgroupShuffle(own_b1, 1), subgroupShuffle(own_scale_b, 1) * own_scale_a); - lane_output1[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 2), own_a1, subgroupShuffle(own_b1, 2), subgroupShuffle(own_scale_b, 2) * own_scale_a); - lane_output1[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 3), own_a1, subgroupShuffle(own_b1, 3), subgroupShuffle(own_scale_b, 3) * own_scale_a); - - lane_output2[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 4), own_a1, subgroupShuffle(own_b1, 4), subgroupShuffle(own_scale_b, 4) * own_scale_a); - lane_output2[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 5), own_a1, subgroupShuffle(own_b1, 5), subgroupShuffle(own_scale_b, 5) * own_scale_a); - lane_output2[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 6), own_a1, subgroupShuffle(own_b1, 6), subgroupShuffle(own_scale_b, 6) * own_scale_a); - lane_output2[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 7), own_a1, subgroupShuffle(own_b1, 7), subgroupShuffle(own_scale_b, 7) * own_scale_a); - - lane_output3[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 8), own_a1, subgroupShuffle(own_b1, 8), subgroupShuffle(own_scale_b, 8) * own_scale_a); - lane_output3[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 9), own_a1, subgroupShuffle(own_b1, 9), subgroupShuffle(own_scale_b, 9) * own_scale_a); - lane_output3[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 10), own_a1, subgroupShuffle(own_b1, 10), subgroupShuffle(own_scale_b, 10) * own_scale_a); - lane_output3[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 11), own_a1, subgroupShuffle(own_b1, 11), subgroupShuffle(own_scale_b, 11) * own_scale_a); - - lane_output4[0] += SDP8AI(own_a0, subgroupShuffle(own_b0, 12), own_a1, subgroupShuffle(own_b1, 12), subgroupShuffle(own_scale_b, 12) * own_scale_a); - lane_output4[1] += SDP8AI(own_a0, subgroupShuffle(own_b0, 13), own_a1, subgroupShuffle(own_b1, 13), subgroupShuffle(own_scale_b, 13) * own_scale_a); - lane_output4[2] += SDP8AI(own_a0, subgroupShuffle(own_b0, 14), own_a1, subgroupShuffle(own_b1, 14), subgroupShuffle(own_scale_b, 14) * own_scale_a); - lane_output4[3] += SDP8AI(own_a0, subgroupShuffle(own_b0, 15), own_a1, subgroupShuffle(own_b1, 15), subgroupShuffle(own_scale_b, 15) * own_scale_a); - } - else - { - // Code for other subgroup sizes, simply doesnt use subgroups at all. - // Relies on reads from single location tile_B[][base_B + col] by all - // being optimized by the hardware. - lane_output1[0] += SDP8AI(own_a0, tile_B[0][base_B + 0], own_a1, tile_B[1][base_B + 0], own_scale_a * scale_B[base_B + 0]); - lane_output1[1] += SDP8AI(own_a0, tile_B[0][base_B + 1], own_a1, tile_B[1][base_B + 1], own_scale_a * scale_B[base_B + 1]); - lane_output1[2] += SDP8AI(own_a0, tile_B[0][base_B + 2], own_a1, tile_B[1][base_B + 2], own_scale_a * scale_B[base_B + 2]); - lane_output1[3] += SDP8AI(own_a0, tile_B[0][base_B + 3], own_a1, tile_B[1][base_B + 3], own_scale_a * scale_B[base_B + 3]); - - lane_output2[0] += SDP8AI(own_a0, tile_B[0][base_B + 4], own_a1, tile_B[1][base_B + 4], own_scale_a * scale_B[base_B + 4]); - lane_output2[1] += SDP8AI(own_a0, tile_B[0][base_B + 5], own_a1, tile_B[1][base_B + 5], own_scale_a * scale_B[base_B + 5]); - lane_output2[2] += SDP8AI(own_a0, tile_B[0][base_B + 6], own_a1, tile_B[1][base_B + 6], own_scale_a * scale_B[base_B + 6]); - lane_output2[3] += SDP8AI(own_a0, tile_B[0][base_B + 7], own_a1, tile_B[1][base_B + 7], own_scale_a * scale_B[base_B + 7]); - - lane_output3[0] += SDP8AI(own_a0, tile_B[0][base_B + 8], own_a1, tile_B[1][base_B + 8], own_scale_a * scale_B[base_B + 8]); - lane_output3[1] += SDP8AI(own_a0, tile_B[0][base_B + 9], own_a1, tile_B[1][base_B + 9], own_scale_a * scale_B[base_B + 9]); - lane_output3[2] += SDP8AI(own_a0, tile_B[0][base_B + 10], own_a1, tile_B[1][base_B + 10], own_scale_a * scale_B[base_B + 10]); - lane_output3[3] += SDP8AI(own_a0, tile_B[0][base_B + 11], own_a1, tile_B[1][base_B + 11], own_scale_a * scale_B[base_B + 11]); - - lane_output4[0] += SDP8AI(own_a0, tile_B[0][base_B + 12], own_a1, tile_B[1][base_B + 12], own_scale_a * scale_B[base_B + 12]); - lane_output4[1] += SDP8AI(own_a0, tile_B[0][base_B + 13], own_a1, tile_B[1][base_B + 13], own_scale_a * scale_B[base_B + 13]); - lane_output4[2] += SDP8AI(own_a0, tile_B[0][base_B + 14], own_a1, tile_B[1][base_B + 14], own_scale_a * scale_B[base_B + 14]); - lane_output4[3] += SDP8AI(own_a0, tile_B[0][base_B + 15], own_a1, tile_B[1][base_B + 15], own_scale_a * scale_B[base_B + 15]); - } - workgroupBarrier(); - } - - let a_global = a_global_base + base_A + a_idx; - let b_global = b_global_base + base_B; - let output_idx = ((a_global) * uniforms.N + b_global)/4; - // This creates a shader requirement that uniforms.N % 16 == 0 - if (a_global < uniforms.M && b_global < uniforms.N) - { - output[output_idx] = lane_output1; - output[output_idx+1] = lane_output2; - output[output_idx+2] = lane_output3; - output[output_idx+3] = lane_output4; - } -)MAIN_FN"; - - return Status::OK(); -} - Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) const { const Tensor* a = context.Input(0); const Tensor* b = context.Input(1); @@ -822,54 +574,15 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context return ApplySubgroupMatrixMatMulNBits(a, b, scales, M, N, K, context, y); } - const bool has_subgroup = context.Device().HasFeature(wgpu::FeatureName::Subgroups); - // macOS - Avoid using dp4a on Metal, as it does not appear to have native dp4a support. - // https://github.com/gpuweb/gpuweb/issues/2677#issuecomment-1713292226 - const bool use_dp4a = has_subgroup && context.AdapterInfo().backendType != wgpu::BackendType::Metal; - if (accuracy_level_ == 4 && block_size == 32 && - batch_count == 1 && components_a == 4 && K % 64 == 0 && N % 16 == 0 && - !has_zero_points && use_dp4a && M >= kMinMForTileOptimization) { - constexpr uint32_t kVec4Components = 4; - constexpr uint32_t kVec2Components = 2; - constexpr uint32_t kU32Components = 4; - - constexpr uint32_t kBlockSizeA = 128; - DP4AMatMulQuantizeProgram quantize_program; - quantize_program.SetWorkgroupSize(1); - quantize_program.SetDispatchGroupSize(M * K / kBlockSizeA, 1, 1); - TensorShape a_quant_shape{1, M, K / kU32Components}; - Tensor a_quant = context.CreateGPUTensor(DataTypeImpl::GetType(), a_quant_shape); - TensorShapeVector a_scales_dims({1, 1, M, K / kBlockSizeA}); - Tensor a_scale = context.CreateGPUTensor(a->DataType(), a_scales_dims); - quantize_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec4Components)}}) - .AddOutputs({{&a_quant, ProgramTensorMetadataDependency::Rank, a_quant.Shape(), gsl::narrow(1)}, - {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), gsl::narrow(1)}}) - .AddUniformVariable({static_cast(M * K / kVec4Components)}); - ORT_RETURN_IF_ERROR(context.RunProgram(quantize_program)); - - constexpr uint32_t kTileSize = 64; - TensorShape reshaped_y_shape{1, M, N / kVec4Components}; - DP4AMatMulNBitsProgram mul_program; - mul_program.SetWorkgroupSize(256); - mul_program.SetDispatchGroupSize( - (M + kTileSize - 1) / kTileSize, - (N + kTileSize - 1) / kTileSize, 1); - mul_program.AddInputs({{&a_quant, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec4Components)}, - {&a_scale, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}, - {b, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec2Components * kU32Components)}, - {scales, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}}) - .AddUniformVariables({{static_cast(M)}, - {static_cast(N)}, - {static_cast(K)}, - {static_cast(K / 8)}, - {static_cast(K / 16)}}) - .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, gsl::narrow(kVec4Components)}); - return context.RunProgram(mul_program); + if (M >= kMinMForTileOptimization && + CanApplyDP4AMatrixMatMulNBits(context, accuracy_level_, block_size, batch_count, N, K, components_a, has_zero_points)) { + return ApplyDP4AMatrixMatMulNBits(a, b, scales, M, N, K, block_size, context, y); } // TODO: Support output_number > 1. Some cases are failed when output_number > 1. constexpr uint32_t output_number = 1; const uint32_t tile_m = M > kMinMForTileOptimization ? 4 : 1; + const bool has_subgroup = context.Device().HasFeature(wgpu::FeatureName::Subgroups); const bool use_subgroup = has_subgroup && context.AdapterInfo().vendor == std::string_view{"intel"} && components_a == 4 && block_size == 32; MatMulNBitsProgram program{output_number, block_size, tile_m, gsl::narrow(components_b), has_zero_points, use_subgroup}; if (M > kMinMForTileOptimization && block_size == 32) { diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h index 3d72629bf6b25..10221e19c7400 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h @@ -35,25 +35,6 @@ class MatMulNBitsProgram final : public Program { bool use_subgroup_; }; -class DP4AMatMulQuantizeProgram final : public Program { - public: - DP4AMatMulQuantizeProgram() : Program{"DP4AMatMulQuantize"} {} - Status GenerateShaderCode(ShaderHelper& sh) const override; - WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"input_size", ProgramUniformVariableDataType::Uint32}); -}; - -class DP4AMatMulNBitsProgram final : public Program { - public: - DP4AMatMulNBitsProgram() : Program{"DP4AMatMulNBits"} {} - Status GenerateShaderCode(ShaderHelper& sh) const override; - WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( - {"M", ProgramUniformVariableDataType::Uint32}, - {"N", ProgramUniformVariableDataType::Uint32}, - {"K", ProgramUniformVariableDataType::Uint32}, - {"K8", ProgramUniformVariableDataType::Uint32}, - {"K16", ProgramUniformVariableDataType::Uint32}); -}; - class MatMulNBits final : public WebGpuKernel { public: MatMulNBits(const OpKernelInfo& info) : WebGpuKernel(info) { From c28bf78841458eee694924408c40ac7958278a16 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Fri, 7 Mar 2025 12:13:41 +1000 Subject: [PATCH 054/266] Example custom op with output type inferencing (#23916) ### Description Add example of a custom op that is required to do type inference for the output type for the model load to work. Also acts as an example of how to override an ONNX op with a custom implementation. ### Motivation and Context #23891 --- .../core/session/onnxruntime_cxx_api.h | 3 + onnxruntime/core/session/custom_ops.cc | 23 ++++--- .../test/shared_lib/custom_op_utils.cc | 20 ++++++ onnxruntime/test/shared_lib/custom_op_utils.h | 61 +++++++++++++++++- onnxruntime/test/shared_lib/test_inference.cc | 30 ++++++++- .../test/testdata/cast_float_to_double.onnx | Bin 0 -> 136 bytes 6 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 onnxruntime/test/testdata/cast_float_to_double.onnx diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 89488b5158c93..979b478e2fbb4 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -2532,6 +2532,9 @@ struct CustomOpBase : OrtCustomOp { return std::vector{}; } + // Ort::CustomOpBase derived class should provide the following static method with the type/shape inferencing + // implementation if needed: + // static OrtStatusPtr InferOutputShape(Ort::ShapeInferContext& context) template decltype(&C::InferOutputShape) SetShapeInferFn(decltype(&C::InferOutputShape)) { OrtCustomOp::InferOutputShapeFn = [](const OrtCustomOp*, OrtShapeInferContext* ort_ctx) -> OrtStatusPtr { diff --git a/onnxruntime/core/session/custom_ops.cc b/onnxruntime/core/session/custom_ops.cc index bb9f278d83cf7..f583767346d88 100644 --- a/onnxruntime/core/session/custom_ops.cc +++ b/onnxruntime/core/session/custom_ops.cc @@ -900,13 +900,14 @@ KernelCreateInfo CreateKernelCreateInfo(const std::string& domain, const OrtCust ONNX_NAMESPACE::OpSchema CreateSchema(const std::string& domain, const std::vector& ops) { // The function registers the first schema assuming all the other one are the same except the types constraints. ORT_ENFORCE(ops.size() > 0, "No kernels to registers."); - int undefined = 0; + int num_inputs_with_dynamic_type = 0; // Creation of the schema for the first kernel in ops. const OrtCustomOp* op = *ops.begin(); ONNX_NAMESPACE::OpSchema schema(op->GetName(op), "custom op registered at runtime", 0); - auto create_type_constraint = [&ops, &schema, &undefined](const OrtCustomOp* op, int count, int i, bool is_input) { + auto create_type_constraint = [&ops, &schema, &num_inputs_with_dynamic_type]( + const OrtCustomOp* op, int count, int i, bool is_input) { onnx::OpSchema::FormalParameterOption option = onnx::OpSchema::FormalParameterOption::Single; bool is_homogeneous = true; int min_arity = 1; @@ -976,7 +977,9 @@ ONNX_NAMESPACE::OpSchema CreateSchema(const std::string& domain, const std::vect } else { // all_types is empty. As mentioned in the previous loop, all types are allowed. schema.TypeConstraint(name, DataTypeImpl::ToString(SUPPORTED_TENSOR_TYPES), "all types"); - undefined++; + if (is_input) { + ++num_inputs_with_dynamic_type; + } } }; @@ -985,19 +988,21 @@ ONNX_NAMESPACE::OpSchema CreateSchema(const std::string& domain, const std::vect create_type_constraint(op, static_cast(input_count), static_cast(i), true); } + const bool have_shape_infer_fn = op->version >= min_ort_version_with_shape_inference && op->InferOutputShapeFn; + const size_t output_count = op->GetOutputTypeCount(op); for (size_t i = 0; i < output_count; i++) { const auto type = op->GetOutputType(op, i); if (ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED == type) { if (op->GetOutputCharacteristic(op, i) == OrtCustomOpInputOutputCharacteristic::INPUT_OUTPUT_REQUIRED) { - ORT_ENFORCE(1 == undefined, - "There must be one (and only one) dynamic typed input to the custom op. " - "Its type info at runtime will be used to infer the type info of this dynamic typed output " - "which is required for the success of the model loading step. " - "More than one dynamic typed inputs are currently not supported as differing types at runtime " - "means the output type cannot be inferred without which model loading cannot proceed."); + // if there's a dynamically typed input and output we infer they both have the same type from the input. + // if that isn't the case the user must provide an output shape inference fn which must set the output type. + ORT_ENFORCE(num_inputs_with_dynamic_type == 1 || have_shape_infer_fn, + "The type of a dynamically typed output can be inferred from a single dynamically typed input, " + "or by a user provided OrtCustomOp->InferOutputShapeFn that sets the output type."); } } + create_type_constraint(op, static_cast(output_count), static_cast(i), false); } diff --git a/onnxruntime/test/shared_lib/custom_op_utils.cc b/onnxruntime/test/shared_lib/custom_op_utils.cc index bf7efacdbb505..a624479bcd00b 100644 --- a/onnxruntime/test/shared_lib/custom_op_utils.cc +++ b/onnxruntime/test/shared_lib/custom_op_utils.cc @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include #include "gtest/gtest.h" #include "custom_op_utils.h" @@ -639,3 +640,22 @@ void StandaloneCustomKernel::Compute(OrtKernelContext* context) { StandaloneCustomKernel::~StandaloneCustomKernel() { } + +OrtStatusPtr CustomCastKernel::ComputeV2(OrtKernelContext* context) { + Ort::KernelContext ctx(context); + + auto in = ctx.GetInput(0); + std::vector shape = in.GetTensorTypeAndShapeInfo().GetShape(); + int64_t num_elements = std::accumulate(shape.cbegin(), shape.cend(), int64_t(1), std::multiplies()); + + // CustomCast::GetInputType constraint ensures we only get float input + const float* data = in.GetTensorData(); + double* out_data = ctx.GetOutput(0, shape).GetTensorMutableData(); + gsl::span input_span(data, num_elements); + gsl::span output_span(out_data, num_elements); + + std::transform(input_span.begin(), input_span.end(), output_span.begin(), + [](float val) { return static_cast(val); }); + + return nullptr; +} diff --git a/onnxruntime/test/shared_lib/custom_op_utils.h b/onnxruntime/test/shared_lib/custom_op_utils.h index ea2a5f2771342..424c2e2fe3a08 100644 --- a/onnxruntime/test/shared_lib/custom_op_utils.h +++ b/onnxruntime/test/shared_lib/custom_op_utils.h @@ -458,4 +458,63 @@ struct MulTopOpFloat16 : Ort::CustomOpBase OrtCustomOpInputOutputCharacteristic GetInputCharacteristic(size_t) const { return OrtCustomOpInputOutputCharacteristic::INPUT_OUTPUT_OPTIONAL; } -}; \ No newline at end of file +}; + +// +// Example overriding an operator where type inference is required for the output so kernel matching works correctly +// +struct CustomCastKernel { + CustomCastKernel(const OrtApi& /*ort_api*/, const OrtKernelInfo* /*info*/) + /*: ort_(ort_api)*/ { + } + + OrtStatusPtr ComputeV2(OrtKernelContext* context); + + private: + // const OrtApi& ort_; +}; + +// Custom Cast op that takes float input and converts based on 'to' attribute. +// Example implementation only supports cast to double. +struct CustomCast : Ort::CustomOpBase { + explicit CustomCast(const char* provider) : provider_(provider) { + // if overriding an ONNX op you need to set the opset versions you are overriding + start_ver_ = 7; // should match minimum ONNX schema you implement + // end_ver_ = ...; should match maximum ONNX schema you implement or unset for unlimited. + } + + // static method used by Ort::CustomOpBase::SetShapeInferFn + static OrtStatusPtr InferOutputShape(Ort::ShapeInferContext& context) { + auto shape = context.GetInputShape(0); + + // infer output type based on 'to'. + auto to = context.GetAttrInt("to"); + if (to != ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE) { + return Ort::Status("Unexpected type", ORT_INVALID_ARGUMENT).release(); + } + + context.SetOutputShape(0, shape, ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE); + return nullptr; + } + + OrtStatusPtr CreateKernelV2(const OrtApi& api, const OrtKernelInfo* info, void** op_kernel) const { + Ort::ConstKernelInfo ki(info); + *op_kernel = new CustomCastKernel(api, info); + return nullptr; + }; + + const char* GetName() const { return "Cast"; }; + const char* GetExecutionProviderType() const { return provider_; }; + + size_t GetInputTypeCount() const { return 1; }; + ONNXTensorElementDataType GetInputType(size_t /*index*/) const { + // example only accepts float input + return ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT; + }; + + size_t GetOutputTypeCount() const { return 1; }; + ONNXTensorElementDataType GetOutputType(size_t /*index*/) const { return ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; }; + + private: + const char* provider_{"CPUExecutionProvider"}; +}; diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc index 4216efdfdfdb8..b517ba7032886 100644 --- a/onnxruntime/test/shared_lib/test_inference.cc +++ b/onnxruntime/test/shared_lib/test_inference.cc @@ -4805,4 +4805,32 @@ TEST(CApiTest, GenerateNodeStatsFile) { output_names, 1); } -#endif \ No newline at end of file +#endif + +// Test that creates a custom Cast kernel which requires type inference of the output type to work. +// Also demonstrates overriding an ONNX operator as we register the custom op in the ONNX domain. +TEST(CApiTest, custom_cast) { + std::vector> inputs(1); + auto& input = inputs[0]; + input.name = "input"; + input.dims = {3, 4}; + input.values = {1.0f, 2.0f, 3.0f, 4.0f, + -1.0f, -2.0f, -3.0f, -4.0f, + 1.0f, 2.0f, 3.0f, 4.0f}; + + // prepare expected inputs and outputs + std::vector expected_dims_y = {3, 4}; + std::vector expected_values_y = {1.0, 2.0, 3.0, 4.0, + -1.0, -2.0, -3.0, -4.0, + 1.0, 2.0, 3.0, 4.0}; + + CustomCast custom_op{onnxruntime::kCpuExecutionProvider}; + + Ort::CustomOpDomain custom_op_domain(""); // onnx domain is empty string + custom_op_domain.Add(&custom_op); + + // model with Cast from ONNX test data + TestInference(*ort_env, TSTR("testdata/cast_float_to_double.onnx"), + inputs, "output", expected_dims_y, expected_values_y, 0, + custom_op_domain, nullptr); +} diff --git a/onnxruntime/test/testdata/cast_float_to_double.onnx b/onnxruntime/test/testdata/cast_float_to_double.onnx new file mode 100644 index 0000000000000000000000000000000000000000..dc7997cddd8a8c762e354316662fb0d734e25e86 GIT binary patch literal 136 zcmdfpOwLZtOVKS!EiSPt;8NgX&CDw(EfHeNFD(JmN-WNa#U)ytTudeT65I-kD&v!ZqVaA%{*EE>CHe6#{-I7ju2JGJ&3s%u9E?I7TudCyK+KXP!38x=2qeRe Mka1$+Vh|7o0L&R4`v3p{ literal 0 HcmV?d00001 From 1199dc081582fc25fbbd17e7130341391bad704c Mon Sep 17 00:00:00 2001 From: Chi Lo <54722500+chilo-ms@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:24:07 -0800 Subject: [PATCH 055/266] Enabling L2+ Optimizations for EPs (#23517) There are some requirements to modify the graph which are specific to the EP/hardware. ORT has the hardcoded EP list for optimizations but that can't scale and it's hard be extended to enable EP custom optimizations. Here is the prototype to enable L2+ optimizations for EPs (The original overview is provided by @skottmckay) as well as the TRT EP implementation for the ConstantFoldingDQ optimization. Signatures for selection and optimization functions: ```` - Selection: std::function>(const GraphViewer&, const KeyValueConfig&)> - Optimization: std::function ```` GetCapability - call (new) provider bridge API to lookup pre-defined optimizer by name and get selection function - ComputeCapability.optimize_func, i.e. optimization function, would be set by the optimizer to the function that does the optimization - EP has to update the returning ComputeCapability to include the optimization ComputeCapability in nodes_to_optimize. So that later ORT can perform optimization/transformation accordingly. GraphPartitioner - After assigning the ComputeCapability to the EP and prior to Compile, if the ComputeCapability has nodes_to_optimize, iterate that list - optimization function needs to be called with - a mutable Graph instance - the ComputeCapability for the individual optimization - the overall ComputeCapability so it can be updated --- cmake/onnxruntime_optimizer.cmake | 1 + .../core/framework/execution_provider.h | 16 ++ .../core/graph/indexed_sub_graph.h | 6 + .../core/framework/compute_capability.h | 20 ++ .../core/framework/execution_provider.cc | 1 + .../core/framework/graph_partitioner.cc | 220 +++++++++++------- .../core/framework/graph_partitioner.h | 9 +- .../core/optimizer/constant_folding.cc | 13 +- onnxruntime/core/optimizer/constant_folding.h | 18 ++ .../optimizer/graph_optimizer_registry.cc | 49 ++++ .../core/optimizer/graph_optimizer_registry.h | 77 ++++++ .../constant_folding_dq_node.cc | 26 +++ .../constant_folding_dq_node.h | 37 +++ .../selection_and_optimization_func.cc | 99 ++++++++ .../selection_and_optimization_func.h | 31 +++ .../providers/acl/acl_execution_provider.cc | 1 + .../providers/acl/acl_execution_provider.h | 1 + .../providers/cann/cann_execution_provider.cc | 1 + .../providers/cann/cann_execution_provider.h | 1 + .../coreml/coreml_execution_provider.cc | 1 + .../coreml/coreml_execution_provider.h | 1 + .../providers/cuda/cuda_execution_provider.cc | 1 + .../providers/cuda/cuda_execution_provider.h | 1 + .../src/ExecutionProvider.cpp | 6 +- .../src/ExecutionProvider.h | 3 + .../providers/dnnl/dnnl_execution_provider.cc | 1 + .../providers/dnnl/dnnl_execution_provider.h | 1 + .../providers/js/js_execution_provider.cc | 1 + .../core/providers/js/js_execution_provider.h | 1 + .../migraphx/migraphx_execution_provider.cc | 1 + .../migraphx/migraphx_execution_provider.h | 1 + .../nnapi_builtin/nnapi_execution_provider.cc | 1 + .../nnapi_builtin/nnapi_execution_provider.h | 1 + .../openvino/openvino_execution_provider.cc | 1 + .../openvino/openvino_execution_provider.h | 1 + .../providers/qnn/qnn_execution_provider.cc | 1 + .../providers/qnn/qnn_execution_provider.h | 1 + .../rknpu/rknpu_execution_provider.cc | 1 + .../rknpu/rknpu_execution_provider.h | 1 + .../providers/rocm/rocm_execution_provider.cc | 1 + .../providers/rocm/rocm_execution_provider.h | 1 + .../providers/shared_library/provider_api.h | 1 + .../provider_bridge_provider.cc | 3 +- .../shared_library/provider_interfaces.h | 9 + .../shared_library/provider_wrappedtypes.h | 3 + .../providers/snpe/snpe_execution_provider.cc | 1 + .../providers/snpe/snpe_execution_provider.h | 1 + .../tensorrt/tensorrt_execution_provider.cc | 55 ++++- .../tensorrt/tensorrt_execution_provider.h | 31 +++ .../tensorrt_execution_provider_helper.cc | 129 ++++++++++ .../vitisai/vitisai_execution_provider.cc | 2 +- .../vitisai/vitisai_execution_provider.h | 1 + .../vsinpu/vsinpu_execution_provider.cc | 1 + .../vsinpu/vsinpu_execution_provider.h | 1 + .../webgpu/webgpu_execution_provider.cc | 1 + .../webgpu/webgpu_execution_provider.h | 1 + .../webnn/webnn_execution_provider.cc | 1 + .../webnn/webnn_execution_provider.h | 1 + .../xnnpack/xnnpack_execution_provider.cc | 1 + .../xnnpack/xnnpack_execution_provider.h | 1 + onnxruntime/core/session/inference_session.cc | 21 +- .../core/session/provider_bridge_ort.cc | 23 +- .../test/framework/inference_session_test.cc | 1 + .../test/framework/session_state_test.cc | 27 ++- .../internal_testing_execution_provider.cc | 1 + .../internal_testing_execution_provider.h | 1 + .../test/providers/qnn/qnn_test_utils.cc | 7 +- 67 files changed, 874 insertions(+), 107 deletions(-) create mode 100644 onnxruntime/core/optimizer/graph_optimizer_registry.cc create mode 100644 onnxruntime/core/optimizer/graph_optimizer_registry.h create mode 100644 onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.cc create mode 100644 onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.h create mode 100644 onnxruntime/core/optimizer/selection_and_optimization_func.cc create mode 100644 onnxruntime/core/optimizer/selection_and_optimization_func.h diff --git a/cmake/onnxruntime_optimizer.cmake b/cmake/onnxruntime_optimizer.cmake index 9d680cd04af10..173c872d4cc06 100644 --- a/cmake/onnxruntime_optimizer.cmake +++ b/cmake/onnxruntime_optimizer.cmake @@ -9,6 +9,7 @@ if (onnxruntime_MINIMAL_BUILD) list(APPEND onnxruntime_optimizer_src_patterns "${ONNXRUNTIME_INCLUDE_DIR}/core/optimizer/graph_transformer.h" "${ONNXRUNTIME_ROOT}/core/optimizer/graph_transformer.cc" + "${ONNXRUNTIME_ROOT}/core/optimizer/graph_optimizer_registry.cc" ) if (onnxruntime_EXTENDED_MINIMAL_BUILD) diff --git a/include/onnxruntime/core/framework/execution_provider.h b/include/onnxruntime/core/framework/execution_provider.h index c9a15de9ef897..2245ff5791feb 100644 --- a/include/onnxruntime/core/framework/execution_provider.h +++ b/include/onnxruntime/core/framework/execution_provider.h @@ -20,6 +20,7 @@ struct ComputeCapability; class KernelRegistry; struct KernelCreateInfo; class Node; +class GraphOptimizerRegistry; } // namespace onnxruntime #else #include @@ -129,10 +130,25 @@ class IExecutionProvider { and decide whether a node will be assigned to <*this> execution provider. For kernels registered in a kernel registry, `kernel_lookup` must be used to find a matching kernel for this EP. + + The graph_optimizer_registry is designed for enabling L2+ graph optimizations tailored for EPs. + These optimizations are applied after the graph partitioner assigns ComputeCapability to the EP + and before EP's "Compile" or fusion. + + Steps to use graph_optimizer_registry and create the optimization ComputeCapability: + 1. Lookup Optimizer: The EP calls provider bridge API to lookup pre-defined optimizer by name and get selection function. + - Example: g_host->GetOptimizerByName(optimizer_name, graph_optimizer_registry, selection_func) + 2. Run Selection Function: The EP executes the selection function to obtain the selection ComputeCapability. + - ComputeCapability.optimize_func would be set by the optimizer to the function that does the optimization. + 3. Create Optimization ComputeCapability: The EP uses the selection ComputeCapability to create the optimization ComputeCapability. + 4. Return ComputeCapability: The EP returns the final ComputeCapability, with nodes_to_optimize set to the optimization ComputeCapability. + + Note: For more detailed implementations of using graph_optimizer_registry, please refer to TensorRT EP. */ virtual std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& graph_optimizer_registry, IResourceAccountant* resource_accountant = nullptr) const; /** diff --git a/include/onnxruntime/core/graph/indexed_sub_graph.h b/include/onnxruntime/core/graph/indexed_sub_graph.h index e457d3dcad1f1..088db79a7e005 100644 --- a/include/onnxruntime/core/graph/indexed_sub_graph.h +++ b/include/onnxruntime/core/graph/indexed_sub_graph.h @@ -72,6 +72,12 @@ struct IndexedSubGraph { return meta_def_.get(); } + /** Gets the mutable meta definition needed to represent this subgraph as a FunctionProto. + @returns MetaDef instance if it has been set. nullptr if not. */ + MetaDef* GetMutableMetaDef() { + return meta_def_.get(); + } + // Check if the accounting is enabled for the current EP bool IsAccountingEnabled() const { return resource_accountant != nullptr && diff --git a/onnxruntime/core/framework/compute_capability.h b/onnxruntime/core/framework/compute_capability.h index 5f21ba2f013e0..819264b3960e7 100644 --- a/onnxruntime/core/framework/compute_capability.h +++ b/onnxruntime/core/framework/compute_capability.h @@ -2,8 +2,11 @@ // Licensed under the MIT License. #pragma once +#include #include "core/common/common.h" #include "core/graph/indexed_sub_graph.h" +#include "core/graph/graph.h" +#include "core/optimizer/graph_optimizer_registry.h" namespace onnxruntime { // A structure encodes a subgraph and the method to run it. @@ -21,5 +24,22 @@ struct ComputeCapability { ComputeCapability(std::unique_ptr t_sub_graph) : sub_graph(std::move(t_sub_graph)) {} + + // Optional function to optimize this ComputeCapability. + // This will be called by ORT once the ComputeCapability is assigned to the EP. + std::function + optimization_func; + + // Optional ComputeCapability instances for sets of nodes within this ComputeCapability that should be optimized. + // when an optimization is applied, ORT will update this ComputeCapability to reflect the changes made. + // IndexedSubGraph.nodes: + // - update based on RemovedNode/AddNode calls + // IndexedSubGraph.MetaDef (if present): + // - inputs and outputs will be unchanged + // - constant_initializers MAY change if we constant fold an initializer during optimization + std::vector> nodes_to_optimize; }; } // namespace onnxruntime diff --git a/onnxruntime/core/framework/execution_provider.cc b/onnxruntime/core/framework/execution_provider.cc index 3a937a119d03b..df85daa006a43 100644 --- a/onnxruntime/core/framework/execution_provider.cc +++ b/onnxruntime/core/framework/execution_provider.cc @@ -14,6 +14,7 @@ namespace onnxruntime { std::vector> IExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry&, IResourceAccountant*) const { std::vector> result; for (const auto& node : graph.Nodes()) { diff --git a/onnxruntime/core/framework/graph_partitioner.cc b/onnxruntime/core/framework/graph_partitioner.cc index b79d0327c3ef5..ff4d300f665b1 100644 --- a/onnxruntime/core/framework/graph_partitioner.cc +++ b/onnxruntime/core/framework/graph_partitioner.cc @@ -142,13 +142,15 @@ struct GetCapabilityForEPParams { std::reference_wrapper debug_graph_fn; #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) IResourceAccountant* resource_accountant; + std::reference_wrapper graph_optimizer_registry; }; auto get_capabilities = [](const IExecutionProvider& ep, const GraphViewer& graph_viewer, const IExecutionProvider::IKernelLookup& kernel_lookup, - IResourceAccountant* resource_accountant) { - auto capabilities = ep.GetCapability(graph_viewer, kernel_lookup, resource_accountant); + IResourceAccountant* resource_accountant, + const GraphOptimizerRegistry& graph_optimizer_registry) { + auto capabilities = ep.GetCapability(graph_viewer, kernel_lookup, graph_optimizer_registry, resource_accountant); // In theory an EP could return an empty capability. Remove those. capabilities.erase(std::remove_if(capabilities.begin(), capabilities.end(), @@ -182,10 +184,11 @@ static Status GetCapabilityForEP(const GetCapabilityForEPParams& params, const l auto& graph = params.graph.get(); auto& capabilities = params.capabilities.get(); + const auto& graph_optimizer_registry = params.graph_optimizer_registry.get(); { const GraphViewer graph_viewer(graph); - capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant); + capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant, graph_optimizer_registry); if (capabilities.empty()) { return Status::OK(); @@ -223,7 +226,7 @@ static Status GetCapabilityForEP(const GetCapabilityForEPParams& params, const l capabilities.clear(); const GraphViewer graph_viewer(graph); - capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant); + capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant, graph_optimizer_registry); // all nodes with an index >= first_new_node with domain of kMSInternalNHWCDomain should be in the capabilities InlinedHashSet new_nodes_in_capabilities; @@ -261,6 +264,7 @@ static Status GetCapabilityForEP(const GetCapabilityForEPParams& params, const l static Status GetCapabilityForEPForAotInlining(const GraphViewer& graph_viewer, const KernelRegistryManager& kernel_registry_mgr, const IExecutionProvider& current_ep, + const GraphOptimizerRegistry& graph_optimizer_registry, const logging::Logger& logger, std::vector>& capabilities) { const auto& ep_type = current_ep.Type(); @@ -272,14 +276,62 @@ static Status GetCapabilityForEPForAotInlining(const GraphViewer& graph_viewer, logger}; // TODO: Provide EP with a capability to look inside the functions. - capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, nullptr); + capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, nullptr, graph_optimizer_registry); return Status::OK(); } /** - * Check if a node can be placed on a specific provider. - * Do nothing if the node is already assigned + * Check whether the given IndexedSubGraph is available for assigning to a specific provider. + * + */ +static bool IsIndexedSubGraphAvailableForAssignment(Graph& graph, + const IndexedSubGraph& capability, + GraphPartitioner::Mode mode, + const std::string& provider_type) { + // The provider can run a single node in the if not using meta-defs. + if (capability.GetMetaDef() == nullptr && capability.nodes.size() == 1) { + auto* node = graph.GetNode(capability.nodes[0]); + if (nullptr != node && node->GetExecutionProviderType().empty()) { + // The node was not fused or assigned. + return true; + } + return false; + } + + // if mode is kAssignOnly we want all nodes that can _potentially_ be taken by compiling EPs to be assigned, + // so that we aggregate the nodes covered and ensure the original nodes remain in the ORT format model by + // preventing level 2 and 3 optimizers from changing them. optimizers check the EP the node is assigned to + // and only make changes if the EP is on the optimizer's list of supported EPs. an EP that compiles nodes + // should never be on those lists. + // + // when the ORT format model is loaded we will process it normally with EP priority being applied for + // whichever EPs are enabled at the time. + // + // e.g. an Android NNAPI EP may take different/overlapping nodes to a iOS CoreML EP. + // We want the ORT format model to be able to be run as efficiently as possible on either platform, + // so we want all the nodes that either may take to be preserved. If we did not do this we would + // need to create one ORT format model for Android and one for iOS. + if (mode == GraphPartitioner::Mode::kAssignOnly) { + return true; + } + + for (auto node_index : capability.nodes) { + const auto* node = graph.GetNode(node_index); + if ((nullptr == node) || + (!node->GetExecutionProviderType().empty() && node->GetExecutionProviderType() != provider_type)) { + // The node was fused or assigned, so that the whole sub-graph will not be assigned to this + // The assumption is that this can only run the sub-graph as a whole unit. + return false; + } + } + + return true; +} + +/** + * Return a fused node or assign the nodes in the indexed subgraph to the current EP. + * * \param graph * \param capability * \param kernel_registry_mgr @@ -298,75 +350,42 @@ static Node* PlaceNode(Graph& graph, const IndexedSubGraph& capability, if (nullptr == capability.GetMetaDef()) { TryAssignSingleNode(graph, capability, provider_type); } else { - // The can run a fused in the . + const bool acc_enabled = capability.IsAccountingEnabled(); + if (mode == GraphPartitioner::Mode::kNormal) { + std::ostringstream oss; + oss << provider_type << "_" << capability.GetMetaDef()->name << "_" << fused_node_unique_id++; + std::string node_name = oss.str(); - // Check whether any node in the was already assigned. If so it cannot be stolen as assignment is done - // in order of EP priority - bool sub_graph_available_for_assignment = true; - if (mode != GraphPartitioner::Mode::kAssignOnly) { - // if mode is kAssignOnly we want all nodes that can _potentially_ be taken by compiling EPs to be assigned, - // so that we aggregate the nodes covered and ensure the original nodes remain in the ORT format model by - // preventing level 2 and 3 optimizers from changing them. optimizers check the EP the node is assigned to - // and only make changes if the EP is on the optimizer's list of supported EPs. an EP that compiles nodes - // should never be on those lists. - // - // when the ORT format model is loaded we will process it normally with EP priority being applied for - // whichever EPs are enabled at the time. - // - // e.g. an Android NNAPI EP may take different/overlapping nodes to a iOS CoreML EP. - // We want the ORT format model to be able to be run as efficiently as possible on either platform, - // so we want all the nodes that either may take to be preserved. If we did not do this we would - // need to create one ORT format model for Android and one for iOS. - for (auto node_index : capability.nodes) { - const auto* node = graph.GetNode(node_index); - if ((nullptr == node) || - (!node->GetExecutionProviderType().empty() && node->GetExecutionProviderType() != provider_type)) { - // The node was fused or assigned, so that the whole sub-graph will not be assigned to this - // The assumption is that this can only run the sub-graph as a whole unit. - sub_graph_available_for_assignment = false; - break; - } + Node* fused_node = nullptr; + if (fusion_style == IExecutionProvider::FusionStyle::Function) { + fused_node = &graph.FuseSubGraph(capability, node_name); + } else { + // create a fused node without copying everything to a Function body. The IndexedSubGraph will be passed + // through to Compile via a filtered GraphViewer. + fused_node = &graph.BeginFuseSubGraph(capability, node_name); } - } - - if (sub_graph_available_for_assignment) { - const bool acc_enabled = capability.IsAccountingEnabled(); - if (mode == GraphPartitioner::Mode::kNormal) { - std::ostringstream oss; - oss << provider_type << "_" << capability.GetMetaDef()->name << "_" << fused_node_unique_id++; - std::string node_name = oss.str(); - - Node* fused_node = nullptr; - if (fusion_style == IExecutionProvider::FusionStyle::Function) { - fused_node = &graph.FuseSubGraph(capability, node_name); - } else { - // create a fused node without copying everything to a Function body. The IndexedSubGraph will be passed - // through to Compile via a filtered GraphViewer. - fused_node = &graph.BeginFuseSubGraph(capability, node_name); - } - fused_node->SetExecutionProviderType(provider_type); - if (acc_enabled) { - // We account for the fused node. We operate under assumption - // that the fused node would use no more memory when the nodes we are fusing. - // and potentially less than that, and therefore, no threshold check is needed here. - // All threshold checks are done within the EP. - capability.ComputeAndAccountForNode(*fused_node); - } + fused_node->SetExecutionProviderType(provider_type); + if (acc_enabled) { + // We account for the fused node. We operate under assumption + // that the fused node would use no more memory when the nodes we are fusing. + // and potentially less than that, and therefore, no threshold check is needed here. + // All threshold checks are done within the EP. + capability.ComputeAndAccountForNode(*fused_node); + } - result = fused_node; - } else { - // assign the nodes in the indexed subgraph to the current EP so that level 2+ optimizers will not change them. - // This is used when exporting an ORT format model to maintain the original nodes and re-do the fusion - // at runtime. The original nodes provide a fallback if fewer nodes can be fused at runtime due to device - // capabilities. - for (size_t i = 0, limit = capability.nodes.size(); i < limit; ++i) { - auto* node = graph.GetNode(capability.nodes[i]); - if (node != nullptr) { - node->SetExecutionProviderType(provider_type); - if (acc_enabled) { - capability.AccountForNode(i); - } + result = fused_node; + } else { + // assign the nodes in the indexed subgraph to the current EP so that level 2+ optimizers will not change them. + // This is used when exporting an ORT format model to maintain the original nodes and re-do the fusion + // at runtime. The original nodes provide a fallback if fewer nodes can be fused at runtime due to device + // capabilities. + for (size_t i = 0, limit = capability.nodes.size(); i < limit; ++i) { + auto* node = graph.GetNode(capability.nodes[i]); + if (node != nullptr) { + node->SetExecutionProviderType(provider_type); + if (acc_enabled) { + capability.AccountForNode(i); } } } @@ -386,7 +405,8 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, int& fused_node_unique_id, const layout_transformation::TransformLayoutFunction& transform_layout_fn, const layout_transformation::DebugGraphFn& debug_graph_fn, - const logging::Logger& logger, IResourceAccountant* resource_accountant) { + const logging::Logger& logger, IResourceAccountant* resource_accountant, + const GraphOptimizerRegistry& graph_optimizer_registry) { // handle testing edge case where optimizers or constant lifting results in graph with no nodes. // doing it here saves all providers checking for this in GetCapability if (graph.NumberOfNodes() == 0) { @@ -400,7 +420,7 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, // we pass through the FuncManager from the top level graph ORT_RETURN_IF_ERROR(PartitionOnnxFormatModelImpl(*subgraph, func_mgr, kernel_registry_mgr, fused_kernel_registry, current_ep, mode, fused_node_unique_id, - transform_layout_fn, debug_graph_fn, logger, resource_accountant)); + transform_layout_fn, debug_graph_fn, logger, resource_accountant, graph_optimizer_registry)); } } @@ -424,7 +444,8 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, mode, std::cref(transform_layout_fn), std::cref(debug_graph_fn), - resource_accountant}; + resource_accountant, + std::ref(graph_optimizer_registry)}; ORT_RETURN_IF_ERROR(GetCapabilityForEP(get_capability_params, logger)); if (capabilities.empty()) { @@ -450,7 +471,30 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, entry->sub_graph->GetMetaDef() != nullptr; })); for (auto& capability : capabilities) { - Node* n = PlaceNode(graph, *capability->sub_graph, fusion_style, type, mode, fused_node_unique_id); + // The can run a fused in the . + // Check whether any node in the was already assigned. If so it cannot be stolen as assignment is done + // in order of EP priority + bool sub_graph_available_for_assignment = IsIndexedSubGraphAvailableForAssignment(graph, *capability->sub_graph, mode, type); + + // If the is available to be assigned to the EP and the ComputeCapability has nodes_to_optimize, + // run EP related optimizations and update ComputeCapability. + if (sub_graph_available_for_assignment && !capability->nodes_to_optimize.empty()) { + for (auto& optimization_cc : capability->nodes_to_optimize) { + if (optimization_cc->optimization_func) { + auto status = optimization_cc->optimization_func(graph, *optimization_cc, *capability, graph_optimizer_registry); + if (status != Status::OK()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, type, "The optimization function failed to finish."); + } + // #TODO: Handle nested optimization ComputeCapability + } + } + } + + Node* n = nullptr; + if (sub_graph_available_for_assignment) { + n = PlaceNode(graph, *capability->sub_graph, fusion_style, type, mode, fused_node_unique_id); + } + if (n != nullptr) { // searching in kernel registries, if no kernel registered for the fused_node, use compile approach if (!KernelRegistryManager::HasImplementationOf(kernel_registry_mgr, *n, type, logger)) { @@ -587,6 +631,7 @@ static Status InlineNodes(Graph& graph, bool& modified_graph) { static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_providers, const KernelRegistryManager& kernel_registry_mgr, Graph& graph, + const GraphOptimizerRegistry& graph_optimizer_registry, const logging::Logger& logger, InlinedHashSet& not_inlined, size_t& inlined_count) { @@ -603,6 +648,7 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide ORT_RETURN_IF_ERROR(InlineFunctionsAOTImpl(execution_providers, kernel_registry_mgr, *subgraph, + graph_optimizer_registry, logger, not_inlined, inlined_count)); @@ -627,7 +673,7 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide InlinedHashSet claimed_by_ep; for (const auto& ep : execution_providers) { std::vector> capabilities; - ORT_RETURN_IF_ERROR(GetCapabilityForEPForAotInlining(graph_viewer, kernel_registry_mgr, *ep, logger, + ORT_RETURN_IF_ERROR(GetCapabilityForEPForAotInlining(graph_viewer, kernel_registry_mgr, *ep, graph_optimizer_registry, logger, capabilities)); for (auto& capability : capabilities) { const auto& nodes = capability->sub_graph->nodes; @@ -791,6 +837,7 @@ static Status PartitionOnnxFormatModel(const PartitionParams& partition_params, const ExecutionProviders& execution_providers, KernelRegistryManager& kernel_registry_manager, const std::optional& acc_map, + const GraphOptimizerRegistry& graph_optimizer_registry, const logging::Logger& logger) { bool modified_graph = false; @@ -814,7 +861,7 @@ static Status PartitionOnnxFormatModel(const PartitionParams& partition_params, fused_kernel_registry, *ep, mode, fused_node_unique_id, transform_layout_function, partition_params.debug_graph_fn, - logger, resource_accountant)); + logger, resource_accountant, graph_optimizer_registry)); } // expand any nodes that have an ONNX function definition but no matching ORT kernel. @@ -835,6 +882,7 @@ static Status PartitionOnnxFormatModel(const PartitionParams& partition_params, static Status PartitionOrtFormatModelImpl(const PartitionParams& partition_params, KernelRegistryManager& kernel_registry_mgr, IExecutionProvider& current_ep, + const GraphOptimizerRegistry& graph_optimizer_registry, const logging::Logger& logger) { // handle testing edge case where optimizers or constant lifting results in graph with no nodes. // doing it here saves all providers checking for this in GetCapability @@ -850,7 +898,7 @@ static Status PartitionOrtFormatModelImpl(const PartitionParams& partition_param PartitionParams subgraph_partition_params = partition_params; subgraph_partition_params.graph = std::ref(subgraph); ORT_RETURN_IF_ERROR(PartitionOrtFormatModelImpl(subgraph_partition_params, kernel_registry_mgr, - current_ep, logger)); + current_ep, graph_optimizer_registry, logger)); } } @@ -866,7 +914,8 @@ static Status PartitionOrtFormatModelImpl(const PartitionParams& partition_param std::cref(partition_params.transform_layout_function), std::cref(partition_params.debug_graph_fn), #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) - nullptr + nullptr, + std::ref(graph_optimizer_registry) }; // clang-format on @@ -959,10 +1008,11 @@ static Status PartitionOrtFormatModelImpl(const PartitionParams& partition_param static Status PartitionOrtFormatModel(const PartitionParams& partition_params, const ExecutionProviders& execution_providers, KernelRegistryManager& kernel_registry_manager, + const GraphOptimizerRegistry& graph_optimizer_registry, const logging::Logger& logger) { // process full graph with each EP for (const auto& ep : execution_providers) { - ORT_RETURN_IF_ERROR(PartitionOrtFormatModelImpl(partition_params, kernel_registry_manager, *ep, logger)); + ORT_RETURN_IF_ERROR(PartitionOrtFormatModelImpl(partition_params, kernel_registry_manager, *ep, graph_optimizer_registry, logger)); } return Status::OK(); @@ -989,6 +1039,7 @@ Status GraphPartitioner::InlineFunctionsAOT(Model& model, ORT_RETURN_IF_ERROR(InlineFunctionsAOTImpl(execution_providers, kernel_registry_manager, graph, + *graph_optimizer_registry_, logger, not_inlined, inlined_count)); @@ -1045,8 +1096,7 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, std::ref(*fused_kernel_registry), std::ref(fused_node_unique_id), std::cref(transform_layout_function), - std::cref(debug_graph_fn), - }; + std::cref(debug_graph_fn)}; #else // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) @@ -1075,7 +1125,7 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, ORT_RETURN_IF_ERROR(NodeStatsRecorder::CreateAccountants(config_options, graph.ModelPath(), ep_acc_map)); ORT_RETURN_IF_ERROR(PartitionOnnxFormatModel(partition_params, mode, providers_, kernel_registry_mgr_, - ep_acc_map, logger)); + ep_acc_map, *graph_optimizer_registry_, logger)); if (ep_context_enabled) { std::string ep_context_path = config_options.GetConfigOrDefault(kOrtSessionOptionEpContextFilePath, ""); @@ -1089,7 +1139,7 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "ONNX models are not supported in this build."); #endif //! defined(ORT_MINIMAL_BUILD) } else { - ORT_RETURN_IF_ERROR(PartitionOrtFormatModel(partition_params, providers_, kernel_registry_mgr_, logger)); + ORT_RETURN_IF_ERROR(PartitionOrtFormatModel(partition_params, providers_, kernel_registry_mgr_, *graph_optimizer_registry_, logger)); } #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) diff --git a/onnxruntime/core/framework/graph_partitioner.h b/onnxruntime/core/framework/graph_partitioner.h index d1ef193cf1520..b9d4022cb5a14 100644 --- a/onnxruntime/core/framework/graph_partitioner.h +++ b/onnxruntime/core/framework/graph_partitioner.h @@ -7,6 +7,7 @@ #include "core/graph/graph.h" #include "core/framework/fuse_nodes_funcs.h" #include "core/framework/transform_layout_functions.h" +#include "core/optimizer/graph_optimizer_registry.h" namespace onnxruntime { @@ -24,9 +25,12 @@ class GraphPartitioner { }; // The order of providers represents the user preference. - GraphPartitioner(KernelRegistryManager& kernel_registry_mgr, const ExecutionProviders& providers) + GraphPartitioner(KernelRegistryManager& kernel_registry_mgr, + const ExecutionProviders& providers, + std::unique_ptr graph_optimizer_registry) : kernel_registry_mgr_(kernel_registry_mgr), - providers_(providers) { + providers_(providers), + graph_optimizer_registry_(std::move(graph_optimizer_registry)) { } // Run partitioning. @@ -64,6 +68,7 @@ class GraphPartitioner { KernelRegistryManager& kernel_registry_mgr_; const ExecutionProviders& providers_; + std::unique_ptr graph_optimizer_registry_; }; } // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/constant_folding.cc b/onnxruntime/core/optimizer/constant_folding.cc index e755b4bfa6364..e36eef672c1ed 100644 --- a/onnxruntime/core/optimizer/constant_folding.cc +++ b/onnxruntime/core/optimizer/constant_folding.cc @@ -21,7 +21,16 @@ ConstantFolding::ConstantFolding(const IExecutionProvider& execution_provider, const ConfigOptions& config_options, const InlinedHashSet& compatible_execution_providers, const InlinedHashSet& excluded_initializers) noexcept - : GraphTransformer("ConstantFolding", compatible_execution_providers), + : ConstantFolding("ConstantFolding", execution_provider, skip_dequantize_linear, config_options, compatible_execution_providers, excluded_initializers) { +} + +ConstantFolding::ConstantFolding(const std::string& name, + const IExecutionProvider& execution_provider, + bool skip_dequantize_linear, + const ConfigOptions& config_options, + const InlinedHashSet& compatible_execution_providers, + const InlinedHashSet& excluded_initializers) noexcept + : GraphTransformer(name, compatible_execution_providers), skip_dequantize_linear_(skip_dequantize_linear), config_options_(config_options), excluded_initializers_(excluded_initializers), @@ -144,7 +153,7 @@ Status ConstantFolding::ApplyImpl(Graph& graph, bool& modified, int graph_level, for (NodeIndex i : order) { auto* node = graph.GetNode(i); - if (!node) { + if (!node || !AllowConstantFolding(*node)) { continue; } diff --git a/onnxruntime/core/optimizer/constant_folding.h b/onnxruntime/core/optimizer/constant_folding.h index 14eb2a9c5f06b..29bc67d560788 100644 --- a/onnxruntime/core/optimizer/constant_folding.h +++ b/onnxruntime/core/optimizer/constant_folding.h @@ -28,6 +28,24 @@ class ConstantFolding : public GraphTransformer { const InlinedHashSet& compatible_execution_providers = {}, const InlinedHashSet& excluded_initializers = {}) noexcept; + protected: + /** + * Same as the constructor above but with a name provided by derived class. + */ + ConstantFolding(const std::string& name, + const IExecutionProvider& execution_provider, + bool skip_dequantize_linear, + const ConfigOptions& config_options, + const InlinedHashSet& compatible_execution_providers = {}, + const InlinedHashSet& excluded_initializers = {}) noexcept; + /** + * Derived class can implement this virtual function to limit the nodes that can be constant folded. + */ + virtual bool AllowConstantFolding(const Node& node) const { + ORT_UNUSED_PARAMETER(node); + return true; + } + private: Status ApplyImpl(Graph& graph, bool& modified, int graph_level, const logging::Logger& logger) const override; diff --git a/onnxruntime/core/optimizer/graph_optimizer_registry.cc b/onnxruntime/core/optimizer/graph_optimizer_registry.cc new file mode 100644 index 0000000000000..8ede372470485 --- /dev/null +++ b/onnxruntime/core/optimizer/graph_optimizer_registry.cc @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/optimizer/graph_optimizer_registry.h" +#include "core/optimizer/graph_transformer_utils.h" +#include "core/optimizer/selection_and_optimization_func.h" +#include "core/optimizer/qdq_transformer/constant_folding_dq_node.h" + +using namespace onnxruntime; +using namespace ::onnxruntime::common; + +namespace onnxruntime { +#if !defined(ORT_MINIMAL_BUILD) +GraphOptimizerRegistry::GraphOptimizerRegistry(const onnxruntime::SessionOptions* sess_options, + const onnxruntime::IExecutionProvider* cpu_ep, + const logging::Logger* logger) : session_options_(sess_options), + cpu_ep_(cpu_ep), + logger_(logger) { + auto status = CreatePredefinedSelectionFuncs(); + ORT_ENFORCE(status.IsOK(), "Could not create pre-defined selection functions. Error Message: ", + status.ErrorMessage()); +} + +Status GraphOptimizerRegistry::CreatePredefinedSelectionFuncs() { + transformer_name_to_selection_func_[kConstantFoldingDQ] = ConstantFoldingDQFuncs::Select; + + return Status::OK(); +} + +std::optional GraphOptimizerRegistry::GetSelectionFunc(std::string& name) const { + auto lookup = transformer_name_to_selection_func_.find(name); + if (lookup != transformer_name_to_selection_func_.end()) { + return transformer_name_to_selection_func_.at(name); + } + LOGS(*logger_, WARNING) << "Can't find selection function of " << name; + return std::nullopt; +} +#else +GraphOptimizerRegistry::GraphOptimizerRegistry(const onnxruntime::SessionOptions* sess_options, + const onnxruntime::IExecutionProvider* cpu_ep, + const logging::Logger* logger) : session_options_(sess_options), + cpu_ep_(cpu_ep), + logger_(logger) {} + +std::optional GraphOptimizerRegistry::GetSelectionFunc(std::string& /*name*/) const { + return std::nullopt; +} +#endif +} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/graph_optimizer_registry.h b/onnxruntime/core/optimizer/graph_optimizer_registry.h new file mode 100644 index 0000000000000..15c9287c0eac8 --- /dev/null +++ b/onnxruntime/core/optimizer/graph_optimizer_registry.h @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/inlined_containers.h" +#include "core/common/logging/logging.h" +#include "core/common/common.h" +#include "core/optimizer/graph_transformer.h" +#include "core/framework/execution_providers.h" +#include "core/framework/compute_capability.h" + +namespace onnxruntime { +/** + * Optimizer's selection function: Selects a set of nodes from a given graph for optimization. Additional key/value strings can be provided to configure the optimizer. + * If needed, use graph_optimizer_registry to access the session options, the CPU EP and the logger. + * + * Optimizer's optimization function: Gets the nodes in ComputeCapability from nodes_to_optimize. Use graph_optimizer_registry to access the session options, the CPU EP + * and the logger if needed to create the optimizer. Run optimization on the nodes/subgraph, and finally, update the ComputeCapability. + * + */ +using KeyValueConfig = std::unordered_map; +using SelectionFunc = std::function>(const GraphViewer&, + const KeyValueConfig&, + const GraphOptimizerRegistry& graph_optimizer_registry)>; +using OptimizationFunc = std::function; + +/** + * A registration/lookup class for re-usable optimizers for EPs. + */ +class GraphOptimizerRegistry { + public: + /** + * The constructor takes in session options, the CPU EP and a logger as these are required by some optimizers. + */ + GraphOptimizerRegistry(const onnxruntime::SessionOptions* sess_options, + const onnxruntime::IExecutionProvider* cpu_ep, + const logging::Logger* logger); + + /** + * Get optimizer selection function. If the optimizer name can't be found, return nullopt. + */ + std::optional GetSelectionFunc(std::string& name) const; + + /** + * Get CPU EP. + */ + const onnxruntime::IExecutionProvider& GetCpuEp() const { return *cpu_ep_; } + + /** + * Get Session Options. + */ + const onnxruntime::SessionOptions& GetSessionOptions() const { return *session_options_; } + + /** + * Get Logger. + */ + const logging::Logger* GetLogger() const { return logger_; } + + private: + const onnxruntime::SessionOptions* session_options_; + const onnxruntime::IExecutionProvider* cpu_ep_; + const logging::Logger* logger_; + +#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) + InlinedHashMap transformer_name_to_selection_func_; + + /** + * Create pre-defined selection functions. + */ + Status CreatePredefinedSelectionFuncs(); +#endif +}; +} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.cc b/onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.cc new file mode 100644 index 0000000000000..a2f46d6ae693c --- /dev/null +++ b/onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.cc @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/optimizer/qdq_transformer/constant_folding_dq_node.h" +#include "core/optimizer/graph_optimizer_registry.h" +#include "core/graph/graph_utils.h" + +namespace onnxruntime { + +ConstantFoldingDQ::ConstantFoldingDQ(const IExecutionProvider& execution_provider, + bool skip_dequantize_linear, + const ConfigOptions& config_options, + const InlinedHashSet& node_index_set, + const InlinedHashSet& compatible_execution_providers, + const InlinedHashSet& excluded_initializers) noexcept + : ConstantFolding("ConstantFoldingDQ", execution_provider, skip_dequantize_linear, config_options, compatible_execution_providers, excluded_initializers), + node_index_set_(node_index_set) {} + +bool ConstantFoldingDQ::AllowConstantFolding(const Node& node) const { + if (node_index_set_.find(node.Index()) != node_index_set_.end()) { + return true; + } + return false; +} + +} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.h b/onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.h new file mode 100644 index 0000000000000..7aed87fa06adb --- /dev/null +++ b/onnxruntime/core/optimizer/qdq_transformer/constant_folding_dq_node.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/optimizer/graph_transformer.h" +#include "core/optimizer/constant_folding.h" +#include "core/framework/ort_value.h" +#include +#include "core/framework/execution_provider.h" + +namespace onnxruntime { + +/** +@class ConstantFoldingDQ + +It's the derived class from ConstantFolding. +*/ +class ConstantFoldingDQ : public ConstantFolding { + public: + /*! Constant folding will not be applied to nodes that have one of initializers from excluded_initializers as input. + \param execution_provider Execution provider instance to execute constant folding. + */ + ConstantFoldingDQ(const IExecutionProvider& execution_provider, + bool skip_dequantize_linear, + const ConfigOptions& config_options, + const InlinedHashSet& node_index_set, + const InlinedHashSet& compatible_execution_providers = {}, + const InlinedHashSet& excluded_initializers = {}) noexcept; + + bool AllowConstantFolding(const Node& node) const override; + + private: + InlinedHashSet node_index_set_; +}; + +} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/selection_and_optimization_func.cc b/onnxruntime/core/optimizer/selection_and_optimization_func.cc new file mode 100644 index 0000000000000..151c61952a631 --- /dev/null +++ b/onnxruntime/core/optimizer/selection_and_optimization_func.cc @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "selection_and_optimization_func.h" +#include "core/graph/graph_utils.h" +#include "core/framework/compute_capability.h" +#include "core/optimizer/qdq_transformer/constant_folding_dq_node.h" + +namespace onnxruntime { + +std::vector> ConstantFoldingDQFuncs::Select(const GraphViewer& graph_viewer, + const KeyValueConfig& /*config*/, + const GraphOptimizerRegistry& /*graph_optimizer_registry*/) { + std::vector> result; + std::unique_ptr sub_graph = std::make_unique(); + const std::vector& node_index = graph_viewer.GetNodesInTopologicalOrder(ExecutionOrder::PRIORITY_BASED /*priority-based topological sort*/); + InitializedTensorSet constant_inputs; + const InlinedHashSet excluded_initializers; + + // Select DequantizeLinear node where all inputs are constant + for (const auto& index : node_index) { + const auto& node = graph_viewer.GetNode(index); + if (node->OpType() != "DequantizeLinear") { + continue; + } + if (!graph_utils::AllNodeInputsAreConstant(graph_viewer.GetGraph(), *node, constant_inputs, excluded_initializers)) { + continue; + } + sub_graph->nodes.push_back(index); + } + + result.push_back(std::make_unique(std::move(sub_graph))); + result.back()->optimization_func = ConstantFoldingDQFuncs::Optimize; + return result; +} + +Status ConstantFoldingDQFuncs::Optimize(Graph& graph, + const ComputeCapability& optimization_cc, + ComputeCapability& cc_to_update, + const GraphOptimizerRegistry& graph_optimizer_registry) { + std::string optimizer_name = kConstantFoldingDQ; + std::unordered_set original_initializers_to_remove; + std::unordered_set new_initializers_to_add; + InlinedHashSet dq_node_index_set; + + // iterate the nodes in node_to_optimize to: + // 1. get original initializers to remove + // 2. add new initializers + // 3. create dq node index set + for (const auto& index : optimization_cc.sub_graph->nodes) { + auto node = graph.GetNode(index); + if (node->OpType() != "DequantizeLinear") { + continue; + } + auto input_0 = node->InputDefs()[0]; + auto output_0 = node->OutputDefs()[0]; + original_initializers_to_remove.insert(input_0->Name()); + new_initializers_to_add.insert(output_0->Name()); + dq_node_index_set.insert(index); + } + + static auto transformer = std::make_unique(graph_optimizer_registry.GetCpuEp(), + false /*skip_dequantize_linear*/, + graph_optimizer_registry.GetSessionOptions().config_options, + dq_node_index_set); + + bool modified = false; + ORT_RETURN_IF_ERROR(transformer->Apply(graph, modified, *graph_optimizer_registry.GetLogger())); + + // update the overall ComputeCapability + std::vector updated_nodes; + for (auto index : cc_to_update.sub_graph->nodes) { + if (dq_node_index_set.find(index) != dq_node_index_set.end()) { + continue; + } + updated_nodes.push_back(index); + } + cc_to_update.sub_graph->nodes = updated_nodes; + + auto meta_def = cc_to_update.sub_graph->GetMutableMetaDef(); + std::vector updated_constant_initializers; + + for (auto constant_initializer : meta_def->constant_initializers) { + if (original_initializers_to_remove.find(constant_initializer) != original_initializers_to_remove.end()) { + continue; + } + updated_constant_initializers.push_back(constant_initializer); + } + + for (auto constant_initializer : new_initializers_to_add) { + updated_constant_initializers.push_back(constant_initializer); + } + + meta_def->constant_initializers = updated_constant_initializers; + + return Status::OK(); +} + +} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/selection_and_optimization_func.h b/onnxruntime/core/optimizer/selection_and_optimization_func.h new file mode 100644 index 0000000000000..6ad62518833b0 --- /dev/null +++ b/onnxruntime/core/optimizer/selection_and_optimization_func.h @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/optimizer/graph_optimizer_registry.h" +#include "core/framework/compute_capability.h" +#include "core/graph/graph_viewer.h" + +namespace onnxruntime { +static const std::string kConstantFoldingDQ = "ConstantFoldingDQ"; + +/** + * Optimizer's selection function: Selects a set of nodes from a given graph for optimization. Additional key/value strings can be provided to configure the optimizer. + * If needed, use graph_optimizer_registry to access the session options, the CPU EP and the logger. + * + * Optimizer's optimization function: Gets the nodes in ComputeCapability from nodes_to_optimize. Use graph_optimizer_registry to access the session options, the CPU EP + * and the logger if needed to create the optimizer. Run optimization on the nodes/subgraph, and finally, update the ComputeCapability. + * + */ + +struct ConstantFoldingDQFuncs { + static std::vector> Select(const GraphViewer& graph_viewer, + const KeyValueConfig& configs, + const GraphOptimizerRegistry& graph_optimizer_registry); + static Status Optimize(Graph& graph, + const ComputeCapability& optimization_cc, + ComputeCapability& cc_to_update, + const GraphOptimizerRegistry& graph_optimizer_registry); +}; +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/acl/acl_execution_provider.cc b/onnxruntime/core/providers/acl/acl_execution_provider.cc index ede476ff74d1b..def1d5e4b704c 100644 --- a/onnxruntime/core/providers/acl/acl_execution_provider.cc +++ b/onnxruntime/core/providers/acl/acl_execution_provider.cc @@ -153,6 +153,7 @@ std::shared_ptr ACLExecutionProvider::GetKernelRegistry() const std::vector> ACLExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant*) const { std::vector> result; for (const auto& node : graph.Nodes()) { diff --git a/onnxruntime/core/providers/acl/acl_execution_provider.h b/onnxruntime/core/providers/acl/acl_execution_provider.h index d635e56add30b..80e4aaaf021e3 100755 --- a/onnxruntime/core/providers/acl/acl_execution_provider.h +++ b/onnxruntime/core/providers/acl/acl_execution_provider.h @@ -39,6 +39,7 @@ class ACLExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* resource_accountant) const override; Status OnRunStart(const onnxruntime::RunOptions&) override; diff --git a/onnxruntime/core/providers/cann/cann_execution_provider.cc b/onnxruntime/core/providers/cann/cann_execution_provider.cc index 07e83933a890c..be09eefba791b 100644 --- a/onnxruntime/core/providers/cann/cann_execution_provider.cc +++ b/onnxruntime/core/providers/cann/cann_execution_provider.cc @@ -1254,6 +1254,7 @@ GetSubGraphPartition(const std::vector& topological_order, const std: std::vector> CANNExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant*) const { std::vector> result; diff --git a/onnxruntime/core/providers/cann/cann_execution_provider.h b/onnxruntime/core/providers/cann/cann_execution_provider.h index 5ff935463a1c1..f28ae77e49f83 100644 --- a/onnxruntime/core/providers/cann/cann_execution_provider.h +++ b/onnxruntime/core/providers/cann/cann_execution_provider.h @@ -56,6 +56,7 @@ class CANNExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* resource_accountant) const override; Status Compile(const std::vector& fused_nodes_and_graphs, diff --git a/onnxruntime/core/providers/coreml/coreml_execution_provider.cc b/onnxruntime/core/providers/coreml/coreml_execution_provider.cc index 3fa3868267c9b..cc7beed6bb298 100644 --- a/onnxruntime/core/providers/coreml/coreml_execution_provider.cc +++ b/onnxruntime/core/providers/coreml/coreml_execution_provider.cc @@ -39,6 +39,7 @@ CoreMLExecutionProvider::~CoreMLExecutionProvider() {} std::vector> CoreMLExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector> result; diff --git a/onnxruntime/core/providers/coreml/coreml_execution_provider.h b/onnxruntime/core/providers/coreml/coreml_execution_provider.h index 0609bf6af726d..574ae1fc0106b 100644 --- a/onnxruntime/core/providers/coreml/coreml_execution_provider.h +++ b/onnxruntime/core/providers/coreml/coreml_execution_provider.h @@ -20,6 +20,7 @@ class CoreMLExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* resource_accountant) const override; #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc index b675c08e5f804..54fb4429c0536 100644 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc @@ -2660,6 +2660,7 @@ std::unique_ptr CUDAExecutionProvider::GetDataTransf std::vector> CUDAExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* resource_accountant) const { std::vector> result; const logging::Logger& logger = *GetLogger(); diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.h b/onnxruntime/core/providers/cuda/cuda_execution_provider.h index 79a48e7cb89e1..a75e81f1f0c6d 100644 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.h +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.h @@ -73,6 +73,7 @@ class CUDAExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* resource_accountant) const override; int GetDeviceId() const override { return info_.device_id; } diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp index 9d23b8b950272..868b2103586f9 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp @@ -93,12 +93,13 @@ namespace Dml ExecutionProvider::GetCapability( const onnxruntime::GraphViewer& graph, const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup, + const onnxruntime::GraphOptimizerRegistry& graph_optimizer_registry, onnxruntime::IResourceAccountant* resource_accountant) const { #ifdef ENABLE_GRAPH_COMPILATION - return m_impl->GetCapability(graph, kernel_lookup, resource_accountant, *GetLogger()); + return m_impl->GetCapability(graph, kernel_lookup, graph_optimizer_registry, resource_accountant, *GetLogger()); #else - return onnxruntime::IExecutionProvider::GetCapability(graph, kernel_lookup, resource_accountant); + return onnxruntime::IExecutionProvider::GetCapability(graph, kernel_lookup, graph_optimizer_registry, resource_accountant); #endif } @@ -878,6 +879,7 @@ namespace Dml ExecutionProviderImpl::GetCapability( const onnxruntime::GraphViewer& graph, const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup, + const onnxruntime::GraphOptimizerRegistry& /* graph_optimizer_registry */, onnxruntime::IResourceAccountant*, const onnxruntime::logging::Logger& logger) const { uint32_t deviceDataTypeMask = GetSupportedDeviceDataTypeMask(); // Each bit corresponds to each DML_TENSOR_DATA_TYPE. diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h index 7f420f8850001..aa3d8b0b4a409 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h @@ -13,6 +13,7 @@ namespace onnxruntime { class IResourceAccountant; +class GraphOptimizerRegistry; } namespace WRL { @@ -93,6 +94,7 @@ namespace Dml GetCapability( const onnxruntime::GraphViewer& graph, const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup, + const onnxruntime::GraphOptimizerRegistry& graph_optimizer_registry, onnxruntime::IResourceAccountant* resource_accountant, const onnxruntime::logging::Logger& logger) const; @@ -288,6 +290,7 @@ namespace Dml std::vector> GetCapability(const onnxruntime::GraphViewer& graph, const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup, + const onnxruntime::GraphOptimizerRegistry& /* graph_optimizer_registry */, onnxruntime::IResourceAccountant* resource_accountant) const final override; onnxruntime::common::Status OnSessionInitializationEnd() override diff --git a/onnxruntime/core/providers/dnnl/dnnl_execution_provider.cc b/onnxruntime/core/providers/dnnl/dnnl_execution_provider.cc index 4da82b351f1d6..d0e5b0b1588ef 100644 --- a/onnxruntime/core/providers/dnnl/dnnl_execution_provider.cc +++ b/onnxruntime/core/providers/dnnl/dnnl_execution_provider.cc @@ -147,6 +147,7 @@ std::vector> DnnlExecutionProvider::GetSupportedNodes(con std::vector> DnnlExecutionProvider::GetCapability( const GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { // follow from coreml ep's Getcapability diff --git a/onnxruntime/core/providers/dnnl/dnnl_execution_provider.h b/onnxruntime/core/providers/dnnl/dnnl_execution_provider.h index bde18e139f2a3..8f951efef2a94 100644 --- a/onnxruntime/core/providers/dnnl/dnnl_execution_provider.h +++ b/onnxruntime/core/providers/dnnl/dnnl_execution_provider.h @@ -25,6 +25,7 @@ class DnnlExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, onnxruntime::IResourceAccountant* /* resource_accountant */) const override; common::Status Compile(const std::vector& fused_nodes_and_graphs, diff --git a/onnxruntime/core/providers/js/js_execution_provider.cc b/onnxruntime/core/providers/js/js_execution_provider.cc index 9d00436150286..d8e24ff1f5053 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.cc +++ b/onnxruntime/core/providers/js/js_execution_provider.cc @@ -791,6 +791,7 @@ std::vector JsExecutionProvider::CreatePreferredAllocators() { std::vector> JsExecutionProvider::GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { InlinedVector candidates; // `tenative_candidates` is a subset of `candidates`. diff --git a/onnxruntime/core/providers/js/js_execution_provider.h b/onnxruntime/core/providers/js/js_execution_provider.h index 4bead50fc782e..c87303209c689 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.h +++ b/onnxruntime/core/providers/js/js_execution_provider.h @@ -45,6 +45,7 @@ class JsExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; std::shared_ptr GetKernelRegistry() const override; diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc index 1558d22137c05..9a694b03387ae 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc @@ -993,6 +993,7 @@ GetPartitionedSubgraphs(const std::vector& topological_order, std::vector> MIGraphXExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector> result; auto model = graph_viewer.CreateModel(*GetLogger()); diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h index d6af991f9b77e..7c89b5ec544a1 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h @@ -69,6 +69,7 @@ class MIGraphXExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; common::Status Compile(const std::vector& fused_nodes, diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc index 27bd584e2d3c6..28cfde817a620 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc @@ -81,6 +81,7 @@ NnapiExecutionProvider::~NnapiExecutionProvider() {} std::vector> NnapiExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector> result; const logging::Logger& logger = *GetLogger(); diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.h b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.h index ebf9372eb668d..a2269fdd89436 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.h +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.h @@ -26,6 +26,7 @@ class NnapiExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_view, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) diff --git a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc index 12c16e9c9b8f6..6482a07ee92bc 100644 --- a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc +++ b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc @@ -107,6 +107,7 @@ OpenVINOExecutionProvider::~OpenVINOExecutionProvider() { std::vector> OpenVINOExecutionProvider::GetCapability(const GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector> result; diff --git a/onnxruntime/core/providers/openvino/openvino_execution_provider.h b/onnxruntime/core/providers/openvino/openvino_execution_provider.h index bbcca583b074b..020aec16e507c 100644 --- a/onnxruntime/core/providers/openvino/openvino_execution_provider.h +++ b/onnxruntime/core/providers/openvino/openvino_execution_provider.h @@ -51,6 +51,7 @@ class OpenVINOExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; Status Compile(const std::vector& fused_nodes, diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index 1ad17d96e9322..a5813dc2a4adc 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -669,6 +669,7 @@ static void PartitionCtxModel(const onnxruntime::GraphViewer& graph_viewer, std::vector> QNNExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector> result; diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.h b/onnxruntime/core/providers/qnn/qnn_execution_provider.h index 0f40e40c2fa36..d7a5d04d22692 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.h +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.h @@ -31,6 +31,7 @@ class QNNExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_view, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; Status Compile(const std::vector& fused_nodes_and_graphs, diff --git a/onnxruntime/core/providers/rknpu/rknpu_execution_provider.cc b/onnxruntime/core/providers/rknpu/rknpu_execution_provider.cc index 10fd81786f977..e9343e2b2e06a 100644 --- a/onnxruntime/core/providers/rknpu/rknpu_execution_provider.cc +++ b/onnxruntime/core/providers/rknpu/rknpu_execution_provider.cc @@ -51,6 +51,7 @@ std::vector> RknpuExecutionProvider::GetSupportedNodes( std::vector> RknpuExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { // Find inputs, initializers and outputs for each supported subgraph std::vector> result; diff --git a/onnxruntime/core/providers/rknpu/rknpu_execution_provider.h b/onnxruntime/core/providers/rknpu/rknpu_execution_provider.h index ce16d63e111d9..75cae37d117a0 100644 --- a/onnxruntime/core/providers/rknpu/rknpu_execution_provider.h +++ b/onnxruntime/core/providers/rknpu/rknpu_execution_provider.h @@ -20,6 +20,7 @@ class RknpuExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; common::Status Compile(const std::vector& fused_nodes_and_graphs, std::vector& node_compute_funcs) override; diff --git a/onnxruntime/core/providers/rocm/rocm_execution_provider.cc b/onnxruntime/core/providers/rocm/rocm_execution_provider.cc index 9d6e9df907ce3..49771488efc44 100644 --- a/onnxruntime/core/providers/rocm/rocm_execution_provider.cc +++ b/onnxruntime/core/providers/rocm/rocm_execution_provider.cc @@ -2441,6 +2441,7 @@ std::unique_ptr ROCMExecutionProvider::GetDataTransf std::vector> ROCMExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { InlinedVector candidates; // A subset of the above vector. A subset of the tentative_nodes might be moved to CPU. diff --git a/onnxruntime/core/providers/rocm/rocm_execution_provider.h b/onnxruntime/core/providers/rocm/rocm_execution_provider.h index ff2bff7c98723..2baaf2ff1a886 100644 --- a/onnxruntime/core/providers/rocm/rocm_execution_provider.h +++ b/onnxruntime/core/providers/rocm/rocm_execution_provider.h @@ -62,6 +62,7 @@ class ROCMExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; int GetDeviceId() const override { return info_.device_id; } diff --git a/onnxruntime/core/providers/shared_library/provider_api.h b/onnxruntime/core/providers/shared_library/provider_api.h index 6ff2572e5e668..9d61e1f12f5b6 100644 --- a/onnxruntime/core/providers/shared_library/provider_api.h +++ b/onnxruntime/core/providers/shared_library/provider_api.h @@ -200,6 +200,7 @@ struct SparseTensor; class TensorSeq; class SessionState; class ModelMetadefIdGenerator; +class GraphOptimizerRegistry; class If; class Loop; diff --git a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc index 2dab9f6a402a0..90fd36ea29956 100644 --- a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc +++ b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc @@ -332,8 +332,9 @@ bool IAllocator::CalcMemSizeForArrayWithAlignment(size_t nmemb, size_t size, siz std::vector> IExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& graph_optimizer_registry, IResourceAccountant* resource_accountant) const { - return g_host->IExecutionProvider__GetCapability(this, graph_viewer, kernel_lookup, resource_accountant); + return g_host->IExecutionProvider__GetCapability(this, graph_viewer, kernel_lookup, graph_optimizer_registry, resource_accountant); } common::Status IExecutionProvider::Compile(const std::vector& fused_nodes_and_graphs, std::vector& node_compute_funcs) { diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index a77f0cb4c27b0..83d615c1bde0a 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -105,6 +105,8 @@ using ModelMetaData = std::unordered_map; using IOnnxRuntimeOpSchemaCollectionPtr = std::shared_ptr; using IOnnxRuntimeOpSchemaRegistryList = std::list; using InitializedTensorSet = std::unordered_map; +using KeyValueConfig = std::unordered_map; +using SelectionFunc = std::function>(const GraphViewer&, const KeyValueConfig&, const GraphOptimizerRegistry&)>; struct Node__NodeIterator { virtual ~Node__NodeIterator() {} @@ -151,6 +153,10 @@ struct ConstGraphNodes_Iterator { struct ProviderHost { virtual const OrtApiBase* OrtGetApiBase() = 0; + virtual Status GetOptimizerByName(const std::string& name, + const GraphOptimizerRegistry& graph_optimizer_registry, + SelectionFunc& selection_func) = 0; + virtual void* HeapAllocate(size_t size) = 0; virtual void HeapFree(void*) = 0; @@ -253,6 +259,7 @@ struct ProviderHost { // IExecutionProvider virtual std::vector> IExecutionProvider__GetCapability(const IExecutionProvider* p, const onnxruntime::GraphViewer& graph_viewer, const IExecutionProvider::IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& graph_optimizer_registry, IResourceAccountant* resource_accountant) = 0; virtual common::Status IExecutionProvider__Compile(IExecutionProvider* p, const std::vector& fused_nodes_and_graphs, std::vector& node_compute_funcs) = 0; @@ -627,6 +634,8 @@ struct ProviderHost { virtual std::unique_ptr ComputeCapability__construct(std::unique_ptr t_sub_graph) = 0; virtual void ComputeCapability__operator_delete(ComputeCapability* p) = 0; virtual std::unique_ptr& ComputeCapability__SubGraph(ComputeCapability* p) = 0; + virtual void ComputeCapability__copy_optimization_func(ComputeCapability* p, ComputeCapability* selection_cc) = 0; + virtual void ComputeCapability__add_nodes_to_optimize(ComputeCapability* p, std::unique_ptr optimization_cc) = 0; // DataTransferManager virtual Status DataTransferManager__CopyTensor(const DataTransferManager* p, const Tensor& src, Tensor& dst) = 0; diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index a502ce9c66f69..e2af144f455e4 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -527,6 +527,9 @@ struct ComputeCapability final { std::unique_ptr& SubGraph() { return g_host->ComputeCapability__SubGraph(this); } + void copy_optimization_func(ComputeCapability* selection_cc) { g_host->ComputeCapability__copy_optimization_func(this, selection_cc); } + void add_nodes_to_optimize(std::unique_ptr optimization_cc) { g_host->ComputeCapability__add_nodes_to_optimize(this, std::move(optimization_cc)); } + ComputeCapability() = delete; ComputeCapability(const ComputeCapability&) = delete; void operator=(const ComputeCapability&) = delete; diff --git a/onnxruntime/core/providers/snpe/snpe_execution_provider.cc b/onnxruntime/core/providers/snpe/snpe_execution_provider.cc index c7fc6d3a556a7..4eae7c97f9ab0 100644 --- a/onnxruntime/core/providers/snpe/snpe_execution_provider.cc +++ b/onnxruntime/core/providers/snpe/snpe_execution_provider.cc @@ -72,6 +72,7 @@ SNPEExecutionProvider::~SNPEExecutionProvider() {} std::vector> SNPEExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector candidates; for (auto& node_index : graph.GetNodesInTopologicalOrder()) { diff --git a/onnxruntime/core/providers/snpe/snpe_execution_provider.h b/onnxruntime/core/providers/snpe/snpe_execution_provider.h index 99033649fcbbf..4b7987b38ee93 100644 --- a/onnxruntime/core/providers/snpe/snpe_execution_provider.h +++ b/onnxruntime/core/providers/snpe/snpe_execution_provider.h @@ -19,6 +19,7 @@ class SNPEExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; std::shared_ptr GetKernelRegistry() const override; diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index e59d252793532..523ebbfae807a 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -2459,6 +2459,7 @@ bool TensorrtExecutionProvider::DetectTensorRTGraphCycles(SubGraphCollection_t& std::vector> TensorrtExecutionProvider::GetCapability(const GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& graph_optimizer_registry, IResourceAccountant* /* resource_accountant */) const { // Construct subgraph capability from node list std::vector> result; @@ -2664,11 +2665,61 @@ TensorrtExecutionProvider::GetCapability(const GraphViewer& graph, } } + /** + * Enable EP related L2+ graph optimizations: + * + * 1. Calls provider bridge API to lookup pre-defined optimizer by name and get selection function. + * - Example: g_host->GetOptimizerByName(optimizer_name, graph_optimizer_registry, selection_func) + * 2. Executes the selection function to obtain the selection ComputeCapability. + * - ComputeCapability.optimize_func would be set by the optimizer to the function that does the optimization. + * 3. Uses the selection ComputeCapability to create the optimization ComputeCapability. + * 4. Returns the final ComputeCapability, with nodes_to_optimize set to the optimization ComputeCapability. + * + * Current available optimizations: + * - (ConstantFoldingDQ) constant folding on DQ nodes, i.e. dequantize INT32, UINT16, INT16 constant to FP32. + */ + + SelectionFunc selection_func; + std::vector> selection_cc; + + // Prepare for ConstantFoldingDQ optimizer + // Note: The NodeIndex here is the node index in the graph, not the index in node vector in supported_nodes_vector. + std::unordered_set trt_selection_node_set; // The qualified dq nodes selected by TRT EP + std::unordered_map consumer_to_dq; // consumer node -> dq node + + if (dla_enable_) { + std::string optimizer_name = "ConstantFoldingDQ"; + const std::unordered_map key_value_config; + auto status = g_host->GetOptimizerByName(optimizer_name, graph_optimizer_registry, selection_func); + if (status == Status::OK()) { + if (selection_func) { + selection_cc = selection_func(graph, key_value_config, graph_optimizer_registry); + SelectQualifiedDQNode(graph, trt_selection_node_set, consumer_to_dq); + } + } else { + LOGS_DEFAULT(WARNING) << "[TensorRT EP] Can't get optimizer " << optimizer_name; + } + } + + // Create ComputeCapability int number_of_trt_nodes = 0, subgraph_index = 0; - for (const auto& group : supported_nodes_vector) { + for (auto& group : supported_nodes_vector) { if (!group.first.empty()) { + if (!selection_cc.empty()) { + // Include DQ nodes that are filtered out by TRT parser + UpdateSupportedNodeVectorForDQ(graph, group, supported_nodes_vector, consumer_to_dq); + } + std::unique_ptr sub_graph = GetSubGraph(group, graph, model_hash, subgraph_index); - result.push_back(ComputeCapability::Create(std::move(sub_graph))); + auto compute_capability = ComputeCapability::Create(std::move(sub_graph)); + + // add optimization ComputeCapability to node_to_optimize + for (auto& cc : selection_cc) { + std::unique_ptr optimization_cc = CreateOptimizationComputeCapability(cc.get(), trt_selection_node_set, compute_capability.get()); + compute_capability->add_nodes_to_optimize(std::move(optimization_cc)); + } + + result.push_back(std::move(compute_capability)); number_of_trt_nodes += static_cast(group.first.size()); subgraph_index++; } diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h index 873826a81c51b..934cc06eed45f 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h @@ -249,6 +249,7 @@ class TensorrtExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& graph_optimizer_registry, IResourceAccountant* /* resource_accountant */) const override; int GetDeviceId() const { return device_id_; } @@ -592,5 +593,35 @@ class TensorrtExecutionProvider : public IExecutionProvider { * This function only creates the instance at the first time it's being called." */ nvinfer1::IBuilder* GetBuilder(TensorrtLogger& trt_logger) const; + + /** + * This is the helper function for ConstantFoldingDQ graph transformer. + * + * It selects the qualified/required DQ node to be optimized as well as provides a mapping table + * to help TRT EP later include the DQ node which is filtered out by TRT parser. + */ + void SelectQualifiedDQNode(const GraphViewer& graph, + std::unordered_set& selection_node_set, + std::unordered_map& consumer_to_dq) const; + + /** + * This function returns an optimization ComputeCapability that is limited to: + * 1. the DQ nodes in this individual TRT ComputeCapability + * 2. the DQ nodes that are qualified and selected by TRT EP + * + * It also needs to make sure the DQ nodes is a subset of the complete list of DQ nodes to optimize in original selection ComputeCapability. + * Finally, copy the optimization function from the original selection ComputeCapability. + */ + std::unique_ptr CreateOptimizationComputeCapability(ComputeCapability* selection_cc, + std::unordered_set& trt_selection_node_set, + ComputeCapability* trt_cc) const; + /** + * This function helps add back the DQ nodes that are filtered out by TRT parser. + * The reason is the DQ nodes can be optimized and dequantized by applying ConstantFoldingDQ optimizer by ORT L2+ optimization. + */ + void UpdateSupportedNodeVectorForDQ(const GraphViewer& graph, + SubGraph_t& supported_node_vector, + SubGraphCollection_t& supported_nodes_vector, + std::unordered_map consumer_to_dq) const; }; } // namespace onnxruntime diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc index 92fa101118506..71674f7c9c557 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc @@ -258,4 +258,133 @@ void TensorrtExecutionProvider::SetAllGraphInputs(Graph& graph) const { graph.SetInputs(graph_inputs_including_initializers); } + +/** + * This is the helper function for ConstantFoldingDQ graph transformer. + * + * It selects the qualified/required DQ node to be optimized as well as provides a mapping table + * to help TRT EP later include the DQ node which is filtered out by TRT parser. + */ +void TensorrtExecutionProvider::SelectQualifiedDQNode(const GraphViewer& graph, + std::unordered_set& selection_node_set, + std::unordered_map& consumer_to_dq) const { + LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] Select qualified DQ nodes ..."; + const std::vector& node_index = graph.GetNodesInTopologicalOrder(1 /*priority-based topological sort*/); + for (auto index : node_index) { + auto* node = graph.GetNode(index); + if (!node) { + continue; + } + + const auto* input_def = node->InputDefs()[0]; // Get NodeArg of the initializer of the DequantizeLinear node; + auto data_type = input_def->TypeAsProto()->tensor_type().elem_type(); + auto constant_initializer = graph.IsConstantInitializer(input_def->Name(), true); + + // Node selection: (i.e. initializer -> DQ -> bias of X) + // 1. DequantizeLinear op + // 2. DQ node does not produce graph output, single consumer + // 3. The first input of DQ is constant initializer. + // 4. The data type of initializer is INT32, UINT16 or INT16 + // 5. X should be Gemm, Conv or LayerNormalization ? + if (node->OpType() == "DequantizeLinear" && + node->GetOutputEdgesCount() == 1 && + (data_type == ONNX_NAMESPACE::TensorProto_DataType_INT32 || data_type == ONNX_NAMESPACE::TensorProto_DataType_INT16 || data_type == ONNX_NAMESPACE::TensorProto_DataType_UINT16) && + constant_initializer) { + const Node& consumer_node = *node->OutputNodesBegin(); + selection_node_set.insert(index); + consumer_to_dq[consumer_node.Index()] = index; + LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] " << consumer_node.Name() << " <- " << node->Name(); + } + } + LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] Total " << selection_node_set.size() << " DequantizeLinear node(s) are selected."; +} + +/** + * This function returns an optimization ComputeCapability that is limited to: + * 1. the DQ nodes in this individual TRT ComputeCapability + * 2. the DQ nodes that are qualified and selected by TRT EP + * + * It also needs to make sure the DQ nodes is a subset of the complete list of DQ nodes to optimize in original selection ComputeCapability. + * Finally, copy the optimization function from the original selection ComputeCapability. + */ +std::unique_ptr TensorrtExecutionProvider::CreateOptimizationComputeCapability(ComputeCapability* selection_cc, + std::unordered_set& trt_selection_node_set, + ComputeCapability* trt_cc) const { + auto sub_graph = onnxruntime::IndexedSubGraph::Create(); + std::unordered_set selection_node_set; + + for (auto index : selection_cc->SubGraph()->Nodes()) { + selection_node_set.insert(index); + } + + for (auto index : trt_cc->SubGraph()->Nodes()) { + if (selection_node_set.find(index) == selection_node_set.end()) { + continue; + } + if (trt_selection_node_set.find(index) == trt_selection_node_set.end()) { + continue; + } + sub_graph->Nodes().push_back(index); + } + auto compute_capability = ComputeCapability::Create(std::move(sub_graph)); + compute_capability->copy_optimization_func(selection_cc); + return compute_capability; +} + +/** + * This function helps add back the DQ nodes that are filtered out by TRT parser. + * The reason is the DQ nodes can be optimized and dequantized by applying ConstantFoldingDQ optimizer by ORT L2+ optimization. + */ +void TensorrtExecutionProvider::UpdateSupportedNodeVectorForDQ(const GraphViewer& graph, + SubGraph_t& supported_node_vector, + SubGraphCollection_t& supported_nodes_vector, + std::unordered_map consumer_to_dq) const { + if (consumer_to_dq.empty()) { + return; + } + + if (!supported_node_vector.second) { + return; + } + + const std::vector& node_index = graph.GetNodesInTopologicalOrder(1); + auto supported_nodes = supported_node_vector.first; + for (auto index : supported_nodes) { + if (consumer_to_dq.find(node_index[index]) == consumer_to_dq.end()) { + continue; + } + + auto dq_node_index = consumer_to_dq[node_index[index]]; + + // Check if DQ node is included in one of the subgraphs + auto in_the_subgraph_collection = [&](NodeIndex node_idx) -> bool { + for (auto& node_vector : supported_nodes_vector) { + if (!node_vector.second) { + continue; + } + for (auto i : node_vector.first) { + if (node_index[i] == node_idx) { + return true; + } + } + } + return false; + }; + + // If the DQ node is already in the subgraph, do nothing. + if (in_the_subgraph_collection(dq_node_index)) { + continue; + } + + // Find the iterator pointing to the target element + auto it = std::find(node_index.begin(), node_index.end(), dq_node_index); + if (it != node_index.end()) { + // Calculate the index + size_t idx = std::distance(node_index.begin(), it); + supported_node_vector.first.push_back(idx); + auto node = graph.GetNode(dq_node_index); + LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] " << node->Name() << " is included which is filtered out by TRT parser."; + } + } +} } // namespace onnxruntime diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc index 5d2204b0b1979..ab8a95b38491d 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc @@ -51,7 +51,7 @@ const InlinedVector VitisAIExecutionProvider::GetEpContextNodes() c return ep_context_node_ptrs; } std::vector> VitisAIExecutionProvider::GetCapability( - const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, IResourceAccountant* /* resource_accountant */) const { + const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { if (graph_viewer.IsSubgraph()) { // VITIS AI EP not support sungraph. Assigned to CPU. return {}; diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h index 5b031ab882839..f72f8cc721fbd 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h @@ -29,6 +29,7 @@ class VitisAIExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; int GetDeviceId() const { return 0; } diff --git a/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.cc b/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.cc index 4b9f6fae86423..3b5daef04dd50 100644 --- a/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.cc +++ b/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.cc @@ -62,6 +62,7 @@ VSINPUExecutionProvider::~VSINPUExecutionProvider() {} std::vector> VSINPUExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { std::vector> result; diff --git a/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.h b/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.h index 16cfbc8a9c581..1c0b8b63a8e6c 100644 --- a/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.h +++ b/onnxruntime/core/providers/vsinpu/vsinpu_execution_provider.h @@ -40,6 +40,7 @@ class VSINPUExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; std::shared_ptr GetKernelRegistry() const override; Status Compile(const std::vector& fused_nodes_and_graphs, diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index f3bf2402252b7..df7f2d6dcdeab 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -765,6 +765,7 @@ std::vector WebGpuExecutionProvider::CreatePreferredAllocators() { std::vector> WebGpuExecutionProvider::GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { InlinedVector candidates; // `tenative_candidates` is a subset of `candidates`. diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h index dc25636821651..e2e23b6a307cf 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h @@ -45,6 +45,7 @@ class WebGpuExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; std::shared_ptr GetKernelRegistry() const override; diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index 39e6520e3912b..7410ff66add30 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -56,6 +56,7 @@ WebNNExecutionProvider::~WebNNExecutionProvider() {} std::vector> WebNNExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_registries*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { // For subgraph which is the attribute of the control flow nodes, part of its initializers are stored in its // ancestor graphs as common initializers shared for other subgraphs. We need to collect all of them used for diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.h b/onnxruntime/core/providers/webnn/webnn_execution_provider.h index e806dc340d53e..b8775e717668a 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.h +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.h @@ -25,6 +25,7 @@ class WebNNExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_registries*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; DataLayout GetPreferredLayout() const override { return preferred_layout_; } diff --git a/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.cc b/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.cc index 641f8b0729d0a..ab14c083884d3 100644 --- a/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.cc +++ b/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.cc @@ -258,6 +258,7 @@ static void AddComputeCapabilityForEachNodeInNodeUnit( std::vector> XnnpackExecutionProvider::GetCapability( const onnxruntime::GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { const auto& logger = *GetLogger(); std::vector> capabilities; diff --git a/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.h b/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.h index 152bef1a1c52c..9c4d2484f9f4b 100644 --- a/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.h +++ b/onnxruntime/core/providers/xnnpack/xnnpack_execution_provider.h @@ -33,6 +33,7 @@ class XnnpackExecutionProvider : public IExecutionProvider { std::vector> GetCapability( const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; std::shared_ptr GetKernelRegistry() const override; diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index e941b1ebbaba8..e5ea562ce3535 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -42,6 +42,7 @@ #include "core/graph/model_saving_options.h" #include "core/optimizer/graph_transformer_utils.h" #include "core/optimizer/graph_transformer.h" +#include "core/optimizer/graph_optimizer_registry.h" #include "core/optimizer/layout_transformation/layout_transformation.h" #include "core/optimizer/insert_cast_transformer.h" #include "core/optimizer/qdq_transformer/ensure_unique_dq_for_node_unit.h" @@ -1278,8 +1279,13 @@ common::Status InferenceSession::TransformGraph(onnxruntime::Graph& graph, bool // 6. insert cast nodes (required transformer). // 7. insert copy nodes (required transformer). + // Create GraphOptimizerRegistry instance for providing predefined graph optimizers and selection functions for EPs to lookup + auto graph_optimizer_registry = std::make_unique(&session_options_, + execution_providers_.Get(onnxruntime::kCpuExecutionProvider), + session_logger_); + GraphPartitioner partitioner(kernel_registry_manager_, execution_providers_, std::move(graph_optimizer_registry)); + // Run Ahead Of time function inlining - GraphPartitioner partitioner(kernel_registry_manager_, execution_providers_); if (const bool disable_aot_function_inlining = session_options_.config_options.GetConfigOrDefault( kOrtSessionOptionsDisableAheadOfTimeFunctionInlining, "0") == "1"; @@ -1682,7 +1688,7 @@ Status PartitionOrtFormatModel(onnxruntime::Graph& graph, const ExecutionProviders& providers, KernelRegistryManager& kernel_registry_manager, SessionState& session_state, - const ConfigOptions& config_options, + const SessionOptions& sess_options, const logging::Logger& logger) { layout_transformation::TransformLayoutFunction transform_layout_fn = nullptr; @@ -1700,11 +1706,16 @@ Status PartitionOrtFormatModel(onnxruntime::Graph& graph, } #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) - GraphPartitioner partitioner(kernel_registry_manager, providers); + // Create GraphOptimizerRegistry instance for providing predefined graph optimizers and selection functions for EPs to lookup + auto graph_optimizer_registry = std::make_unique(&sess_options, + providers.Get(onnxruntime::kCpuExecutionProvider), + &logger); + + GraphPartitioner partitioner(kernel_registry_manager, providers, std::move(graph_optimizer_registry)); ORT_RETURN_IF_ERROR(partitioner.Partition(graph, session_state.GetMutableFuncMgr(), transform_layout_fn, - config_options, + sess_options.config_options, logger, GraphPartitioner::Mode::kOrtFormatLoad)); @@ -2147,7 +2158,7 @@ common::Status InferenceSession::Initialize() { #endif // !defined(ORT_MINIMAL_BUILD) } else { ORT_RETURN_IF_ERROR_SESSIONID_(PartitionOrtFormatModel(graph, execution_providers_, kernel_registry_manager_, - *session_state_, session_options_.config_options, *session_logger_)); + *session_state_, session_options_, *session_logger_)); #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) const auto& cpu_ep = *execution_providers_.Get(onnxruntime::kCpuExecutionProvider); diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 1d25ceb9af8a3..69dea34175155 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -4,6 +4,7 @@ // This is the Onnxruntime side of the bridge to allow providers to be built as a DLL // It implements onnxruntime::ProviderHost +#include #include "core/common/inlined_containers.h" #include "core/common/path_string.h" #include "core/framework/allocator_utils.h" @@ -35,6 +36,7 @@ #include "core/graph/graph_proto_serializer.h" #include "core/framework/murmurhash3.h" #include "core/framework/model_metadef_id_generator.h" +#include "core/optimizer/graph_optimizer_registry.h" #include "core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.h" #include "core/optimizer/qdq_transformer/selectors_actions/shared/utils.h" @@ -237,6 +239,21 @@ common::Status LoadDynamicLibraryFromProvider(onnxruntime::PathString library_na struct ProviderHostImpl : ProviderHost { const OrtApiBase* OrtGetApiBase() override { return ::OrtGetApiBase(); } + Status GetOptimizerByName(const std::string& name, + const GraphOptimizerRegistry& graph_optimizer_registry, + SelectionFunc& selection_func) override { + std::string optimizer_name(name); + + auto func = graph_optimizer_registry.GetSelectionFunc(optimizer_name); + + if (func.has_value()) { + selection_func = func.value(); + } else { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to get optimizer " + optimizer_name); + } + return Status::OK(); + }; + void* HeapAllocate(size_t size) override { return new uint8_t[size]; } void HeapFree(void* p) override { delete[] reinterpret_cast(p); } @@ -360,8 +377,9 @@ struct ProviderHostImpl : ProviderHost { std::vector> IExecutionProvider__GetCapability( const IExecutionProvider* p, const onnxruntime::GraphViewer& graph_viewer, const IExecutionProvider::IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& graph_optimizer_registry, IResourceAccountant* resource_accountant) override { - return p->IExecutionProvider::GetCapability(graph_viewer, kernel_lookup, resource_accountant); + return p->IExecutionProvider::GetCapability(graph_viewer, kernel_lookup, graph_optimizer_registry, resource_accountant); } common::Status IExecutionProvider__Compile(IExecutionProvider* p, const std::vector& fused_nodes_and_graphs, std::vector& node_compute_funcs) override { @@ -797,6 +815,8 @@ struct ProviderHostImpl : ProviderHost { std::unique_ptr ComputeCapability__construct(std::unique_ptr t_sub_graph) override { return std::make_unique(std::move(t_sub_graph)); } void ComputeCapability__operator_delete(ComputeCapability* p) override { delete p; } std::unique_ptr& ComputeCapability__SubGraph(ComputeCapability* p) override { return p->sub_graph; } + void ComputeCapability__copy_optimization_func(ComputeCapability* p, ComputeCapability* selection_cc) override { p->optimization_func = selection_cc->optimization_func; } + void ComputeCapability__add_nodes_to_optimize(ComputeCapability* p, std::unique_ptr optimization_cc) override { p->nodes_to_optimize.push_back(std::move(optimization_cc)); } // DataTransferManager (wrapped) Status DataTransferManager__CopyTensor(const DataTransferManager* p, const Tensor& src, Tensor& dst) override { return p->CopyTensor(src, dst); } @@ -1631,6 +1651,7 @@ struct ProviderHostImpl : ProviderHost { Status LoadDynamicLibrary(onnxruntime::PathString library_name) override { return LoadDynamicLibraryFromProvider(library_name); }; #endif } provider_host_; + #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif diff --git a/onnxruntime/test/framework/inference_session_test.cc b/onnxruntime/test/framework/inference_session_test.cc index 1b06eb55afbd2..95101c8075fc2 100644 --- a/onnxruntime/test/framework/inference_session_test.cc +++ b/onnxruntime/test/framework/inference_session_test.cc @@ -138,6 +138,7 @@ class FuseExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override { // Fuse two add into one. std::vector> result; diff --git a/onnxruntime/test/framework/session_state_test.cc b/onnxruntime/test/framework/session_state_test.cc index b6b915f90d99a..8f4eede76b905 100644 --- a/onnxruntime/test/framework/session_state_test.cc +++ b/onnxruntime/test/framework/session_state_test.cc @@ -27,6 +27,7 @@ #include "test/util/include/default_providers.h" #include "test/util/include/file_util.h" #include "core/optimizer/layout_transformation/layout_transformation.h" +#include "core/optimizer/graph_optimizer_registry.h" using namespace ONNX_NAMESPACE; namespace onnxruntime { @@ -264,7 +265,11 @@ TEST_P(SessionStateTestP, TestInitializerProcessing) { SessionState session_state(graph, execution_providers, tp.get(), nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); - GraphPartitioner partitioner(krm, execution_providers); + // Create GraphOptimizerRegistry instance for providing predefined graph optimizers and selection functions for EPs to lookup + auto graph_optimizer_registry = std::make_unique(&sess_options, + execution_providers.Get(onnxruntime::kCpuExecutionProvider), + &DefaultLoggingManager().DefaultLogger()); + GraphPartitioner partitioner(krm, execution_providers, std::move(graph_optimizer_registry)); ASSERT_STATUS_OK( partitioner.Partition( graph, session_state.GetMutableFuncMgr(), @@ -350,8 +355,12 @@ TEST(SessionStateTest, TestInitializerMemoryAllocatedUsingNonArenaMemory) { SessionState session_state(graph, execution_providers, nullptr, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); + // Create GraphOptimizerRegistry instance for providing predefined graph optimizers and selection functions for EPs to lookup + auto graph_optimizer_registry = std::make_unique(&sess_options, + execution_providers.Get(onnxruntime::kCpuExecutionProvider), + &DefaultLoggingManager().DefaultLogger()); // Partition the graph - GraphPartitioner partitioner(krm, execution_providers); + GraphPartitioner partitioner(krm, execution_providers, std::move(graph_optimizer_registry)); ASSERT_STATUS_OK(partitioner.Partition( graph, session_state.GetMutableFuncMgr(), [&cpu_allocator](Graph& graph, bool& modified, const IExecutionProvider& execution_provider, @@ -409,8 +418,13 @@ TEST(SessionStateTest, TestInitializerMemoryAllocatedUsingNonArenaMemory) { SessionState session_state(graph, execution_providers, nullptr, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); + // Create GraphOptimizerRegistry instance for providing predefined graph optimizers and selection functions for EPs to lookup + auto graph_optimizer_registry = std::make_unique(&sess_options, + execution_providers.Get(onnxruntime::kCpuExecutionProvider), + &DefaultLoggingManager().DefaultLogger()); + // Partition the graph - GraphPartitioner partitioner(krm, execution_providers); + GraphPartitioner partitioner(krm, execution_providers, std::move(graph_optimizer_registry)); ASSERT_STATUS_OK(partitioner.Partition( graph, session_state.GetMutableFuncMgr(), [&cpu_allocator](Graph& graph, bool& modified, @@ -479,7 +493,12 @@ void LoadWithResourceAwarePartitioning(const ORTCHAR_T* model_path, SessionState session_state(model->MainGraph(), execution_providers, tp.get(), nullptr, dtm, edlm, default_logger, profiler, sess_options); - GraphPartitioner partitioner(krm, execution_providers); + // Create GraphOptimizerRegistry instance for providing predefined graph optimizers and selection functions for EPs to lookup + auto graph_optimizer_registry = std::make_unique(&sess_options, + execution_providers.Get(onnxruntime::kCpuExecutionProvider), + &DefaultLoggingManager().DefaultLogger()); + + GraphPartitioner partitioner(krm, execution_providers, std::move(graph_optimizer_registry)); layout_transformation::TransformLayoutFunction transform_layout_fn; layout_transformation::DebugGraphFn debug_graph_fn; ASSERT_STATUS_OK( diff --git a/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.cc b/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.cc index b753bc386d722..ee0aff6d26444 100644 --- a/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.cc +++ b/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.cc @@ -111,6 +111,7 @@ DataLayout InternalTestingExecutionProvider::GetPreferredLayout() const { std::vector> InternalTestingExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const { // find nodes that have ops in our supported list std::unordered_set supported_static_nodes; diff --git a/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.h b/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.h index d2ed8259ee974..0caa0febc2796 100644 --- a/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.h +++ b/onnxruntime/test/providers/internal_testing/internal_testing_execution_provider.h @@ -20,6 +20,7 @@ class InternalTestingExecutionProvider : public IExecutionProvider { std::vector> GetCapability(const onnxruntime::GraphViewer& graph_view, const IKernelLookup& /*kernel_lookup*/, + const GraphOptimizerRegistry& /* graph_optimizer_registry */, IResourceAccountant* /* resource_accountant */) const override; common::Status Compile(const std::vector& fused_nodes, diff --git a/onnxruntime/test/providers/qnn/qnn_test_utils.cc b/onnxruntime/test/providers/qnn/qnn_test_utils.cc index e2deccc4fff0f..2361e179d1cf1 100644 --- a/onnxruntime/test/providers/qnn/qnn_test_utils.cc +++ b/onnxruntime/test/providers/qnn/qnn_test_utils.cc @@ -14,6 +14,7 @@ #include "core/framework/compute_capability.h" #include "core/graph/graph.h" #include "core/session/onnxruntime_session_options_config_keys.h" +#include "core/optimizer/graph_optimizer_registry.h" namespace onnxruntime { namespace test { @@ -279,9 +280,10 @@ static BackendSupport GetHTPSupport(const onnxruntime::logging::Logger& logger) onnxruntime::GraphViewer graph_viewer(graph); std::unique_ptr qnn_ep = QnnExecutionProviderWithOptions( {{"backend_path", "QnnHtp.dll"}, {"offload_graph_io_quantization", "0"}}); + GraphOptimizerRegistry graph_optimizer_registry(nullptr, nullptr, nullptr); // as a placeholder to feed into GetCapability qnn_ep->SetLogger(&logger); - auto result = qnn_ep->GetCapability(graph_viewer, kernel_lookup, nullptr); + auto result = qnn_ep->GetCapability(graph_viewer, kernel_lookup, graph_optimizer_registry, nullptr); return result.empty() ? BackendSupport::UNSUPPORTED : BackendSupport::SUPPORTED; } @@ -342,9 +344,10 @@ static BackendSupport GetCPUSupport(const onnxruntime::logging::Logger& logger) onnxruntime::GraphViewer graph_viewer(graph); std::unique_ptr qnn_ep = QnnExecutionProviderWithOptions( {{"backend_path", "QnnCpu.dll"}, {"offload_graph_io_quantization", "0"}}); + GraphOptimizerRegistry graph_optimizer_registry(nullptr, nullptr, nullptr); // as a placeholder to feed into GetCapability qnn_ep->SetLogger(&logger); - auto result = qnn_ep->GetCapability(graph_viewer, kernel_lookup, nullptr); + auto result = qnn_ep->GetCapability(graph_viewer, kernel_lookup, graph_optimizer_registry, nullptr); return result.empty() ? BackendSupport::UNSUPPORTED : BackendSupport::SUPPORTED; } From 2ba076aa9ea8e3c68e97dc0f2463fb2786fcb96f Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 6 Mar 2025 23:09:22 -0800 Subject: [PATCH 056/266] fix binplace file in web pipeline (#23930) --- .../github/azure-pipelines/templates/win-web-ci.yml | 12 ++++++++++-- .../templates/win-web-multi-browsers.yml | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml index b77cab6a19ba0..6868043f64d81 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml @@ -88,10 +88,18 @@ jobs: inputs: sourceFolder: $(Pipeline.Workspace)\artifacts contents: | - **\*.* + **\ort-*.wasm targetFolder: $(Build.SourcesDirectory)\js\web\dist flattenFolders: true - displayName: 'Binplace dist files' + displayName: 'Binplace dist files (.wasm)' + - task: CopyFiles@2 + inputs: + sourceFolder: $(Pipeline.Workspace)\artifacts + contents: | + **\ort-*.mjs + targetFolder: $(Build.SourcesDirectory)\js\web\dist + flattenFolders: true + displayName: 'Binplace dist files (.mjs)' - script: | npm ci workingDirectory: '$(Build.SourcesDirectory)\js' diff --git a/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml b/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml index e201cc0ffdd5a..00df695889b1d 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml @@ -44,10 +44,18 @@ jobs: inputs: sourceFolder: $(Pipeline.Workspace)\artifacts contents: | - **\*.* + **\ort-*.wasm targetFolder: $(Build.SourcesDirectory)\js\web\dist flattenFolders: true - displayName: 'Binplace dist files' + displayName: 'Binplace dist files (.wasm)' + - task: CopyFiles@2 + inputs: + sourceFolder: $(Pipeline.Workspace)\artifacts + contents: | + **\ort-*.mjs + targetFolder: $(Build.SourcesDirectory)\js\web\dist + flattenFolders: true + displayName: 'Binplace dist files (.mjs)' - script: | npm ci workingDirectory: '$(Build.SourcesDirectory)\js' From e47c6c165df7403bf7267ceb8c1558cf5e2ddd3f Mon Sep 17 00:00:00 2001 From: Yi-Hong Lyu Date: Fri, 7 Mar 2025 00:39:49 -0800 Subject: [PATCH 057/266] Updated run_CIs_for_external_pr.py to support the Windows OpenVINO CI pipeline (#23931) --- tools/python/run_CIs_for_external_pr.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/python/run_CIs_for_external_pr.py b/tools/python/run_CIs_for_external_pr.py index 1546a9143831a..aca5f1df7d18b 100644 --- a/tools/python/run_CIs_for_external_pr.py +++ b/tools/python/run_CIs_for_external_pr.py @@ -24,6 +24,7 @@ def get_pipeline_names(): "Windows GPU DML CI Pipeline", "Windows GPU Doc Gen CI Pipeline", "Windows GPU TensorRT CI Pipeline", + "Windows OpenVINO CI Pipeline", "ONNX Runtime Web CI Pipeline", "Win_TRT_Minimal_CUDA_Test_CI", # linux From 8969ee7817de81de36affad8feecc13aae8d97aa Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Fri, 7 Mar 2025 18:58:01 +1000 Subject: [PATCH 058/266] Fix ConvInteger handling of optional inputs. (#23935) ### Description Fix ConvInteger handling of optional inputs. Need to check Exists() and not just the number of inputs. ### Motivation and Context #23927 --- .../cpu/quantization/conv_integer.cc | 7 ++-- .../providers/cpu/nn/conv_integer_test.cc | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/providers/cpu/quantization/conv_integer.cc b/onnxruntime/core/providers/cpu/quantization/conv_integer.cc index 03b39e19ed748..f3c6b18f8e753 100644 --- a/onnxruntime/core/providers/cpu/quantization/conv_integer.cc +++ b/onnxruntime/core/providers/cpu/quantization/conv_integer.cc @@ -34,17 +34,18 @@ ONNX_OPERATOR_KERNEL_EX( ConvInteger); Status ConvInteger::Compute(OpKernelContext* context) const { - size_t num_inputs = OpKernel::Node().InputDefs().size(); + const auto input_defs = Node().InputDefs(); + size_t num_inputs = input_defs.size(); const auto* X = context->Input(0); const auto* W = context->Input(1); uint8_t input_offset = 0; uint8_t filter_offset = 0; - if (num_inputs >= 3) { + if (num_inputs >= 3 && input_defs[2]->Exists()) { const auto* X_Zero_Point = context->Input(2); ORT_ENFORCE(IsScalarOr1ElementVector(X_Zero_Point), "Must be a scalar or 1D tensor or size 1."); input_offset = *(X_Zero_Point->Data()); } - if (num_inputs >= 4) { + if (num_inputs >= 4 && input_defs[3]->Exists()) { const auto* W_Zero_Point = context->Input(3); ORT_ENFORCE(IsScalarOr1ElementVector(W_Zero_Point), "Non per-tensor quantization is not supported now."); filter_offset = *(W_Zero_Point->Data()); diff --git a/onnxruntime/test/providers/cpu/nn/conv_integer_test.cc b/onnxruntime/test/providers/cpu/nn/conv_integer_test.cc index a5378fa3cefd7..c98d9e28b2f46 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_integer_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_integer_test.cc @@ -254,5 +254,45 @@ TEST(ConvIntegerTest, WithStride3_2D_u8u8) { test.Run(); } +TEST(ConvIntegerTest, NoXZeroPoint) { + OpTester test("ConvInteger", 10); + std::vector x_dims{1, 1, 3, 3}; + test.AddInput("x", x_dims, + {2, 3, 4, + 5, 6, 7, + 8, 9, 10}); + std::vector w_dims{1, 1, 2, 2}; + test.AddInput("w", w_dims, + {2, 2, + 2, 2}); + test.AddOptionalInputEdge(); + test.AddInput("w_zero_point", {}, {1}); + std::vector y_dims{1, 1, 2, 2}; + test.AddOutput("y", y_dims, + {16, 20, + 28, 32}); + test.Run(); +} + +// provide optional input with empty name for w. tests that input args == 4 but the w_zero_point does not exist. +TEST(ConvIntegerTest, NoWZeroPoint) { + OpTester test("ConvInteger", 10); + std::vector x_dims{1, 1, 3, 3}; + test.AddInput("x", x_dims, + {2, 3, 4, + 5, 6, 7, + 8, 9, 10}); + std::vector w_dims{1, 1, 2, 2}; + test.AddInput("w", w_dims, + {2, 2, + 2, 2}); + test.AddInput("x_zero_point", {}, {1}); + test.AddOptionalInputEdge(); + std::vector y_dims{1, 1, 2, 2}; + test.AddOutput("y", y_dims, + {24, 32, + 48, 56}); + test.Run(); +} } // namespace test } // namespace onnxruntime From 26f590b34519c4da964f7c01c40c5a0963eb82b8 Mon Sep 17 00:00:00 2001 From: saurabh Date: Fri, 7 Mar 2025 01:45:39 -0800 Subject: [PATCH 059/266] Updated ov version in pipeline (#595) (#23882) ### Description This PR updates the OpenVINO version used in the pipeline from 2024.5.0 to 2025.0.0 Co-authored-by: jatinwadhwa921 <110383850+jatinwadhwa921@users.noreply.github.com> --- .../github/azure-pipelines/linux-openvino-ci-pipeline.yml | 2 +- .../github/linux/docker/Dockerfile.ubuntu_openvino | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml index e89fa0ece2c76..48627e656b9a8 100644 --- a/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml @@ -33,5 +33,5 @@ jobs: parameters: AgentPool : 'Linux-CPU-2019' JobName: 'Linux_CI_Dev' - RunDockerBuildArgs: '-o ubuntu22.04 -p 3.10 -d openvino -v 2024.5.0 -x "--enable_generic_interface --use_openvino CPU --build_wheel"' + RunDockerBuildArgs: '-o ubuntu22.04 -p 3.10 -d openvino -v 2025.0.0 -x "--enable_generic_interface --use_openvino CPU --build_wheel"' TimeoutInMinutes: 120 diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_openvino b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_openvino index 7b1e3fa677375..b53a2302be403 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_openvino +++ b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_openvino @@ -1,7 +1,7 @@ ARG UBUNTU_VERSION=22.04 FROM ubuntu:${UBUNTU_VERSION} -ARG OPENVINO_VERSION=2024.5.0 +ARG OPENVINO_VERSION=2025.0.0 ARG PYTHON_VERSION=3.10 ADD scripts /tmp/scripts @@ -19,9 +19,9 @@ ENV IE_PLUGINS_PATH=$INTEL_OPENVINO_DIR/runtime/lib/intel64 ENV DEBIAN_FRONTEND=noninteractive RUN cd /opt && mkdir -p intel && cd intel && \ - wget https://storage.openvinotoolkit.org/repositories/openvino/packages/2024.5/linux/l_openvino_toolkit_ubuntu22_2024.5.0.17288.7975fa5da0c_x86_64.tgz && \ - tar xzf l_openvino_toolkit_ubuntu22_2024.5.0.17288.7975fa5da0c_x86_64.tgz && rm -rf l_openvino_toolkit_ubuntu22_2024.5.0.17288.7975fa5da0c_x86_64.tgz && \ - mv l_openvino_toolkit_ubuntu22_2024.5.0.17288.7975fa5da0c_x86_64 openvino_2024.5.0 && \ + wget https://storage.openvinotoolkit.org/repositories/openvino/packages/2025.0/linux/openvino_toolkit_ubuntu22_2025.0.0.17942.1f68be9f594_x86_64.tgz && \ + tar xzf openvino_toolkit_ubuntu22_2025.0.0.17942.1f68be9f594_x86_64.tgz && rm -rf openvino_toolkit_ubuntu22_2025.0.0.17942.1f68be9f594_x86_64.tgz && \ + mv openvino_toolkit_ubuntu22_2025.0.0.17942.1f68be9f594_x86_64 openvino_2025.0.0 && \ cd $INTEL_OPENVINO_DIR/install_dependencies && ./install_openvino_dependencies.sh -y WORKDIR /root From f25deaeaa46fab20d560687a528413ef031adb91 Mon Sep 17 00:00:00 2001 From: Ranjit Ranjan <165394499+ranjitshs@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:17:30 +0530 Subject: [PATCH 060/266] [AIX] External data handling (#23859) ### Description In BE system, model tensor data coming from external file is not handled properly. This was found during the debugging of (https://github.com/microsoft/onnxruntime-genai/issues/1104)(url) This PR changes do the endianness conversion of data loaded from external file in BE system. --- .../core/framework/session_state_utils.cc | 5 +++++ onnxruntime/core/framework/tensorprotoutils.cc | 16 +++++++++++++++- onnxruntime/core/framework/tensorprotoutils.h | 10 ++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/framework/session_state_utils.cc b/onnxruntime/core/framework/session_state_utils.cc index 343d634b44691..9d45ec38e5a32 100644 --- a/onnxruntime/core/framework/session_state_utils.cc +++ b/onnxruntime/core/framework/session_state_utils.cc @@ -81,6 +81,11 @@ static common::Status ExtDataTensorProtoToTensor(const Env& env, ORT_RETURN_IF_ERROR(utils::GetExtDataFromTensorProto(env, proto_path.c_str(), tensor_proto, ext_data_buf, ext_data_len, ext_data_deleter, buffered_tensor, &prepacked_for_graph)); + if constexpr (endian::native != endian::little) { + if (!proto_path.empty() && (proto_path.compare(onnxruntime::utils::kTensorProtoMemoryAddressTag) != 0)) { + utils::ConvertRawDataInTensorProto(const_cast(&tensor_proto), ext_data_buf, ext_data_len); + } + } // NB: creating a do-nothing allocator per tensor is wasteful; can perhaps be // avoided if the Tensor class implements the do-nothing behavior when given a diff --git a/onnxruntime/core/framework/tensorprotoutils.cc b/onnxruntime/core/framework/tensorprotoutils.cc index ae1ec2e53bd7c..94a2a6677358e 100644 --- a/onnxruntime/core/framework/tensorprotoutils.cc +++ b/onnxruntime/core/framework/tensorprotoutils.cc @@ -270,10 +270,15 @@ void SetRawDataInTensorProto(ONNX_NAMESPACE::TensorProto& tensor_proto, std::str tensor_proto.set_raw_data(std::move(param)); } -void ConvertRawDataInTensorProto(TensorProto* tensor) { +void ConvertRawDataInTensorProto(TensorProto* tensor, + void* ext_data_buf, + size_t ext_data_len) { size_t element_size = 1; char* bytes = NULL; size_t num_elements = 0; + if (ext_data_buf && !ext_data_len) { + return; + } switch (tensor->data_type()) { case TensorProto_DataType_FLOAT: bytes = reinterpret_cast(tensor->mutable_float_data()->mutable_data()); @@ -337,6 +342,15 @@ void ConvertRawDataInTensorProto(TensorProto* tensor) { num_elements = (tensor->raw_data().size()) / element_size; bytes = const_cast(tensor->mutable_raw_data()->c_str()); } + + if (element_size == 1) { + return; + } + if (ext_data_buf) { + ORT_ENFORCE(ext_data_len % element_size == 0); + num_elements = ext_data_len / element_size; + bytes = reinterpret_cast(ext_data_buf); + } for (size_t i = 0; i < num_elements; ++i) { char* start_byte = bytes + i * element_size; char* end_byte = start_byte + element_size - 1; diff --git a/onnxruntime/core/framework/tensorprotoutils.h b/onnxruntime/core/framework/tensorprotoutils.h index f5dec7ae988f2..79eae48c10411 100644 --- a/onnxruntime/core/framework/tensorprotoutils.h +++ b/onnxruntime/core/framework/tensorprotoutils.h @@ -41,12 +41,18 @@ Status GetExternalDataInfo(const ONNX_NAMESPACE::TensorProto& tensor_proto, ExternalDataInfo::PrepackedInfos* prepacked_infos = nullptr); /** * This function is used to convert the endianess of Tensor data. + * If ext_data_buf is provided, then this buffer content's endianess + * will be changed. * Mostly, will be used in big endian system to support the model file * generated on little endian system. - * @param initializer given initializer tensor + * @param tensor_proto given initializer tensor + * @param ext_data_buf optional externl data buffer + * @param ext_data_len optional externl data buffer lengeh * @returns None */ -void ConvertRawDataInTensorProto(ONNX_NAMESPACE::TensorProto* initializer); +void ConvertRawDataInTensorProto(ONNX_NAMESPACE::TensorProto* tensor_proto, + void* ext_data_buf = NULL, + size_t ext_data_len = 0); /** * Wrapper function for set_raw_data. From 593d5c0ed407ea1f7cfa110f0e4dc5873533705e Mon Sep 17 00:00:00 2001 From: Baiju Meswani Date: Fri, 7 Mar 2025 10:13:55 -0800 Subject: [PATCH 061/266] Create a packaging pipeline for a custom nuget package (#23918) --- .../custom-nuget-packaging-pipeline.yml | 142 +++++++++++++++++ ...acts-package-and-publish-steps-windows.yml | 16 ++ .../azure-pipelines/templates/qnn-ep-win.yml | 27 +++- .../azure-pipelines/templates/win-ci.yml | 2 +- .../nuget/generate_nuspec_for_custom_nuget.py | 150 ++++++++++++++++++ 5 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml create mode 100644 tools/nuget/generate_nuspec_for_custom_nuget.py diff --git a/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml new file mode 100644 index 0000000000000..8aaaa0e85585a --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml @@ -0,0 +1,142 @@ +parameters: +- name: CudaVersion + type: string + default: '12.2' + +- name: QnnSdk + displayName: QNN SDK Version + type: string + default: 2.31.0.250130 + +- name: IsReleaseBuild + displayName: Is a release build? Set it to true if you are doing an Onnx Runtime release. + type: boolean + default: false + +- name: PackageName + displayName: What is the package name? + type: string + default: 'Microsoft.ML.OnnxRuntime.Flamingo' + +variables: + - template: templates/common-variables.yml + - name: ReleaseVersionSuffix + value: '' + - name: win_cuda_home + ${{ if eq(parameters.CudaVersion, '11.8') }}: + value: $(Agent.TempDirectory)\v11.8 + ${{ if eq(parameters.CudaVersion, '12.2') }}: + value: $(Agent.TempDirectory)\v12.2 + +stages: + - template: templates/win-ci.yml + parameters: + ort_build_pool_name: 'onnxruntime-Win2022-GPU-A10' + DoCompliance: false + DoEsrp: true + stage_name_suffix: CUDA + buildArch: x64 + msbuildPlatform: x64 + packageName: x64-cuda + CudaVersion: ${{ parameters.CudaVersion }} + buildparameter: --use_cuda --cuda_home=${{ variables.win_cuda_home }} --enable_onnx_tests --enable_wcos --use_webgpu --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52-real;61-real;75-real;86-real;89-real;90-virtual" + runTests: false + buildJava: false + java_artifact_id: onnxruntime_gpu + UseIncreasedTimeoutForTests: false + SpecificArtifact: false + BuildId: '0' + + - template: templates/qnn-ep-win.yml + parameters: + qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' + QnnSdk: ${{ parameters.QnnSdk }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + DoEsrp: true + ArtifactName: 'drop-nuget-qnn-arm64' + # Add --use_webgpu to enable WebGPU + buildParameter: '--arm64' + buildPlatform: 'ARM64' + buildArch: 'ARM64' + StageName: 'OnnxRuntime_QNN_Nuget_Win_Arm64' + build_config: 'RelWithDebInfo' + Is1ES: false + PublishArchive: true + + - stage: NugetPackaging + dependsOn: [Windows_Packaging_CUDA, OnnxRuntime_QNN_Nuget_Win_Arm64] + jobs: + - job: CreateNugetPackage + pool: 'Onnxruntime-Win2022-GPU-A10' + timeoutInMinutes: 120 + steps: + - checkout: self + clean: true + submodules: none + + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + addToPath: true + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - managed nuget' + inputs: + artifactName: 'drop-nuget-qnn-arm64' + targetPath: '$(Build.BinariesDirectory)/managed-nuget' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - win-x64' + inputs: + artifactName: 'onnxruntime-win-x64-cuda' + targetPath: '$(Build.BinariesDirectory)/win-x64' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - win-arm64' + inputs: + artifactName: 'onnxruntime-win-ARM64-qnn' + targetPath: '$(Build.BinariesDirectory)/win-arm64' + + - task: PowerShell@2 + displayName: 'Extract Nuget Package Version' + inputs: + targetType: 'inline' + script: | + $nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/managed-nuget -Filter Microsoft.ML.OnnxRuntime.Managed.*.nupkg -Recurse) + $package_name = $nupkgs[0].Name + $version_length = $package_name.Length - "Microsoft.ML.OnnxRuntime.Managed.".Length - ".nupkg".Length + $package_version = $package_name.Substring("Microsoft.ML.OnnxRuntime.Managed.".Length, $version_length) + Write-Host "##vso[task.setvariable variable=package_version;]$package_version" + workingDirectory: $(Build.BinariesDirectory) + + - task: PowerShell@2 + displayName: 'Extract Archives' + inputs: + targetType: 'inline' + script: | + Expand-Archive -Path $(Build.BinariesDirectory)/win-x64/onnxruntime-win-x64-cuda*.zip -DestinationPath $(Build.BinariesDirectory)/win-x64 + Expand-Archive -Path $(Build.BinariesDirectory)/win-arm64/onnxruntime-win-ARM64-qnn*.zip -DestinationPath $(Build.BinariesDirectory)/win-arm64 + $win_x64 = (Get-ChildItem -Path $(Build.BinariesDirectory)/win-x64 -Filter onnxruntime-win-x64-cuda*)[0].FullName + $win_arm64 = (Get-ChildItem -Path $(Build.BinariesDirectory)/win-arm64 -Filter onnxruntime-win-ARM64-qnn*)[0].FullName + Write-Host "##vso[task.setvariable variable=win_x64;]$win_x64" + Write-Host "##vso[task.setvariable variable=win_arm64;]$win_arm64" + workingDirectory: $(Build.BinariesDirectory) + + - task: PythonScript@0 + displayName: 'Generate Nuget Package' + inputs: + scriptPath: '$(Build.SourcesDirectory)/tools/nuget/generate_nuspec_for_custom_nuget.py' + arguments: '--nuspec_path "$(Build.BinariesDirectory)/${{ parameters.PackageName }}.nuspec" --root_dir "$(Build.SourcesDirectory)" --commit_id "$(Build.SourceVersion)" --win_arm64 "$(win_arm64)" --win_x64 "$(win_x64)" --package_version "$(package_version)" --package_name "${{ parameters.PackageName }}"' + + - task: NuGetCommand@2 + displayName: 'Pack Nuget Package' + inputs: + command: 'pack' + packagesToPack: '$(Build.BinariesDirectory)/${{ parameters.PackageName }}.nuspec' + packDestination: $(Build.ArtifactStagingDirectory)\ + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: Nuget' + inputs: + pathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: '${{ parameters.PackageName }}' diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml index 5ee425405ac70..e1a514ea54123 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml @@ -57,6 +57,22 @@ steps: copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\onnxruntime_providers_cuda.pdb $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\onnxruntime_providers_cuda.lib $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + # Copy WebGPU dependencies if required + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\dxcompiler.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\dxil.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + + # Copy QNN dependencies if required + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\onnxruntime_providers_qnn.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\libQnnHtp*.so $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib /Y + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\libqnnhtp*.cat $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib /Y + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnCpu.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnHtp.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnHtpPrepare.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnHtpV68Stub.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnHtpV73Stub.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnSaver.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\QnnSystem.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib + # copy trt ep libraries only when trt ep is enabled copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\onnxruntime_providers_tensorrt.dll $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib copy $(Build.BinariesDirectory)\${{parameters.buildConfig}}\${{parameters.buildConfig}}\onnxruntime_providers_tensorrt.pdb $(Build.BinariesDirectory)\${{parameters.artifactName}}\lib diff --git a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml index b591a3e3e121b..3fa4799ec9c0e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml +++ b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml @@ -10,6 +10,8 @@ parameters: buildPlatform: 'x64' buildArch: 'x64' StageName: 'OnnxRuntime_QNN_Nuget_Win_x64' + Is1ES: true + PublishArchive: false stages: - stage: ${{ parameters.StageName }} @@ -107,6 +109,14 @@ stages: DoEsrp: ${{ parameters.DoEsrp }} Pattern: 'onnxruntime*.dll' + - ${{ if eq(parameters.PublishArchive, true) }}: + - template: c-api-artifacts-package-and-publish-steps-windows.yml + parameters: + buildConfig: ${{ parameters.build_config }} + artifactName: 'onnxruntime-win-${{ parameters.buildPlatform }}-qnn' + artifactNameNoVersionString: 'onnxruntime-win-${{ parameters.buildPlatform }}-qnn' + DoEsrp: ${{ parameters.DoEsrp }} + - task: MSBuild@1 displayName: 'Restore NuGet Packages and create project.assets.json' inputs: @@ -155,8 +165,15 @@ stages: Contents: '*.snupkg' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: 1ES.PublishPipelineArtifact@1 - displayName: 'Publish Pipeline x64 NuGet Artifact' - inputs: - artifactName: ${{ parameters.ArtifactName }} - targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.Is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline x64 NuGet Artifact' + inputs: + artifactName: ${{ parameters.ArtifactName }} + targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ else }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Pipeline x64 NuGet Artifact' + inputs: + artifactName: ${{ parameters.ArtifactName }} + targetPath: '$(Build.ArtifactStagingDirectory)' diff --git a/tools/ci_build/github/azure-pipelines/templates/win-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-ci.yml index 600e6d857185f..69a06c3db24b8 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-ci.yml @@ -161,7 +161,7 @@ stages: displayName: 'Generate cmake config' inputs: scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: '--config RelWithDebInfo --use_binskim_compliant_compile_flags --enable_lto --disable_rtti --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --update --build --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_generator "$(VSGenerator)" --enable_onnx_tests $(TelemetryOption) ${{ parameters.buildparameter }} $(timeoutParameter) $(buildJavaParameter)' + arguments: '--config RelWithDebInfo --use_binskim_compliant_compile_flags --enable_lto --disable_rtti --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --update --build --cmake_generator "$(VSGenerator)" --enable_onnx_tests $(TelemetryOption) ${{ parameters.buildparameter }} $(timeoutParameter) $(buildJavaParameter)' workingDirectory: '$(Build.BinariesDirectory)' diff --git a/tools/nuget/generate_nuspec_for_custom_nuget.py b/tools/nuget/generate_nuspec_for_custom_nuget.py new file mode 100644 index 0000000000000..baf46743cbf1b --- /dev/null +++ b/tools/nuget/generate_nuspec_for_custom_nuget.py @@ -0,0 +1,150 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import argparse +import glob +import os +import shutil + +from generate_nuspec_for_native_nuget import generate_metadata + + +def generate_files(lines, args): + files_list = [""] + platform_map = { + "win-arm64": args.win_arm64, + "win-x64": args.win_x64, + } + + avoid_keywords = {"pdb"} + processed_includes = set() + for platform, platform_dir in platform_map.items(): + for file in glob.glob(os.path.join(platform_dir, "lib", "*")): + if not os.path.isfile(file): + continue + if any(keyword in file for keyword in avoid_keywords): + continue + file_name = os.path.basename(file) + + files_list.append(f'') + + for file in glob.glob(os.path.join(platform_dir, "include", "*")): + if not os.path.isfile(file): + continue + file_name = os.path.basename(file) + if file_name in processed_includes: + continue + processed_includes.add(file_name) + files_list.append(f'') + + files_list.append( + f'' + ) + + files_list.append(f'') + files_list.append( + f'' + ) + files_list.append(f'') + files_list.append( + f'' + ) + + source_props = os.path.join( + args.root_dir, + "csharp", + "src", + "Microsoft.ML.OnnxRuntime", + "targets", + "netstandard", + "props.xml", + ) + target_props = os.path.join( + args.root_dir, + "csharp", + "src", + "Microsoft.ML.OnnxRuntime", + "targets", + "netstandard", + f"{args.package_name}.props", + ) + shutil.copyfile(source_props, target_props) + files_list.append(f'') + files_list.append(f'') + + source_targets = os.path.join( + args.root_dir, + "csharp", + "src", + "Microsoft.ML.OnnxRuntime", + "targets", + "netstandard", + "targets.xml", + ) + target_targets = os.path.join( + args.root_dir, + "csharp", + "src", + "Microsoft.ML.OnnxRuntime", + "targets", + "netstandard", + f"{args.package_name}.targets", + ) + shutil.copyfile(source_targets, target_targets) + files_list.append(f'') + files_list.append(f'') + + files_list.append("") + lines.extend(files_list) + + +def parse_arguments(): + parser = argparse.ArgumentParser( + description="Create a nuspec file for the custom nuget package.", + ) + + parser.add_argument("--nuspec_path", required=True, help="Nuspec output file path.") + parser.add_argument("--root_dir", required=True, help="ORT repository root.") + parser.add_argument( + "--commit_id", + required=True, + help="The last commit id included in this package.", + ) + parser.add_argument("--win_arm64", required=True, help="Ort win-arm64 directory") + parser.add_argument("--win_x64", required=True, help="Ort win-x64 directory") + parser.add_argument("--package_version", required=True, help="Version of the package") + parser.add_argument("--package_name", required=True, help="Name of the package") + + args = parser.parse_args() + + args.sdk_info = "" + + return args + + +def generate_nuspec(args: argparse.Namespace): + lines = [''] + lines.append("") + + generate_metadata(lines, args) + generate_files(lines, args) + + lines.append("") + return lines + + +def main(): + args = parse_arguments() + + lines = generate_nuspec(args) + + with open(os.path.join(args.nuspec_path), "w") as f: + for line in lines: + # Uncomment the printing of the line if you need to debug what's produced on a CI machine + print(line) + f.write(line) + f.write("\n") + + +if __name__ == "__main__": + main() From 7dbbfe0860e91a737cabe58ae02aeb3bba836417 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Sat, 8 Mar 2025 04:16:44 +1000 Subject: [PATCH 062/266] Fix license in example test code. (#23936) --- .../custom_execution_provider_library/my_execution_provider.cc | 2 +- .../custom_execution_provider_library/my_execution_provider.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.cc b/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.cc index 57471f7c029c2..27a4b06a99e64 100644 --- a/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.cc +++ b/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.cc @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. -// Confidential and Proprietary. +// Licensed under the MIT License. #include "my_execution_provider.h" #include "my_allocator.h" diff --git a/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.h b/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.h index ff0c7e80c4eeb..efb359a9e5e43 100644 --- a/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.h +++ b/onnxruntime/test/testdata/custom_execution_provider_library/my_execution_provider.h @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. -// Confidential and Proprietary. +// Licensed under the MIT License. #pragma once From ab38607de08f7e69f1b43e254ceac80c66b2ae79 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 7 Mar 2025 11:01:53 -0800 Subject: [PATCH 063/266] replace usage of gsl::narrow and gsl::narrow_cast in WebGPU EP (#23926) ### Description `gsl::narrow` does not work in no exception build. - use `onnxruntime::narrow` if necessary; - or change to `static_cast` if it's obviously safe. also apply the changes to usage of `gsl::narrow_cast`, which does not apply checks. --- .../contrib_ops/webgpu/bert/fast_gelu.cc | 4 +-- .../webgpu/bert/flash_attention.cc | 2 +- .../webgpu/bert/rotary_embedding.cc | 14 +++++----- .../webgpu/bert/skip_layer_norm.cc | 4 +-- .../webgpu/quantization/dp4a_matmul_nbits.cc | 16 +++++------ .../webgpu/quantization/matmul_nbits.cc | 22 +++++++-------- .../subgroup_matrix_matmul_nbits.cc | 8 +++--- .../core/providers/webgpu/generator/range.cc | 2 +- .../webgpu/math/binary_elementwise_ops.cc | 2 +- .../webgpu/math/unary_elementwise_ops.cc | 2 +- .../core/providers/webgpu/nn/layer_norm.cc | 6 ++-- .../core/providers/webgpu/program_manager.cc | 10 +++---- .../core/providers/webgpu/shader_variable.cc | 2 +- .../core/providers/webgpu/tensor/cast.cc | 2 +- .../core/providers/webgpu/tensor/cast.h | 2 +- .../core/providers/webgpu/tensor/concat.cc | 2 +- .../core/providers/webgpu/tensor/expand.cc | 2 +- .../core/providers/webgpu/tensor/gather.cc | 2 +- .../core/providers/webgpu/tensor/pad.cc | 2 +- .../providers/webgpu/tensor/resize_impl.cc | 8 +++--- .../core/providers/webgpu/tensor/split.cc | 6 ++-- .../core/providers/webgpu/tensor/transpose.cc | 6 ++-- .../core/providers/webgpu/tensor/where.cc | 2 +- .../core/providers/webgpu/webgpu_context.cc | 4 +-- .../win-gpu-webgpu-ci-pipeline.yml | 28 +++++++++++++++++++ 25 files changed, 94 insertions(+), 66 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/fast_gelu.cc b/onnxruntime/contrib_ops/webgpu/bert/fast_gelu.cc index a5cae7e7f6747..29ea4f81dd5e1 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/fast_gelu.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/fast_gelu.cc @@ -50,7 +50,7 @@ Status FastGelu::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) c const auto* bias = context.Input(1); auto* output = context.Output(0, input->Shape()); - uint32_t data_size = gsl::narrow(output->Shape().Size()); + uint32_t data_size = onnxruntime::narrow(output->Shape().Size()); if (data_size == 0) { return Status::OK(); } @@ -60,7 +60,7 @@ Status FastGelu::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) c int bias_components = 1; if (bias != nullptr) { - bias_size = gsl::narrow(bias->Shape().Size()); + bias_size = onnxruntime::narrow(bias->Shape().Size()); if (bias_size % 4 == 0) { bias_components = 4; bias_size = bias_size / 4; diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index c1b025b10e067..1e95d3d9610ff 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -98,7 +98,7 @@ Status CopyKVCache(onnxruntime::webgpu::ComputeContext& context, const WebgpuAtt program.AddOutputs({{present_key, ProgramTensorMetadataDependency::Rank, components}, {present_value, ProgramTensorMetadataDependency::Rank, components}}) .AddIndices(valid_present_shape); - program.SetDispatchGroupSize(gsl::narrow(valid_kv_size + 63 / 64)) + program.SetDispatchGroupSize(onnxruntime::narrow(valid_kv_size + 63 / 64)) .SetWorkgroupSize(64) .CacheHint(has_past, parameters.qkv_format_, parameters.past_present_share_buffer_) .AddUniformVariables({{static_cast(valid_kv_size)}, diff --git a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc index bc8b7493fc916..20e1583e0da8f 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc @@ -66,11 +66,11 @@ Status RotaryEmbedding::ComputeInternal(onnxruntime::webgpu::ComputeContext& con const auto* sin_cache = context.Input(3); auto* output = context.Output(0, input_shape); - const auto batch_size = gsl::narrow(input->Shape()[0]); - const auto batch_stride = gsl::narrow(input_shape.SizeFromDimension(1)); - const auto sequence_length = gsl::narrow(input_shape[input_shape.NumDimensions() - 2]); + const auto batch_size = onnxruntime::narrow(input->Shape()[0]); + const auto batch_stride = onnxruntime::narrow(input_shape.SizeFromDimension(1)); + const auto sequence_length = onnxruntime::narrow(input_shape[input_shape.NumDimensions() - 2]); const auto hidden_size = batch_stride / sequence_length; - const auto half_rotary_embedding_dim = gsl::narrow(cos_cache->Shape()[1]); + const auto half_rotary_embedding_dim = onnxruntime::narrow(cos_cache->Shape()[1]); const auto head_size = rotary_embedding_dim_ == 0 ? half_rotary_embedding_dim * 2 : hidden_size / num_heads_; // Rotary embeddings will be calculated in a pair-wise fashion. In accordance, use the shape @@ -85,11 +85,11 @@ Status RotaryEmbedding::ComputeInternal(onnxruntime::webgpu::ComputeContext& con std::vector global_dims(rank); std::vector global_strides(rank); for (size_t j = 0; j < rank; ++j) { - global_dims[j] = gsl::narrow(global_shape[j]); - global_strides[j] = gsl::narrow(global_shape.SizeFromDimension(j + 1)); + global_dims[j] = onnxruntime::narrow(global_shape[j]); + global_strides[j] = onnxruntime::narrow(global_shape.SizeFromDimension(j + 1)); } - const auto output_size = gsl::narrow(global_shape.Size()); + const auto output_size = onnxruntime::narrow(global_shape.Size()); RotaryEmbeddingProgram program{interleaved_}; const auto input_output_strides = input_shape.NumDimensions() == 3 diff --git a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc index a1840257d734f..d5d4632c01e2a 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc @@ -122,7 +122,7 @@ Status SkipLayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeCo } const bool is_fp16 = x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16; - const uint32_t hidden_size = gsl::narrow(x_shape[x_shape.NumDimensions() - 1]); + const uint32_t hidden_size = onnxruntime::narrow(x_shape[x_shape.NumDimensions() - 1]); const int components = GetMaxComponents(hidden_size); const bool has_input_skip_bias_sum = input_skip_bias_sum != nullptr; @@ -133,7 +133,7 @@ Status SkipLayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeCo .AddInputs({{skip, ProgramTensorMetadataDependency::Type, components}}) .AddInputs({{gamma, ProgramTensorMetadataDependency::Type, components}}) .AddOutputs({{output, ProgramTensorMetadataDependency::None, components}}) - .SetDispatchGroupSize(gsl::narrow(ceil(1.0 * data_size / hidden_size))) + .SetDispatchGroupSize(onnxruntime::narrow(ceil(1.0 * data_size / hidden_size))) .AddUniformVariables({ {static_cast(components)}, }) diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc index 6720a6072f7bb..05cbfb1f99c48 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc @@ -277,9 +277,9 @@ Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor Tensor a_quant = context.CreateGPUTensor(DataTypeImpl::GetType(), a_quant_shape); TensorShapeVector a_scales_dims({1, 1, M, K / kBlockSizeA}); Tensor a_scale = context.CreateGPUTensor(a->DataType(), a_scales_dims); - quantize_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec4Components)}}) - .AddOutputs({{&a_quant, ProgramTensorMetadataDependency::Rank, a_quant.Shape(), gsl::narrow(1)}, - {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), gsl::narrow(1)}}) + quantize_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec4Components)}}) + .AddOutputs({{&a_quant, ProgramTensorMetadataDependency::Rank, a_quant.Shape(), 1}, + {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), 1}}) .AddUniformVariable({static_cast(M * K / kVec4Components)}); ORT_RETURN_IF_ERROR(context.RunProgram(quantize_program)); @@ -290,16 +290,16 @@ Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor mul_program.SetDispatchGroupSize( (M + kTileSize - 1) / kTileSize, (N + kTileSize - 1) / kTileSize, 1); - mul_program.AddInputs({{&a_quant, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec4Components)}, - {&a_scale, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}, - {b, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kVec2Components * kU32Components)}, - {scales, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}}) + mul_program.AddInputs({{&a_quant, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec4Components)}, + {&a_scale, ProgramTensorMetadataDependency::TypeAndRank, 1}, + {b, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec2Components * kU32Components)}, + {scales, ProgramTensorMetadataDependency::TypeAndRank, 1}}) .AddUniformVariables({{static_cast(M)}, {static_cast(N)}, {static_cast(K)}, {static_cast(K / 8)}, {static_cast(K / 16)}}) - .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, gsl::narrow(kVec4Components)}) + .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, static_cast(kVec4Components)}) .CacheHint("Block" + std::to_string(block_size)); return context.RunProgram(mul_program); } diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index e10a7f551eec9..cce10a59fbd4b 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -372,7 +372,7 @@ Status MatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { } } else { const std::string quantized_data_type = QuantizedDataType(a.NumComponents()); - const int output_element_number = y.NumComponents() * gsl::narrow(output_number_); + const int output_element_number = y.NumComponents() * onnxruntime::narrow(output_number_); const uint32_t shared_memory_size = output_number_ * WORKGROUP_SIZE; std::string offset = "workgroup_idx * " + std::to_string(output_number_); @@ -548,16 +548,16 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context TensorShape b_shape({N_, K_}); ORT_RETURN_IF_ERROR(helper.Compute(a->Shape(), b_shape, false, true)); auto* y = context.Output(0, helper.OutputShape()); - const uint32_t data_size = gsl::narrow(y->Shape().Size()); + const uint32_t data_size = onnxruntime::narrow(y->Shape().Size()); if (data_size == 0) { return Status::OK(); } - const uint32_t batch_count = gsl::narrow(helper.OutputOffsets().size()); - const uint32_t M = gsl::narrow(helper.M()); - const uint32_t N = gsl::narrow(helper.N()); - const uint32_t K = gsl::narrow(helper.K()); - const uint32_t block_size = gsl::narrow(block_size_); + const uint32_t batch_count = onnxruntime::narrow(helper.OutputOffsets().size()); + const uint32_t M = onnxruntime::narrow(helper.M()); + const uint32_t N = onnxruntime::narrow(helper.N()); + const uint32_t K = onnxruntime::narrow(helper.K()); + const uint32_t block_size = onnxruntime::narrow(block_size_); constexpr uint32_t nbits = 4; const uint32_t n_blocks_per_col = (K + block_size - 1) / block_size; @@ -584,7 +584,7 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context const uint32_t tile_m = M > kMinMForTileOptimization ? 4 : 1; const bool has_subgroup = context.Device().HasFeature(wgpu::FeatureName::Subgroups); const bool use_subgroup = has_subgroup && context.AdapterInfo().vendor == std::string_view{"intel"} && components_a == 4 && block_size == 32; - MatMulNBitsProgram program{output_number, block_size, tile_m, gsl::narrow(components_b), has_zero_points, use_subgroup}; + MatMulNBitsProgram program{output_number, block_size, tile_m, static_cast(components_b), has_zero_points, use_subgroup}; if (M > kMinMForTileOptimization && block_size == 32) { components = 1; constexpr uint32_t workgroup_size = 64; @@ -614,10 +614,10 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context TensorShape reshaped_y_shape{batch_count, M, N / components}; program - .AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, reshaped_a_shape, gsl::narrow(components_a)}, - {b, ProgramTensorMetadataDependency::TypeAndRank, reshaped_b_shape, gsl::narrow(components_b * 4 /** b will be accessed as uint32 which includs 4 uint8. So here we need to multiply 4.*/)}, + .AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, reshaped_a_shape, static_cast(components_a)}, + {b, ProgramTensorMetadataDependency::TypeAndRank, reshaped_b_shape, static_cast(components_b * 4 /** b will be accessed as uint32 which includs 4 uint8. So here we need to multiply 4.*/)}, {scales, ProgramTensorMetadataDependency::None}}) - .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, gsl::narrow(components)}) + .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, static_cast(components)}) .AddUniformVariable({block_size}); if (has_zero_points) { program.AddInput({zero_points, ProgramTensorMetadataDependency::None, {(zero_points->Shape().Size() + 3) / 4}, 4}); diff --git a/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc index 2944a4d61b8ef..cb024d2a758a9 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc @@ -185,13 +185,13 @@ Status ApplySubgroupMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Te mul_program.SetDispatchGroupSize( (N + kTileSizeB - 1) / kTileSizeB, (M + kTileSizeA - 1) / kTileSizeA, 1); - mul_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}, - {b, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(kU32Components)}, - {scales, ProgramTensorMetadataDependency::TypeAndRank, gsl::narrow(1)}}) + mul_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, 1}, + {b, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kU32Components)}, + {scales, ProgramTensorMetadataDependency::TypeAndRank, 1}}) .AddUniformVariables({{static_cast(M)}, {static_cast(N)}, {static_cast(K)}}) - .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, y_shape, gsl::narrow(1)}); + .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, y_shape, 1}); return context.RunProgram(mul_program); } diff --git a/onnxruntime/core/providers/webgpu/generator/range.cc b/onnxruntime/core/providers/webgpu/generator/range.cc index a0b65f08a5b4e..99c5a1c1b5566 100644 --- a/onnxruntime/core/providers/webgpu/generator/range.cc +++ b/onnxruntime/core/providers/webgpu/generator/range.cc @@ -23,7 +23,7 @@ Status Range::ComputeInternal(ComputeContext& context) const { return Status::OK(); } - uint32_t output_size = gsl::narrow(n); + uint32_t output_size = onnxruntime::narrow(n); RangeProgram program{}; #if defined(__GNUC__) #pragma GCC diagnostic push diff --git a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc index 75866513e2c7d..8a22e45f17047 100644 --- a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc @@ -141,7 +141,7 @@ Status BinaryElementwise::ComputeInternal(ComputeContext& context) const { } } - uint32_t vec_size = gsl::narrow((size + 3) / 4); + uint32_t vec_size = onnxruntime::narrow((size + 3) / 4); BinaryElementwiseProgram program{kernel_name_, expression_, is_broadcast, diff --git a/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc index eaaad206ebaf5..189d7baafce6a 100644 --- a/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc @@ -27,7 +27,7 @@ Status UnaryElementwise::ComputeInternal(ComputeContext& context) const { if (size == 0) { return Status::OK(); } - uint32_t vec_size = gsl::narrow((size + 3) / 4); + uint32_t vec_size = onnxruntime::narrow((size + 3) / 4); UnaryElementwiseProgram program{kernel_name_, expression_, additional_impl_, additional_usage_}; program .AddInputs({{input_tensor, ProgramTensorMetadataDependency::Type, {vec_size}, 4}}) diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc index 64172021e82f1..28ad686909a47 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc @@ -23,7 +23,7 @@ static size_t NormalizeAxis(int64_t axis, size_t tensor_rank) { if (axis < -rank && axis >= rank) { ORT_THROW("invalid axis: ", axis); } - return gsl::narrow(axis < 0 ? axis + rank : axis); + return onnxruntime::narrow(axis < 0 ? axis + rank : axis); } static std::string SumVector(std::string x, int components) { @@ -92,10 +92,10 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex const bool is_fp16 = x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16; const size_t axis = NormalizeAxis(axis_, x_shape.NumDimensions()); - const uint32_t norm_count = gsl::narrow(x_shape.SizeToDimension(axis)); + const uint32_t norm_count = onnxruntime::narrow(x_shape.SizeToDimension(axis)); const int64_t norm_size = x_shape.SizeFromDimension(axis); const int components = GetMaxComponents(norm_size); - const uint32_t norm_size_vectorized = gsl::narrow((norm_size + components - 1) / components); + const uint32_t norm_size_vectorized = onnxruntime::narrow((norm_size + components - 1) / components); const auto scale_size = scale->Shape().Size(); const auto bias_size = (bias) ? bias->Shape().Size() : 0; diff --git a/onnxruntime/core/providers/webgpu/program_manager.cc b/onnxruntime/core/providers/webgpu/program_manager.cc index 1fdd312d4f0d8..7a4a873a1adf3 100644 --- a/onnxruntime/core/providers/webgpu/program_manager.cc +++ b/onnxruntime/core/providers/webgpu/program_manager.cc @@ -24,14 +24,14 @@ Status ProgramManager::NormalizeDispatchGroupSize(uint32_t& x, uint32_t& y, uint auto limit_per_dimension = limits_.maxComputeWorkgroupsPerDimension; if (x > limit_per_dimension || y > limit_per_dimension || z > limit_per_dimension) { - auto size = static_cast(x) * static_cast(y) * static_cast(z); - uint32_t dispatch_avg = gsl::narrow(std::ceil(std::sqrt(size))); + double size = static_cast(x) * static_cast(y) * static_cast(z); + double dispatch_avg = std::ceil(std::sqrt(size)); if (dispatch_avg > limit_per_dimension) { - dispatch_avg = gsl::narrow(std::ceil(std::cbrt(size))); + dispatch_avg = std::ceil(std::cbrt(size)); ORT_RETURN_IF(dispatch_avg > limit_per_dimension, "The dispatch group size exceeds WebGPU maximum."); - x = y = z = dispatch_avg; + x = y = z = static_cast(dispatch_avg); } else { - x = y = dispatch_avg; + x = y = static_cast(dispatch_avg); z = 1; } } diff --git a/onnxruntime/core/providers/webgpu/shader_variable.cc b/onnxruntime/core/providers/webgpu/shader_variable.cc index 5e5920f582251..f8e1e0b3b8d2b 100644 --- a/onnxruntime/core/providers/webgpu/shader_variable.cc +++ b/onnxruntime/core/providers/webgpu/shader_variable.cc @@ -91,7 +91,7 @@ ShaderIndicesHelper::ShaderIndicesHelper(std::string_view name, ProgramVariableD : name_(name), type_(type), num_components_{NumberOfComponents(type)}, - rank_{gsl::narrow(dims.NumDimensions())}, + rank_{static_cast(dims.NumDimensions())}, dims_{dims}, usage_(usage), indices_type_{GetIndicesType(rank_)}, diff --git a/onnxruntime/core/providers/webgpu/tensor/cast.cc b/onnxruntime/core/providers/webgpu/tensor/cast.cc index 8b5bede34e6d0..7f92ea4ed3776 100644 --- a/onnxruntime/core/providers/webgpu/tensor/cast.cc +++ b/onnxruntime/core/providers/webgpu/tensor/cast.cc @@ -69,7 +69,7 @@ Status Cast::ComputeInternal(ComputeContext& context) const { if (size == 0) { return Status::OK(); } - uint32_t vec_size = gsl::narrow((size + 3) / 4); + uint32_t vec_size = onnxruntime::narrow((size + 3) / 4); CastProgram program{to_}; program diff --git a/onnxruntime/core/providers/webgpu/tensor/cast.h b/onnxruntime/core/providers/webgpu/tensor/cast.h index ef5c4d5d0dabe..925cd200f0aba 100644 --- a/onnxruntime/core/providers/webgpu/tensor/cast.h +++ b/onnxruntime/core/providers/webgpu/tensor/cast.h @@ -26,7 +26,7 @@ class Cast final : public WebGpuKernel { int64_t to; Status status = info.GetAttr("to", &to); ORT_ENFORCE(status.IsOK(), "Attribute to is not set."); - to_ = gsl::narrow(to); + to_ = onnxruntime::narrow(to); // ignore attribute 'saturate' as float8 is not supported in WebGPU } diff --git a/onnxruntime/core/providers/webgpu/tensor/concat.cc b/onnxruntime/core/providers/webgpu/tensor/concat.cc index 5ed8099fde05e..5cfd6c78f8929 100644 --- a/onnxruntime/core/providers/webgpu/tensor/concat.cc +++ b/onnxruntime/core/providers/webgpu/tensor/concat.cc @@ -104,7 +104,7 @@ Status Concat::ComputeInternal(ComputeContext& context) const { return Status::OK(); } - uint32_t output_size = gsl::narrow_cast(prepare.output_tensor->Shape().Size()); + uint32_t output_size = onnxruntime::narrow(prepare.output_tensor->Shape().Size()); size_t axis = static_cast(prepare.axis); ConcatProgram program{axis}; diff --git a/onnxruntime/core/providers/webgpu/tensor/expand.cc b/onnxruntime/core/providers/webgpu/tensor/expand.cc index 809616660aa9e..9bdebe2c1e0d3 100644 --- a/onnxruntime/core/providers/webgpu/tensor/expand.cc +++ b/onnxruntime/core/providers/webgpu/tensor/expand.cc @@ -42,7 +42,7 @@ Status Expand::ComputeInternal(ComputeContext& context) const { : 1; const int components_o = output_shape.IsScalar() ? 1 : output_shape[output_shape.NumDimensions() - 1] % 4 == 0 ? 4 : 1; - uint32_t data_size = gsl::narrow(output_shape.Size() / components_o); + uint32_t data_size = onnxruntime::narrow(output_shape.Size() / components_o); ExpandProgram program{}; program diff --git a/onnxruntime/core/providers/webgpu/tensor/gather.cc b/onnxruntime/core/providers/webgpu/tensor/gather.cc index 9f6e5f2420d86..39d07991f3c5a 100644 --- a/onnxruntime/core/providers/webgpu/tensor/gather.cc +++ b/onnxruntime/core/providers/webgpu/tensor/gather.cc @@ -42,7 +42,7 @@ Status GatherProgram::GenerateShaderCode(ShaderHelper& shader) const { Status Gather::ComputeInternal(ComputeContext& context) const { Prepare p; ORT_RETURN_IF_ERROR(PrepareForCompute(&context.KernelContext(), p)); - uint32_t data_size = gsl::narrow(p.output_tensor->Shape().Size()); + uint32_t data_size = onnxruntime::narrow(p.output_tensor->Shape().Size()); if (data_size == 0) { return Status::OK(); } diff --git a/onnxruntime/core/providers/webgpu/tensor/pad.cc b/onnxruntime/core/providers/webgpu/tensor/pad.cc index 9ee13aada67fe..6a8bc6554b772 100644 --- a/onnxruntime/core/providers/webgpu/tensor/pad.cc +++ b/onnxruntime/core/providers/webgpu/tensor/pad.cc @@ -130,7 +130,7 @@ Status Pad::ComputeInternal(ComputeContext& context) const { } auto* output_tensor = context.Output(0, output_shape); - uint32_t output_size = gsl::narrow(output_shape.Size()); + uint32_t output_size = onnxruntime::narrow(output_shape.Size()); if (output_size == 0) { // Do not need to fill output, return return Status::OK(); diff --git a/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc b/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc index 455e7dc54bf1d..f68ace3c1d8a1 100644 --- a/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc +++ b/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc @@ -211,7 +211,7 @@ Status ResizeNearestImpl(ComputeContext& context, onnxruntime::ResizeNearestMode nearest_mode) { TensorShape output_shape(output_dims); auto* output_tensor = context.Output(0, output_shape); - uint32_t output_size = gsl::narrow(output_shape.Size()); + uint32_t output_size = onnxruntime::narrow(output_shape.Size()); ResizeNearestProgram program{coordinate_transform_mode, nearest_mode, extrapolation_enabled, rank}; program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) @@ -299,7 +299,7 @@ Status ResizeBilinearImpl(ComputeContext& context, onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode) { TensorShape output_shape(output_dims); auto* output_tensor = context.Output(0, output_shape); - uint32_t output_size = gsl::narrow(output_shape.Size()); + uint32_t output_size = onnxruntime::narrow(output_shape.Size()); ResizeBilinearProgram program{coordinate_transform_mode, extrapolation_enabled, rank}; program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) @@ -413,7 +413,7 @@ Status ResizeTrilinearImpl(ComputeContext& context, onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode) { TensorShape output_shape(output_dims); auto* output_tensor = context.Output(0, output_shape); - uint32_t output_size = gsl::narrow(output_shape.Size()); + uint32_t output_size = onnxruntime::narrow(output_shape.Size()); ResizeTrilinearProgram program{coordinate_transform_mode, extrapolation_enabled, rank}; program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) @@ -534,7 +534,7 @@ Status ResizeBiCubicImpl(ComputeContext& context, onnxruntime::ResizeCoordinateTransformationMode coordinate_transform_mode) { TensorShape output_shape(output_dims); auto* output_tensor = context.Output(0, output_shape); - uint32_t output_size = gsl::narrow(output_shape.Size()); + uint32_t output_size = onnxruntime::narrow(output_shape.Size()); ResizeBiCubicProgram program{coordinate_transform_mode, extrapolation_enabled, exclude_outside, rank}; program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) diff --git a/onnxruntime/core/providers/webgpu/tensor/split.cc b/onnxruntime/core/providers/webgpu/tensor/split.cc index 83bf832cc5b11..d93b75fa21c16 100644 --- a/onnxruntime/core/providers/webgpu/tensor/split.cc +++ b/onnxruntime/core/providers/webgpu/tensor/split.cc @@ -107,7 +107,7 @@ Status Split::ComputeInternal(ComputeContext& context) const { ORT_RETURN_IF_ERROR(PrepareForCompute(input_shape, num_outputs, axis, before_dims, after_dims_including_split_axis, after_dims_excluding_split, split_sizes)); - SplitProgram program{gsl::narrow_cast(axis)}; + SplitProgram program{static_cast(axis)}; program.AddInput({input, ProgramTensorMetadataDependency::TypeAndRank}); auto output_dimensions = input_shape.AsShapeVector(); @@ -120,7 +120,7 @@ Status Split::ComputeInternal(ComputeContext& context) const { program.AddOutput({output, ProgramTensorMetadataDependency::Rank}); } - uint32_t input_size = gsl::narrow(input_shape.Size()); + uint32_t input_size = onnxruntime::narrow(input_shape.Size()); // Early return if the input tensor is empty. if (input_size == 0) { return Status::OK(); @@ -130,7 +130,7 @@ Status Split::ComputeInternal(ComputeContext& context) const { std::vector sizes_in_split_axis; // sizes_in_split_axis are the cumulative sizes of the splits in the split axis. for (auto split_size : split_sizes) { - previous_sum += gsl::narrow(split_size); + previous_sum += onnxruntime::narrow(split_size); sizes_in_split_axis.push_back(previous_sum); } diff --git a/onnxruntime/core/providers/webgpu/tensor/transpose.cc b/onnxruntime/core/providers/webgpu/tensor/transpose.cc index 24b98e9533d17..0df7d1ae9fa2f 100644 --- a/onnxruntime/core/providers/webgpu/tensor/transpose.cc +++ b/onnxruntime/core/providers/webgpu/tensor/transpose.cc @@ -105,7 +105,7 @@ Status Transpose::DoTranspose(onnxruntime::webgpu::ComputeContext& context, const Tensor& input, Tensor& output) { const auto& input_shape = input.Shape(); const auto& input_dims = input_shape.GetDims(); - int32_t rank = gsl::narrow_cast(input_shape.NumDimensions()); + int32_t rank = static_cast(input_shape.NumDimensions()); TensorShapeVector output_dims(rank); @@ -131,7 +131,7 @@ Status Transpose::DoTranspose(onnxruntime::webgpu::ComputeContext& context, new_output_shape = TensorShape({new_input_shape[1], new_input_shape[0]}); } - uint32_t output_size = gsl::narrow_cast(input_shape.Size()); + uint32_t output_size = onnxruntime::narrow(input_shape.Size()); TransposeProgram program{permutations, use_shared}; if (use_shared) { @@ -156,7 +156,7 @@ Status Transpose::DoTranspose(onnxruntime::webgpu::ComputeContext& context, Status Transpose::ComputeInternal(ComputeContext& context) const { const auto* input_tensor = context.Input(0); const TensorShape& input_shape = input_tensor->Shape(); - int32_t rank = gsl::narrow_cast(input_shape.NumDimensions()); + int32_t rank = static_cast(input_shape.NumDimensions()); TensorShapeVector output_dims(rank); InlinedVector default_perm(rank); diff --git a/onnxruntime/core/providers/webgpu/tensor/where.cc b/onnxruntime/core/providers/webgpu/tensor/where.cc index e8cdabb9dbe40..d7272ec525296 100644 --- a/onnxruntime/core/providers/webgpu/tensor/where.cc +++ b/onnxruntime/core/providers/webgpu/tensor/where.cc @@ -127,7 +127,7 @@ Status Where::ComputeInternal(ComputeContext& context) const { ORT_RETURN_IF_ERROR(ComputeOutputShape(cond_shape, x_shape, y_shape, output_shape)); auto* output_tensor = context.Output(0, output_shape); constexpr int component = 4; - uint32_t vec_size = gsl::narrow_cast((output_shape.Size() + 3) / component); + uint32_t vec_size = onnxruntime::narrow((output_shape.Size() + 3) / component); const auto is_broadcast = !(x_shape == y_shape && y_shape == cond_shape); WhereProgram program{is_broadcast}; diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 14c12ac247080..97144573dde2d 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -322,9 +322,9 @@ Status WebGpuContext::Run(ComputeContext& context, const ProgramBase& program) { std::vector dims(expected_rank); std::vector stride(expected_rank - 1); for (size_t j = 0; j < expected_rank; ++j) { - dims[j] = gsl::narrow(shape[j]); + dims[j] = onnxruntime::narrow(shape[j]); if (j < expected_rank - 1) { - stride[j] = gsl::narrow(shape.SizeFromDimension(j + 1)); + stride[j] = onnxruntime::narrow(shape.SizeFromDimension(j + 1)); } } diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-webgpu-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-webgpu-ci-pipeline.yml index bb6c210161952..a0f22fcfce14e 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-webgpu-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-webgpu-ci-pipeline.yml @@ -105,3 +105,31 @@ stages: onnxruntime_webgpu_external_dawn_test.exe --no_proc_table displayName: Run tests (onnxruntime_webgpu_external_dawn_test) workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' + +- stage: webgpu_minimal_build_edge + dependsOn: [] + jobs: + - template: templates/jobs/win-ci-vs-2022-job.yml + parameters: + BuildConfig: 'RelWithDebInfo' + EnvSetupScript: setup_env.bat + buildArch: x64 + additionalBuildFlags: >- + --build_shared_lib + --disable_exceptions + --disable_rtti + --enable_msvc_static_runtime + --enable_reduced_operator_type_support + --skip_tests + --use_binskim_compliant_compile_flags + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF onnxruntime_DISABLE_SPARSE_TENSORS=ON onnxruntime_DISABLE_OPTIONAL_TYPE=ON + --minimal_build extended + --use_webgpu + msbuildPlatform: x64 + isX86: false + job_name_suffix: x64_RelWithDebInfo + RunOnnxRuntimeTests: false + ORT_EP_NAME: WebGPU + EnablePython: false + WITH_CACHE: true + MachinePool: onnxruntime-Win2022-VS2022-webgpu-A10 From cffef2e028acf23dd1a579639c9591ac3730a866 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Fri, 7 Mar 2025 12:47:43 -0800 Subject: [PATCH 064/266] VCPKG improvement: set VCPKG_OSX_DEPLOYMENT_TARGET (#23933) ### Description 1. Set VCPKG_OSX_DEPLOYMENT_TARGET for macOS targets 2. Enable VCPKG in more pipelines. --- tools/ci_build/build.py | 14 +++- .../stages/py-cpu-packaging-stage.yml | 2 +- .../templates/windowsai-steps.yml | 2 +- .../win-qnn-arm64-ci-pipeline.yml | 2 +- .../azure-pipelines/win-qnn-ci-pipeline.yml | 2 +- tools/python/util/__init__.py | 3 +- tools/python/util/vcpkg_helpers.py | 78 +++++++++++++------ 7 files changed, 71 insertions(+), 32 deletions(-) diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index fe20351b0e8bb..db7dbed23a2d2 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -35,7 +35,8 @@ def version_to_tuple(version: str) -> tuple: import util.android as android # noqa: E402 from util import ( # noqa: E402 generate_android_triplets, - generate_posix_triplets, + generate_linux_triplets, + generate_macos_triplets, generate_vcpkg_triplets_for_emscripten, generate_windows_triplets, get_logger, @@ -1115,7 +1116,6 @@ def generate_build_tree( cmake_extra_args, ): log.info("Generating CMake build tree") - cmake_dir = os.path.join(source_dir, "cmake") cmake_args = [cmake_path, cmake_dir] if not use_dev_mode(args): @@ -1330,8 +1330,16 @@ def generate_build_tree( generate_android_triplets(build_dir, args.android_cpp_shared, args.android_api) elif is_windows(): generate_windows_triplets(build_dir) + elif is_macOS(): + osx_target = args.apple_deploy_target + if args.apple_deploy_target is None: + osx_target = os.environ.get("MACOSX_DEPLOYMENT_TARGET") + if osx_target is not None: + log.info(f"Setting VCPKG_OSX_DEPLOYMENT_TARGET to {osx_target}") + generate_macos_triplets(build_dir, osx_target) else: - generate_posix_triplets(build_dir) + # Linux, *BSD, AIX or other platforms + generate_linux_triplets(build_dir) add_default_definition(cmake_extra_defines, "CMAKE_TOOLCHAIN_FILE", str(vcpkg_toolchain_path)) vcpkg_install_options = generate_vcpkg_install_options(build_dir, args) diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml index 4ff539df9f914..42d6e4371ccce 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml @@ -123,7 +123,7 @@ stages: --skip_submodule_sync --cmake_generator "Visual Studio 17 2022" --enable_pybind - --enable_onnx_tests + --enable_onnx_tests --use_vcpkg --use_vcpkg_ms_internal_asset_cache ${{ parameters.build_py_parameters }} --parallel --use_binskim_compliant_compile_flags --update --build $(TelemetryOption) diff --git a/tools/ci_build/github/azure-pipelines/templates/windowsai-steps.yml b/tools/ci_build/github/azure-pipelines/templates/windowsai-steps.yml index fb3ebdc760a7b..355a575307f0b 100644 --- a/tools/ci_build/github/azure-pipelines/templates/windowsai-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/windowsai-steps.yml @@ -89,7 +89,7 @@ jobs: # must call vsdevcmd first to add cmake to PATH - script: | python --version - python "$(Build.SourcesDirectory)\tools\ci_build\build.py" --build_dir $(Build.BinariesDirectory) --parallel --use_binskim_compliant_compile_flags --build_shared_lib --enable_onnx_tests --ms_experimental --use_dml --use_winml --cmake_generator "Visual Studio 17 2022" --update --config RelWithDebInfo --enable_lto --use_telemetry --disable_rtti --enable_wcos --windows_sdk_version "10.0.22621.0" $(BuildFlags) --cmake_extra_defines "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO=/PROFILE" "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO=/PROFILE" + python "$(Build.SourcesDirectory)\tools\ci_build\build.py" --build_dir $(Build.BinariesDirectory) --parallel --use_binskim_compliant_compile_flags --build_shared_lib --enable_onnx_tests --ms_experimental --use_dml --use_winml --cmake_generator "Visual Studio 17 2022" --update --config RelWithDebInfo --enable_lto --use_telemetry --disable_rtti --enable_wcos --use_vcpkg --use_vcpkg_ms_internal_asset_cache --windows_sdk_version "10.0.22621.0" $(BuildFlags) --cmake_extra_defines "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO=/PROFILE" "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO=/PROFILE" workingDirectory: '$(Build.BinariesDirectory)' displayName: 'Generate cmake config' diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml index e08d7eb2b12de..1c3d911fa7dbb 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml @@ -90,7 +90,7 @@ jobs: --config $(BuildConfig) --build_dir $(Build.BinariesDirectory) --cmake_generator "Visual Studio 17 2022" - --build_shared_lib + --build_shared_lib --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_qnn $(QnnLibKind) --qnn_home $(QnnSDKRootDir) --update --build --parallel diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml index 81de3335a07d2..faef469e010f6 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml @@ -78,7 +78,7 @@ jobs: --build_dir $(Build.BinariesDirectory) --cmake_generator "Visual Studio 17 2022" --build_java - --build_shared_lib + --build_shared_lib --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_qnn $(QnnLibKind) --qnn_home $(QnnSDKRootDir) --use_binskim_compliant_compile_flags diff --git a/tools/python/util/__init__.py b/tools/python/util/__init__.py index a669963e84bcf..8631218ca9e00 100644 --- a/tools/python/util/__init__.py +++ b/tools/python/util/__init__.py @@ -7,7 +7,8 @@ from .run import run # noqa: F401 from .vcpkg_helpers import ( # noqa: F401 generate_android_triplets, - generate_posix_triplets, + generate_linux_triplets, + generate_macos_triplets, generate_vcpkg_triplets_for_emscripten, generate_windows_triplets, ) diff --git a/tools/python/util/vcpkg_helpers.py b/tools/python/util/vcpkg_helpers.py index d33b2f7675690..875a6186e55c2 100644 --- a/tools/python/util/vcpkg_helpers.py +++ b/tools/python/util/vcpkg_helpers.py @@ -222,6 +222,7 @@ def generate_triplet_for_posix_platform( enable_asan: bool, crt_linkage: str, target_abi: str, + osx_deployment_target: str, ) -> None: """ Generate triplet file for POSIX platforms (Linux, macOS). @@ -235,6 +236,7 @@ def generate_triplet_for_posix_platform( enable_asan (bool): Flag indicating if AddressSanitizer is enabled. crt_linkage (str): The CRT linkage type ("static" or "dynamic"). target_abi (str): The target ABI, which maps to the VCPKG_TARGET_ARCHITECTURE variable. Valid options include x86, x64, arm, arm64, arm64ec, s390x, ppc64le, riscv32, riscv64, loongarch32, loongarch64, mips64. + osx_deployment_target (str, optional): The macOS deployment target version. The parameter sets the minimum macOS version for compiled binaries. It also changes what versions of the macOS platform SDK CMake will search for. See the CMake documentation for CMAKE_OSX_DEPLOYMENT_TARGET for more information. """ folder_name_parts = [] if enable_asan: @@ -341,6 +343,8 @@ def generate_triplet_for_posix_platform( else: osx_abi = target_abi f.write(f'set(VCPKG_OSX_ARCHITECTURES "{osx_abi}")\n') + if osx_deployment_target: + f.write(f'set(VCPKG_OSX_DEPLOYMENT_TARGET "{osx_deployment_target}")\n') f.write("set(CMAKE_POSITION_INDEPENDENT_CODE ON)\n") f.write( "list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF)\n" @@ -501,32 +505,58 @@ def generate_windows_triplets(build_dir: str) -> None: add_port_configs(f, enable_exception, False) -def generate_posix_triplets(build_dir: str) -> None: +def generate_linux_triplets(build_dir: str) -> None: """ - Generate triplet files for POSIX platforms (Linux, macOS). + Generate triplet files for Linux platforms. Args: build_dir (str): The directory to save the generated triplet files. """ - for os_name in ["linux", "osx"]: - if os_name == "linux": - target_abis = ["x86", "x64", "arm", "arm64", "s390x", "ppc64le", "riscv64", "loongarch64", "mips64"] - else: - target_abis = ["x64", "arm64", "universal2"] - for enable_rtti in [True, False]: - for enable_exception in [True, False]: - for enable_binskim in [True, False]: - for enable_asan in [True, False]: - if enable_asan and enable_binskim: - continue - for target_abi in target_abis: - generate_triplet_for_posix_platform( - build_dir, - os_name, - enable_rtti, - enable_exception, - enable_binskim, - enable_asan, - "dynamic", - target_abi, - ) + target_abis = ["x86", "x64", "arm", "arm64", "s390x", "ppc64le", "riscv64", "loongarch64", "mips64"] + for enable_rtti in [True, False]: + for enable_exception in [True, False]: + for enable_binskim in [True, False]: + for enable_asan in [True, False]: + if enable_asan and enable_binskim: + continue + for target_abi in target_abis: + generate_triplet_for_posix_platform( + build_dir, + "linux", + enable_rtti, + enable_exception, + enable_binskim, + enable_asan, + "dynamic", + target_abi, + None, + ) + + +def generate_macos_triplets(build_dir: str, osx_deployment_target: str) -> None: + """ + Generate triplet files for macOS platforms. + + Args: + build_dir (str): The directory to save the generated triplet files. + osx_deployment_target (str, optional): The macOS deployment target version. + """ + target_abis = ["x64", "arm64", "universal2"] + for enable_rtti in [True, False]: + for enable_exception in [True, False]: + for enable_binskim in [True, False]: + for enable_asan in [True, False]: + if enable_asan and enable_binskim: + continue + for target_abi in target_abis: + generate_triplet_for_posix_platform( + build_dir, + "osx", + enable_rtti, + enable_exception, + enable_binskim, + enable_asan, + "dynamic", + target_abi, + osx_deployment_target, + ) From 49328fe63789c424a4b9335ebee791ec8f154e1c Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Fri, 7 Mar 2025 14:04:02 -0800 Subject: [PATCH 065/266] Allow using a different version of flatbuffers when building with vcpkg (#23946) ### Description Allow using a different version of flatbuffers when building with vcpkg, so that users do not need to pin flatbuffer's version, which provides more flexibility in the build process. Delete utf8_range from the dependencies, because it is an indirect dependency of protobuf, which is already included in the build process. ### Motivation and Context --- cmake/deps.txt | 1 - .../external/onnxruntime_external_deps.cmake | 21 ++++--------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/cmake/deps.txt b/cmake/deps.txt index d0bab93d3c16f..c7db8ef51505d 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -53,7 +53,6 @@ re2;https://github.com/google/re2/archive/refs/tags/2024-07-02.zip;646e1728269cd safeint;https://github.com/dcleblanc/SafeInt/archive/refs/tags/3.0.28.zip;23f252040ff6cb9f1fd18575b32fa8fb5928daac tensorboard;https://github.com/tensorflow/tensorboard/archive/373eb09e4c5d2b3cc2493f0949dc4be6b6a45e81.zip;67b833913605a4f3f499894ab11528a702c2b381 cutlass;https://github.com/NVIDIA/cutlass/archive/refs/tags/v3.5.1.zip;e49b2b964163d27765a5002d210a2f3c73771835 -utf8_range;https://github.com/protocolbuffers/utf8_range/archive/72c943dea2b9240cd09efde15191e144bc7c7d38.zip;9925739c9debc0efa2adcb194d371a35b6a03156 extensions;https://github.com/microsoft/onnxruntime-extensions/archive/c24b7bab0c12f53da76d0c31b03b9f0f8ec8f3b4.zip;239063aee4946a9af147b473a4c3da78ba7413b4 composable_kernel;https://github.com/ROCmSoftwarePlatform/composable_kernel/archive/204da9c522cebec5220bba52cd3542ebcaf99e7a.zip;1827348efd47831c13074245274d41b7cae8a557 directx_headers;https://github.com/microsoft/DirectX-Headers/archive/refs/tags/v1.613.1.zip;47653509a3371eabb156360f42faf582f314bf2e diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index 2ab9fc129a90d..a477d6edb3a3f 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -107,23 +107,6 @@ if(onnxruntime_USE_MIMALLOC) FetchContent_MakeAvailable(mimalloc) endif() -#Protobuf depends on utf8_range -onnxruntime_fetchcontent_declare( - utf8_range - URL ${DEP_URL_utf8_range} - URL_HASH SHA1=${DEP_SHA1_utf8_range} - EXCLUDE_FROM_ALL - FIND_PACKAGE_ARGS NAMES utf8_range -) - -set(utf8_range_ENABLE_TESTS OFF CACHE BOOL "Build test suite" FORCE) -set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "Configure installation" FORCE) - -# The next line will generate an error message "fatal: not a git repository", but it is ok. It is from flatbuffers -onnxruntime_fetchcontent_makeavailable(utf8_range) -# protobuf's cmake/utf8_range.cmake has the following line -include_directories(${utf8_range_SOURCE_DIR}) - # Download a protoc binary from Internet if needed if(NOT ONNX_CUSTOM_PROTOC_EXECUTABLE AND NOT onnxruntime_USE_VCPKG) # This part of code is only for users' convenience. The code couldn't handle all cases. Users always can manually @@ -442,6 +425,9 @@ target_include_directories(safeint_interface INTERFACE ${safeint_SOURCE_DIR}) # Flatbuffers +if(onnxruntime_USE_VCPKG) + find_package(flatbuffers REQUIRED) +else() # We do not need to build flatc for iOS or Android Cross Compile if (CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "Emscripten") set(FLATBUFFERS_BUILD_FLATC OFF CACHE BOOL "FLATBUFFERS_BUILD_FLATC" FORCE) @@ -492,6 +478,7 @@ namespace std { using ::getenv; } endif() endif() endif() +endif() # ONNX if (NOT onnxruntime_USE_FULL_PROTOBUF) From 95dcd15053575e01a6bdc8ef7af347e553be9ccf Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Fri, 7 Mar 2025 20:05:05 -0500 Subject: [PATCH 066/266] Make python package pipeline 1ES compliant (#23800) ### Description Make [Python packaging pipeline](https://aiinfra.visualstudio.com/530acbc4-21bc-487d-8cd8-348ff451d2ff/_build?definitionId=841) 1ES compliant ### Motivation and Context ### Checklist - [x] Make Onnxruntime-QNNEP-Windows-2022-CPU stateless --- .../py-package-test-pipeline.yml | 2 + .../azure-pipelines/py-packaging-pipeline.yml | 50 ++-- .../stages/py-cpu-packaging-stage.yml | 122 ++++---- .../templates/py-linux-qnn.yml | 118 ++++---- .../azure-pipelines/templates/py-linux.yml | 144 +++++---- .../templates/py-package-smoking-test.yml | 13 +- .../templates/py-packaging-linux-test-cpu.yml | 18 +- .../templates/py-win-arm64-qnn.yml | 273 +++++++++--------- .../templates/py-win-arm64ec-qnn.yml | 241 ++++++++-------- .../templates/py-win-x64-qnn.yml | 21 +- .../templates/react-native-ci.yml | 12 +- 11 files changed, 564 insertions(+), 450 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml index a0e49692220f9..7a78c6ba0fcdf 100644 --- a/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml @@ -31,10 +31,12 @@ stages: machine_pool: vmImage: 'macOS-13' itemPattern: '*/*mac*x86_64.whl' + arch: 'x86_64' - template: templates/py-package-smoking-test.yml parameters: job_name: Test_LINUX_x86_64_Wheels itemPattern: '*/*manylinux*x86_64.whl' + arch: 'x86_64' machine_pool: name: 'onnxruntime-Ubuntu2204-AMD-CPU' diff --git a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml index 01d30d0e1ba86..28ddd29ec63e6 100644 --- a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml @@ -50,10 +50,10 @@ parameters: displayName: 'Linux packages cmake build type. Linux Only.' default: 'Release' values: - - Debug - - Release - - RelWithDebInfo - - MinSizeRel + - Debug + - Release + - RelWithDebInfo + - MinSizeRel # Only applies to QNN packages. - name: qnn_sdk_version @@ -63,17 +63,33 @@ parameters: trigger: none -stages: -- template: stages/py-cpu-packaging-stage.yml +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: - enable_linux_cpu: ${{ parameters.enable_linux_cpu }} - enable_windows_cpu: ${{ parameters.enable_windows_cpu }} - enable_mac_cpu: ${{ parameters.enable_mac_cpu }} - enable_linux_arm: ${{ parameters.enable_linux_arm }} - enable_windows_arm64_qnn: ${{ parameters.enable_windows_arm64_qnn }} - enable_windows_arm64ec_qnn: ${{ parameters.enable_windows_arm64ec_qnn }} - enable_windows_x64_qnn: ${{ parameters.enable_windows_x64_qnn }} - enable_linux_x64_qnn: ${{ parameters.enable_linux_x64_qnn }} - build_py_parameters: ${{ parameters.build_py_parameters }} - cmake_build_type: ${{ parameters.cmake_build_type }} - qnn_sdk_version: ${{ parameters.qnn_sdk_version }} + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: + - template: stages/py-cpu-packaging-stage.yml + parameters: + enable_linux_cpu: ${{ parameters.enable_linux_cpu }} + enable_windows_cpu: ${{ parameters.enable_windows_cpu }} + enable_mac_cpu: ${{ parameters.enable_mac_cpu }} + enable_linux_arm: ${{ parameters.enable_linux_arm }} + enable_windows_arm64_qnn: ${{ parameters.enable_windows_arm64_qnn }} + enable_windows_arm64ec_qnn: ${{ parameters.enable_windows_arm64ec_qnn }} + enable_windows_x64_qnn: ${{ parameters.enable_windows_x64_qnn }} + enable_linux_x64_qnn: ${{ parameters.enable_linux_x64_qnn }} + build_py_parameters: ${{ parameters.build_py_parameters }} + cmake_build_type: ${{ parameters.cmake_build_type }} + qnn_sdk_version: ${{ parameters.qnn_sdk_version }} diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml index 42d6e4371ccce..5e783607e3622 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml @@ -151,10 +151,11 @@ stages: Contents: '*.whl' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: PublishBuildArtifacts@1 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Artifact: ONNXRuntime python wheel' inputs: - ArtifactName: onnxruntime + artifactName: onnxruntime-win-$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' - script: | 7z x *.whl @@ -199,7 +200,9 @@ stages: workspace: clean: all pool: - vmImage: 'macOS-13' + name: "Azure Pipelines" + image: "macOS-13" + os: macOS variables: MACOSX_DEPLOYMENT_TARGET: '13.3' strategy: @@ -251,74 +254,81 @@ stages: Contents: '*.whl' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: PublishBuildArtifacts@1 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Artifact: ONNXRuntime python wheel' inputs: - ArtifactName: onnxruntime + artifactName: onnxruntime-macos-$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' - template: ../templates/component-governance-component-detection-steps.yml parameters: condition: 'succeeded' - - ${{ if eq(parameters.enable_linux_arm, true) }}: - - stage: Python_Packaging_Linux_ARM - dependsOn: [] - jobs: - - template: ../templates/py-linux.yml - parameters: - arch: 'aarch64' - machine_pool: 'onnxruntime-linux-ARM64-CPU-2019' - extra_build_arg: ${{ parameters.build_py_parameters }} - cmake_build_type: ${{ parameters.cmake_build_type }} - - - ${{ if eq(parameters.enable_linux_cpu, true) }}: - - stage: Python_Packaging_Linux_CPU - dependsOn: [] - jobs: +- ${{ if eq(parameters.enable_linux_arm, true) }}: + - stage: Python_Packaging_Linux_ARM + dependsOn: [] + jobs: - template: ../templates/py-linux.yml parameters: - arch: 'x86_64' - machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU-Large' + arch: 'aarch64' + machine_pool: 'onnxruntime-linux-ARM64-CPU-2019' extra_build_arg: ${{ parameters.build_py_parameters }} cmake_build_type: ${{ parameters.cmake_build_type }} + is1ES: true - - ${{ if eq(parameters.enable_windows_arm64_qnn, true) }}: - - stage: Python_Packaging_Windows_ARM64_QNN - dependsOn: [] - jobs: - - template: ../templates/py-win-arm64-qnn.yml +- ${{ if eq(parameters.enable_linux_cpu, true) }}: + - stage: Python_Packaging_Linux_CPU + dependsOn: [] + jobs: + - template: ../templates/py-linux.yml + parameters: + arch: 'x86_64' + machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU-Large' + extra_build_arg: ${{ parameters.build_py_parameters }} + cmake_build_type: ${{ parameters.cmake_build_type }} + is1ES: true + +- ${{ if eq(parameters.enable_windows_arm64_qnn, true) }}: + - stage: Python_Packaging_Windows_ARM64_QNN + dependsOn: [] + jobs: + - template: ../templates/py-win-arm64-qnn.yml + parameters: + MACHINE_POOL: 'onnxruntime-qnn-windows-vs-2022-arm64' + QNN_SDK: ${{ parameters.qnn_sdk_version }} + BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} + is1ES: true + +- ${{ if eq(parameters.enable_windows_arm64ec_qnn, true) }}: + - stage: Python_Packaging_Windows_arm64ec_QNN + dependsOn: [] + jobs: + - template: ../templates/py-win-arm64ec-qnn.yml parameters: - MACHINE_POOL: 'onnxruntime-qnn-windows-vs-2022-arm64' + MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' QNN_SDK: ${{ parameters.qnn_sdk_version }} BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} + is1ES: true - - ${{ if eq(parameters.enable_windows_arm64ec_qnn, true) }}: - - stage: Python_Packaging_Windows_arm64ec_QNN - dependsOn: [] - jobs: - - template: ../templates/py-win-arm64ec-qnn.yml - parameters: - MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' - QNN_SDK: ${{ parameters.qnn_sdk_version }} - BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} - - - ${{ if eq(parameters.enable_windows_x64_qnn, true) }}: - - stage: Python_Packaging_Windows_x64_QNN - dependsOn: [] - jobs: - - template: ../templates/py-win-x64-qnn.yml - parameters: - MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' - QNN_SDK: ${{ parameters.qnn_sdk_version }} - BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} - - - ${{ if eq(parameters.enable_linux_x64_qnn, true) }}: - - stage: Python_Packaging_Linux_x64_QNN - dependsOn: [] - jobs: - - template: ../templates/py-linux-qnn.yml +- ${{ if eq(parameters.enable_windows_x64_qnn, true) }}: + - stage: Python_Packaging_Windows_x64_QNN + dependsOn: [] + jobs: + - template: ../templates/py-win-x64-qnn.yml parameters: - machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU' - extra_build_arg: ${{ parameters.build_py_parameters }} - cmake_build_type: ${{ parameters.cmake_build_type }} + MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' + QNN_SDK: ${{ parameters.qnn_sdk_version }} + BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} + is1ES: true + +- ${{ if eq(parameters.enable_linux_x64_qnn, true) }}: + - stage: Python_Packaging_Linux_x64_QNN + dependsOn: [] + jobs: + - template: ../templates/py-linux-qnn.yml + parameters: + machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + extra_build_arg: ${{ parameters.build_py_parameters }} + cmake_build_type: ${{ parameters.cmake_build_type }} + is1ES: true diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml index 347a3145e8c70..8126cda449daa 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml @@ -6,10 +6,10 @@ parameters: type: string default: 'Release' values: - - Debug - - Release - - RelWithDebInfo - - MinSizeRel + - Debug + - Release + - RelWithDebInfo + - MinSizeRel - name: device type: string @@ -27,68 +27,82 @@ parameters: displayName: QNN SDK version type: string default: 2.31.0.250130 + +- name: is1ES + displayName: 'Whether the pipeline is running in 1ES' + type: boolean + default: false jobs: - job: Linux_py_qnn_Wheels_x64 timeoutInMinutes: 240 workspace: clean: all - pool: ${{ parameters.machine_pool }} + pool: + name: ${{ parameters.machine_pool }} + os: linux variables: - # The build machine pool doesn't have dotnet, so it can't run CG. - - name: skipComponentGovernanceDetection - value: true - - name: ORT_CACHE_DIR - value: $(Agent.TempDirectory)/ort_ccache - - name: TODAY - value: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - - name: extra_build_args - ${{ if ne(parameters.extra_build_arg, '') }}: - value: -x ${{ parameters.extra_build_arg }} - ${{ if eq(parameters.extra_build_arg, '') }}: - value: '' + # The build machine pool doesn't have dotnet, so it can't run CG. + - name: skipComponentGovernanceDetection + value: true + - name: ORT_CACHE_DIR + value: $(Agent.TempDirectory)/ort_ccache + - name: TODAY + value: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] + - name: extra_build_args + ${{ if ne(parameters.extra_build_arg, '') }}: + value: -x ${{ parameters.extra_build_arg }} + ${{ if eq(parameters.extra_build_arg, '') }}: + value: '' steps: - - checkout: self - clean: true - submodules: none + - checkout: self + clean: true + submodules: none - - template: jobs/download_linux_qnn_sdk.yml - parameters: - QnnSDKVersion: ${{ parameters.QnnSdk }} + - template: jobs/download_linux_qnn_sdk.yml + parameters: + QnnSDKVersion: ${{ parameters.QnnSdk }} - - template: set-nightly-build-option-variable-step.yml + - template: set-nightly-build-option-variable-step.yml - - template: get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/python/cpu/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/x86_64/python/cpu - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuildpythonx86_64_qnn + - template: get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/python/cpu/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/x86_64/python/cpu + DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" + Repository: onnxruntimecpubuildpythonx86_64_qnn - - template: linux-build-step-with-cache.yml - parameters: - WithCache: ${{parameters.with_cache}} - Today: $(TODAY) - AdditionalKey: Linux_py_qnn_Wheels_x64 - CacheDir: $(ORT_CACHE_DIR) - ChangeEveryCommit: true - BuildStep: - - task: Bash@3 - displayName: 'Build Python Wheel' - inputs: - targetType: filePath - filePath: tools/ci_build/github/linux/run_python_dockerbuild.sh - arguments: -i onnxruntimecpubuildpythonx86_64_qnn -d "${{ parameters.device }}" -c ${{ parameters.cmake_build_type }} $(extra_build_args) - env: - ADDITIONAL_DOCKER_PARAMETER: "--volume $(QnnSDKRootDir):/qnn_sdk" + - template: linux-build-step-with-cache.yml + parameters: + WithCache: ${{parameters.with_cache}} + Today: $(TODAY) + AdditionalKey: Linux_py_qnn_Wheels_x64 + CacheDir: $(ORT_CACHE_DIR) + ChangeEveryCommit: true + BuildStep: + - task: Bash@3 + displayName: 'Build Python Wheel' + inputs: + targetType: filePath + filePath: tools/ci_build/github/linux/run_python_dockerbuild.sh + arguments: -i onnxruntimecpubuildpythonx86_64_qnn -d "${{ parameters.device }}" -c ${{ parameters.cmake_build_type }} $(extra_build_args) + env: + ADDITIONAL_DOCKER_PARAMETER: "--volume $(QnnSDKRootDir):/qnn_sdk" + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Artifact: Linux ONNXRuntime QNN python wheel' + inputs: + targetPath: '$(Build.BinariesDirectory)/dist' + artifactName: onnxruntime-linux-qnn-x64 - - task: PublishBuildArtifacts@1 + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 displayName: 'Publish Artifact: Linux ONNXRuntime QNN python wheel' inputs: - PathtoPublish: '$(Build.BinariesDirectory)/dist' - ArtifactName: onnxruntime-linux-qnn-x64 + targetPath: '$(Build.BinariesDirectory)/dist' + artifactName: onnxruntime-linux-qnn-x64 - - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux.yml index e591b719ecfa9..8d0c4334f4874 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-linux.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux.yml @@ -9,10 +9,10 @@ parameters: type: string default: 'Release' values: - - Debug - - Release - - RelWithDebInfo - - MinSizeRel + - Debug + - Release + - RelWithDebInfo + - MinSizeRel - name: device type: string @@ -34,76 +34,98 @@ parameters: type: string default: '' +- name: is1ES + displayName: 'Whether the pipeline is running in 1ES' + type: boolean + default: false + jobs: - job: Linux_py_Wheels_${{ parameters.arch }}_${{parameters.ep}} timeoutInMinutes: 240 workspace: clean: all - pool: ${{ parameters.machine_pool }} + pool: + name: ${{ parameters.machine_pool }} + os: 'linux' + ${{ if eq(parameters.arch, 'aarch64') }}: + hostArchitecture: Arm64 variables: - # The build machine pool doesn't have dotnet, so it can't run CG. - - name: skipComponentGovernanceDetection - value: true - - name: ORT_CACHE_DIR - value: $(Agent.TempDirectory)/ort_ccache - - name: TODAY - value: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - - name: extra_build_args - ${{ if ne(parameters.extra_build_arg, '') }}: - value: '-x ${{ parameters.extra_build_arg }}' - ${{ if eq(parameters.extra_build_arg, '') }}: - value: '' - - name: python_exe_path - ${{ if ne(parameters.python_exe_path, '') }}: - value: '-p ${{ parameters.python_exe_path }}' - ${{ if eq(parameters.python_exe_path, '') }}: - value: '' + # The build machine pool doesn't have dotnet, so it can't run CG. + - name: skipComponentGovernanceDetection + value: true + - name: ORT_CACHE_DIR + value: $(Agent.TempDirectory)/ort_ccache + - name: TODAY + value: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] + - name: extra_build_args + ${{ if ne(parameters.extra_build_arg, '') }}: + value: '-x ${{ parameters.extra_build_arg }}' + ${{ if eq(parameters.extra_build_arg, '') }}: + value: '' + - name: python_exe_path + ${{ if ne(parameters.python_exe_path, '') }}: + value: '-p ${{ parameters.python_exe_path }}' + ${{ if eq(parameters.python_exe_path, '') }}: + value: '' steps: - - checkout: self - clean: true - submodules: none - - - template: set-nightly-build-option-variable-step.yml - - - template: get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cpu/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cpu - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuildpython${{ parameters.arch }} - - - template: linux-build-step-with-cache.yml - parameters: - WithCache: ${{parameters.with_cache}} - Today: $(TODAY) - AdditionalKey: Linux_py_Wheels_${{ parameters.arch }} - CacheDir: $(ORT_CACHE_DIR) - ChangeEveryCommit: true - BuildStep: - - task: Bash@3 - displayName: 'Build Python Wheel' - inputs: - targetType: filePath - filePath: tools/ci_build/github/linux/run_python_dockerbuild.sh - arguments: -i onnxruntimecpubuildpython${{ parameters.arch }} -d "${{ parameters.device }}" -c ${{ parameters.cmake_build_type }} $(extra_build_args) $(python_exe_path) - ${{ if eq(parameters.with_cache, 'true') }}: - env: - ADDITIONAL_DOCKER_PARAMETER: "--volume $(ORT_CACHE_DIR):/cache -e CCACHE_DIR=/cache -e ORT_BUILD_WITH_CACHE=1" - - - task: PublishBuildArtifacts@1 + - checkout: self + clean: true + submodules: none + + - template: set-nightly-build-option-variable-step.yml + + - template: get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cpu/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cpu + DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" + Repository: onnxruntimecpubuildpython${{ parameters.arch }} + + - template: linux-build-step-with-cache.yml + parameters: + WithCache: ${{parameters.with_cache}} + Today: $(TODAY) + AdditionalKey: Linux_py_Wheels_${{ parameters.arch }} + CacheDir: $(ORT_CACHE_DIR) + ChangeEveryCommit: true + BuildStep: + - task: Bash@3 + displayName: 'Build Python Wheel' + inputs: + targetType: filePath + filePath: tools/ci_build/github/linux/run_python_dockerbuild.sh + arguments: -i onnxruntimecpubuildpython${{ parameters.arch }} -d "${{ parameters.device }}" -c ${{ parameters.cmake_build_type }} $(extra_build_args) $(python_exe_path) + ${{ if eq(parameters.with_cache, 'true') }}: + env: + ADDITIONAL_DOCKER_PARAMETER: "--volume $(ORT_CACHE_DIR):/cache -e CCACHE_DIR=/cache -e ORT_BUILD_WITH_CACHE=1" + + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Artifact: ONNXRuntime python wheel' inputs: - PathtoPublish: '$(Build.BinariesDirectory)/dist' - ArtifactName: onnxruntime-${{ parameters.ep }} - - - task: PublishPipelineArtifact@0 + targetPath: '$(Build.BinariesDirectory)/dist' + artifactName: onnxruntime-${{ parameters.arch }}-${{ parameters.ep }} + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Test Binaries' + inputs: + artifactName: 'drop-linux-cpu-${{ parameters.arch }}-${{ parameters.ep }}' + targetPath: '$(Build.BinariesDirectory)/${{ parameters.cmake_build_type }}' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + targetPath: '$(Build.BinariesDirectory)/dist' + artifactName: onnxruntime-${{ parameters.arch }}-${{ parameters.ep }} + - task: PublishPipelineArtifact@1 displayName: 'Publish Test Binaries' inputs: artifactName: 'drop-linux-cpu-${{ parameters.arch }}-${{ parameters.ep }}' targetPath: '$(Build.BinariesDirectory)/${{ parameters.cmake_build_type }}' - - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + + + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml b/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml index 3a3da0f8f5afa..c0bd740b2d483 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml @@ -9,9 +9,13 @@ parameters: - name: machine_pool type: object -- name: python_arch +- name: ep type: string - default: 'x64' + default: 'cpu' + +- name: arch + type: string + default: 'x86_64' jobs: - job: ${{ parameters.job_name }} @@ -37,10 +41,9 @@ jobs: displayName: 'Use Python' inputs: versionSpec: $(PythonVersion) - architecture: ${{ parameters.python_arch }} - download: build # pipeline resource identifier. - artifact: 'onnxruntime' + artifact: 'onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}' - task: Bash@3 inputs: @@ -51,7 +54,7 @@ jobs: FILE_NAME="${files[0]}" FILE_NAME=$(basename $FILE_NAME) PYTHON_PACKAGE_NAME=$(echo "$FILE_NAME" | cut -f 1 -d '-') - python3 -m pip install --find-links "$(Pipeline.Workspace)/build/onnxruntime" $PYTHON_PACKAGE_NAME + python3 -m pip install --find-links "$(Pipeline.Workspace)/build/onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}" $PYTHON_PACKAGE_NAME python3 -m pip show $PYTHON_PACKAGE_NAME python3 -c "import onnxruntime as ort; print(ort.__version__)" workingDirectory: $(Pipeline.Workspace)/build/onnxruntime diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cpu.yml index c475feaef0018..eef97341b8d53 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cpu.yml @@ -19,10 +19,10 @@ parameters: type: string default: 'Release' values: - - Debug - - Release - - RelWithDebInfo - - MinSizeRel + - Debug + - Release + - RelWithDebInfo + - MinSizeRel - name: timeout type: number @@ -50,29 +50,31 @@ jobs: artifact: 'drop-linux-cpu-${{ parameters.arch }}-${{parameters.ep}}' - download: current # pipeline resource identifier. - artifact: 'onnxruntime${{ parameters.python_wheel_suffix }}-${{ parameters.ep }}' + artifact: 'onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}' - bash: | set -e -x mv "$(Pipeline.Workspace)/drop-linux-cpu-${{ parameters.arch }}-${{parameters.ep}}" $(Build.BinariesDirectory)/${{parameters.cmake_build_type}} - mv "$(Pipeline.Workspace)/onnxruntime${{ parameters.python_wheel_suffix }}-${{parameters.ep}}" "$(Build.BinariesDirectory)/whl" + mv "$(Pipeline.Workspace)/onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}" "$(Build.BinariesDirectory)/whl" cp -r "$(Build.BinariesDirectory)/whl" $(Build.BinariesDirectory)/tmp find "$(Build.BinariesDirectory)/tmp" -name '*.whl' -exec bash -c 'unzip -d "${1%.*}" "$1"' _ {} \; + displayName: 'Move the artifacts to the binaries directory' # The private ADO project - ${{ if eq(variables['System.CollectionId'], 'bc038106-a83b-4dab-9dd3-5a41bc58f34c') }}: - download: build # pipeline resource identifier. artifact: 'drop-linux-cpu-${{ parameters.arch }}-${{parameters.ep}}' - download: build # pipeline resource identifier. - artifact: 'onnxruntime${{ parameters.python_wheel_suffix }}-${{ parameters.ep }}' + artifact: 'onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}' - bash: | set -e -x ls $(Pipeline.Workspace)/build mv "$(Pipeline.Workspace)/build/drop-linux-cpu-${{ parameters.arch }}-${{parameters.ep}}" $(Build.BinariesDirectory)/${{parameters.cmake_build_type}} - mv "$(Pipeline.Workspace)/build/onnxruntime${{ parameters.python_wheel_suffix }}-${{parameters.ep}}" "$(Build.BinariesDirectory)/whl" + mv "$(Pipeline.Workspace)/build/onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}" "$(Build.BinariesDirectory)/whl" cp -r "$(Build.BinariesDirectory)/whl" $(Build.BinariesDirectory)/tmp find "$(Build.BinariesDirectory)/tmp" -name '*.whl' -exec bash -c 'unzip -d "${1%.*}" "$1"' _ {} \; + displayName: 'Move the artifacts to the binaries directory' # The BinSkim task uses a dotnet program which doesn't support ARM CPUs yet - ${{ if eq(parameters.arch, 'x86_64') }}: diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml index 4c9d0dccaf48d..10ea7f6203bb1 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml @@ -19,6 +19,11 @@ parameters: type: string default: '' +- name: is1ES + displayName: 'Whether the pipeline is running in 1ES' + type: boolean + default: false + jobs: - job: Win_py_arm64_qnn_Wheels timeoutInMinutes: 210 @@ -26,6 +31,8 @@ jobs: clean: all pool: name: ${{ parameters.MACHINE_POOL }} + os: windows + hostArchitecture: Arm64 strategy: matrix: Python311_arm64: @@ -41,132 +48,140 @@ jobs: GRADLE_OPTS: '-Dorg.gradle.daemon=false' VSGenerator: 'Visual Studio 17 2022' steps: - - checkout: self - clean: true - submodules: recursive - - - template: telemetry-steps.yml - - - script: | - MKDIR $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64 - XCOPY /s /y /h /e /c /q "$(LocalPythonDir)\*.*" $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64\ - COPY NUL $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64.complete - DIR $(Agent.ToolsDirectory)\Python - DIR $(Agent.ToolsDirectory)\Python\$(PythonVersion) - DIR $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64 - displayName: Copy python $(PythonVersion) version to agent tools directory - - - task: UsePythonVersion@0 - inputs: - versionSpec: $(PythonVersion) - addToPath: true - architecture: 'arm64' - - - task: PipAuthenticate@1 - displayName: 'Pip Authenticate' - inputs: - artifactFeeds: 'Lotus' - - - task: onebranch.pipeline.tsaoptions@1 - displayName: 'OneBranch TSAOptions' - inputs: - tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json' - appendSourceBranchName: false - - - task: PythonScript@0 - inputs: - scriptSource: inline - script: | - import subprocess - subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel']) - workingDirectory: '$(Build.BinariesDirectory)' - displayName: 'Install python modules' - - - template: set-nightly-build-option-variable-step.yml - - - template: jobs/download_win_qnn_sdk.yml - parameters: - QnnSDKVersion: ${{ parameters.QNN_SDK }} - - - task: PythonScript@0 - displayName: 'Generate cmake config' - inputs: - scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: > - --config RelWithDebInfo - --build_dir $(Build.BinariesDirectory) - --skip_submodule_sync - --cmake_generator "$(VSGenerator)" - --build_shared_lib - --use_qnn - --qnn_home $(QnnSDKRootDir) - --enable_pybind - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --update - $(TelemetryOption) ${{ parameters.BUILD_PY_PARAMETERS }} - workingDirectory: '$(Build.BinariesDirectory)' - - - task: VSBuild@1 - displayName: 'Build' - inputs: - solution: '$(Build.BinariesDirectory)\RelWithDebInfo\onnxruntime.sln' - platform: 'arm64' - configuration: RelWithDebInfo - msbuildArchitecture: 'arm64' - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo' - createLogFile: true - - # Esrp signing - - template: win-esrp-dll.yml - parameters: - FolderPath: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\onnxruntime\capi' - DisplayName: 'ESRP - Sign Native dlls' - DoEsrp: true - Pattern: '*.pyd' - - - task: PythonScript@0 - displayName: 'Build wheel' - inputs: - scriptPath: '$(Build.SourcesDirectory)\setup.py' - arguments: 'bdist_wheel $(NightlyBuildOption) --wheel_name_suffix=qnn' - workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - - - task: CopyFiles@2 - displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\dist' - Contents: '*.whl' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: ONNXRuntime python wheel' - inputs: - ArtifactName: onnxruntime_qnn_arm64 - - - script: | - 7z x *.whl - workingDirectory: '$(Build.ArtifactStagingDirectory)' - displayName: 'unzip the package' - - - task: CredScan@3 - displayName: 'Run CredScan' - inputs: - debugMode: false - continueOnError: true - - - task: BinSkim@4 - displayName: 'Run BinSkim' - inputs: - AnalyzeTargetGlob: '+:file|$(Build.ArtifactStagingDirectory)\**\*.dll' - - - task: TSAUpload@2 - displayName: 'TSA upload' - condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) - inputs: - GdnPublishTsaOnboard: false - GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - checkout: self + clean: true + submodules: recursive + + - template: telemetry-steps.yml + + - script: | + MKDIR $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64 + XCOPY /s /y /h /e /c /q "$(LocalPythonDir)\*.*" $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64\ + COPY NUL $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64.complete + DIR $(Agent.ToolsDirectory)\Python + DIR $(Agent.ToolsDirectory)\Python\$(PythonVersion) + DIR $(Agent.ToolsDirectory)\Python\$(PythonVersion)\arm64 + displayName: Copy python $(PythonVersion) version to agent tools directory + + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PythonVersion) + addToPath: true + architecture: 'arm64' + + - task: PipAuthenticate@1 + displayName: 'Pip Authenticate' + inputs: + artifactFeeds: 'Lotus' + + - task: onebranch.pipeline.tsaoptions@1 + displayName: 'OneBranch TSAOptions' + inputs: + tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json' + appendSourceBranchName: false + + - task: PythonScript@0 + inputs: + scriptSource: inline + script: | + import subprocess + subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel']) + workingDirectory: '$(Build.BinariesDirectory)' + displayName: 'Install python modules' + + - template: set-nightly-build-option-variable-step.yml + + - template: jobs/download_win_qnn_sdk.yml + parameters: + QnnSDKVersion: ${{ parameters.QNN_SDK }} + + - task: PythonScript@0 + displayName: 'Generate cmake config' + inputs: + scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' + arguments: > + --config RelWithDebInfo + --build_dir $(Build.BinariesDirectory) + --skip_submodule_sync + --cmake_generator "$(VSGenerator)" + --build_shared_lib + --use_qnn + --qnn_home $(QnnSDKRootDir) + --enable_pybind + --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --update + $(TelemetryOption) ${{ parameters.BUILD_PY_PARAMETERS }} + workingDirectory: '$(Build.BinariesDirectory)' + + - task: VSBuild@1 + displayName: 'Build' + inputs: + solution: '$(Build.BinariesDirectory)\RelWithDebInfo\onnxruntime.sln' + platform: 'arm64' + configuration: RelWithDebInfo + msbuildArchitecture: 'arm64' + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo' + createLogFile: true + + # Esrp signing + - template: win-esrp-dll.yml + parameters: + FolderPath: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\onnxruntime\capi' + DisplayName: 'ESRP - Sign Native dlls' + DoEsrp: true + Pattern: '*.pyd' + + - task: PythonScript@0 + displayName: 'Build wheel' + inputs: + scriptPath: '$(Build.SourcesDirectory)\setup.py' + arguments: 'bdist_wheel $(NightlyBuildOption) --wheel_name_suffix=qnn' + workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' + + - task: CopyFiles@2 + displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\dist' + Contents: '*.whl' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + artifactName: onnxruntime_qnn_arm64_$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + input: + artifactName: onnxruntime_qnn_arm64_$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' + + - script: | + 7z x *.whl + workingDirectory: '$(Build.ArtifactStagingDirectory)' + displayName: 'unzip the package' + + - task: CredScan@3 + displayName: 'Run CredScan' + inputs: + debugMode: false + continueOnError: true + + - task: BinSkim@4 + displayName: 'Run BinSkim' + inputs: + AnalyzeTargetGlob: '+:file|$(Build.ArtifactStagingDirectory)\**\*.dll' + + - task: TSAUpload@2 + displayName: 'TSA upload' + condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + inputs: + GdnPublishTsaOnboard: false + GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' + + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml index ed29f1e67515e..24321d2a3e1ec 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml @@ -19,6 +19,11 @@ parameters: type: string default: '' +- name: is1ES + displayName: 'Whether the pipeline is running in 1ES' + type: boolean + default: false + jobs: - job: Win_py_x64_qnn_Wheels timeoutInMinutes: 210 @@ -26,6 +31,7 @@ jobs: clean: all pool: name: ${{ parameters.MACHINE_POOL }} + os: windows strategy: matrix: Python310_x64: @@ -40,117 +46,124 @@ jobs: GRADLE_OPTS: '-Dorg.gradle.daemon=false' VSGenerator: 'Visual Studio 17 2022' steps: - - checkout: self - clean: true - submodules: recursive - - - template: telemetry-steps.yml - - - task: UsePythonVersion@0 - inputs: - versionSpec: $(PythonVersion) - addToPath: true - architecture: 'x64' - - - task: PipAuthenticate@1 - displayName: 'Pip Authenticate' - inputs: - artifactFeeds: 'Lotus' - - - task: onebranch.pipeline.tsaoptions@1 - displayName: 'OneBranch TSAOptions' - inputs: - tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json' - appendSourceBranchName: fals - - - script: python -m pip install -r $(Build.SourcesDirectory)\tools\ci_build\github\linux\python\requirements.txt - - - - template: set-nightly-build-option-variable-step.yml - - - template: jobs/download_win_qnn_sdk.yml - parameters: - QnnSDKVersion: ${{ parameters.QNN_SDK }} - - - task: PythonScript@0 - displayName: 'Generate cmake config' - inputs: - scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: > - --config RelWithDebInfo - --build_dir $(Build.BinariesDirectory) - --skip_submodule_sync - --cmake_generator "$(VSGenerator)" - --build_shared_lib - --use_qnn - --qnn_home $(QnnSDKRootDir) - --enable_pybind - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --update --arm64ec - $(TelemetryOption) ${{ parameters.BUILD_PY_PARAMETERS }} - workingDirectory: '$(Build.BinariesDirectory)' - - - task: VSBuild@1 - displayName: 'Build' - inputs: - solution: '$(Build.BinariesDirectory)\RelWithDebInfo\onnxruntime.sln' - platform: 'arm64ec' - configuration: RelWithDebInfo - msbuildArchitecture: 'x64' - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo' - createLogFile: true - - # Esrp signing - - template: win-esrp-dll.yml - parameters: - FolderPath: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\onnxruntime\capi' - DisplayName: 'ESRP - Sign Native dlls' - DoEsrp: true - Pattern: '*.pyd' - - - task: PythonScript@0 - displayName: 'Build wheel' - inputs: - scriptPath: '$(Build.SourcesDirectory)\setup.py' - arguments: 'bdist_wheel $(NightlyBuildOption) --wheel_name_suffix=qnn' - workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - - - task: CopyFiles@2 - displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\dist' - Contents: '*.whl' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: ONNXRuntime python wheel' - inputs: - ArtifactName: onnxruntime_qnn_arm64ec - - - script: | - 7z x *.whl - workingDirectory: '$(Build.ArtifactStagingDirectory)' - displayName: 'unzip the package' - - - task: CredScan@3 - displayName: 'Run CredScan' - inputs: - debugMode: false - continueOnError: true - - - task: BinSkim@4 - displayName: 'Run BinSkim' - inputs: - AnalyzeTargetGlob: '+:file|$(Build.ArtifactStagingDirectory)\**\*.dll' - - - task: TSAUpload@2 - displayName: 'TSA upload' - condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) - inputs: - GdnPublishTsaOnboard: false - GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - checkout: self + clean: true + submodules: recursive + + - template: telemetry-steps.yml + + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PythonVersion) + addToPath: true + architecture: 'x64' + + - task: PipAuthenticate@1 + displayName: 'Pip Authenticate' + inputs: + artifactFeeds: 'Lotus' + + - task: onebranch.pipeline.tsaoptions@1 + displayName: 'OneBranch TSAOptions' + inputs: + tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json' + appendSourceBranchName: fals + + - script: python -m pip install -r $(Build.SourcesDirectory)\tools\ci_build\github\linux\python\requirements.txt + + + - template: set-nightly-build-option-variable-step.yml + + - template: jobs/download_win_qnn_sdk.yml + parameters: + QnnSDKVersion: ${{ parameters.QNN_SDK }} + + - task: PythonScript@0 + displayName: 'Generate cmake config' + inputs: + scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' + arguments: > + --config RelWithDebInfo + --build_dir $(Build.BinariesDirectory) + --skip_submodule_sync + --cmake_generator "$(VSGenerator)" + --build_shared_lib + --use_qnn + --qnn_home $(QnnSDKRootDir) + --enable_pybind + --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --update --arm64ec + $(TelemetryOption) ${{ parameters.BUILD_PY_PARAMETERS }} + workingDirectory: '$(Build.BinariesDirectory)' + + - task: VSBuild@1 + displayName: 'Build' + inputs: + solution: '$(Build.BinariesDirectory)\RelWithDebInfo\onnxruntime.sln' + platform: 'arm64ec' + configuration: RelWithDebInfo + msbuildArchitecture: 'x64' + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo' + createLogFile: true + + # Esrp signing + - template: win-esrp-dll.yml + parameters: + FolderPath: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\onnxruntime\capi' + DisplayName: 'ESRP - Sign Native dlls' + DoEsrp: true + Pattern: '*.pyd' + + - task: PythonScript@0 + displayName: 'Build wheel' + inputs: + scriptPath: '$(Build.SourcesDirectory)\setup.py' + arguments: 'bdist_wheel $(NightlyBuildOption) --wheel_name_suffix=qnn' + workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' + + - task: CopyFiles@2 + displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\dist' + Contents: '*.whl' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + artifactName: onnxruntime_qnn_arm64ec_$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + artifactName: onnxruntime_qnn_arm64ec_$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' + - script: | + 7z x *.whl + workingDirectory: '$(Build.ArtifactStagingDirectory)' + displayName: 'unzip the package' + + - task: CredScan@3 + displayName: 'Run CredScan' + inputs: + debugMode: false + continueOnError: true + + - task: BinSkim@4 + displayName: 'Run BinSkim' + inputs: + AnalyzeTargetGlob: '+:file|$(Build.ArtifactStagingDirectory)\**\*.dll' + + - task: TSAUpload@2 + displayName: 'TSA upload' + condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + inputs: + GdnPublishTsaOnboard: false + GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' + + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml index 13069846da342..175b343e55d57 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml @@ -19,6 +19,11 @@ parameters: type: string default: '' +- name: is1ES + displayName: 'Whether the pipeline is running in 1ES' + type: boolean + default: false + jobs: - job: Win_py_x64_qnn_Wheels timeoutInMinutes: 210 @@ -116,10 +121,18 @@ jobs: Contents: '*.whl' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: ONNXRuntime python wheel' - inputs: - ArtifactName: onnxruntime_qnn_x64 + - ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + artifactName: onnxruntime_qnn_x64_$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' + - ${{ if eq(parameters.is1ES, false) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + artifactName: onnxruntime_qnn_x64_$(PythonVersion) + targetPath: '$(Build.ArtifactStagingDirectory)' - script: | 7z x *.whl diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index 7991916a47ca4..52dbb76632e0c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -62,10 +62,14 @@ stages: dependsOn: '${{parameters.InitialStageDependsOn}}' jobs: - job: ReactNative_CI_iOS - pool: - name: 'Azure Pipelines' - image: 'macOS-13' - os: 'macOS' + ${{ if eq(parameters.is1ES, false) }}: + pool: + vmImage: 'macOS-13' + ${{ if eq(parameters.is1ES, true) }}: + pool: + name: 'Azure Pipelines' + image: 'macOS-13' + os: 'macOS' timeoutInMinutes: 120 From 989d4177ed99db324ba4a4a35149977626120b14 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Fri, 7 Mar 2025 23:35:26 -0500 Subject: [PATCH 067/266] Delete ROCM Nuget Publishing Pipeline (#23948) --- .../rocm-nuget-packaging-pipeline.yml | 339 ------------------ .../rocm-publish-nuget-pipeline.yml | 21 -- 2 files changed, 360 deletions(-) delete mode 100644 tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/rocm-publish-nuget-pipeline.yml diff --git a/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml deleted file mode 100644 index 286f92b36f7e4..0000000000000 --- a/tools/ci_build/github/azure-pipelines/rocm-nuget-packaging-pipeline.yml +++ /dev/null @@ -1,339 +0,0 @@ -parameters: -- name: RunOnnxRuntimeTests - displayName: Run Tests? - type: boolean - default: true - -- name: UseIncreasedTimeoutForTests - displayName: Increase timeout for tests? Set it to false if you are doing an Onnx Runtime release. - type: boolean - default: false - -- name: DoCompliance - displayName: Run Compliance Tasks? - type: boolean - default: true - -- name: DoEsrp - displayName: Run code sign tasks? Must be true if you are doing an ONNX Runtime release - type: boolean - default: true - -- name: IsReleaseBuild - displayName: Is a release build? Set it to true if you are doing an ONNX Runtime release. - type: boolean - default: false - -- name: PreReleaseVersionSuffixString - displayName: Suffix added to pre-release package version. Only used if IsReleaseBuild is true. Denotes the type of pre-release package. - type: string - values: - - alpha - - beta - - rc - - none - default: none - -- name: PreReleaseVersionSuffixNumber - displayName: Number added to pre-release package version. Only used if IsReleaseBuild is true. Denotes the sequence of a pre-release package. - type: number - default: 0 - -# these 2 parameters are used for debugging. -- name: SpecificArtifact - displayName: Use Specific Artifact (Debugging only) - type: boolean - default: false - -- name: BuildId - displayName: Pipeline BuildId, you could find it in the URL - type: string - default: '0' - -- name: NugetPackageSuffix - displayName: Suffix to append to nuget package - type: string - default: 'NONE' - -resources: - repositories: - - repository: onnxruntime-inference-examples # The name used to reference this repository in the checkout step - type: github - endpoint: ort-examples - name: microsoft/onnxruntime-inference-examples - - repository: manylinux - type: Github - endpoint: Microsoft - name: pypa/manylinux - ref: 5eda9aded5462201e6310105728d33016e637ea7 - -variables: -- name: ReleaseVersionSuffix - value: '' - -stages: -- template: stages/set_packaging_variables_stage.yml - parameters: - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - PreReleaseVersionSuffixString: ${{ parameters.PreReleaseVersionSuffixString }} - PreReleaseVersionSuffixNumber: ${{ parameters.PreReleaseVersionSuffixNumber }} - -# ROCm -- stage: Linux_C_API_Packaging_ROCm_x64 - dependsOn: [] - jobs: - - job: Linux_C_API_Packaging_ROCm_x64 - workspace: - clean: all - timeoutInMinutes: 480 - pool: onnxruntime-Ubuntu2204-AMD-CPU - variables: - RocmVersion: '6.2' - RocmVersionPatchSuffix: '' - steps: - - checkout: self # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/onnxruntime - submodules: recursive - - checkout: manylinux # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/manylinux, for get-docker-image-steps.yml - submodules: false - - # get-docker-image-steps.yml will move the $(Build.SourcesDirectory)/manylinux into $(Build.SourcesDirectory)/onnxruntime, - # then rename $(Build.SourcesDirectory)/onnxruntime as $(Build.SourcesDirectory) - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_rocm - Context: tools/ci_build/github/linux/docker - DockerBuildArgs: >- - --build-arg INSTALL_DEPS_EXTRA_ARGS=-tmur - --build-arg BUILD_UID=$(id -u) - --network=host --build-arg POLICY=manylinux_2_28 --build-arg PLATFORM=x86_64 - --build-arg ROCM_VERSION=$(RocmVersion)$(RocmVersionPatchSuffix) - --build-arg DEVTOOLSET_ROOTPATH=/opt/rh/gcc-toolset-12/root - --build-arg PREPEND_PATH=/opt/rh/gcc-toolset-12/root/usr/bin: - --build-arg LD_LIBRARY_PATH_ARG=/opt/rh/gcc-toolset-12/root/usr/lib64:/opt/rh/gcc-toolset-12/root/usr/lib:/opt/rh/gcc-toolset-12/root/usr/lib64/dyninst:/opt/rh/gcc-toolset-12/root/usr/lib/dyninst:/usr/local/lib64:/usr/local/lib - Repository: onnxruntimetrainingrocmbuild-rocm$(RocmVersion) - CheckOutManyLinux: true - - - template: templates/set-version-number-variables-step.yml - - - task: Bash@3 - displayName: 'Build' - inputs: - targetType: filePath - filePath: tools/ci_build/github/linux/build_rocm_c_api_package.sh - arguments: >- - -S $(Build.SourcesDirectory) - -B $(Build.BinariesDirectory) - -V $(RocmVersion) - -I onnxruntimetrainingrocmbuild-rocm$(RocmVersion) - -P python3.10 - - - script: | - set -e -x - mkdir $(Build.ArtifactStagingDirectory)/testdata - cp $(Build.BinariesDirectory)/Release/libcustom_op_library.so* $(Build.ArtifactStagingDirectory)/testdata - ls -al $(Build.ArtifactStagingDirectory) - displayName: 'Create Artifacts for CustomOp' # libcustom_op_library.so from cpu build is built with fp8, ROCm does not support it. - - - template: templates/c-api-artifacts-package-and-publish-steps-posix.yml - parameters: - buildConfig: 'Release' - artifactName: 'onnxruntime-linux-x64-rocm-$(OnnxRuntimeVersion)' - artifactNameNoVersionString: 'onnxruntime-linux-x64-rocm' - libraryName: 'libonnxruntime.so.$(OnnxRuntimeVersion)' - - - template: templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - - template: templates/clean-agent-build-directory-step.yml - -- stage: NuGet_Packaging_ROCm - dependsOn: - - Setup - - Linux_C_API_Packaging_ROCm_x64 - condition: succeeded() - jobs: - - job: NuGet_Packaging_ROCm - workspace: - clean: all - # we need to use a 2022 pool to create the nuget package with MAUI targets. - # VS2019 has no support for net6/MAUI and we need to use msbuild (from the VS install) to do the packing - pool: 'Onnxruntime-Win-CPU-2022' - variables: - breakCodesignValidationInjection: ${{ parameters.DoEsrp }} - ReleaseVersionSuffix: $[stageDependencies.Setup.Set_Variables.outputs['Set_Release_Version_Suffix.ReleaseVersionSuffix']] - BuildDate : $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Date.BuildDate']] - BuildTime : $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Time.BuildTime']] - - steps: - - checkout: self - submodules: true - fetchDepth: 1 - - - template: templates/flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline Artifact - NuGet' - ArtifactName: 'onnxruntime-linux-x64-rocm' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact' - SpecificArtifact: ${{ parameters.specificArtifact }} - BuildId: ${{ parameters.BuildId }} - - - task: PowerShell@2 - displayName: 'Reconstruct Build Directory' - inputs: - targetType: inline - script: | - Get-ChildItem $(Build.BinariesDirectory)\nuget-artifact -Filter *.tgz | % { - # *.tar will be created after *.tgz is extracted - $cmd = "7z.exe x $($_.FullName) -y -o$(Build.BinariesDirectory)\nuget-artifact" - Write-Output $cmd - Invoke-Expression -Command $cmd - } - - Get-ChildItem $(Build.BinariesDirectory)\nuget-artifact -Filter *.tar | % { - $cmd = "7z.exe x $($_.FullName) -y -o$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts" - Write-Output $cmd - Invoke-Expression -Command $cmd - } - - $ort_dirs = Get-ChildItem -Path $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-* -Directory - foreach ($ort_dir in $ort_dirs) - { - $dirname = Split-Path -Path $ort_dir -Leaf - $dirname = $dirname.SubString(0, $dirname.LastIndexOf('-')) - Write-Output "Renaming $ort_dir to $dirname" - Rename-Item -Path $ort_dir -NewName $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\$dirname - } - - Copy-Item -Path $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-linux-x64-rocm\lib\* -Destination $(Build.BinariesDirectory)\RelWithDebInfo - - - script: | - tree /F - workingDirectory: '$(Build.BinariesDirectory)' - displayName: 'Inspect Build Binaries Directory' - - - script: | - mklink /D /J models C:\local\models - workingDirectory: '$(Build.BinariesDirectory)' - displayName: 'Create models link' - - - task: NuGetToolInstaller@0 - displayName: Use Nuget 6.10.x - inputs: - versionSpec: 6.10.x - - - task: MSBuild@1 - displayName: 'Restore NuGet Packages and create project.assets.json' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: RelWithDebInfo - msbuildArguments: '-t:restore -p:OrtPackageId="Microsoft.ML.OnnxRuntime.ROCm"' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - task: MSBuild@1 - displayName: 'Build C# bindings' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: RelWithDebInfo - msbuildArguments: > - -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" - -p:OrtPackageId="Microsoft.ML.OnnxRuntime.ROCm" - -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} - -p:ReleaseVersionSuffix=$(ReleaseVersionSuffix) - -p:IsLinuxBuild=true - -p:IsWindowsBuild=false - -p:IsMacOSBuild=false - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - template: templates/win-esrp-dll.yml - parameters: - FolderPath: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo' - DisplayName: 'ESRP - Sign C# dlls' - DoEsrp: ${{ parameters.DoEsrp }} - - - task: UsePythonVersion@0 - displayName: 'Use Python' - inputs: - versionSpec: 3.12 - - - task: MSBuild@1 - displayName: 'Build Nuget Packages' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj' - configuration: RelWithDebInfo - platform: 'Any CPU' - msbuildArguments: > - -t:CreatePackage - -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" - -p:OrtPackageId=Microsoft.ML.OnnxRuntime.ROCm - -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} - -p:ReleaseVersionSuffix=$(ReleaseVersionSuffix) - -p:CurrentTime=$(BuildTime) - -p:CurrentDate=$(BuildDate) - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - task: CopyFiles@2 - displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - Contents: '*.snupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: CopyFiles@2 - displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - Contents: '*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: CopyFiles@2 - displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo' - Contents: '*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - template: templates/esrp_nuget.yml - parameters: - DisplayName: 'ESRP - sign NuGet package' - FolderPath: '$(Build.ArtifactStagingDirectory)' - DoEsrp: ${{ parameters.DoEsrp }} - - - template: templates/validate-package.yml - parameters: - PackageType: 'nuget' - PackagePath: '$(Build.ArtifactStagingDirectory)' - PackageName: 'Microsoft.ML.OnnxRuntime.*nupkg' - PlatformsSupported: 'linux-x64' - VerifyNugetSigning: false - - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline NuGet Artifact' - inputs: - artifactName: 'drop-signed-nuget-ROCm' - targetPath: '$(Build.ArtifactStagingDirectory)' - - - task: MSBuild@1 - displayName: 'Clean C#' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: RelWithDebInfo - msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.ROCm' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - template: templates/component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' - - -- template: nuget/templates/test_linux.yml - parameters: - AgentPool: AMD-GPU - ArtifactSuffix: 'ROCm' - StageSuffix: 'ROCm' - NugetPackageName: 'Microsoft.ML.OnnxRuntime.ROCm' - SpecificArtifact: ${{ parameters.specificArtifact }} - CustomOpArtifactName: 'onnxruntime-linux-x64-rocm' - BuildId: ${{ parameters.BuildId }} diff --git a/tools/ci_build/github/azure-pipelines/rocm-publish-nuget-pipeline.yml b/tools/ci_build/github/azure-pipelines/rocm-publish-nuget-pipeline.yml deleted file mode 100644 index 1d2393d8f96d5..0000000000000 --- a/tools/ci_build/github/azure-pipelines/rocm-publish-nuget-pipeline.yml +++ /dev/null @@ -1,21 +0,0 @@ -resources: - pipelines: - - pipeline: build - source: 'Nuget ROCM Packaging pipeline' - trigger: - branches: - include: - - main - - rel-* - branch: main - -# ROCm -stages: -- template: templates/publish-nuget-steps.yml - parameters: - stage_name: 'Publish_ROCM_NuGet_Package' - download_artifacts_steps: - - download: build - displayName: 'Download Pipeline Artifact - Signed NuGet Package' - artifact: 'drop-signed-nuget-ROCm' - - script: move "$(Pipeline.Workspace)\build\drop-signed-nuget-ROCm\*" $(Build.BinariesDirectory)\nuget-artifact\final-package From fe7634eb6f20b656a3df978a6a2ef9b3ea00c59d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Mar 2025 19:07:47 -0700 Subject: [PATCH 068/266] Bump SixLabors.ImageSharp from 2.1.9 to 2.1.10 in /csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample (#23924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) from 2.1.9 to 2.1.10.
Release notes

Sourced from SixLabors.ImageSharp's releases.

v2.1.10

What's Changed

Full Changelog: https://github.com/SixLabors/ImageSharp/compare/v2.1.9...v2.1.10

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=SixLabors.ImageSharp&package-manager=nuget&previous-version=2.1.9&new-version=2.1.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj b/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj index f00a08a1a3595..b1452a64934c2 100644 --- a/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj @@ -8,7 +8,7 @@ - + From 246c2191035d79f2e3c8bd123a1765d73b63c1af Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Mon, 10 Mar 2025 15:29:37 -0400 Subject: [PATCH 069/266] Make python CUDA package pipeline 1ES compliant (#23802) ### Description Make [Python-Cuda-Publishing-Pipeline](https://dev.azure.com/aiinfra/Lotus/_build?definitionId=1311&_a=summary) 1ES compliant ### Motivation and Context --- .../py-cuda-publishing-pipeline.yml | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/py-cuda-publishing-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-cuda-publishing-pipeline.yml index e4499705efdf5..230c391c00ebd 100644 --- a/tools/ci_build/github/azure-pipelines/py-cuda-publishing-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-cuda-publishing-pipeline.yml @@ -7,7 +7,11 @@ resources: include: - main branch: main - + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release parameters: - name: isReleaseBuild type: boolean @@ -20,7 +24,17 @@ variables: ${{ else }}: value: onnxruntime-cuda-12 -stages: -- template: stages/py-cuda-publishing-stage.yml +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: - artifact_feed: $(ArtifactFeed) \ No newline at end of file + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + stages: + - template: stages/py-cuda-publishing-stage.yml + parameters: + artifact_feed: $(ArtifactFeed) \ No newline at end of file From 773bb4ff58c14dc74be9e34cb8500224b14d4bc4 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Mon, 10 Mar 2025 16:50:56 -0400 Subject: [PATCH 070/266] Migrate yarn to npm (#22116) ### Description This PR change all reference to yarn to npm ### Motivation and Context This PR is needed to address all Component Governce issue that ORT is facing ### Current issue - [x] use_react_native!(:path => config["reactNativePath"]) return nil - [x] For error `CocoaPods could not find compatible versions for pod "RCTRequired"`, we might need to increase iOS targe version from 13.0 to a higher version. - [x] For 'react-native' >= 0.73.x , react-native/react.gradle file is no longer used - [x] We need to update to gradle 7.6 or above to upgrade the RN. current gradlew version 7.3.3 that we use does not works on RN 71+. - [x] Instruction on how to implement the React-Native has changed since [0.72](https://reactnative.dev/docs/integration-with-existing-apps). - [x] Error `The new Java toolchain feature cannot be used at the project level in combination with source and/or target compatibility` from gradle. - [x] duplicate class: com.facebook.react.PackageList solution: remove `apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)` from bottom of andoird/app/build.gradle - [x] Need to update the OnnxruntimeModuleTest because `ReactApplicationContext` is now a abstract class. --------- Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com> --- js/README.md | 12 +- js/react_native/README.md | 2 +- js/react_native/e2e/package-lock.json | 9408 +++++++++++++ js/react_native/package-lock.json | 11067 ++++++++++++++++ js/react_native/package.json | 10 +- js/react_native/scripts/bootstrap.js | 5 +- .../templates/react-native-ci.yml | 25 +- tools/python/update_version.py | 5 +- 8 files changed, 20505 insertions(+), 29 deletions(-) create mode 100644 js/react_native/e2e/package-lock.json create mode 100644 js/react_native/package-lock.json diff --git a/js/README.md b/js/README.md index 635f5faa54981..eb95c9224c081 100644 --- a/js/README.md +++ b/js/README.md @@ -361,7 +361,7 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published From `/js/react_native, ```sh - yarn bootstrap + npm run bootstrap ``` When testing with a custom built ONNX Runtime Android package, copy `/aar_out/MinSizeRel/com/microsoft/onnxruntime/onnxruntime-android//onnxruntime-android-.aar` into the `/js/react_native/e2e/android/app/libs` directory. @@ -377,7 +377,7 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published Install detox command line tools: ``` - yarn global add detox-cli + npm install -g detox-cli ``` Install applesimutils which is required by Detox to work with iOS simulators. (Requires a MacOS device) @@ -439,13 +439,13 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published To record logs for testing results, add `--record-logs`. Output logs and test results will be produced in the `e2e/artifacts/` folder. See: [Detox/logger#artifacts](https://wix.github.io/Detox/docs/api/logger#artifacts) - **_`yarn bootstrap` changes `packages.json` and `yarn.lock` files. Once testing is done, restore changes to avoid unwanted commit._** + **_`npm run bootstrap` changes `packages.json` and `package-lock.json` files. Once testing is done, restore changes to avoid unwanted commit._** 5. Run Android and iOS apps. ```sh - yarn e2e android - yarn e2e ios + npm run e2e:android + npm run e2e:ios ``` ### NPM Packaging @@ -460,4 +460,4 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published ### Distribution -It should be able to consumed by React Native projects that uses Yarn packages through `yarn add onnxruntime-react-native`. +It should be able to consumed by React Native projects that uses npm packages through `npm install onnxruntime-react-native`. diff --git a/js/react_native/README.md b/js/react_native/README.md index b45182d16a3fc..f7b118e81573d 100644 --- a/js/react_native/README.md +++ b/js/react_native/README.md @@ -13,7 +13,7 @@ With ONNX Runtime React Native, React Native developers can score pre-trained ON ### Installation ```sh -yarn add onnxruntime-react-native +npm install onnxruntime-react-native ``` ### Usage diff --git a/js/react_native/e2e/package-lock.json b/js/react_native/e2e/package-lock.json new file mode 100644 index 0000000000000..c7dad7a91f6f2 --- /dev/null +++ b/js/react_native/e2e/package-lock.json @@ -0,0 +1,9408 @@ +{ + "name": "onnxruntime-reactnative-example", + "version": "0.5.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "onnxruntime-reactnative-example", + "version": "0.5.0", + "dependencies": { + "react": "^18.1.0", + "react-native": "^0.75.3", + "react-native-fs": "^2.20.0" + }, + "devDependencies": { + "@babel/core": "^7.17.0", + "@babel/runtime": "^7.17.0", + "babel-plugin-module-resolver": "^4.0.0", + "detox": "^20.7.0", + "jest": "^29", + "metro-react-native-babel-preset": "^0.67.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.4", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-export-default-from": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz", + "integrity": "sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-assign": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-jsx": "^7.17.12", + "@babel/types": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.18.5", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/preset-env/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/@babel/preset-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", + "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-flow-strip-types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "license": "MIT" + }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.5.0", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.5.0", + "@jest/reporters": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-resolve-dependencies": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "jest-watcher": "^29.5.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.5.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@jridgewell/trace-mapping": "^0.3.15", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.15", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.5.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.5.0", + "@jridgewell/trace-mapping": "^0.3.15", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@react-native-community/cli": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-14.1.0.tgz", + "integrity": "sha512-k7aTdKNZIec7WMSqMJn9bDVLWPPOaYmshXcnjWy6t5ItsJnREju9p2azMTR5tXY5uIeynose3cxettbhk2Tbnw==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-clean": "14.1.0", + "@react-native-community/cli-config": "14.1.0", + "@react-native-community/cli-debugger-ui": "14.1.0", + "@react-native-community/cli-doctor": "14.1.0", + "@react-native-community/cli-server-api": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-types": "14.1.0", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "deepmerge": "^4.3.0", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.2", + "semver": "^7.5.2" + }, + "bin": { + "rnc-cli": "build/bin.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native-community/cli-clean": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-14.1.0.tgz", + "integrity": "sha512-/C4j1yntLo6faztNgZnsDtgpGqa6j0+GYrxOY8LqaKAN03OCnoeUUKO6w78dycbYSGglc1xjJg2RZI/M2oF2AA==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2" + } + }, + "node_modules/@react-native-community/cli-config": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-14.1.0.tgz", + "integrity": "sha512-P3FK2rPUJBD1fmQHLgTqpHxsc111pnMdEEFR7KeqprCNz+Qr2QpPxfNy0V7s15tGL5rAv+wpbOGcioIV50EbxA==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "cosmiconfig": "^9.0.0", + "deepmerge": "^4.3.0", + "fast-glob": "^3.3.2", + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli-debugger-ui": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.1.0.tgz", + "integrity": "sha512-+YbeCL0wLcBcqDwraJFGsqzcXu9S+bwTVrfImne/4mT6itfe3Oa93yrOVJgNbstrt5pJHuwpU76ZXfXoiuncsg==", + "license": "MIT", + "dependencies": { + "serve-static": "^1.13.1" + } + }, + "node_modules/@react-native-community/cli-doctor": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-14.1.0.tgz", + "integrity": "sha512-xIf0oQDRKt7lufUenRwcLYdINGc0x1FSXHaHjd7lQDGT5FJnCEYlIkYEDDgAl5tnVJSvM/IL2c6O+mffkNEPzQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-config": "14.1.0", + "@react-native-community/cli-platform-android": "14.1.0", + "@react-native-community/cli-platform-apple": "14.1.0", + "@react-native-community/cli-platform-ios": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "deepmerge": "^4.3.0", + "envinfo": "^7.13.0", + "execa": "^5.0.0", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-platform-android": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-14.1.0.tgz", + "integrity": "sha512-4JnXkAV+ca8XdUhZ7xjgDhXAMwTVjQs8JqiwP7FTYVrayShXy2cBXm/C3HNDoe+oQOF5tPT2SqsDAF2vYTnKiQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2", + "fast-xml-parser": "^4.4.1", + "logkitty": "^0.7.1" + } + }, + "node_modules/@react-native-community/cli-platform-apple": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.1.0.tgz", + "integrity": "sha512-DExd+pZ7hHxXt8I6BBmckeYUxxq7PQ+o4YSmGIeQx0xUpi+f82obBct2WNC3VWU72Jw6obwfoN6Fwe6F7Wxp5Q==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2", + "fast-xml-parser": "^4.4.1", + "ora": "^5.4.1" + } + }, + "node_modules/@react-native-community/cli-platform-ios": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.1.0.tgz", + "integrity": "sha512-ah/ZTiJXUdCVHujyRJ4OmCL5nTq8OWcURcE3UXa1z0sIIiA8io06n+v5n299T9rtPKMwRtVJlQjtO/nbODABPQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-platform-apple": "14.1.0" + } + }, + "node_modules/@react-native-community/cli-server-api": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-14.1.0.tgz", + "integrity": "sha512-1k2LBQaYsy9RDWFIfKVne3frOye73O33MV6eYMoRPff7wqxHCrsX1CYJQkmwpgVigZHxYwalHj+Axtu3gpomCA==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-debugger-ui": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^6.2.3" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native-community/cli-tools": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-14.1.0.tgz", + "integrity": "sha512-r1KxSu2+OSuhWFoE//1UR7aSTXMLww/UYWQprEw4bSo/kvutGX//4r9ywgXSWp+39udpNN4jQpNTHuWhGZd/Bg==", + "license": "MIT", + "dependencies": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-14.1.0.tgz", + "integrity": "sha512-aJwZI9mGRx3HdP8U4CGhqjt3S4r8GmeOqv4kRagC1UHDk4QNMC+bZ8JgPA4W7FrGiPey+lJQHMDPAXOo51SOUw==", + "license": "MIT", + "dependencies": { + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.75.3.tgz", + "integrity": "sha512-i7MaRbYR06WdpJWv3a0PQ2ScFBUeevwcJ0tVopnFwTg0tBWp3NFEMDIcU8lyXVy9Y59WmrP1V2ROaRDaPiESgg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.75.3.tgz", + "integrity": "sha512-8JmXEKq+Efb9AffsV48l8gmKe/ZQ2PbBygZjHdIf8DNZZhO/z5mt27J4B43MWNdp5Ww1l59T0mEaf8l/uywQUg==", + "license": "MIT", + "dependencies": { + "@react-native/codegen": "0.75.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.75.3.tgz", + "integrity": "sha512-VZQkQEj36DKEGApXFYdVcFtqdglbnoVr7aOZpjffURSgPcIA9vWTm1b+OL4ayOaRZXTZKiDBNQCXvBX5E5AgQg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.5", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.5", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.20.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "@react-native/babel-plugin-codegen": "0.75.3", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/babel-preset/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.75.3.tgz", + "integrity": "sha512-I0bz5jwOkiR7vnhYLGoV22RGmesErUg03tjsCiQgmsMpbyCYumudEtLNN5+DplHGK56bu8KyzBqKkWXGSKSCZQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.0", + "glob": "^7.1.1", + "hermes-parser": "0.22.0", + "invariant": "^2.2.4", + "jscodeshift": "^0.14.0", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.75.3.tgz", + "integrity": "sha512-njsYm+jBWzfLcJcxavAY5QFzYTrmPtjbxq/64GSqwcQYzy9qAkI7LNTK/Wprq1I/4HOuHJO7Km+EddCXB+ByRQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-server-api": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "@react-native/dev-middleware": "0.75.3", + "@react-native/metro-babel-transformer": "0.75.3", + "chalk": "^4.0.0", + "execa": "^5.1.1", + "metro": "^0.80.3", + "metro-config": "^0.80.3", + "metro-core": "^0.80.3", + "node-fetch": "^2.2.0", + "readline": "^1.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.75.3.tgz", + "integrity": "sha512-99bLQsUwsxUMNR7Wa9eV2uyR38yfd6mOEqfN+JIm8/L9sKA926oh+CZkjDy1M8RmCB6spB5N9fVFVkrVdf2yFA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.75.3.tgz", + "integrity": "sha512-h2/6+UGmeMWjnT43axy27jNqoDRsE1C1qpjRC3sYpD4g0bI0jSTkY1kAgj8uqGGXLnHXiHOtjLDGdbAgZrsPaA==", + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.75.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.13.1", + "ws": "^6.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.75.3.tgz", + "integrity": "sha512-mSfa/Mq/AsALuG/kvXz5ECrc6HdY5waMHal2sSfa8KA0Gt3JqYQVXF9Pdwd4yR5ClPZDI2HRa1tdE8GVlhMvPA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.75.3.tgz", + "integrity": "sha512-+JVFJ351GSJT3V7LuXscMqfnpR/UxzsAjbBjfAHBR3kqTbVqrAmBccqPCA3NLzgb/RY8khLJklwMUVlWrn8iFg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.75.3.tgz", + "integrity": "sha512-gDlEl6C2mwQPLxFOR+yla5MpJpDPNOFD6J5Hd9JM9+lOdUq6MNujh1Xn4ZMvglW7rfViq3nMjg4xPQeGUhDG+w==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.75.3", + "hermes-parser": "0.22.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.75.3.tgz", + "integrity": "sha512-3mhF8AJFfIN0E5bEs/DQ4U2LzMJYm+FPSwY5bJ1DZhrxW1PFAh24bAPrSd8PwS0iarQ7biLdr1lWf/8LFv8pDA==", + "license": "MIT" + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.75.3.tgz", + "integrity": "sha512-cTLm7k7Y//SvV8UK8esrDHEw5OrwwSJ4Fqc3x52Imi6ROuhshfGIPFwhtn4pmAg9nWHzHwwqiJ+9hCSVnXXX+g==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "2.0.0", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.0.2", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^2.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.18.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "18.0.0", + "license": "MIT" + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "license": "MIT" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "license": "MIT", + "dependencies": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-fragments/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "license": "MIT", + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-module-resolver": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base-64": { + "version": "0.1.0" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/bunyan": { + "version": "1.8.15", + "dev": true, + "engines": [ + "node >=0.10.0" + ], + "license": "MIT", + "bin": { + "bunyan": "bin/bunyan" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/bunyan-debug-stream": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "bunyan": "*" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/caf": { + "version": "15.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "license": "MIT", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "license": "MIT", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/child-process-promise": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^4.0.2", + "node-version": "^1.0.0", + "promise-polyfill": "^6.0.1" + } + }, + "node_modules/child-process-promise/node_modules/cross-spawn": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/child-process-promise/node_modules/lru-cache": { + "version": "4.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/child-process-promise/node_modules/yallist": { + "version": "2.1.2", + "dev": true, + "license": "ISC" + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", + "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.3.2", + "license": "MIT" + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "license": "MIT" + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detox": { + "version": "20.7.0", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.6.3", + "bunyan": "^1.8.12", + "bunyan-debug-stream": "^3.1.0", + "caf": "^15.0.1", + "chalk": "^4.0.0", + "child-process-promise": "^2.2.0", + "execa": "^5.1.1", + "find-up": "^4.1.0", + "fs-extra": "^4.0.2", + "funpermaproxy": "^1.1.0", + "glob": "^8.0.3", + "ini": "^1.3.4", + "json-cycle": "^1.3.0", + "lodash": "^4.17.11", + "multi-sort-stream": "^1.0.3", + "multipipe": "^4.0.0", + "node-ipc": "^9.2.1", + "proper-lockfile": "^3.0.2", + "resolve-from": "^5.0.0", + "sanitize-filename": "^1.6.1", + "semver": "^7.0.0", + "serialize-error": "^8.0.1", + "shell-quote": "^1.7.2", + "signal-exit": "^3.0.3", + "stream-json": "^1.7.4", + "strip-ansi": "^6.0.1", + "telnet-client": "1.2.8", + "tempfile": "^2.0.0", + "trace-event-lib": "^1.3.1", + "which": "^1.3.1", + "ws": "^7.0.0", + "yargs": "^16.0.3", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "detox": "local-cli/cli.js" + }, + "engines": { + "node": ">=14.5.0" + }, + "peerDependencies": { + "jest": "29.x.x || 28.x.x || ^27.2.5" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, + "node_modules/detox/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/detox/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/detox/node_modules/fs-extra": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/detox/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/detox/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/detox/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/detox/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/diff-sequences": { + "version": "29.4.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dtrace-provider": { + "version": "0.8.8", + "dev": true, + "hasInstallScript": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "nan": "^2.14.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/easy-stack": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", + "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-pubsub": { + "version": "4.3.0", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "license": "Apache-2.0" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", + "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-babel-config": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.2.tgz", + "integrity": "sha512-oK59njMyw2y3yxto1BCfVK7MQp/OYf4FleHu0RgosH3riFJ1aOuo/7naLDLAObfrgn3ueFhw5sAT/cp0QuJI3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^1.0.2", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-babel-config/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up/node_modules/path-exists": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT" + }, + "node_modules/flow-parser": { + "version": "0.246.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.246.0.tgz", + "integrity": "sha512-WHRizzSrWFTcKo7cVcbP3wzZVhzsoYxoWqbnH4z+JXGqrjVmnsld6kBZWVlB200PwD5ur8r+HV3KUDxv3cHhOQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/funpermaproxy": { + "version": "1.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "license": "ISC" + }, + "node_modules/has": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-estree": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.22.0.tgz", + "integrity": "sha512-FLBt5X9OfA8BERUdc6aZS36Xz3rRuB0Y/mfocSADWEJfomc1xfene33GdyAmtTkKTBXTN/EgAy+rjTKkkZJHlw==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.22.0.tgz", + "integrity": "sha512-gn5RfZiEXCsIWsFGsKiykekktUoh0PdFWYocXsUdZIyWSckT6UIyPcyyUIPSR3kpnELWeK3n3ztAse7Mat6PSA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.22.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "dev": true, + "license": "ISC" + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", + "import-local": "^3.0.2", + "jest-cli": "^29.5.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.5.0", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.5.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/jest-config/node_modules/babel-jest": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.5.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.5.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/jest-config/node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/jest-config/node_modules/babel-preset-jest": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.5.0", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/jest-diff": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.5.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.4.3", + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.5.0", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.4.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/is-core-module": { + "version": "2.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jest-resolve/node_modules/resolve": { + "version": "1.22.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jest-runner": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.5.0", + "@jest/environment": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-leak-detector": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-resolve": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-util": "^29.5.0", + "jest-watcher": "^29.5.0", + "jest-worker": "^29.5.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/globals": "^29.5.0", + "@jest/source-map": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/babel__traverse": "^7.0.6", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.5.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.5.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/jest-snapshot/node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher": { + "version": "29.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.5.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-message": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/js-queue": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "easy-stack": "^1.0.1" + }, + "engines": { + "node": ">=1.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "license": "BSD-2-Clause" + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD" + }, + "node_modules/jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-cycle": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "license": "MIT", + "dependencies": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "bin": { + "logkitty": "bin/logkitty.js" + } + }, + "node_modules/logkitty/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/logkitty/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/logkitty/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/logkitty/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "license": "Apache-2.0" + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "license": "MIT" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/metro": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.12.tgz", + "integrity": "sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.23.1", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-config": "0.80.12", + "metro-core": "0.80.12", + "metro-file-map": "0.80.12", + "metro-resolver": "0.80.12", + "metro-runtime": "0.80.12", + "metro-source-map": "0.80.12", + "metro-symbolicate": "0.80.12", + "metro-transform-plugins": "0.80.12", + "metro-transform-worker": "0.80.12", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz", + "integrity": "sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.23.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT" + }, + "node_modules/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro-cache": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.12.tgz", + "integrity": "sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA==", + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "metro-core": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-cache-key": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.12.tgz", + "integrity": "sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.12.tgz", + "integrity": "sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ==", + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.6.3", + "metro": "0.80.12", + "metro-cache": "0.80.12", + "metro-core": "0.80.12", + "metro-runtime": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config/node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "license": "MIT", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-core": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.12.tgz", + "integrity": "sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-file-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.12.tgz", + "integrity": "sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz", + "integrity": "sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-react-native-babel-preset": { + "version": "0.67.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.14.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/metro-resolver": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.12.tgz", + "integrity": "sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-runtime": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.12.tgz", + "integrity": "sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.12.tgz", + "integrity": "sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.80.12", + "nullthrows": "^1.1.1", + "ob1": "0.80.12", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz", + "integrity": "sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.80.12", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz", + "integrity": "sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz", + "integrity": "sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "metro": "0.80.12", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-minify-terser": "0.80.12", + "metro-source-map": "0.80.12", + "metro-transform-plugins": "0.80.12", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro/node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multi-sort-stream": { + "version": "1.0.4", + "dev": true, + "license": "bsd" + }, + "node_modules/multipipe": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "^0.1.2", + "object-assign": "^4.1.0" + } + }, + "node_modules/mv": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/mv/node_modules/glob": { + "version": "6.0.4", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mv/node_modules/rimraf": { + "version": "2.4.5", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^6.0.1" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/nan": { + "version": "2.17.0", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ncp": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/node-ipc": { + "version": "9.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "event-pubsub": "4.3.0", + "js-message": "1.0.7", + "js-queue": "2.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } + }, + "node_modules/node-version": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT" + }, + "node_modules/ob1": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.12.tgz", + "integrity": "sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "license": "MIT", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/open/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/promise": { + "version": "8.3.0", + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-polyfill": { + "version": "6.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proper-lockfile": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/punycode": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.1", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "18.2.0", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.1.tgz", + "integrity": "sha512-7FSb9meX0btdBQLwdFOwt6bGqvRPabmVMMslv8fgoSPqXyuGpgQe36kx8gR86XPw7aV1yVouTp6fyZ0EH+NfUw==", + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "license": "MIT" + }, + "node_modules/react-native": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.75.3.tgz", + "integrity": "sha512-+Ne6u5H+tPo36sme19SCd1u2UID2uo0J/XzAJarxmrDj4Nsdi44eyUDKtQHmhgxjRGsuVJqAYrMK0abLSq8AHw==", + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "14.1.0", + "@react-native-community/cli-platform-android": "14.1.0", + "@react-native-community/cli-platform-ios": "14.1.0", + "@react-native/assets-registry": "0.75.3", + "@react-native/codegen": "0.75.3", + "@react-native/community-cli-plugin": "0.75.3", + "@react-native/gradle-plugin": "0.75.3", + "@react-native/js-polyfills": "0.75.3", + "@react-native/normalize-colors": "0.75.3", + "@react-native/virtualized-lists": "0.75.3", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "commander": "^9.4.1", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^5.3.1", + "react-refresh": "^0.14.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "semver": "^7.1.3", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "^18.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native-fs": { + "version": "2.20.0", + "license": "MIT", + "dependencies": { + "base-64": "^0.1.0", + "utf8": "^3.0.0" + }, + "peerDependencies": { + "react-native": "*", + "react-native-windows": "*" + }, + "peerDependenciesMeta": { + "react-native-windows": { + "optional": true + } + } + }, + "node_modules/react-native/node_modules/@jest/types": { + "version": "26.6.2", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/react-native/node_modules/@types/yargs": { + "version": "15.0.14", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/pretty-format": { + "version": "26.6.2", + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/react-native/node_modules/react-is": { + "version": "17.0.2", + "license": "MIT" + }, + "node_modules/react-native/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-native/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.4.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "license": "BSD" + }, + "node_modules/recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "license": "MIT", + "dependencies": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "license": "MIT", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/reselect": { + "version": "4.1.6", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.0", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.7.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "license": "MIT" + }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/telnet-client": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.4" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "license": "MIT", + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempfile": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser": { + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", + "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "license": "BSD-3-Clause" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex-range/node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trace-event-lib": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^1.0.0", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "dev": true, + "license": "WTFPL" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/js/react_native/package-lock.json b/js/react_native/package-lock.json new file mode 100644 index 0000000000000..4b31128c92fd7 --- /dev/null +++ b/js/react_native/package-lock.json @@ -0,0 +1,11067 @@ +{ + "name": "onnxruntime-react-native", + "version": "1.20.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "onnxruntime-react-native", + "version": "1.20.0", + "license": "MIT", + "dependencies": { + "@expo/config-plugins": "^7.2.4", + "buffer": "^6.0.3", + "onnxruntime-common": "file:../common" + }, + "devDependencies": { + "@types/jest": "^27.4.0", + "@types/react": "^18.0.9", + "@types/react-native": "^0.67.7", + "jest": "^27.4.7", + "pod-install": "^0.1.36", + "prettier": "^2.6.2", + "react": "^18.1.0", + "react-native": "^0.75.3", + "react-native-builder-bob": "^0.18.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "../common": { + "name": "onnxruntime-common", + "version": "1.20.0", + "license": "MIT", + "devDependencies": { + "typedoc": "^0.25.7" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.4", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.24.7.tgz", + "integrity": "sha512-CcmFwUJ3tKhLjPdt4NP+SHMshebytF8ZTYOv5ZDpkzq2sin80Wb5vJrGt8fhPrORQCfoSa0LAxC/DW+GAC5+Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-default-from": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.24.7.tgz", + "integrity": "sha512-bTPz4/635WQ9WhwsyPdxUJDVpsi/X9BMmy/8Rf/UAlOO4jSql4CxUCjWI5PiM+jG+c4LVPTScoTw80geFj9+Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz", + "integrity": "sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.18.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.18.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-simple-access": "^7.18.2", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-jsx": "^7.17.12", + "@babel/types": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.4.tgz", + "integrity": "sha512-8hsyG+KUYGY0coX6KUCDancA0Vw225KJ2HJO0yCNr1vq5r+lJTleDaJf0K7iOhjw4SWhu03TMBzYTJ9krmzULQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.18.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-typescript": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.18.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.17.12", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.17.12", + "@babel/plugin-proposal-async-generator-functions": "^7.17.12", + "@babel/plugin-proposal-class-properties": "^7.17.12", + "@babel/plugin-proposal-class-static-block": "^7.18.0", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.17.12", + "@babel/plugin-proposal-json-strings": "^7.17.12", + "@babel/plugin-proposal-logical-assignment-operators": "^7.17.12", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.18.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.17.12", + "@babel/plugin-proposal-private-methods": "^7.17.12", + "@babel/plugin-proposal-private-property-in-object": "^7.17.12", + "@babel/plugin-proposal-unicode-property-regex": "^7.17.12", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.17.12", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.17.12", + "@babel/plugin-transform-async-to-generator": "^7.17.12", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.17.12", + "@babel/plugin-transform-classes": "^7.17.12", + "@babel/plugin-transform-computed-properties": "^7.17.12", + "@babel/plugin-transform-destructuring": "^7.18.0", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.17.12", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.18.1", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.17.12", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.18.0", + "@babel/plugin-transform-modules-commonjs": "^7.18.2", + "@babel/plugin-transform-modules-systemjs": "^7.18.0", + "@babel/plugin-transform-modules-umd": "^7.18.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.12", + "@babel/plugin-transform-new-target": "^7.17.12", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.17.12", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.18.0", + "@babel/plugin-transform-reserved-words": "^7.17.12", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.17.12", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.18.2", + "@babel/plugin-transform-typeof-symbol": "^7.17.12", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.2", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-flow-strip-types": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-react-display-name": "^7.16.7", + "@babel/plugin-transform-react-jsx": "^7.17.12", + "@babel/plugin-transform-react-jsx-development": "^7.16.7", + "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.17.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@expo/config-plugins": { + "version": "7.2.5", + "license": "MIT", + "dependencies": { + "@expo/config-types": "^49.0.0-alpha.1", + "@expo/json-file": "~8.2.37", + "@expo/plist": "^0.0.20", + "@expo/sdk-runtime-versions": "^1.0.0", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.5.3", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "0.6.0" + } + }, + "node_modules/@expo/config-plugins/node_modules/@react-native/normalize-color": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/@expo/config-plugins/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@expo/config-plugins/node_modules/find-up": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/glob": { + "version": "7.1.6", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/config-plugins/node_modules/locate-path": { + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@expo/config-plugins/node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/p-locate": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/config-types": { + "version": "49.0.0", + "license": "MIT" + }, + "node_modules/@expo/json-file": { + "version": "8.2.37", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^2.2.2", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/json-file/node_modules/@babel/code-frame": { + "version": "7.10.4", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/plist": { + "version": "0.0.20", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "~0.7.7", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + } + }, + "node_modules/@expo/sdk-runtime-versions": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/create-cache-key-function/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/create-cache-key-function/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "3.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@react-native-community/cli": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-14.1.0.tgz", + "integrity": "sha512-k7aTdKNZIec7WMSqMJn9bDVLWPPOaYmshXcnjWy6t5ItsJnREju9p2azMTR5tXY5uIeynose3cxettbhk2Tbnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-clean": "14.1.0", + "@react-native-community/cli-config": "14.1.0", + "@react-native-community/cli-debugger-ui": "14.1.0", + "@react-native-community/cli-doctor": "14.1.0", + "@react-native-community/cli-server-api": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-types": "14.1.0", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "deepmerge": "^4.3.0", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.2", + "semver": "^7.5.2" + }, + "bin": { + "rnc-cli": "build/bin.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native-community/cli-clean": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-14.1.0.tgz", + "integrity": "sha512-/C4j1yntLo6faztNgZnsDtgpGqa6j0+GYrxOY8LqaKAN03OCnoeUUKO6w78dycbYSGglc1xjJg2RZI/M2oF2AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2" + } + }, + "node_modules/@react-native-community/cli-config": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-14.1.0.tgz", + "integrity": "sha512-P3FK2rPUJBD1fmQHLgTqpHxsc111pnMdEEFR7KeqprCNz+Qr2QpPxfNy0V7s15tGL5rAv+wpbOGcioIV50EbxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "cosmiconfig": "^9.0.0", + "deepmerge": "^4.3.0", + "fast-glob": "^3.3.2", + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli-debugger-ui": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.1.0.tgz", + "integrity": "sha512-+YbeCL0wLcBcqDwraJFGsqzcXu9S+bwTVrfImne/4mT6itfe3Oa93yrOVJgNbstrt5pJHuwpU76ZXfXoiuncsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "serve-static": "^1.13.1" + } + }, + "node_modules/@react-native-community/cli-doctor": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-14.1.0.tgz", + "integrity": "sha512-xIf0oQDRKt7lufUenRwcLYdINGc0x1FSXHaHjd7lQDGT5FJnCEYlIkYEDDgAl5tnVJSvM/IL2c6O+mffkNEPzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-config": "14.1.0", + "@react-native-community/cli-platform-android": "14.1.0", + "@react-native-community/cli-platform-apple": "14.1.0", + "@react-native-community/cli-platform-ios": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "deepmerge": "^4.3.0", + "envinfo": "^7.13.0", + "execa": "^5.0.0", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@react-native-community/cli-platform-android": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-14.1.0.tgz", + "integrity": "sha512-4JnXkAV+ca8XdUhZ7xjgDhXAMwTVjQs8JqiwP7FTYVrayShXy2cBXm/C3HNDoe+oQOF5tPT2SqsDAF2vYTnKiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2", + "fast-xml-parser": "^4.4.1", + "logkitty": "^0.7.1" + } + }, + "node_modules/@react-native-community/cli-platform-apple": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.1.0.tgz", + "integrity": "sha512-DExd+pZ7hHxXt8I6BBmckeYUxxq7PQ+o4YSmGIeQx0xUpi+f82obBct2WNC3VWU72Jw6obwfoN6Fwe6F7Wxp5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "14.1.0", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2", + "fast-xml-parser": "^4.4.1", + "ora": "^5.4.1" + } + }, + "node_modules/@react-native-community/cli-platform-ios": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.1.0.tgz", + "integrity": "sha512-ah/ZTiJXUdCVHujyRJ4OmCL5nTq8OWcURcE3UXa1z0sIIiA8io06n+v5n299T9rtPKMwRtVJlQjtO/nbODABPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-platform-apple": "14.1.0" + } + }, + "node_modules/@react-native-community/cli-server-api": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-14.1.0.tgz", + "integrity": "sha512-1k2LBQaYsy9RDWFIfKVne3frOye73O33MV6eYMoRPff7wqxHCrsX1CYJQkmwpgVigZHxYwalHj+Axtu3gpomCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-debugger-ui": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^6.2.3" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native-community/cli-tools": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-14.1.0.tgz", + "integrity": "sha512-r1KxSu2+OSuhWFoE//1UR7aSTXMLww/UYWQprEw4bSo/kvutGX//4r9ywgXSWp+39udpNN4jQpNTHuWhGZd/Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-14.1.0.tgz", + "integrity": "sha512-aJwZI9mGRx3HdP8U4CGhqjt3S4r8GmeOqv4kRagC1UHDk4QNMC+bZ8JgPA4W7FrGiPey+lJQHMDPAXOo51SOUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.75.3.tgz", + "integrity": "sha512-i7MaRbYR06WdpJWv3a0PQ2ScFBUeevwcJ0tVopnFwTg0tBWp3NFEMDIcU8lyXVy9Y59WmrP1V2ROaRDaPiESgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.75.3.tgz", + "integrity": "sha512-8JmXEKq+Efb9AffsV48l8gmKe/ZQ2PbBygZjHdIf8DNZZhO/z5mt27J4B43MWNdp5Ww1l59T0mEaf8l/uywQUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native/codegen": "0.75.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.75.3.tgz", + "integrity": "sha512-VZQkQEj36DKEGApXFYdVcFtqdglbnoVr7aOZpjffURSgPcIA9vWTm1b+OL4ayOaRZXTZKiDBNQCXvBX5E5AgQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.5", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.5", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.20.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "@react-native/babel-plugin-codegen": "0.75.3", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.75.3.tgz", + "integrity": "sha512-I0bz5jwOkiR7vnhYLGoV22RGmesErUg03tjsCiQgmsMpbyCYumudEtLNN5+DplHGK56bu8KyzBqKkWXGSKSCZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.0", + "glob": "^7.1.1", + "hermes-parser": "0.22.0", + "invariant": "^2.2.4", + "jscodeshift": "^0.14.0", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.75.3.tgz", + "integrity": "sha512-njsYm+jBWzfLcJcxavAY5QFzYTrmPtjbxq/64GSqwcQYzy9qAkI7LNTK/Wprq1I/4HOuHJO7Km+EddCXB+ByRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native-community/cli-server-api": "14.1.0", + "@react-native-community/cli-tools": "14.1.0", + "@react-native/dev-middleware": "0.75.3", + "@react-native/metro-babel-transformer": "0.75.3", + "chalk": "^4.0.0", + "execa": "^5.1.1", + "metro": "^0.80.3", + "metro-config": "^0.80.3", + "metro-core": "^0.80.3", + "node-fetch": "^2.2.0", + "readline": "^1.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.75.3.tgz", + "integrity": "sha512-99bLQsUwsxUMNR7Wa9eV2uyR38yfd6mOEqfN+JIm8/L9sKA926oh+CZkjDy1M8RmCB6spB5N9fVFVkrVdf2yFA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.75.3.tgz", + "integrity": "sha512-h2/6+UGmeMWjnT43axy27jNqoDRsE1C1qpjRC3sYpD4g0bI0jSTkY1kAgj8uqGGXLnHXiHOtjLDGdbAgZrsPaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.75.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.13.1", + "ws": "^6.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.75.3.tgz", + "integrity": "sha512-mSfa/Mq/AsALuG/kvXz5ECrc6HdY5waMHal2sSfa8KA0Gt3JqYQVXF9Pdwd4yR5ClPZDI2HRa1tdE8GVlhMvPA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.75.3.tgz", + "integrity": "sha512-+JVFJ351GSJT3V7LuXscMqfnpR/UxzsAjbBjfAHBR3kqTbVqrAmBccqPCA3NLzgb/RY8khLJklwMUVlWrn8iFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.75.3.tgz", + "integrity": "sha512-gDlEl6C2mwQPLxFOR+yla5MpJpDPNOFD6J5Hd9JM9+lOdUq6MNujh1Xn4ZMvglW7rfViq3nMjg4xPQeGUhDG+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.75.3", + "hermes-parser": "0.22.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.75.3.tgz", + "integrity": "sha512-3mhF8AJFfIN0E5bEs/DQ4U2LzMJYm+FPSwY5bJ1DZhrxW1PFAh24bAPrSd8PwS0iarQ7biLdr1lWf/8LFv8pDA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.75.3.tgz", + "integrity": "sha512-cTLm7k7Y//SvV8UK8esrDHEw5OrwwSJ4Fqc3x52Imi6ROuhshfGIPFwhtn4pmAg9nWHzHwwqiJ+9hCSVnXXX+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/babel__core": { + "version": "7.1.19", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "node_modules/@types/node": { + "version": "17.0.35", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prettier": { + "version": "2.6.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.7.tgz", + "integrity": "sha512-KUnDCJF5+AiZd8owLIeVHqmW9yM4sqmDVf2JRJiBMFkGvkoZ4/WyV2lL4zVsoinmRS/W3FeEdZLEWFRofnT2FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-native": { + "version": "0.67.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "16.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.7.11", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-fragments/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.51", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", + "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/dedent": { + "version": "0.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", + "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.8.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", + "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.13.0", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/flow-parser": { + "version": "0.246.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.246.0.tgz", + "integrity": "sha512-WHRizzSrWFTcKo7cVcbP3wzZVhzsoYxoWqbnH4z+JXGqrjVmnsld6kBZWVlB200PwD5ur8r+HV3KUDxv3cHhOQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-extra/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getenv": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "license": "ISC" + }, + "node_modules/has": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hermes-estree": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.22.0.tgz", + "integrity": "sha512-FLBt5X9OfA8BERUdc6aZS36Xz3rRuB0Y/mfocSADWEJfomc1xfene33GdyAmtTkKTBXTN/EgAy+rjTKkkZJHlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.22.0.tgz", + "integrity": "sha512-gn5RfZiEXCsIWsFGsKiykekktUoh0PdFWYocXsUdZIyWSckT6UIyPcyyUIPSR3kpnELWeK3n3ztAse7Mat6PSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.22.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "1.1.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-git-dirty": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^4.0.3", + "is-git-repository": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-git-dirty/node_modules/execa": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/is-git-dirty/node_modules/get-stream": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-git-repository": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^4.0.3", + "is-absolute": "^1.0.0" + } + }, + "node_modules/is-git-repository/node_modules/execa": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/is-git-repository/node_modules/get-stream": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-relative": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jetifier": { + "version": "1.6.8", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "jetifier": "bin/jetify", + "jetifier-standalone": "bin/jetifier-standalone", + "jetify": "bin/jetify" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "dev": true, + "license": "0BSD" + }, + "node_modules/jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "bin": { + "logkitty": "bin/logkitty.js" + } + }, + "node_modules/logkitty/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/logkitty/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/logkitty/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/metro": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.12.tgz", + "integrity": "sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.23.1", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-config": "0.80.12", + "metro-core": "0.80.12", + "metro-file-map": "0.80.12", + "metro-resolver": "0.80.12", + "metro-runtime": "0.80.12", + "metro-source-map": "0.80.12", + "metro-symbolicate": "0.80.12", + "metro-transform-plugins": "0.80.12", + "metro-transform-worker": "0.80.12", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz", + "integrity": "sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.23.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "dev": true, + "license": "MIT" + }, + "node_modules/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro-cache": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.12.tgz", + "integrity": "sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "metro-core": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-cache-key": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.12.tgz", + "integrity": "sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.12.tgz", + "integrity": "sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.6.3", + "metro": "0.80.12", + "metro-cache": "0.80.12", + "metro-core": "0.80.12", + "metro-runtime": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-config/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/metro-config/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/metro-config/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/metro-config/node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-config/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-config/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-config/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/metro-config/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-core": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.12.tgz", + "integrity": "sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-file-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.12.tgz", + "integrity": "sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/metro-file-map/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-file-map/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/metro-file-map/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-file-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-file-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz", + "integrity": "sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-resolver": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.12.tgz", + "integrity": "sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-runtime": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.12.tgz", + "integrity": "sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.12.tgz", + "integrity": "sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.80.12", + "nullthrows": "^1.1.1", + "ob1": "0.80.12", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz", + "integrity": "sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.80.12", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz", + "integrity": "sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz", + "integrity": "sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "metro": "0.80.12", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-minify-terser": "0.80.12", + "metro-source-map": "0.80.12", + "metro-transform-plugins": "0.80.12", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "dev": true, + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro/node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/metro/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro/node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "1.2.6", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nwsapi": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ob1": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.12.tgz", + "integrity": "sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onnxruntime-common": { + "resolved": "../common", + "link": true + }, + "node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/open/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pod-install": { + "version": "0.1.36", + "dev": true, + "license": "MIT", + "bin": { + "pod-install": "build/index.js" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.6.2", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/psl": { + "version": "1.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.1.tgz", + "integrity": "sha512-7FSb9meX0btdBQLwdFOwt6bGqvRPabmVMMslv8fgoSPqXyuGpgQe36kx8gR86XPw7aV1yVouTp6fyZ0EH+NfUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/react-native": { + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.75.3.tgz", + "integrity": "sha512-+Ne6u5H+tPo36sme19SCd1u2UID2uo0J/XzAJarxmrDj4Nsdi44eyUDKtQHmhgxjRGsuVJqAYrMK0abLSq8AHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "14.1.0", + "@react-native-community/cli-platform-android": "14.1.0", + "@react-native-community/cli-platform-ios": "14.1.0", + "@react-native/assets-registry": "0.75.3", + "@react-native/codegen": "0.75.3", + "@react-native/community-cli-plugin": "0.75.3", + "@react-native/gradle-plugin": "0.75.3", + "@react-native/js-polyfills": "0.75.3", + "@react-native/normalize-colors": "0.75.3", + "@react-native/virtualized-lists": "0.75.3", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "commander": "^9.4.1", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^5.3.1", + "react-refresh": "^0.14.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "semver": "^7.1.3", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "^18.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native-builder-bob": { + "version": "0.18.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-flow": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "browserslist": "^4.16.0", + "chalk": "^4.1.0", + "cosmiconfig": "^7.0.0", + "cross-spawn": "^7.0.3", + "dedent": "^0.7.0", + "del": "^6.0.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "is-git-dirty": "^2.0.1", + "json5": "^2.1.3", + "prompts": "^2.4.0", + "which": "^2.0.2", + "yargs": "^16.2.0" + }, + "bin": { + "bob": "bin/bob" + }, + "engines": { + "node": ">= 10.0.0" + }, + "optionalDependencies": { + "jetifier": "^1.6.6" + } + }, + "node_modules/react-native-builder-bob/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/react-native-builder-bob/node_modules/cosmiconfig": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native-builder-bob/node_modules/fs-extra": { + "version": "9.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native-builder-bob/node_modules/jsonfile": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/react-native-builder-bob/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native-builder-bob/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/@jest/environment/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/@jest/environment/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/@jest/fake-timers/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/@jest/fake-timers/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/@jest/types": { + "version": "26.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/react-native/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/react-native/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/react-native/node_modules/@types/yargs": { + "version": "15.0.14", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-environment-node/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-message-util/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-message-util/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/react-native/node_modules/jest-message-util/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-message-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-native/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-mock/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-mock/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-util/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-util/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/pretty-format": { + "version": "26.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/react-native/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "dev": true, + "license": "BSD" + }, + "node_modules/recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.8.4", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.2.4", + "license": "ISC" + }, + "node_modules/saxes": { + "version": "5.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/plist": { + "version": "3.0.6", + "license": "MIT", + "dependencies": { + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/simple-plist/node_modules/xmlbuilder": { + "version": "15.1.1", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/string-length": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "dev": true, + "license": "MIT" + }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", + "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/throat": { + "version": "6.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex-range/node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.7.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "7.0.3", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.3", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/word-wrap": { + "version": "1.2.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/xml2js": { + "version": "0.6.0", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "14.0.0", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/js/react_native/package.json b/js/react_native/package.json index 3a8004a716646..253f7e24cf7ed 100644 --- a/js/react_native/package.json +++ b/js/react_native/package.json @@ -65,15 +65,15 @@ }, "scripts": { "typescript": "tsc --noEmit", - "bootstrap": "yarn pack-common && yarn unpack-common && yarn pack-libs && yarn unpack-libs && yarn e2e && yarn pods", + "bootstrap": "npm run pack-common && npm run unpack-common && npm run pack-libs && npm run unpack-libs && npm run e2e && npm run pods", "test": "jest", "pack-common": "cd ../common && npm pack && mv -f onnxruntime-common-*.tgz ../react_native/e2e/onnxruntime-common.tgz", - "unpack-common": "cd e2e && yarn add --no-lockfile file:./onnxruntime-common.tgz", + "unpack-common": "cd e2e && npm install --no-save ./onnxruntime-common.tgz", "pack-libs": "npm pack --ort-js-pack-mode=e2e && mv -f onnxruntime-react-native-*.tgz e2e/onnxruntime-react-native.tgz", - "unpack-libs": "cd e2e && yarn add --no-lockfile file:./onnxruntime-react-native.tgz", + "unpack-libs": "cd e2e && npm install --no-save ./onnxruntime-react-native.tgz", "prepack": "tsc --build ./tsconfig.scripts.json && node ./scripts/prepack", - "pods": "cd e2e && pod-install --quiet", - "e2e": "yarn --cwd e2e" + "pods": "cd e2e && npx pod-install --quiet", + "e2e": "npm --prefix e2e install" }, "types": "dist/typescript/index.d.ts", "name": "onnxruntime-react-native", diff --git a/js/react_native/scripts/bootstrap.js b/js/react_native/scripts/bootstrap.js index 34650de57d4c6..11b00c3c5bee4 100644 --- a/js/react_native/scripts/bootstrap.js +++ b/js/react_native/scripts/bootstrap.js @@ -17,10 +17,7 @@ let result; if (process.cwd() !== root || args.length) { // We're not in the root of the project, or additional arguments were passed // In this case, forward the command to `yarn` - result = child_process.spawnSync('yarn', args, options); -} else { - // If `yarn` is run without arguments, perform bootstrap - result = child_process.spawnSync('yarn', ['bootstrap'], options); + result = child_process.spawnSync('npm', args, options); } process.exitCode = result.status; diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index 52dbb76632e0c..58ebdd52998ea 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -118,11 +118,11 @@ stages: inputs: versionSpec: '20.x' - script: - brew install coreutils ninja npm yarn - displayName: Install coreutils, ninja, npm, and yarn + brew install coreutils ninja npm + displayName: Install coreutils, ninja, npm - script: - yarn global add detox-cli + npm install -g detox-cli displayName: Install detox cli tools - script: @@ -144,9 +144,9 @@ stages: displayName: npm ci js/common - script: | - yarn + npm install workingDirectory: '$(Build.SourcesDirectory)/js/react_native' - displayName: yarn js/react_native + displayName: npm install js/react_native - task: PowerShell@2 inputs: @@ -159,17 +159,22 @@ stages: displayName: Pack NPM packages - script: | - set -x -e + set -e -x + npm install + ls node_modules mv $(Build.SourcesDirectory)/js/common/onnxruntime-common*.tgz onnxruntime-common.tgz - yarn add --no-lockfile file:./onnxruntime-common.tgz mv $(Build.SourcesDirectory)/js/react_native/onnxruntime-react-native*.tgz onnxruntime-react-native.tgz - yarn add --no-lockfile file:./onnxruntime-react-native.tgz - yarn + npm install ./onnxruntime-common.tgz + ls node_modules/onnxruntime* + npm install ./onnxruntime-react-native.tgz + ls node_modules/onnxruntime* + + workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' displayName: Bootstrap Android and iOS e2e tests - script: | - yarn add --dev jest-junit + npm install --save-dev jest-junit workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' displayName: install jest junit reporter js/react_native/e2e diff --git a/tools/python/update_version.py b/tools/python/update_version.py index f6e7acb646b69..b7d2186024ff1 100755 --- a/tools/python/update_version.py +++ b/tools/python/update_version.py @@ -90,10 +90,9 @@ def run(args, cwd): args = ["cmd", "/c", *args] run(*args, cwd=cwd) - # check if node, npm and yarn are installed + # check if node and npm are installed run(["node", "--version"], cwd=js_root) run(["npm", "--version"], cwd=js_root) - run(["yarn", "--version"], cwd=js_root) # upgrade version for onnxruntime-common run(["npm", "version", version], cwd=os.path.join(js_root, "common")) @@ -109,7 +108,7 @@ def run(args, cwd): # upgrade version for onnxruntime-react-native run(["npm", "version", version], cwd=os.path.join(js_root, "react_native")) - run(["yarn", "upgrade", "onnxruntime-common"], cwd=os.path.join(js_root, "react_native")) + run(["npm", "install", "--package-lock-only", "--ignore-scripts"], cwd=os.path.join(js_root, "react_native")) # upgrade version.ts in each package run(["npm", "ci"], cwd=js_root) From 333fbdb4a1161e1a3a8a119bf584ed9549fe9e0f Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Mon, 10 Mar 2025 14:08:12 -0700 Subject: [PATCH 071/266] [WebGPU/JSEP] Support group query attention do_rotary attribute (#23524) ### Description ### Motivation and Context --- .../jsep/webgpu/ops/group-query-attention.ts | 125 ++++++++++++++++-- .../wasm/jsep/webgpu/ops/rotary-embedding.ts | 2 +- 2 files changed, 118 insertions(+), 9 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts index 85b8c4ca5a274..32b3c54f734dc 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts @@ -3,12 +3,15 @@ import { TensorView } from '../../tensor-view'; import { createAttributeWithCacheKey } from '../attribute-with-cache-key'; -import { ComputeContext } from '../types'; +import { ComputeContext, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; +import { DataType } from '../../../wasm-common'; import { applyAttention, AttentionMaskType, AttentionParameters, AttentionQkvFormat } from './attention'; import { maybeTransposeToBNSHAndAddBias } from './multihead-attention'; import { createSplitProgramInfo, SplitAttributes } from './split'; import { createTransposeProgramInfo, TransposeAttributes } from './transpose'; +import { RotaryEmbeddingAttributes, createRotaryEmbeddingProgramInfo } from './rotary-embedding'; +import { inputVariable, outputVariable, ShaderHelper, UniformsArrayType } from './common'; export interface GroupQueryAttentionAttributes { numHeads: number; kvNumHeads: number; @@ -24,9 +27,6 @@ export const validateInputs = ( inputs: readonly TensorView[], attributes: GroupQueryAttentionAttributes, ): AttentionParameters => { - if (attributes.doRotary) { - throw new Error('GroupQuerryAttention do_rotary attribute is not supported'); - } if (attributes.doRotary && inputs.length <= 7) { throw new Error('cos_cache and sin_cache inputs are required if do_rotary is specified'); } @@ -35,6 +35,9 @@ export const validateInputs = ( const value = inputs[2]; const pastKey = inputs[3]; const pastValue = inputs[4]; + if (attributes.doRotary !== 0 && inputs.length <= 7) { + throw new Error('cos_cast and sin_cache are expected if do_rotary attribute is non-zero'); + } if (attributes.localWindowSize !== -1) { throw new Error('Local attention is not supported'); } @@ -238,6 +241,77 @@ const maybeTransposeToBNSH = (context: ComputeContext, input: TensorView, params return reshapedInput; }; +const generatePositionIdsProgramInfo = ( + batchSize: number, + sequenceLength: number, + seqLens: TensorView, + totalSeqLen: TensorView, +) => { + const outputDataType = DataType.int64; + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; + const outputShape = [batchSize * sequenceLength]; + const outputSize = batchSize * sequenceLength; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: sequenceLength }, + { type: DataType.uint32, data: batchSize }, + ]; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const seqLensInputHelper = inputVariable('seq_lens', seqLens.dataType, seqLens.dims); + const totalSeqLenInputHelper = inputVariable('total_seq_lens', totalSeqLen.dataType, totalSeqLen.dims); + const positionIdsHelper = outputVariable('pos_ids', outputDataType, outputShape); + + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'sequence_length', type: 'u32' }, + { name: 'batch_size', type: 'u32' }, + ]; + + return ` + ${shaderHelper.registerUniforms(uniforms).declareVariables(seqLensInputHelper, totalSeqLenInputHelper, positionIdsHelper)} + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} + let total_sequence_length = u32(${totalSeqLenInputHelper.getByOffset('0')}); + let is_subsequent_prompt = uniforms.sequence_length > 1 && uniforms.sequence_length != total_sequence_length; + let is_first_prompt = !is_subsequent_prompt && uniforms.sequence_length == total_sequence_length; + let batch_idx = global_idx / uniforms.sequence_length; + let sequence_idx = i32(global_idx % uniforms.sequence_length); + var pos_id: i32 = 0; + let seqlen = ${seqLensInputHelper.getByOffset('batch_idx')}; + let total_seqlen = seqlen + 1; + if (is_first_prompt) { + if (sequence_idx < total_seqlen) { + pos_id = sequence_idx; + } else { + pos_id = 1; + } + ${positionIdsHelper.setByOffset('global_idx', 'pos_id')} + } else if (is_subsequent_prompt) { + let past_seqlen = total_seqlen - i32(uniforms.sequence_length); + if (past_seqlen + sequence_idx < total_seqlen) { + pos_id = past_seqlen + sequence_idx; + } else { + pos_id = 1; + } + ${positionIdsHelper.setByOffset('global_idx', 'pos_id')} + } else if (global_idx < uniforms.batch_size) { + ${positionIdsHelper.setByOffset('global_idx', 'seqlen')} + }; + } + `; + }; + return { + name: 'GeneratePositionIds', + shaderCache: { hint: `${batchSize};${sequenceLength}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: outputDataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; + export const groupQueryAttention = (context: ComputeContext, attributes: GroupQueryAttentionAttributes): void => { const params = validateInputs(context.inputs, attributes); if (context.inputs[0].dims.length === 5) { @@ -268,22 +342,57 @@ export const groupQueryAttention = (context: ComputeContext, attributes: GroupQu !k && !v ? context.compute(createSplitProgramInfo([q], splitAttributes), { inputs: [q], outputs: [-1, -1, -1] }) : [q, k!, v!]; - + let qRotary: TensorView | undefined; + let kRotary: TensorView | undefined; + if (attributes.doRotary) { + const posIds = context.compute( + generatePositionIdsProgramInfo(params.batchSize, params.sequenceLength, seqLens!, totalSequenceLengthInput!), + { inputs: [seqLens!, totalSequenceLengthInput!], outputs: [-1] }, + )[0]; + const cosCache = context.inputs[7]; + const sinCache = context.inputs[8]; + const qRotaryEmbeddingAttributes: RotaryEmbeddingAttributes = createAttributeWithCacheKey({ + interleaved: attributes.rotaryInterleaved !== 0, + numHeads: params.numHeads, + rotaryEmbeddingDim: 0, + scale: attributes.scale, + }); + const inputs = [query, posIds, cosCache, sinCache]; + const outputs = [-1]; + qRotary = context.compute(createRotaryEmbeddingProgramInfo(inputs, qRotaryEmbeddingAttributes), { + inputs, + outputs, + })[0]; + inputs.splice(0, 1, key); + const kRotaryEmbeddingAttributes: RotaryEmbeddingAttributes = createAttributeWithCacheKey({ + interleaved: attributes.rotaryInterleaved !== 0, + numHeads: params.kvNumHeads!, + rotaryEmbeddingDim: 0, + scale: attributes.scale, + }); + kRotary = context.compute(createRotaryEmbeddingProgramInfo(inputs, kRotaryEmbeddingAttributes), { + inputs, + outputs, + })[0]; + } const Q = maybeTransposeToBNSHAndAddBias( context, params.batchSize, params.numHeads, params.sequenceLength, params.headSize, - query, + attributes.doRotary ? qRotary! : query, undefined, 0, ); + const K = maybeTransposeToBNSH(context, attributes.doRotary ? kRotary! : key, params); + const V = maybeTransposeToBNSH(context, value, params); + applyAttention( context, Q, - maybeTransposeToBNSH(context, key, params), - maybeTransposeToBNSH(context, value, params), + K, + V, undefined, undefined, pastKey, diff --git a/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts b/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts index 8eb7a10ac91fa..fe2567e71d49a 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts @@ -75,7 +75,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: RotaryEmbeddi } }; -const createRotaryEmbeddingProgramInfo = ( +export const createRotaryEmbeddingProgramInfo = ( inputs: readonly TensorView[], attributes: RotaryEmbeddingAttributes, ): ProgramInfo => { From f18e9faab63d9964ee27c01b8b471a092af24e28 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 11 Mar 2025 15:12:02 -0400 Subject: [PATCH 072/266] Fix npm audit in js/react-native/e2e (#23975) --- js/package-lock.json | 1 + js/react_native/e2e/package-lock.json | 7553 ++++++++++++----- js/react_native/e2e/yarn.lock | 7216 ---------------- js/react_native/package-lock.json | 4777 ++--------- js/react_native/yarn.lock | 3748 -------- .../testcases/vite-default/package-lock.json | 384 +- 6 files changed, 6384 insertions(+), 17295 deletions(-) delete mode 100644 js/react_native/e2e/yarn.lock delete mode 100644 js/react_native/yarn.lock diff --git a/js/package-lock.json b/js/package-lock.json index 1fa9032ff6d3c..dbbf42d9c8f35 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "js", "license": "MIT", "devDependencies": { "@types/fs-extra": "^11.0.4", diff --git a/js/react_native/e2e/package-lock.json b/js/react_native/e2e/package-lock.json index c7dad7a91f6f2..2907534fdddd1 100644 --- a/js/react_native/e2e/package-lock.json +++ b/js/react_native/e2e/package-lock.json @@ -8,17 +8,30 @@ "name": "onnxruntime-reactnative-example", "version": "0.5.0", "dependencies": { - "react": "^18.1.0", - "react-native": "^0.75.3", + "react": "^18.2.0", + "react-native": "^0.73.11", "react-native-fs": "^2.20.0" }, "devDependencies": { - "@babel/core": "^7.17.0", - "@babel/runtime": "^7.17.0", - "babel-plugin-module-resolver": "^4.0.0", - "detox": "^20.7.0", - "jest": "^29", - "metro-react-native-babel-preset": "^0.67.0" + "@babel/core": "^7.20.0", + "@babel/preset-env": "^7.20.0", + "@babel/runtime": "^7.20.0", + "@react-native/babel-preset": "0.73.21", + "@react-native/eslint-config": "^0.73.2", + "@react-native/metro-config": "^0.73.5", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", + "@types/react-test-renderer": "^18.0.0", + "babel-jest": "^29.6.3", + "detox": "20.10.0", + "eslint": "^8.19.0", + "jest": "^29.6.3", + "prettier": "^2.8.8", + "react-test-renderer": "18.2.0", + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" } }, "node_modules/@ampproject/remapping": { @@ -44,12 +57,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -114,28 +128,48 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/@babel/eslint-parser": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz", + "integrity": "sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", + "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -186,17 +220,17 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz", + "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.26.9", "semver": "^6.3.1" }, "engines": { @@ -259,42 +293,53 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -304,21 +349,21 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -342,14 +387,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -358,54 +403,41 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -438,90 +470,13 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", + "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.26.9" }, "bin": { "parser": "bin/babel-parser.js" @@ -535,7 +490,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.3" @@ -552,7 +506,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -568,7 +521,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -584,7 +536,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -602,7 +553,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.0" @@ -614,12 +564,34 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.17.12", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -643,10 +615,13 @@ } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.17.12", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -656,16 +631,35 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.0", - "dev": true, + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.17.12" + "@babel/plugin-transform-parameters": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -676,7 +670,6 @@ }, "node_modules/@babel/plugin-proposal-optional-catch-binding": { "version": "7.16.7", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", @@ -690,11 +683,14 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.17.12", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -709,7 +705,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" }, @@ -727,6 +722,19 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "license": "MIT", @@ -742,7 +750,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -781,7 +788,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -790,12 +796,12 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", - "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -809,7 +815,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -825,7 +830,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -861,12 +865,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -970,12 +974,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", - "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -989,7 +993,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1056,7 +1059,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1103,7 +1105,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1172,7 +1173,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1189,7 +1189,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1205,7 +1204,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8" @@ -1222,7 +1220,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1255,7 +1252,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1268,13 +1264,13 @@ } }, "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz", - "integrity": "sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", + "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/plugin-syntax-flow": "^7.24.7" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-flow": "^7.26.0" }, "engines": { "node": ">=6.9.0" @@ -1321,7 +1317,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1369,7 +1364,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1385,7 +1379,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1398,14 +1391,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1419,7 +1411,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8", @@ -1438,7 +1429,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1471,7 +1461,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1514,20 +1503,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-object-assign": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", @@ -1551,7 +1526,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -1650,7 +1624,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1738,7 +1711,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1833,7 +1805,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1845,16 +1816,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", - "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", + "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-typescript": "^7.24.7" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1868,7 +1839,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1884,7 +1854,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1917,7 +1886,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8" @@ -1934,7 +1902,6 @@ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/compat-data": "^7.25.4", "@babel/helper-compilation-targets": "^7.25.2", @@ -2032,7 +1999,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -2049,7 +2015,6 @@ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "license": "MIT", - "peer": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -2064,7 +2029,6 @@ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", "core-js-compat": "^3.38.0" @@ -2078,7 +2042,6 @@ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -2091,7 +2054,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -2108,18 +2070,17 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@babel/preset-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", - "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", + "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-transform-flow-strip-types": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2133,7 +2094,6 @@ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2144,16 +2104,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", - "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2163,9 +2123,9 @@ } }, "node_modules/@babel/register": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", - "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", + "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", @@ -2181,6 +2141,28 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@babel/register/node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -2216,30 +2198,30 @@ "license": "MIT" }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", + "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2267,14 +2249,13 @@ "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", + "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2282,34 +2263,260 @@ }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, "license": "MIT" }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "license": "BSD-3-Clause", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", - "license": "ISC", + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "dev": true, "license": "ISC", @@ -2341,15 +2548,17 @@ } }, "node_modules/@jest/console": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -2357,36 +2566,38 @@ } }, "node_modules/@jest/core": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -2430,23 +2641,27 @@ } }, "node_modules/@jest/expect": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2470,30 +2685,34 @@ } }, "node_modules/@jest/globals": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -2501,13 +2720,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -2525,6 +2744,36 @@ } } }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2538,11 +2787,13 @@ } }, "node_modules/@jest/source-map": { - "version": "29.4.3", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -2551,12 +2802,14 @@ } }, "node_modules/@jest/test-result": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -2565,13 +2818,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -2579,21 +2834,23 @@ } }, "node_modules/@jest/transform": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -2603,18 +2860,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/write-file-atomic": { - "version": "4.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -2690,10 +2935,21 @@ "version": "1.4.14", "license": "MIT" }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -2707,6 +2963,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -2716,6 +2973,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -2726,86 +2984,87 @@ } }, "node_modules/@react-native-community/cli": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-14.1.0.tgz", - "integrity": "sha512-k7aTdKNZIec7WMSqMJn9bDVLWPPOaYmshXcnjWy6t5ItsJnREju9p2azMTR5tXY5uIeynose3cxettbhk2Tbnw==", - "license": "MIT", - "dependencies": { - "@react-native-community/cli-clean": "14.1.0", - "@react-native-community/cli-config": "14.1.0", - "@react-native-community/cli-debugger-ui": "14.1.0", - "@react-native-community/cli-doctor": "14.1.0", - "@react-native-community/cli-server-api": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", - "@react-native-community/cli-types": "14.1.0", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.7.tgz", + "integrity": "sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-clean": "12.3.7", + "@react-native-community/cli-config": "12.3.7", + "@react-native-community/cli-debugger-ui": "12.3.7", + "@react-native-community/cli-doctor": "12.3.7", + "@react-native-community/cli-hermes": "12.3.7", + "@react-native-community/cli-plugin-metro": "12.3.7", + "@react-native-community/cli-server-api": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "@react-native-community/cli-types": "12.3.7", "chalk": "^4.1.2", "commander": "^9.4.1", "deepmerge": "^4.3.0", "execa": "^5.0.0", - "find-up": "^5.0.0", + "find-up": "^4.1.0", "fs-extra": "^8.1.0", "graceful-fs": "^4.1.3", "prompts": "^2.4.2", "semver": "^7.5.2" }, "bin": { - "rnc-cli": "build/bin.js" + "react-native": "build/bin.js" }, "engines": { "node": ">=18" } }, "node_modules/@react-native-community/cli-clean": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-14.1.0.tgz", - "integrity": "sha512-/C4j1yntLo6faztNgZnsDtgpGqa6j0+GYrxOY8LqaKAN03OCnoeUUKO6w78dycbYSGglc1xjJg2RZI/M2oF2AA==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz", + "integrity": "sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ==", "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-glob": "^3.3.2" + "execa": "^5.0.0" } }, "node_modules/@react-native-community/cli-config": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-14.1.0.tgz", - "integrity": "sha512-P3FK2rPUJBD1fmQHLgTqpHxsc111pnMdEEFR7KeqprCNz+Qr2QpPxfNy0V7s15tGL5rAv+wpbOGcioIV50EbxA==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.7.tgz", + "integrity": "sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw==", "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", - "cosmiconfig": "^9.0.0", + "cosmiconfig": "^5.1.0", "deepmerge": "^4.3.0", - "fast-glob": "^3.3.2", + "glob": "^7.1.3", "joi": "^17.2.1" } }, "node_modules/@react-native-community/cli-debugger-ui": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.1.0.tgz", - "integrity": "sha512-+YbeCL0wLcBcqDwraJFGsqzcXu9S+bwTVrfImne/4mT6itfe3Oa93yrOVJgNbstrt5pJHuwpU76ZXfXoiuncsg==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz", + "integrity": "sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q==", "license": "MIT", "dependencies": { "serve-static": "^1.13.1" } }, "node_modules/@react-native-community/cli-doctor": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-14.1.0.tgz", - "integrity": "sha512-xIf0oQDRKt7lufUenRwcLYdINGc0x1FSXHaHjd7lQDGT5FJnCEYlIkYEDDgAl5tnVJSvM/IL2c6O+mffkNEPzQ==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz", + "integrity": "sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg==", "license": "MIT", "dependencies": { - "@react-native-community/cli-config": "14.1.0", - "@react-native-community/cli-platform-android": "14.1.0", - "@react-native-community/cli-platform-apple": "14.1.0", - "@react-native-community/cli-platform-ios": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-config": "12.3.7", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-platform-ios": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", "command-exists": "^1.2.8", "deepmerge": "^4.3.0", - "envinfo": "^7.13.0", + "envinfo": "^7.10.0", "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", "node-stream-zip": "^1.9.1", "ora": "^5.4.1", "semver": "^7.5.2", @@ -2824,9 +3083,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2847,58 +3106,67 @@ "node": ">=6" } }, - "node_modules/@react-native-community/cli-platform-android": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-14.1.0.tgz", - "integrity": "sha512-4JnXkAV+ca8XdUhZ7xjgDhXAMwTVjQs8JqiwP7FTYVrayShXy2cBXm/C3HNDoe+oQOF5tPT2SqsDAF2vYTnKiQ==", + "node_modules/@react-native-community/cli-hermes": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz", + "integrity": "sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg==", "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-glob": "^3.3.2", - "fast-xml-parser": "^4.4.1", - "logkitty": "^0.7.1" + "hermes-profile-transformer": "^0.0.6" } }, - "node_modules/@react-native-community/cli-platform-apple": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.1.0.tgz", - "integrity": "sha512-DExd+pZ7hHxXt8I6BBmckeYUxxq7PQ+o4YSmGIeQx0xUpi+f82obBct2WNC3VWU72Jw6obwfoN6Fwe6F7Wxp5Q==", + "node_modules/@react-native-community/cli-platform-android": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz", + "integrity": "sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ==", "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", "execa": "^5.0.0", - "fast-glob": "^3.3.2", - "fast-xml-parser": "^4.4.1", - "ora": "^5.4.1" + "fast-xml-parser": "^4.2.4", + "glob": "^7.1.3", + "logkitty": "^0.7.1" } }, "node_modules/@react-native-community/cli-platform-ios": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.1.0.tgz", - "integrity": "sha512-ah/ZTiJXUdCVHujyRJ4OmCL5nTq8OWcURcE3UXa1z0sIIiA8io06n+v5n299T9rtPKMwRtVJlQjtO/nbODABPQ==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz", + "integrity": "sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow==", "license": "MIT", "dependencies": { - "@react-native-community/cli-platform-apple": "14.1.0" + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.0.12", + "glob": "^7.1.3", + "ora": "^5.4.1" } }, + "node_modules/@react-native-community/cli-plugin-metro": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz", + "integrity": "sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg==", + "license": "MIT" + }, "node_modules/@react-native-community/cli-server-api": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-14.1.0.tgz", - "integrity": "sha512-1k2LBQaYsy9RDWFIfKVne3frOye73O33MV6eYMoRPff7wqxHCrsX1CYJQkmwpgVigZHxYwalHj+Axtu3gpomCA==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz", + "integrity": "sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg==", "license": "MIT", "dependencies": { - "@react-native-community/cli-debugger-ui": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-debugger-ui": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", "compression": "^1.7.1", "connect": "^3.6.5", "errorhandler": "^1.5.1", "nocache": "^3.0.1", "pretty-format": "^26.6.2", "serve-static": "^1.13.1", - "ws": "^6.2.3" + "ws": "^7.5.1" } }, "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { @@ -2947,26 +3215,17 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "license": "MIT" }, - "node_modules/@react-native-community/cli-server-api/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "license": "MIT", - "dependencies": { - "async-limiter": "~1.0.0" - } - }, "node_modules/@react-native-community/cli-tools": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-14.1.0.tgz", - "integrity": "sha512-r1KxSu2+OSuhWFoE//1UR7aSTXMLww/UYWQprEw4bSo/kvutGX//4r9ywgXSWp+39udpNN4jQpNTHuWhGZd/Bg==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz", + "integrity": "sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw==", "license": "MIT", "dependencies": { "appdirsjs": "^1.2.4", "chalk": "^4.1.2", - "execa": "^5.0.0", "find-up": "^5.0.0", "mime": "^2.4.1", + "node-fetch": "^2.6.0", "open": "^6.2.0", "ora": "^5.4.1", "semver": "^7.5.2", @@ -3030,9 +3289,9 @@ } }, "node_modules/@react-native-community/cli-tools/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3042,73 +3301,41 @@ } }, "node_modules/@react-native-community/cli-types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-14.1.0.tgz", - "integrity": "sha512-aJwZI9mGRx3HdP8U4CGhqjt3S4r8GmeOqv4kRagC1UHDk4QNMC+bZ8JgPA4W7FrGiPey+lJQHMDPAXOo51SOUw==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.7.tgz", + "integrity": "sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w==", "license": "MIT", "dependencies": { "joi": "^17.2.1" } }, - "node_modules/@react-native-community/cli/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/@react-native-community/cli/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6 <7 || >=8" } }, - "node_modules/@react-native-community/cli/node_modules/path-exists": { + "node_modules/@react-native-community/cli/node_modules/jsonfile": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "license": "MIT", - "engines": { - "node": ">=8" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/@react-native-community/cli/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3117,60 +3344,67 @@ "node": ">=10" } }, + "node_modules/@react-native-community/cli/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/@react-native/assets-registry": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.75.3.tgz", - "integrity": "sha512-i7MaRbYR06WdpJWv3a0PQ2ScFBUeevwcJ0tVopnFwTg0tBWp3NFEMDIcU8lyXVy9Y59WmrP1V2ROaRDaPiESgg==", + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", + "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.75.3.tgz", - "integrity": "sha512-8JmXEKq+Efb9AffsV48l8gmKe/ZQ2PbBygZjHdIf8DNZZhO/z5mt27J4B43MWNdp5Ww1l59T0mEaf8l/uywQUg==", + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", + "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", "license": "MIT", "dependencies": { - "@react-native/codegen": "0.75.3" + "@react-native/codegen": "0.73.3" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.75.3.tgz", - "integrity": "sha512-VZQkQEj36DKEGApXFYdVcFtqdglbnoVr7aOZpjffURSgPcIA9vWTm1b+OL4ayOaRZXTZKiDBNQCXvBX5E5AgQg==", + "version": "0.73.21", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", + "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", "license": "MIT", "dependencies": { "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", "@babel/plugin-syntax-dynamic-import": "^7.8.0", "@babel/plugin-syntax-export-default-from": "^7.0.0", "@babel/plugin-syntax-flow": "^7.18.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-syntax-optional-chaining": "^7.0.0", "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", "@babel/plugin-transform-async-to-generator": "^7.20.0", "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-class-properties": "^7.24.1", "@babel/plugin-transform-classes": "^7.0.0", "@babel/plugin-transform-computed-properties": "^7.0.0", "@babel/plugin-transform-destructuring": "^7.20.0", "@babel/plugin-transform-flow-strip-types": "^7.20.0", - "@babel/plugin-transform-for-of": "^7.0.0", "@babel/plugin-transform-function-name": "^7.0.0", "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", "@babel/plugin-transform-modules-commonjs": "^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.5", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.5", "@babel/plugin-transform-parameters": "^7.0.0", "@babel/plugin-transform-private-methods": "^7.22.5", "@babel/plugin-transform-private-property-in-object": "^7.22.11", @@ -3178,7 +3412,6 @@ "@babel/plugin-transform-react-jsx": "^7.0.0", "@babel/plugin-transform-react-jsx-self": "^7.0.0", "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.20.0", "@babel/plugin-transform-runtime": "^7.0.0", "@babel/plugin-transform-shorthand-properties": "^7.0.0", "@babel/plugin-transform-spread": "^7.0.0", @@ -3186,7 +3419,7 @@ "@babel/plugin-transform-typescript": "^7.5.0", "@babel/plugin-transform-unicode-regex": "^7.0.0", "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.75.3", + "@react-native/babel-plugin-codegen": "0.73.4", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, @@ -3207,19 +3440,18 @@ } }, "node_modules/@react-native/codegen": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.75.3.tgz", - "integrity": "sha512-I0bz5jwOkiR7vnhYLGoV22RGmesErUg03tjsCiQgmsMpbyCYumudEtLNN5+DplHGK56bu8KyzBqKkWXGSKSCZQ==", + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", + "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", "license": "MIT", "dependencies": { "@babel/parser": "^7.20.0", + "flow-parser": "^0.206.0", "glob": "^7.1.1", - "hermes-parser": "0.22.0", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" + "nullthrows": "^1.1.1" }, "engines": { "node": ">=18" @@ -3229,15 +3461,15 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.75.3.tgz", - "integrity": "sha512-njsYm+jBWzfLcJcxavAY5QFzYTrmPtjbxq/64GSqwcQYzy9qAkI7LNTK/Wprq1I/4HOuHJO7Km+EddCXB+ByRQ==", + "version": "0.73.18", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz", + "integrity": "sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww==", "license": "MIT", "dependencies": { - "@react-native-community/cli-server-api": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", - "@react-native/dev-middleware": "0.75.3", - "@react-native/metro-babel-transformer": "0.75.3", + "@react-native-community/cli-server-api": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "@react-native/dev-middleware": "0.73.8", + "@react-native/metro-babel-transformer": "0.73.15", "chalk": "^4.0.0", "execa": "^5.1.1", "metro": "^0.80.3", @@ -3251,31 +3483,30 @@ } }, "node_modules/@react-native/debugger-frontend": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.75.3.tgz", - "integrity": "sha512-99bLQsUwsxUMNR7Wa9eV2uyR38yfd6mOEqfN+JIm8/L9sKA926oh+CZkjDy1M8RmCB6spB5N9fVFVkrVdf2yFA==", + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", + "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", "license": "BSD-3-Clause", "engines": { "node": ">=18" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.75.3.tgz", - "integrity": "sha512-h2/6+UGmeMWjnT43axy27jNqoDRsE1C1qpjRC3sYpD4g0bI0jSTkY1kAgj8uqGGXLnHXiHOtjLDGdbAgZrsPaA==", + "version": "0.73.8", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", + "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.75.3", + "@react-native/debugger-frontend": "0.73.3", "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", + "chromium-edge-launcher": "^1.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "node-fetch": "^2.2.0", - "nullthrows": "^1.1.1", "open": "^7.0.3", - "selfsigned": "^2.4.1", "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", "ws": "^6.2.2" }, "engines": { @@ -3298,6 +3529,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@react-native/dev-middleware/node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@react-native/dev-middleware/node_modules/ws": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", @@ -3307,33 +3547,72 @@ "async-limiter": "~1.0.0" } }, + "node_modules/@react-native/eslint-config": { + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/eslint-config/-/eslint-config-0.73.2.tgz", + "integrity": "sha512-YzMfes19loTfbrkbYNAfHBDXX4oRBzc5wnvHs4h2GIHUj6YKs5ZK5lldqSrBJCdZAI3nuaO9Qj+t5JRwou571w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/eslint-parser": "^7.20.0", + "@react-native/eslint-plugin": "0.73.1", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-ft-flow": "^2.0.1", + "eslint-plugin-jest": "^26.5.3", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-native": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": ">=8", + "prettier": ">=2" + } + }, + "node_modules/@react-native/eslint-plugin": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/eslint-plugin/-/eslint-plugin-0.73.1.tgz", + "integrity": "sha512-8BNMFE8CAI7JLWLOs3u33wcwcJ821LYs5g53Xyx9GhSg0h8AygTwDrwmYb/pp04FkCNCPjKPBoaYRthQZmxgwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@react-native/gradle-plugin": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.75.3.tgz", - "integrity": "sha512-mSfa/Mq/AsALuG/kvXz5ECrc6HdY5waMHal2sSfa8KA0Gt3JqYQVXF9Pdwd4yR5ClPZDI2HRa1tdE8GVlhMvPA==", + "version": "0.73.5", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz", + "integrity": "sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@react-native/js-polyfills": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.75.3.tgz", - "integrity": "sha512-+JVFJ351GSJT3V7LuXscMqfnpR/UxzsAjbBjfAHBR3kqTbVqrAmBccqPCA3NLzgb/RY8khLJklwMUVlWrn8iFg==", + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", + "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@react-native/metro-babel-transformer": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.75.3.tgz", - "integrity": "sha512-gDlEl6C2mwQPLxFOR+yla5MpJpDPNOFD6J5Hd9JM9+lOdUq6MNujh1Xn4ZMvglW7rfViq3nMjg4xPQeGUhDG+w==", + "version": "0.73.15", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", + "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", "license": "MIT", "dependencies": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.75.3", - "hermes-parser": "0.22.0", + "@react-native/babel-preset": "0.73.21", + "hermes-parser": "0.15.0", "nullthrows": "^1.1.1" }, "engines": { @@ -3343,16 +3622,39 @@ "@babel/core": "*" } }, + "node_modules/@react-native/metro-config": { + "version": "0.73.5", + "resolved": "https://registry.npmjs.org/@react-native/metro-config/-/metro-config-0.73.5.tgz", + "integrity": "sha512-3bNWoHzOzP/+qoLJtRhOVXrnxKmSY3i4y5PXyMQlIvvOI/GQbXulPpEZxK/yUrf1MmeXHLLFufFbQWlfDEDoxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native/js-polyfills": "0.73.1", + "@react-native/metro-babel-transformer": "0.73.15", + "metro-config": "^0.80.3", + "metro-runtime": "^0.80.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@react-native/normalize-colors": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.75.3.tgz", - "integrity": "sha512-3mhF8AJFfIN0E5bEs/DQ4U2LzMJYm+FPSwY5bJ1DZhrxW1PFAh24bAPrSd8PwS0iarQ7biLdr1lWf/8LFv8pDA==", + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", + "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "license": "MIT" + }, + "node_modules/@react-native/typescript-config": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/typescript-config/-/typescript-config-0.73.1.tgz", + "integrity": "sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w==", + "dev": true, "license": "MIT" }, "node_modules/@react-native/virtualized-lists": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.75.3.tgz", - "integrity": "sha512-cTLm7k7Y//SvV8UK8esrDHEw5OrwwSJ4Fqc3x52Imi6ROuhshfGIPFwhtn4pmAg9nWHzHwwqiJ+9hCSVnXXX+g==", + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", + "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", "license": "MIT", "dependencies": { "invariant": "^2.2.4", @@ -3362,14 +3664,7 @@ "node": ">=18" }, "peerDependencies": { - "@types/react": "^18.2.6", - "react": "*", "react-native": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, "node_modules/@sideway/address": { @@ -3451,7 +3746,9 @@ } }, "node_modules/@types/graceful-fs": { - "version": "4.1.6", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3476,21 +3773,49 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "18.0.0", "license": "MIT" }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-test-renderer": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.1.tgz", + "integrity": "sha512-vAhnk0tG2eGa37lkU9+s5SoroCsRI08xnsWFiAXOuPH2jqzMbcXvKExXViPi1P5fIklDeCvXqyrdmipFaSkZrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "^18" } }, - "node_modules/@types/prettier": { - "version": "2.7.2", + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true, "license": "MIT" }, @@ -3509,531 +3834,963 @@ "version": "21.0.0", "license": "MIT" }, - "node_modules/abort-controller": { - "version": "3.0.0", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=6.5" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "license": "MIT", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", "bin": { - "acorn": "bin/acorn" + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.4.0" + "node": ">=10" } }, - "node_modules/ajv": { - "version": "8.12.0", + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/anser": { - "version": "1.4.10", + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, - "node_modules/ansi-escapes": { - "version": "4.3.2", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-fragments": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", - "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", "dependencies": { - "colorette": "^1.0.7", - "slice-ansi": "^2.0.0", - "strip-ansi": "^5.0.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/ansi-fragments/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-fragments/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "license": "MIT", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "ansi-regex": "^4.1.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-regex": { - "version": "5.0.1", + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/anymatch": { - "version": "3.1.2", + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 8" + "node": ">=10" } }, - "node_modules/appdirsjs": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", - "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "1.0.10", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/asap": { - "version": "2.0.6", - "license": "MIT" + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - "node_modules/ast-types": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", - "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", "license": "MIT", "dependencies": { - "tslib": "^2.0.1" + "event-target-shim": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=6.5" } }, - "node_modules/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/async-limiter": { - "version": "1.0.1", - "license": "MIT" + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/babel-core": { - "version": "7.0.0-bridge.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", - "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "license": "MIT", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", + "node_modules/ajv": { + "version": "8.12.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", + "node_modules/anser": { + "version": "1.4.10", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "type-fest": "^0.21.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-module-resolver": { - "version": "4.1.0", + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", "license": "MIT", "dependencies": { - "find-babel-config": "^1.2.0", - "glob": "^7.1.6", - "pkg-up": "^3.1.0", - "reselect": "^4.0.0", - "resolve": "^1.13.1" - }, + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", "engines": { - "node": ">= 8.0.0" + "node": ">=6" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.1", + "node_modules/ansi-fragments/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" + "ansi-regex": "^4.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" + "color-convert": "^2.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "license": "MIT", + "node_modules/anymatch": { + "version": "3.1.2", + "license": "ISC", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/babel-plugin-transform-flow-enums": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", - "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", "license": "MIT", "dependencies": { - "@babel/plugin-syntax-flow": "^7.12.1" + "sprintf-js": "~1.0.2" } }, - "node_modules/balanced-match": { + "node_modules/array-buffer-byte-length": { "version": "1.0.2", - "license": "MIT" - }, - "node_modules/base-64": { - "version": "0.1.0" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/bluebird": { - "version": "3.7.2", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/braces": { - "version": "3.0.3", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "license": "MIT" - }, - "node_modules/bunyan": { - "version": "1.8.15", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, - "engines": [ - "node >=0.10.0" - ], "license": "MIT", - "bin": { - "bunyan": "bin/bunyan" + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, - "optionalDependencies": { - "dtrace-provider": "~0.8", - "moment": "^2.19.3", - "mv": "~2", - "safe-json-stringify": "~1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/bunyan-debug-stream": { - "version": "3.1.0", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.2" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=0.12.0" + "node": ">= 0.4" }, - "peerDependencies": { - "bunyan": "*" - } - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/caf": { - "version": "15.0.1", - "dev": true, + "node_modules/asap": { + "version": "2.0.6", "license": "MIT" }, - "node_modules/caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", "license": "MIT", "dependencies": { - "callsites": "^2.0.0" + "tslib": "^2.0.1" }, "engines": { "node": ">=4" } }, - "node_modules/caller-callsite/node_modules/callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "license": "MIT", "dependencies": { - "caller-callsite": "^2.0.0" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", "license": "MIT", - "engines": { - "node": ">=6" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/camelcase": { - "version": "6.3.0", + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001660", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", - "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base-64": { + "version": "0.1.0" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -4041,791 +4798,1976 @@ }, { "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/bunyan": { + "version": "1.8.15", + "dev": true, + "engines": [ + "node >=0.10.0" + ], + "license": "MIT", + "bin": { + "bunyan": "bin/bunyan" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/bunyan-debug-stream": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "bunyan": "*" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/caf": { + "version": "15.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "license": "MIT", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "license": "MIT", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/child-process-promise": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^4.0.2", + "node-version": "^1.0.0", + "promise-polyfill": "^6.0.1" + } + }, + "node_modules/child-process-promise/node_modules/cross-spawn": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/child-process-promise/node_modules/lru-cache": { + "version": "4.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/child-process-promise/node_modules/yallist": { + "version": "2.1.2", + "dev": true, + "license": "ISC" + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.3.2", + "license": "MIT" + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "license": "MIT" + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", + "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "license": "MIT", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecated-react-native-prop-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", + "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", + "license": "MIT", + "dependencies": { + "@react-native/normalize-colors": "^0.73.0", + "invariant": "^2.2.4", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detox": { + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/detox/-/detox-20.10.0.tgz", + "integrity": "sha512-c6dCD5xTmiuOklbx4ptnXuznCnK4IMd9ZtB8jXxNJBqZpUXzqhmCniwKPZNwkdtye/xXbEFz4t5JWQKsVJ3z5Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.6.3", + "bunyan": "^1.8.12", + "bunyan-debug-stream": "^3.1.0", + "caf": "^15.0.1", + "chalk": "^4.0.0", + "child-process-promise": "^2.2.0", + "execa": "^5.1.1", + "find-up": "^5.0.0", + "fs-extra": "^11.0.0", + "funpermaproxy": "^1.1.0", + "glob": "^8.0.3", + "ini": "^1.3.4", + "json-cycle": "^1.3.0", + "lodash": "^4.17.11", + "multi-sort-stream": "^1.0.3", + "multipipe": "^4.0.0", + "node-ipc": "9.2.1", + "proper-lockfile": "^3.0.2", + "resolve-from": "^5.0.0", + "sanitize-filename": "^1.6.1", + "semver": "^7.0.0", + "serialize-error": "^8.0.1", + "shell-quote": "^1.7.2", + "signal-exit": "^3.0.3", + "stream-json": "^1.7.4", + "strip-ansi": "^6.0.1", + "telnet-client": "1.2.8", + "tempfile": "^2.0.0", + "trace-event-lib": "^1.3.1", + "which": "^1.3.1", + "ws": "^7.0.0", + "yargs": "^17.0.0", + "yargs-parser": "^21.0.0", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "detox": "local-cli/cli.js" + }, + "engines": { + "node": ">=14.5.0" + }, + "peerDependencies": { + "jest": "29.x.x || 28.x.x || ^27.2.5" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } }, - "node_modules/chalk": { - "version": "4.1.2", + "node_modules/detox/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "balanced-match": "^1.0.0" + } + }, + "node_modules/detox/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/char-regex": { - "version": "1.0.2", + "node_modules/detox/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/detox/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/child-process-promise": { - "version": "2.2.1", + "node_modules/detox/node_modules/minimatch": { + "version": "5.1.6", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "cross-spawn": "^4.0.2", - "node-version": "^1.0.0", - "promise-polyfill": "^6.0.1" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/child-process-promise/node_modules/cross-spawn": { - "version": "4.0.2", + "node_modules/detox/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/child-process-promise/node_modules/lru-cache": { - "version": "4.1.5", + "node_modules/detox/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detox/node_modules/semver": { + "version": "7.5.4", "dev": true, "license": "ISC", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/child-process-promise/node_modules/yallist": { - "version": "2.1.2", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/chrome-launcher": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", - "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" + "esutils": "^2.0.2" }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.js" + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dtrace-provider": { + "version": "0.8.8", + "dev": true, + "hasInstallScript": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "nan": "^2.14.0" }, "engines": { - "node": ">=12.13.0" + "node": ">=0.10" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/easy-stack": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/chrome-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", + "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/chromium-edge-launcher": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", - "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", - "license": "Apache-2.0", - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" }, - "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/chromium-edge-launcher/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "license": "MIT", "bin": { - "mkdirp": "bin/cmd.js" + "envinfo": "dist/cli.js" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/ci-info": { - "version": "3.3.2", - "license": "MIT" + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "dev": true, - "license": "MIT" + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", "license": "MIT", "dependencies": { - "restore-cursor": "^3.1.0" + "accepts": "~1.3.7", + "escape-html": "~1.0.3" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "license": "MIT", + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 0.4" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">= 0.4" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/co": { - "version": "4.6.0", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">= 0.4" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" } }, - "node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", - "license": "MIT" + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "license": "MIT" + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { - "node": "^12.20.0 || >=14" + "node": ">=6" } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "license": "MIT", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, "engines": { - "node": ">= 0.6" + "node": ">=0.8.0" } }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 0.8.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT" + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" }, "engines": { - "node": ">= 0.10.0" + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "license": "MIT" - }, - "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "node_modules/eslint-plugin-ft-flow": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz", + "integrity": "sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg==", + "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "@babel/eslint-parser": "^7.12.0", + "eslint": "^8.1.0" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "node_modules/eslint-plugin-jest": { + "version": "26.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", + "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", + "dev": true, "license": "MIT", "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" + "@typescript-eslint/utils": "^5.10.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "typescript": ">=4.9.5" + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "typescript": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { "optional": true } } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "prettier-linter-helpers": "^1.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/eslint-plugin-react": { + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "node": ">=4" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/eslint-plugin-react-native": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz", + "integrity": "sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "eslint-plugin-react-native-globals": "^0.1.1" + }, + "peerDependencies": { + "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/dedent": { - "version": "0.7.0", + "node_modules/eslint-plugin-react-native-globals": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz", + "integrity": "sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g==", "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "license": "MIT", + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, "license": "MIT", "dependencies": { - "clone": "^1.0.2" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=8.0.0" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=4.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/detox": { - "version": "20.7.0", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { - "ajv": "^8.6.3", - "bunyan": "^1.8.12", - "bunyan-debug-stream": "^3.1.0", - "caf": "^15.0.1", - "chalk": "^4.0.0", - "child-process-promise": "^2.2.0", - "execa": "^5.1.1", - "find-up": "^4.1.0", - "fs-extra": "^4.0.2", - "funpermaproxy": "^1.1.0", - "glob": "^8.0.3", - "ini": "^1.3.4", - "json-cycle": "^1.3.0", - "lodash": "^4.17.11", - "multi-sort-stream": "^1.0.3", - "multipipe": "^4.0.0", - "node-ipc": "^9.2.1", - "proper-lockfile": "^3.0.2", - "resolve-from": "^5.0.0", - "sanitize-filename": "^1.6.1", - "semver": "^7.0.0", - "serialize-error": "^8.0.1", - "shell-quote": "^1.7.2", - "signal-exit": "^3.0.3", - "stream-json": "^1.7.4", - "strip-ansi": "^6.0.1", - "telnet-client": "1.2.8", - "tempfile": "^2.0.0", - "trace-event-lib": "^1.3.1", - "which": "^1.3.1", - "ws": "^7.0.0", - "yargs": "^16.0.3", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "detox": "local-cli/cli.js" - }, - "engines": { - "node": ">=14.5.0" - }, - "peerDependencies": { - "jest": "29.x.x || 28.x.x || ^27.2.5" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependenciesMeta": { - "jest": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/detox/node_modules/brace-expansion": { + "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/detox/node_modules/cliui": { - "version": "7.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } + "license": "Python-2.0" }, - "node_modules/detox/node_modules/fs-extra": { - "version": "4.0.3", + "node_modules/eslint/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/detox/node_modules/glob": { - "version": "8.1.0", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/detox/node_modules/minimatch": { - "version": "5.1.6", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "brace-expansion": "^2.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/detox/node_modules/semver": { - "version": "7.5.4", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/detox/node_modules/yargs": { - "version": "16.2.0", + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/diff-sequences": { - "version": "29.4.3", + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dtrace-provider": { - "version": "0.8.8", - "dev": true, - "hasInstallScript": true, - "license": "BSD-2-Clause", - "optional": true, "dependencies": { - "nan": "^2.14.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/duplexer2": { - "version": "0.1.4", + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "readable-stream": "^2.0.2" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/easy-stack": { - "version": "1.0.1", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, - "node_modules/electron-to-chromium": { - "version": "1.5.24", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", - "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==", - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", + "node_modules/eslint/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/envinfo": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", - "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "license": "MIT", - "dependencies": { - "stackframe": "^1.3.4" + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/errorhandler": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", - "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.7", - "escape-html": "~1.0.3" + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">=6" + "node": ">=0.10" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=0.8.0" + "node": ">=4.0" } }, - "node_modules/esprima": { - "version": "4.0.1", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, "engines": { - "node": ">=4" + "node": ">=4.0" } }, "node_modules/esutils": { @@ -4833,7 +6775,6 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4887,21 +6828,25 @@ }, "node_modules/exit": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/expect": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4918,44 +6863,70 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", - "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" @@ -4965,6 +6936,7 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -4977,6 +6949,19 @@ "bser": "2.1.1" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "license": "MIT", @@ -5005,33 +6990,6 @@ "node": ">= 0.8" } }, - "node_modules/find-babel-config": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.2.tgz", - "integrity": "sha512-oK59njMyw2y3yxto1BCfVK7MQp/OYf4FleHu0RgosH3riFJ1aOuo/7naLDLAObfrgn3ueFhw5sAT/cp0QuJI3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "json5": "^1.0.2", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-babel-config/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, "node_modules/find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -5071,6 +7029,19 @@ "node": ">=6" } }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/find-cache-dir/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -5110,6 +7081,15 @@ "node": ">=6" } }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/find-up": { "version": "4.1.0", "license": "MIT", @@ -5136,6 +7116,28 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/flow-enums-runtime": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", @@ -5143,14 +7145,30 @@ "license": "MIT" }, "node_modules/flow-parser": { - "version": "0.246.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.246.0.tgz", - "integrity": "sha512-WHRizzSrWFTcKo7cVcbP3wzZVhzsoYxoWqbnH4z+JXGqrjVmnsld6kBZWVlB200PwD5ur8r+HV3KUDxv3cHhOQ==", + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", "license": "MIT", "engines": { "node": ">=0.4.0" } }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -5161,17 +7179,18 @@ } }, "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=14.14" } }, "node_modules/fs.realpath": { @@ -5190,8 +7209,44 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "license": "MIT" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/funpermaproxy": { "version": "1.1.0", @@ -5215,6 +7270,31 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "dev": true, @@ -5223,6 +7303,20 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -5235,6 +7329,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.3", "license": "ISC", @@ -5254,15 +7366,16 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/globals": { @@ -5272,18 +7385,79 @@ "node": ">=4" } }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "license": "ISC" }, - "node_modules/has": { - "version": "1.0.3", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { @@ -5293,23 +7467,116 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hermes-estree": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.22.0.tgz", - "integrity": "sha512-FLBt5X9OfA8BERUdc6aZS36Xz3rRuB0Y/mfocSADWEJfomc1xfene33GdyAmtTkKTBXTN/EgAy+rjTKkkZJHlw==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", + "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", "license": "MIT" }, "node_modules/hermes-parser": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.22.0.tgz", - "integrity": "sha512-gn5RfZiEXCsIWsFGsKiykekktUoh0PdFWYocXsUdZIyWSckT6UIyPcyyUIPSR3kpnELWeK3n3ztAse7Mat6PSA==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", + "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.15.0" + } + }, + "node_modules/hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", "license": "MIT", "dependencies": { - "hermes-estree": "0.22.0" + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-profile-transformer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" } }, "node_modules/html-escaper": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" }, @@ -5365,6 +7632,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/image-size": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", @@ -5381,9 +7658,10 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -5400,13 +7678,16 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/import-local": { - "version": "3.1.0", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", "dependencies": { @@ -5447,6 +7728,21 @@ "dev": true, "license": "ISC" }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -5456,15 +7752,139 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "license": "MIT" }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { - "version": "2.9.0", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, "license": "MIT", "dependencies": { - "has": "^1.0.3" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5498,11 +7918,28 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "license": "MIT", @@ -5512,75 +7949,282 @@ }, "node_modules/is-generator-fn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "which-typed-array": "^1.1.16" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-wsl": { @@ -5636,34 +8280,24 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5676,11 +8310,13 @@ } }, "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.4", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -5692,12 +8328,16 @@ } }, "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/istanbul-reports": { - "version": "3.1.5", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5708,15 +8348,35 @@ "node": ">=8" } }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/jest": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -5734,11 +8394,14 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { @@ -5746,27 +8409,29 @@ } }, "node_modules/jest-circus": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -5776,21 +8441,22 @@ } }, "node_modules/jest-cli": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "bin": { @@ -5809,30 +8475,32 @@ } }, "node_modules/jest-config": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -5852,90 +8520,26 @@ } } }, - "node_modules/jest-config/node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/jest-config/node_modules/babel-jest": { - "version": "29.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.5.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/jest-config/node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/jest-config/node_modules/babel-preset-jest": { - "version": "29.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/jest-diff": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "license": "MIT", "dependencies": { @@ -5946,15 +8550,17 @@ } }, "node_modules/jest-each": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5987,19 +8593,21 @@ } }, "node_modules/jest-haste-map": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -6011,26 +8619,30 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -6072,6 +8684,8 @@ }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", "engines": { @@ -6087,7 +8701,9 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", "engines": { @@ -6095,16 +8711,18 @@ } }, "node_modules/jest-resolve": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -6114,68 +8732,45 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve/node_modules/is-core-module": { - "version": "2.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/jest-resolve/node_modules/resolve": { - "version": "1.22.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/jest-runner": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -6184,30 +8779,32 @@ } }, "node_modules/jest-runtime": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -6216,78 +8813,43 @@ } }, "node_modules/jest-snapshot": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/jest-snapshot/node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.5.4", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -6330,17 +8892,19 @@ } }, "node_modules/jest-watcher": { - "version": "29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { @@ -6467,16 +9031,36 @@ "@babel/preset-env": "^7.1.6" } }, + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "node_modules/jsesc": { - "version": "2.5.2", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-cycle": { "version": "1.4.0", "dev": true, @@ -6493,6 +9077,9 @@ }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { @@ -6500,6 +9087,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -6513,12 +9107,44 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -6530,6 +9156,8 @@ }, "node_modules/kleur": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "license": "MIT", "engines": { "node": ">=6" @@ -6542,6 +9170,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lighthouse-logger": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", @@ -6554,6 +9196,9 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, "license": "MIT" }, "node_modules/locate-path": { @@ -6575,6 +9220,13 @@ "version": "4.0.8", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -6708,25 +9360,32 @@ } }, "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, "license": "MIT", "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, "license": "ISC", "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/makeerror": { @@ -6742,6 +9401,16 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "license": "Apache-2.0" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/memoize-one": { "version": "5.2.1", "license": "MIT" @@ -6754,6 +9423,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -6890,56 +9560,6 @@ "node": ">=18" } }, - "node_modules/metro-config/node_modules/cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "license": "MIT", - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "license": "MIT", - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/metro-core": { "version": "0.80.12", "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.12.tgz", @@ -6992,56 +9612,6 @@ "node": ">=18" } }, - "node_modules/metro-react-native-babel-preset": { - "version": "0.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.14.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-assign": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "react-refresh": "^0.4.0" - }, - "peerDependencies": { - "@babel/core": "*" - } - }, "node_modules/metro-resolver": { "version": "0.80.12", "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.12.tgz", @@ -7374,6 +9944,13 @@ "dev": true, "license": "MIT" }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, "node_modules/ncp": { "version": "2.0.0", "dev": true, @@ -7445,15 +10022,6 @@ } } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "license": "MIT" @@ -7537,12 +10105,108 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -7605,6 +10269,24 @@ "node": ">=4" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -7628,8 +10310,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -7675,6 +10377,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -7685,6 +10388,9 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -7735,6 +10441,16 @@ "version": "1.0.7", "license": "MIT" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -7771,6 +10487,8 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7780,63 +10498,53 @@ "node": ">=8" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" + "bin": { + "prettier": "bin-prettier.js" }, "engines": { - "node": ">=6" + "node": ">=10.13.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, "node_modules/pretty-format": { @@ -7881,6 +10589,8 @@ }, "node_modules/prompts": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "license": "MIT", "dependencies": { "kleur": "^3.0.3", @@ -7890,6 +10600,23 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/proper-lockfile": { "version": "3.2.0", "dev": true, @@ -7914,7 +10641,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.1", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -7941,6 +10670,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -7977,9 +10707,9 @@ } }, "node_modules/react-devtools-core": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.1.tgz", - "integrity": "sha512-7FSb9meX0btdBQLwdFOwt6bGqvRPabmVMMslv8fgoSPqXyuGpgQe36kx8gR86XPw7aV1yVouTp6fyZ0EH+NfUw==", + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", "license": "MIT", "dependencies": { "shell-quote": "^1.6.1", @@ -7991,31 +10721,30 @@ "license": "MIT" }, "node_modules/react-native": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.75.3.tgz", - "integrity": "sha512-+Ne6u5H+tPo36sme19SCd1u2UID2uo0J/XzAJarxmrDj4Nsdi44eyUDKtQHmhgxjRGsuVJqAYrMK0abLSq8AHw==", + "version": "0.73.11", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.11.tgz", + "integrity": "sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg==", "license": "MIT", "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "14.1.0", - "@react-native-community/cli-platform-android": "14.1.0", - "@react-native-community/cli-platform-ios": "14.1.0", - "@react-native/assets-registry": "0.75.3", - "@react-native/codegen": "0.75.3", - "@react-native/community-cli-plugin": "0.75.3", - "@react-native/gradle-plugin": "0.75.3", - "@react-native/js-polyfills": "0.75.3", - "@react-native/normalize-colors": "0.75.3", - "@react-native/virtualized-lists": "0.75.3", + "@react-native-community/cli": "12.3.7", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-platform-ios": "12.3.7", + "@react-native/assets-registry": "0.73.1", + "@react-native/codegen": "0.73.3", + "@react-native/community-cli-plugin": "0.73.18", + "@react-native/gradle-plugin": "0.73.5", + "@react-native/js-polyfills": "0.73.1", + "@react-native/normalize-colors": "0.73.2", + "@react-native/virtualized-lists": "0.73.4", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "base64-js": "^1.5.1", "chalk": "^4.0.0", - "commander": "^9.4.1", + "deprecated-react-native-prop-types": "^5.0.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", - "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.6.3", "jsc-android": "^250231.0.0", @@ -8026,11 +10755,11 @@ "nullthrows": "^1.1.1", "pretty-format": "^26.5.2", "promise": "^8.3.0", - "react-devtools-core": "^5.3.1", + "react-devtools-core": "^4.27.7", "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.24.0-canary-efb381bbf-20230505", - "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.2", @@ -8043,13 +10772,7 @@ "node": ">=18" }, "peerDependencies": { - "@types/react": "^18.2.6", - "react": "^18.2.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "react": "18.2.0" } }, "node_modules/react-native-fs": { @@ -8116,18 +10839,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-native/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/react-native/node_modules/ws": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", @@ -8137,12 +10848,42 @@ "async-limiter": "~1.0.0" } }, - "node_modules/react-refresh": { - "version": "0.4.3", + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-test-renderer": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz", + "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "react-is": "^18.2.0", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-test-renderer/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" } }, "node_modules/readable-stream": { @@ -8179,6 +10920,29 @@ "node": ">= 4" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -8210,6 +10974,27 @@ "@babel/runtime": "^7.8.4" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpu-core": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", @@ -8268,11 +11053,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "license": "ISC" }, - "node_modules/reselect": { - "version": "4.1.6", - "dev": true, - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.0", "license": "MIT", @@ -8290,6 +11070,8 @@ }, "node_modules/resolve-cwd": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "license": "MIT", "dependencies": { @@ -8308,7 +11090,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "license": "MIT", "engines": { @@ -8340,6 +11124,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -8366,6 +11151,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -8385,6 +11171,33 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.1.2", "license": "MIT" @@ -8395,6 +11208,48 @@ "license": "MIT", "optional": true }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sanitize-filename": { "version": "1.6.3", "dev": true, @@ -8412,19 +11267,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "license": "MIT", - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semver": { "version": "6.3.1", "license": "ISC", @@ -8539,6 +11381,55 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -8587,12 +11478,90 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "license": "ISC" }, "node_modules/sisteransi": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "license": "MIT" }, "node_modules/slash": { @@ -8661,6 +11630,8 @@ }, "node_modules/source-map-support": { "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", "dependencies": { @@ -8743,6 +11714,8 @@ }, "node_modules/string-length": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8753,6 +11726,13 @@ "node": ">=10" } }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true, + "license": "MIT" + }, "node_modules/string-width": { "version": "4.2.3", "license": "MIT", @@ -8765,6 +11745,104 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "license": "MIT", @@ -8777,6 +11855,8 @@ }, "node_modules/strip-bom": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", "engines": { @@ -8792,6 +11872,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -8802,15 +11884,22 @@ } }, "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "license": "MIT" }, "node_modules/sudo-prompt": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT" }, "node_modules/supports-color": { @@ -8937,6 +12026,13 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -8957,13 +12053,6 @@ "version": "1.0.5", "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "license": "MIT", @@ -9017,11 +12106,47 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, "license": "0BSD" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "license": "MIT", @@ -9040,6 +12165,117 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", @@ -9081,10 +12317,13 @@ } }, "node_modules/universalify": { - "version": "0.1.2", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -9165,23 +12404,20 @@ } }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -9244,12 +12480,118 @@ "which": "bin/which" } }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "license": "ISC" }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "license": "MIT", @@ -9270,14 +12612,17 @@ "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, "license": "ISC", "dependencies": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/ws": { @@ -9323,9 +12668,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -9353,11 +12698,12 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "dev": true, + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -9385,17 +12731,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "license": "MIT", "engines": { "node": ">=10" diff --git a/js/react_native/e2e/yarn.lock b/js/react_native/e2e/yarn.lock deleted file mode 100644 index 32bb0eea55bc5..0000000000000 --- a/js/react_native/e2e/yarn.lock +++ /dev/null @@ -1,7216 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== - dependencies: - "@babel/helper-validator-identifier" "^7.25.9" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5", "@babel/compat-data@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== - -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.20.0", "@babel/core@^7.23.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" - integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.9" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.9" - "@babel/parser" "^7.26.9" - "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.9" - "@babel/types" "^7.26.9" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/eslint-parser@^7.20.0": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz#55c4f4aae4970ae127f7a12369182ed6250e6f09" - integrity sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg== - dependencies: - "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" - eslint-visitor-keys "^2.1.0" - semver "^6.3.1" - -"@babel/generator@^7.20.0", "@babel/generator@^7.26.9", "@babel/generator@^7.7.2": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" - integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== - dependencies: - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/helper-annotate-as-pure@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" - integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== - dependencies: - "@babel/types" "^7.25.9" - -"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" - integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== - dependencies: - "@babel/compat-data" "^7.26.5" - "@babel/helper-validator-option" "^7.25.9" - browserslist "^4.24.0" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" - integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.26.9" - semver "^6.3.1" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz#5169756ecbe1d95f7866b90bb555b022595302a0" - integrity sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - regexpu-core "^6.2.0" - semver "^6.3.1" - -"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": - version "0.6.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" - integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" - integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== - dependencies: - "@babel/types" "^7.24.7" - -"@babel/helper-member-expression-to-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" - integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-optimise-call-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" - integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== - dependencies: - "@babel/types" "^7.25.9" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" - integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== - -"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" - integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-wrap-function" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" - integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/traverse" "^7.26.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" - integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== - -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== - -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== - -"@babel/helper-wrap-function@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" - integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== - dependencies: - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helpers@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" - integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== - dependencies: - "@babel/template" "^7.26.9" - "@babel/types" "^7.26.9" - -"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" - integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== - dependencies: - "@babel/types" "^7.26.9" - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" - integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" - integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" - integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" - integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-transform-optional-chaining" "^7.25.9" - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" - integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-proposal-async-generator-functions@^7.0.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-export-default-from@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz#52702be6ef8367fc8f18b8438278332beeb8f87c" - integrity sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.20.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" - integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== - dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.20.7" - -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" - integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - version "7.21.0-placeholder-for-preset-env.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" - integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-dynamic-import@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-default-from@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz#86614767a9ff140366f0c3766ef218beb32a730a" - integrity sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz#96507595c21b45fccfc2bc758d5c45452e6164fa" - integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-import-assertions@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" - integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-import-attributes@^7.24.7", "@babel/plugin-syntax-import-attributes@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" - integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-import-meta@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.25.9", "@babel/plugin-syntax-jsx@^7.7.2": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" - integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.25.9", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" - integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" - integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" - integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-async-generator-functions@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" - integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-remap-async-to-generator" "^7.25.9" - "@babel/traverse" "^7.26.8" - -"@babel/plugin-transform-async-to-generator@^7.20.0", "@babel/plugin-transform-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" - integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-remap-async-to-generator" "^7.25.9" - -"@babel/plugin-transform-block-scoped-functions@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" - integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" - integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-class-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" - integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-class-static-block@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" - integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" - integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - "@babel/traverse" "^7.25.9" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" - integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/template" "^7.25.9" - -"@babel/plugin-transform-destructuring@^7.20.0", "@babel/plugin-transform-destructuring@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" - integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-dotall-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" - integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-duplicate-keys@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" - integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" - integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-dynamic-import@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" - integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-exponentiation-operator@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz#e29f01b6de302c7c2c794277a48f04a9ca7f03bc" - integrity sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-export-namespace-from@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" - integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.25.9": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz#2904c85a814e7abb1f4850b8baf4f07d0a2389d4" - integrity sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/plugin-syntax-flow" "^7.26.0" - -"@babel/plugin-transform-for-of@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz#27231f79d5170ef33b5111f07fe5cafeb2c96a56" - integrity sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" - integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== - dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-transform-json-strings@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" - integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" - integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-logical-assignment-operators@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" - integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-member-expression-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" - integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-amd@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" - integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== - dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.25.9", "@babel/plugin-transform-modules-commonjs@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" - integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== - dependencies: - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-systemjs@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" - integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== - dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-transform-modules-umd@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" - integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== - dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" - integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-new-target@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" - integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": - version "7.26.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe" - integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-numeric-separator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" - integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-object-rest-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" - integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== - dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/plugin-transform-parameters" "^7.25.9" - -"@babel/plugin-transform-object-super@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" - integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - -"@babel/plugin-transform-optional-catch-binding@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" - integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" - integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" - integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" - integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-private-property-in-object@^7.22.11", "@babel/plugin-transform-private-property-in-object@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" - integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-property-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" - integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-display-name@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" - integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx-self@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" - integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx-source@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" - integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" - integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/plugin-syntax-jsx" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/plugin-transform-regenerator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b" - integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - regenerator-transform "^0.15.2" - -"@babel/plugin-transform-regexp-modifiers@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" - integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-reserved-words@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" - integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-runtime@^7.0.0": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" - integrity sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.26.5" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.6" - babel-plugin-polyfill-regenerator "^0.6.1" - semver "^6.3.1" - -"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" - integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" - integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" - integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-template-literals@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" - integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-typeof-symbol@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz#d0e33acd9223744c1e857dbd6fa17bd0a3786937" - integrity sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-typescript@^7.25.9", "@babel/plugin-transform-typescript@^7.5.0": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" - integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-syntax-typescript" "^7.25.9" - -"@babel/plugin-transform-unicode-escapes@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" - integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-unicode-property-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" - integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" - integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-unicode-sets-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" - integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/preset-env@^7.20.0": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.9.tgz#2ec64e903d0efe743699f77a10bdf7955c2123c3" - integrity sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ== - dependencies: - "@babel/compat-data" "^7.26.8" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.9" - "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.9" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.9" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.25.9" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.9" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-import-assertions" "^7.26.0" - "@babel/plugin-syntax-import-attributes" "^7.26.0" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.25.9" - "@babel/plugin-transform-async-generator-functions" "^7.26.8" - "@babel/plugin-transform-async-to-generator" "^7.25.9" - "@babel/plugin-transform-block-scoped-functions" "^7.26.5" - "@babel/plugin-transform-block-scoping" "^7.25.9" - "@babel/plugin-transform-class-properties" "^7.25.9" - "@babel/plugin-transform-class-static-block" "^7.26.0" - "@babel/plugin-transform-classes" "^7.25.9" - "@babel/plugin-transform-computed-properties" "^7.25.9" - "@babel/plugin-transform-destructuring" "^7.25.9" - "@babel/plugin-transform-dotall-regex" "^7.25.9" - "@babel/plugin-transform-duplicate-keys" "^7.25.9" - "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.9" - "@babel/plugin-transform-dynamic-import" "^7.25.9" - "@babel/plugin-transform-exponentiation-operator" "^7.26.3" - "@babel/plugin-transform-export-namespace-from" "^7.25.9" - "@babel/plugin-transform-for-of" "^7.26.9" - "@babel/plugin-transform-function-name" "^7.25.9" - "@babel/plugin-transform-json-strings" "^7.25.9" - "@babel/plugin-transform-literals" "^7.25.9" - "@babel/plugin-transform-logical-assignment-operators" "^7.25.9" - "@babel/plugin-transform-member-expression-literals" "^7.25.9" - "@babel/plugin-transform-modules-amd" "^7.25.9" - "@babel/plugin-transform-modules-commonjs" "^7.26.3" - "@babel/plugin-transform-modules-systemjs" "^7.25.9" - "@babel/plugin-transform-modules-umd" "^7.25.9" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.25.9" - "@babel/plugin-transform-new-target" "^7.25.9" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.26.6" - "@babel/plugin-transform-numeric-separator" "^7.25.9" - "@babel/plugin-transform-object-rest-spread" "^7.25.9" - "@babel/plugin-transform-object-super" "^7.25.9" - "@babel/plugin-transform-optional-catch-binding" "^7.25.9" - "@babel/plugin-transform-optional-chaining" "^7.25.9" - "@babel/plugin-transform-parameters" "^7.25.9" - "@babel/plugin-transform-private-methods" "^7.25.9" - "@babel/plugin-transform-private-property-in-object" "^7.25.9" - "@babel/plugin-transform-property-literals" "^7.25.9" - "@babel/plugin-transform-regenerator" "^7.25.9" - "@babel/plugin-transform-regexp-modifiers" "^7.26.0" - "@babel/plugin-transform-reserved-words" "^7.25.9" - "@babel/plugin-transform-shorthand-properties" "^7.25.9" - "@babel/plugin-transform-spread" "^7.25.9" - "@babel/plugin-transform-sticky-regex" "^7.25.9" - "@babel/plugin-transform-template-literals" "^7.26.8" - "@babel/plugin-transform-typeof-symbol" "^7.26.7" - "@babel/plugin-transform-unicode-escapes" "^7.25.9" - "@babel/plugin-transform-unicode-property-regex" "^7.25.9" - "@babel/plugin-transform-unicode-regex" "^7.25.9" - "@babel/plugin-transform-unicode-sets-regex" "^7.25.9" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.11.0" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.40.0" - semver "^6.3.1" - -"@babel/preset-flow@^7.13.13": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.25.9.tgz#ef8b5e7e3f24a42b3711e77fb14919b87dffed0a" - integrity sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-transform-flow-strip-types" "^7.25.9" - -"@babel/preset-modules@0.1.6-no-external-plugins": - version "0.1.6-no-external-plugins" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" - integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-typescript@^7.13.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" - integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-syntax-jsx" "^7.25.9" - "@babel/plugin-transform-modules-commonjs" "^7.25.9" - "@babel/plugin-transform-typescript" "^7.25.9" - -"@babel/register@^7.13.16": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.25.9.tgz#1c465acf7dc983d70ccc318eb5b887ecb04f021b" - integrity sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA== - dependencies: - clone-deep "^4.0.1" - find-cache-dir "^2.0.0" - make-dir "^2.1.0" - pirates "^4.0.6" - source-map-support "^0.5.16" - -"@babel/runtime@^7.20.0", "@babel/runtime@^7.25.0", "@babel/runtime@^7.8.4": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" - integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.0.0", "@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.3.3": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" - integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" - -"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" - integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.9" - "@babel/parser" "^7.26.9" - "@babel/template" "^7.26.9" - "@babel/types" "^7.26.9" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" - integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== - dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@eslint-community/eslint-utils@^4.2.0": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" - integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== - dependencies: - eslint-visitor-keys "^3.4.3" - -"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" - integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.1": - version "8.57.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" - integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== - -"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" - integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== - -"@hapi/topo@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@humanwhocodes/config-array@^0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" - integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== - dependencies: - "@humanwhocodes/object-schema" "^2.0.3" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== - -"@isaacs/ttlcache@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" - integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/create-cache-key-function@^29.6.3": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" - integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== - dependencies: - "@jest/types" "^29.6.3" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - -"@jest/types@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" - integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": - version "5.1.1-v1" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" - integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== - dependencies: - eslint-scope "5.1.1" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@react-native-community/cli-clean@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz#303ddf1c930918a8bdc4cc58fe0ac2dd05603cd5" - integrity sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - execa "^5.0.0" - -"@react-native-community/cli-config@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-12.3.7.tgz#feb8b93e8ccd6116ac1df0f1d8a0f06872388e51" - integrity sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - cosmiconfig "^5.1.0" - deepmerge "^4.3.0" - glob "^7.1.3" - joi "^17.2.1" - -"@react-native-community/cli-debugger-ui@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz#522aa11c7b4ff4a2ec86492fabee0366d5428b4c" - integrity sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q== - dependencies: - serve-static "^1.13.1" - -"@react-native-community/cli-doctor@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz#31e4784182d6bbfe62f2e728dca87ee23efe0564" - integrity sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg== - dependencies: - "@react-native-community/cli-config" "12.3.7" - "@react-native-community/cli-platform-android" "12.3.7" - "@react-native-community/cli-platform-ios" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - command-exists "^1.2.8" - deepmerge "^4.3.0" - envinfo "^7.10.0" - execa "^5.0.0" - hermes-profile-transformer "^0.0.6" - node-stream-zip "^1.9.1" - ora "^5.4.1" - semver "^7.5.2" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - yaml "^2.2.1" - -"@react-native-community/cli-hermes@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz#4a284e0091469f6cce8caad2fefcf6b45c0cf229" - integrity sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg== - dependencies: - "@react-native-community/cli-platform-android" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - hermes-profile-transformer "^0.0.6" - -"@react-native-community/cli-platform-android@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz#4826f5126f950e29d7ef1ac779c4eed56d251f98" - integrity sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.2.4" - glob "^7.1.3" - logkitty "^0.7.1" - -"@react-native-community/cli-platform-ios@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz#ef90e5c4d9ff5f15071b18179b17cf16699a70e5" - integrity sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.0.12" - glob "^7.1.3" - ora "^5.4.1" - -"@react-native-community/cli-plugin-metro@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz#f9be724721a52d800a20f641a2241a7b4e6a9477" - integrity sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg== - -"@react-native-community/cli-server-api@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz#81e2a067c120391242740598010abb8d5d36a739" - integrity sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg== - dependencies: - "@react-native-community/cli-debugger-ui" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - compression "^1.7.1" - connect "^3.6.5" - errorhandler "^1.5.1" - nocache "^3.0.1" - pretty-format "^26.6.2" - serve-static "^1.13.1" - ws "^7.5.1" - -"@react-native-community/cli-tools@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz#65cf1c81d13662a1b0396c753e6ff916e3e92083" - integrity sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - find-up "^5.0.0" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - ora "^5.4.1" - semver "^7.5.2" - shell-quote "^1.7.3" - sudo-prompt "^9.0.0" - -"@react-native-community/cli-types@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-12.3.7.tgz#6f55becdc41bb5ebf1a8f6fd27ad0d198831169d" - integrity sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w== - dependencies: - joi "^17.2.1" - -"@react-native-community/cli@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-12.3.7.tgz#8f53ec9310367a0204d859005e9cd137f9888382" - integrity sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ== - dependencies: - "@react-native-community/cli-clean" "12.3.7" - "@react-native-community/cli-config" "12.3.7" - "@react-native-community/cli-debugger-ui" "12.3.7" - "@react-native-community/cli-doctor" "12.3.7" - "@react-native-community/cli-hermes" "12.3.7" - "@react-native-community/cli-plugin-metro" "12.3.7" - "@react-native-community/cli-server-api" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - "@react-native-community/cli-types" "12.3.7" - chalk "^4.1.2" - commander "^9.4.1" - deepmerge "^4.3.0" - execa "^5.0.0" - find-up "^4.1.0" - fs-extra "^8.1.0" - graceful-fs "^4.1.3" - prompts "^2.4.2" - semver "^7.5.2" - -"@react-native/assets-registry@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.73.1.tgz#e2a6b73b16c183a270f338dc69c36039b3946e85" - integrity sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg== - -"@react-native/babel-plugin-codegen@0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz#8a2037d5585b41877611498ae66adbf1dddfec1b" - integrity sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ== - dependencies: - "@react-native/codegen" "0.73.3" - -"@react-native/babel-preset@0.73.21": - version "0.73.21" - resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.73.21.tgz#174c16493fa4e311b2f5f0c58d4f3c6a5a68bbea" - integrity sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-private-methods" "^7.22.5" - "@babel/plugin-transform-private-property-in-object" "^7.22.11" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - "@react-native/babel-plugin-codegen" "0.73.4" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.14.0" - -"@react-native/codegen@0.73.3": - version "0.73.3" - resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.73.3.tgz#cc984a8b17334d986cc600254a0d4b7fa7d68a94" - integrity sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg== - dependencies: - "@babel/parser" "^7.20.0" - flow-parser "^0.206.0" - glob "^7.1.1" - invariant "^2.2.4" - jscodeshift "^0.14.0" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - -"@react-native/community-cli-plugin@0.73.18": - version "0.73.18" - resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz#ba2a0933fad574684534eea29f1c5d2cab494854" - integrity sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww== - dependencies: - "@react-native-community/cli-server-api" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - "@react-native/dev-middleware" "0.73.8" - "@react-native/metro-babel-transformer" "0.73.15" - chalk "^4.0.0" - execa "^5.1.1" - metro "^0.80.3" - metro-config "^0.80.3" - metro-core "^0.80.3" - node-fetch "^2.2.0" - readline "^1.3.0" - -"@react-native/debugger-frontend@0.73.3": - version "0.73.3" - resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz#033757614d2ada994c68a1deae78c1dd2ad33c2b" - integrity sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw== - -"@react-native/dev-middleware@0.73.8": - version "0.73.8" - resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz#2e43722a00c7b8db753f747f40267cbad6caba4d" - integrity sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg== - dependencies: - "@isaacs/ttlcache" "^1.4.1" - "@react-native/debugger-frontend" "0.73.3" - chrome-launcher "^0.15.2" - chromium-edge-launcher "^1.0.0" - connect "^3.6.5" - debug "^2.2.0" - node-fetch "^2.2.0" - open "^7.0.3" - serve-static "^1.13.1" - temp-dir "^2.0.0" - ws "^6.2.2" - -"@react-native/eslint-config@^0.73.2": - version "0.73.2" - resolved "https://registry.yarnpkg.com/@react-native/eslint-config/-/eslint-config-0.73.2.tgz#40b2cd8ce245e90c885b8ab15fae1219a946bfac" - integrity sha512-YzMfes19loTfbrkbYNAfHBDXX4oRBzc5wnvHs4h2GIHUj6YKs5ZK5lldqSrBJCdZAI3nuaO9Qj+t5JRwou571w== - dependencies: - "@babel/core" "^7.20.0" - "@babel/eslint-parser" "^7.20.0" - "@react-native/eslint-plugin" "0.73.1" - "@typescript-eslint/eslint-plugin" "^5.57.1" - "@typescript-eslint/parser" "^5.57.1" - eslint-config-prettier "^8.5.0" - eslint-plugin-eslint-comments "^3.2.0" - eslint-plugin-ft-flow "^2.0.1" - eslint-plugin-jest "^26.5.3" - eslint-plugin-prettier "^4.2.1" - eslint-plugin-react "^7.30.1" - eslint-plugin-react-hooks "^4.6.0" - eslint-plugin-react-native "^4.0.0" - -"@react-native/eslint-plugin@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/eslint-plugin/-/eslint-plugin-0.73.1.tgz#79d2c4d90c80bfad8900db335bfbaf1ca599abdc" - integrity sha512-8BNMFE8CAI7JLWLOs3u33wcwcJ821LYs5g53Xyx9GhSg0h8AygTwDrwmYb/pp04FkCNCPjKPBoaYRthQZmxgwA== - -"@react-native/gradle-plugin@0.73.5": - version "0.73.5" - resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz#900126b4e5737eaac22a0fddb2fc5b4cc20da41c" - integrity sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA== - -"@react-native/js-polyfills@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz#730b0a7aaab947ae6f8e5aa9d995e788977191ed" - integrity sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g== - -"@react-native/metro-babel-transformer@0.73.15": - version "0.73.15" - resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz#c516584dde62d65a46668074084359c03e6a50f1" - integrity sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw== - dependencies: - "@babel/core" "^7.20.0" - "@react-native/babel-preset" "0.73.21" - hermes-parser "0.15.0" - nullthrows "^1.1.1" - -"@react-native/metro-config@^0.73.5": - version "0.73.5" - resolved "https://registry.yarnpkg.com/@react-native/metro-config/-/metro-config-0.73.5.tgz#791242ca93057d7299ce18379ea11d3bdb368ea9" - integrity sha512-3bNWoHzOzP/+qoLJtRhOVXrnxKmSY3i4y5PXyMQlIvvOI/GQbXulPpEZxK/yUrf1MmeXHLLFufFbQWlfDEDoxA== - dependencies: - "@react-native/js-polyfills" "0.73.1" - "@react-native/metro-babel-transformer" "0.73.15" - metro-config "^0.80.3" - metro-runtime "^0.80.3" - -"@react-native/normalize-colors@0.73.2", "@react-native/normalize-colors@^0.73.0": - version "0.73.2" - resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz#cc8e48fbae2bbfff53e12f209369e8d2e4cf34ec" - integrity sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w== - -"@react-native/typescript-config@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/typescript-config/-/typescript-config-0.73.1.tgz#c97a42f5cd264069bfe86b737c531ed2f042ae6d" - integrity sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w== - -"@react-native/virtualized-lists@0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz#640e594775806f63685435b5d9c3d05c378ccd8c" - integrity sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog== - dependencies: - invariant "^2.2.4" - nullthrows "^1.1.1" - -"@sideway/address@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" - integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" - integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== - -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@types/babel__core@^7.1.14": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.6" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" - integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== - dependencies: - "@babel/types" "^7.20.7" - -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/json-schema@^7.0.9": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/node@*": - version "22.13.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.4.tgz#3fe454d77cd4a2d73c214008b3e331bfaaf5038a" - integrity sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg== - dependencies: - undici-types "~6.20.0" - -"@types/prop-types@*": - version "15.7.14" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" - integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== - -"@types/react-test-renderer@^18.0.0": - version "18.3.1" - resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.3.1.tgz#225bfe8d4ad7ee3b04c2fa27642bb74274a5961d" - integrity sha512-vAhnk0tG2eGa37lkU9+s5SoroCsRI08xnsWFiAXOuPH2jqzMbcXvKExXViPi1P5fIklDeCvXqyrdmipFaSkZrA== - dependencies: - "@types/react" "^18" - -"@types/react@^18", "@types/react@^18.2.6": - version "18.3.18" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" - integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/semver@^7.3.12": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^15.0.0": - version "15.0.19" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.19.tgz#328fb89e46109ecbdb70c295d96ff2f46dfd01b9" - integrity sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA== - dependencies: - "@types/yargs-parser" "*" - -"@types/yargs@^17.0.8": - version "17.0.33" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" - integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^5.57.1": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" - integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== - dependencies: - "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/type-utils" "5.62.0" - "@typescript-eslint/utils" "5.62.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.57.1": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" - integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== - dependencies: - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - -"@typescript-eslint/type-utils@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" - integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== - dependencies: - "@typescript-eslint/typescript-estree" "5.62.0" - "@typescript-eslint/utils" "5.62.0" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== - -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" - -"@ungap/structured-clone@^1.2.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" - integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -accepts@^1.3.7, accepts@~1.3.7: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.8.2, acorn@^8.9.0: - version "8.14.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.6.3: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - -anser@^1.4.9: - version "1.4.10" - resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" - integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-fragments@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" - integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== - dependencies: - colorette "^1.0.7" - slice-ansi "^2.0.0" - strip-ansi "^5.0.0" - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-regex@^5.0.0, ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -appdirsjs@^1.2.4: - version "1.2.7" - resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" - integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" - integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== - dependencies: - call-bound "^1.0.3" - is-array-buffer "^3.0.5" - -array-includes@^3.1.6, array-includes@^3.1.8: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.findlast@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" - integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" - integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-shim-unscopables "^1.0.2" - -array.prototype.flatmap@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" - integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-shim-unscopables "^1.0.2" - -array.prototype.tosorted@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" - integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.3" - es-errors "^1.3.0" - es-shim-unscopables "^1.0.2" - -arraybuffer.prototype.slice@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" - integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.6" - is-array-buffer "^3.0.4" - -asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -ast-types@0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d" - integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== - dependencies: - tslib "^2.0.1" - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-function@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" - integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -babel-core@^7.0.0-bridge.0: - version "7.0.0-bridge.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" - integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== - -babel-jest@^29.6.3, babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.12" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" - integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.3" - semver "^6.3.1" - -babel-plugin-polyfill-corejs3@^0.10.6: - version "0.10.6" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" - integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.2" - core-js-compat "^3.38.0" - -babel-plugin-polyfill-corejs3@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz#4e4e182f1bb37c7ba62e2af81d8dd09df31344f6" - integrity sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.3" - core-js-compat "^3.40.0" - -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" - integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.3" - -babel-plugin-transform-flow-enums@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25" - integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ== - dependencies: - "@babel/plugin-syntax-flow" "^7.12.1" - -babel-preset-current-node-syntax@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" - integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-import-attributes" "^7.24.7" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base-64@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" - integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== - -base64-js@^1.3.1, base64-js@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -bluebird@^3.5.4: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - -browserslist@^4.24.0, browserslist@^4.24.3: - version "4.24.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== - dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" - node-releases "^2.0.19" - update-browserslist-db "^1.1.1" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bunyan-debug-stream@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bunyan-debug-stream/-/bunyan-debug-stream-3.1.1.tgz#e3bcb36bbf95f11b5945891cf2618625fe64985c" - integrity sha512-LfMcz4yKM6s9BP5dfT63Prb5B2hAjReLAfQzLbNQF7qBHtn3P1v+/yn0SZ6UAr4PC3VZRX/QzK7HYkkY0ytokQ== - dependencies: - chalk "^4.1.2" - -bunyan@^1.8.12: - version "1.8.15" - resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.15.tgz#8ce34ca908a17d0776576ca1b2f6cbd916e93b46" - integrity sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig== - optionalDependencies: - dtrace-provider "~0.8" - moment "^2.19.3" - mv "~2" - safe-json-stringify "~1" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -caf@^15.0.1: - version "15.0.1" - resolved "https://registry.yarnpkg.com/caf/-/caf-15.0.1.tgz#28f1f17bd93dc4b5d95207ad07066eddf4768160" - integrity sha512-Xp/IK6vMwujxWZXra7djdYzPdPnEQKa7Mudu2wZgDQ3TJry1I0TgtjEgwZHpoBcMp68j4fb0/FZ1SJyMEgJrXQ== - -call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" - integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - -call-bind@^1.0.7, call-bind@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" - integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== - dependencies: - call-bind-apply-helpers "^1.0.0" - es-define-property "^1.0.0" - get-intrinsic "^1.2.4" - set-function-length "^1.2.2" - -call-bound@^1.0.2, call-bound@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" - integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== - dependencies: - call-bind-apply-helpers "^1.0.1" - get-intrinsic "^1.2.6" - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.0.0, camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001688: - version "1.0.30001700" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" - integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== - -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -child-process-promise@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-2.2.1.tgz#4730a11ef610fad450b8f223c79d31d7bdad8074" - integrity sha512-Fi4aNdqBsr0mv+jgWxcZ/7rAIC2mgihrptyVI4foh/rrjY/3BNjfP9+oaiFx/fzim+1ZyCNBae0DlyfQhSugog== - dependencies: - cross-spawn "^4.0.2" - node-version "^1.0.0" - promise-polyfill "^6.0.1" - -chrome-launcher@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" - integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== - dependencies: - "@types/node" "*" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - -chromium-edge-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#0443083074715a13c669530b35df7bfea33b1509" - integrity sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA== - dependencies: - "@types/node" "*" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - mkdirp "^1.0.4" - rimraf "^3.0.2" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -cjs-module-lexer@^1.0.0: - version "1.4.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" - integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.5.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^1.0.7: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - -command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^9.4.1: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - -compressible@~2.0.18: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.1: - version "1.8.0" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.0.tgz#09420efc96e11a0f44f3a558de59e321364180f7" - integrity sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA== - dependencies: - bytes "3.1.2" - compressible "~2.0.18" - debug "2.6.9" - negotiator "~0.6.4" - on-headers "~1.0.2" - safe-buffer "5.2.1" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -connect@^3.6.5: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -core-js-compat@^3.38.0, core-js-compat@^3.40.0: - version "3.40.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" - integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== - dependencies: - browserslist "^4.24.3" - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - -cross-spawn@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - integrity sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA== - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -data-view-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" - integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - is-data-view "^1.0.2" - -data-view-byte-length@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" - integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - is-data-view "^1.0.2" - -data-view-byte-offset@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" - integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -dayjs@^1.8.15: - version "1.11.13" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" - integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== - -debug@2.6.9, debug@^2.2.0, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -dedent@^1.0.0: - version "1.5.3" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" - integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.2.2, deepmerge@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -defaults@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" - integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== - dependencies: - clone "^1.0.2" - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.1.3, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -denodeify@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" - integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -deprecated-react-native-prop-types@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz#02a12f090da7bd9e8c3ac53c31cf786a1315d302" - integrity sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ== - dependencies: - "@react-native/normalize-colors" "^0.73.0" - invariant "^2.2.4" - prop-types "^15.8.1" - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -detox@20.10.0: - version "20.10.0" - resolved "https://registry.yarnpkg.com/detox/-/detox-20.10.0.tgz#2c8df147c6f81d57b22f79f6bc252b8d71438a64" - integrity sha512-c6dCD5xTmiuOklbx4ptnXuznCnK4IMd9ZtB8jXxNJBqZpUXzqhmCniwKPZNwkdtye/xXbEFz4t5JWQKsVJ3z5Q== - dependencies: - ajv "^8.6.3" - bunyan "^1.8.12" - bunyan-debug-stream "^3.1.0" - caf "^15.0.1" - chalk "^4.0.0" - child-process-promise "^2.2.0" - execa "^5.1.1" - find-up "^5.0.0" - fs-extra "^11.0.0" - funpermaproxy "^1.1.0" - glob "^8.0.3" - ini "^1.3.4" - json-cycle "^1.3.0" - lodash "^4.17.11" - multi-sort-stream "^1.0.3" - multipipe "^4.0.0" - node-ipc "9.2.1" - proper-lockfile "^3.0.2" - resolve-from "^5.0.0" - sanitize-filename "^1.6.1" - semver "^7.0.0" - serialize-error "^8.0.1" - shell-quote "^1.7.2" - signal-exit "^3.0.3" - stream-json "^1.7.4" - strip-ansi "^6.0.1" - telnet-client "1.2.8" - tempfile "^2.0.0" - trace-event-lib "^1.3.1" - which "^1.3.1" - ws "^7.0.0" - yargs "^17.0.0" - yargs-parser "^21.0.0" - yargs-unparser "^2.0.0" - -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dtrace-provider@~0.8: - version "0.8.8" - resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" - integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg== - dependencies: - nan "^2.14.0" - -dunder-proto@^1.0.0, dunder-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" - integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== - dependencies: - call-bind-apply-helpers "^1.0.1" - es-errors "^1.3.0" - gopd "^1.2.0" - -duplexer2@^0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA== - dependencies: - readable-stream "^2.0.2" - -easy-stack@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/easy-stack/-/easy-stack-1.0.1.tgz#8afe4264626988cabb11f3c704ccd0c835411066" - integrity sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.5.73: - version "1.5.102" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz#81a452ace8e2c3fa7fba904ea4fed25052c53d3f" - integrity sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -encodeurl@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" - integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== - -envinfo@^7.10.0: - version "7.14.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" - integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -error-stack-parser@^2.0.6: - version "2.1.4" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" - integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== - dependencies: - stackframe "^1.3.4" - -errorhandler@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" - integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== - dependencies: - accepts "~1.3.7" - escape-html "~1.0.3" - -es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: - version "1.23.9" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606" - integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA== - dependencies: - array-buffer-byte-length "^1.0.2" - arraybuffer.prototype.slice "^1.0.4" - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - call-bound "^1.0.3" - data-view-buffer "^1.0.2" - data-view-byte-length "^1.0.2" - data-view-byte-offset "^1.0.1" - es-define-property "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.1.0" - es-to-primitive "^1.3.0" - function.prototype.name "^1.1.8" - get-intrinsic "^1.2.7" - get-proto "^1.0.0" - get-symbol-description "^1.1.0" - globalthis "^1.0.4" - gopd "^1.2.0" - has-property-descriptors "^1.0.2" - has-proto "^1.2.0" - has-symbols "^1.1.0" - hasown "^2.0.2" - internal-slot "^1.1.0" - is-array-buffer "^3.0.5" - is-callable "^1.2.7" - is-data-view "^1.0.2" - is-regex "^1.2.1" - is-shared-array-buffer "^1.0.4" - is-string "^1.1.1" - is-typed-array "^1.1.15" - is-weakref "^1.1.0" - math-intrinsics "^1.1.0" - object-inspect "^1.13.3" - object-keys "^1.1.1" - object.assign "^4.1.7" - own-keys "^1.0.1" - regexp.prototype.flags "^1.5.3" - safe-array-concat "^1.1.3" - safe-push-apply "^1.0.0" - safe-regex-test "^1.1.0" - set-proto "^1.0.0" - string.prototype.trim "^1.2.10" - string.prototype.trimend "^1.0.9" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.3" - typed-array-byte-length "^1.0.3" - typed-array-byte-offset "^1.0.4" - typed-array-length "^1.0.7" - unbox-primitive "^1.1.0" - which-typed-array "^1.1.18" - -es-define-property@^1.0.0, es-define-property@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-iterator-helpers@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" - integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - es-abstract "^1.23.6" - es-errors "^1.3.0" - es-set-tostringtag "^2.0.3" - function-bind "^1.1.2" - get-intrinsic "^1.2.6" - globalthis "^1.0.4" - gopd "^1.2.0" - has-property-descriptors "^1.0.2" - has-proto "^1.2.0" - has-symbols "^1.1.0" - internal-slot "^1.1.0" - iterator.prototype "^1.1.4" - safe-array-concat "^1.1.3" - -es-object-atoms@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== - dependencies: - es-errors "^1.3.0" - -es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" - integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== - dependencies: - es-errors "^1.3.0" - get-intrinsic "^1.2.6" - has-tostringtag "^1.0.2" - hasown "^2.0.2" - -es-shim-unscopables@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" - integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== - dependencies: - hasown "^2.0.2" - -es-to-primitive@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" - integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== - dependencies: - is-callable "^1.2.7" - is-date-object "^1.0.5" - is-symbol "^1.0.4" - -escalade@^3.1.1, escalade@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^8.5.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" - integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== - -eslint-plugin-eslint-comments@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" - integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== - dependencies: - escape-string-regexp "^1.0.5" - ignore "^5.0.5" - -eslint-plugin-ft-flow@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz#3b3c113c41902bcbacf0e22b536debcfc3c819e8" - integrity sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg== - dependencies: - lodash "^4.17.21" - string-natural-compare "^3.0.1" - -eslint-plugin-jest@^26.5.3: - version "26.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz#7931c31000b1c19e57dbfb71bbf71b817d1bf949" - integrity sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng== - dependencies: - "@typescript-eslint/utils" "^5.10.0" - -eslint-plugin-prettier@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" - integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== - -eslint-plugin-react-native-globals@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" - integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== - -eslint-plugin-react-native@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz#5343acd3b2246bc1b857ac38be708f070d18809f" - integrity sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q== - dependencies: - eslint-plugin-react-native-globals "^0.1.1" - -eslint-plugin-react@^7.30.1: - version "7.37.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz#1b6c80b6175b6ae4b26055ae4d55d04c414c7181" - integrity sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ== - dependencies: - array-includes "^3.1.8" - array.prototype.findlast "^1.2.5" - array.prototype.flatmap "^1.3.3" - array.prototype.tosorted "^1.1.4" - doctrine "^2.1.0" - es-iterator-helpers "^1.2.1" - estraverse "^5.3.0" - hasown "^2.0.2" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.8" - object.fromentries "^2.0.8" - object.values "^1.2.1" - prop-types "^15.8.1" - resolve "^2.0.0-next.5" - semver "^6.3.1" - string.prototype.matchall "^4.0.12" - string.prototype.repeat "^1.0.0" - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.19.0: - version "8.57.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" - integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.1" - "@humanwhocodes/config-array" "^0.13.0" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esprima@^4.0.0, esprima@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" - integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -event-pubsub@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/event-pubsub/-/event-pubsub-4.3.0.tgz#f68d816bc29f1ec02c539dc58c8dd40ce72cb36e" - integrity sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ== - -event-target-shim@^5.0.0, event-target-shim@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -execa@^5.0.0, execa@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - -exponential-backoff@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91" - integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - -fast-glob@^3.2.9: - version "3.3.3" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" - integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.8" - -fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-uri@^3.0.1: - version "3.0.6" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" - integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== - -fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: - version "4.5.1" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz#a7e665ff79b7919100a5202f23984b6150f9b31e" - integrity sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w== - dependencies: - strnum "^1.0.5" - -fastq@^1.6.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" - integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flatted@^3.2.9: - version "3.3.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" - integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== - -flow-enums-runtime@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" - integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== - -flow-parser@0.*: - version "0.261.1" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.261.1.tgz#1ce84a0ea0f51f263be779c4988bf6ddd8e7aafb" - integrity sha512-2l5bBKeVtT+d+1CYSsTLJ+iP2FuoR7zjbDQI/v6dDRiBpx3Lb20Z/tLS37ReX/lcodyGSHC2eA/Nk63hB+mkYg== - -flow-parser@^0.206.0: - version "0.206.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef" - integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== - -for-each@^0.3.3: - version "0.3.5" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" - integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== - dependencies: - is-callable "^1.2.7" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs-extra@^11.0.0: - version "11.3.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" - integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" - integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - functions-have-names "^1.2.3" - hasown "^2.0.2" - is-callable "^1.2.7" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -funpermaproxy@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/funpermaproxy/-/funpermaproxy-1.1.0.tgz#39cb0b8bea908051e4608d8a414f1d87b55bf557" - integrity sha512-2Sp1hWuO8m5fqeFDusyhKqYPT+7rGLw34N3qonDcdRP8+n7M7Gl/yKp/q7oCxnnJ6pWCectOmLFJpsMU/++KrQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1, get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044" - integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA== - dependencies: - call-bind-apply-helpers "^1.0.1" - es-define-property "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - function-bind "^1.1.2" - get-proto "^1.0.0" - gopd "^1.2.0" - has-symbols "^1.1.0" - hasown "^2.0.2" - math-intrinsics "^1.1.0" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-proto@^1.0.0, get-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" - integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== - dependencies: - dunder-proto "^1.0.1" - es-object-atoms "^1.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" - integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - get-intrinsic "^1.2.6" - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" - integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== - dependencies: - define-properties "^1.2.1" - gopd "^1.0.1" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1, gopd@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== - -graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -has-bigints@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" - integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" - integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== - dependencies: - dunder-proto "^1.0.0" - -has-symbols@^1.0.3, has-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== - -has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -hermes-estree@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba" - integrity sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ== - -hermes-estree@0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb" - integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg== - -hermes-parser@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.15.0.tgz#f611a297c2a2dbbfbce8af8543242254f604c382" - integrity sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q== - dependencies: - hermes-estree "0.15.0" - -hermes-parser@0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205" - integrity sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA== - dependencies: - hermes-estree "0.23.1" - -hermes-profile-transformer@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" - integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== - dependencies: - source-map "^0.7.3" - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.0.5, ignore@^5.2.0: - version "5.3.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" - integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== - -image-size@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.2.0.tgz#312af27a2ff4ff58595ad00b9344dd684c910df6" - integrity sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w== - dependencies: - queue "6.0.2" - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" - integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" - integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@^1.3.4: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -internal-slot@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" - integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.2" - side-channel "^1.1.0" - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" - integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - get-intrinsic "^1.2.6" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-async-function@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" - integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== - dependencies: - async-function "^1.0.0" - call-bound "^1.0.3" - get-proto "^1.0.1" - has-tostringtag "^1.0.2" - safe-regex-test "^1.1.0" - -is-bigint@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" - integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== - dependencies: - has-bigints "^1.0.2" - -is-boolean-object@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" - integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== - dependencies: - call-bound "^1.0.3" - has-tostringtag "^1.0.2" - -is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.13.0, is-core-module@^2.16.0: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" - integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== - dependencies: - hasown "^2.0.2" - -is-data-view@^1.0.1, is-data-view@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" - integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== - dependencies: - call-bound "^1.0.2" - get-intrinsic "^1.2.6" - is-typed-array "^1.1.13" - -is-date-object@^1.0.5, is-date-object@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" - integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== - dependencies: - call-bound "^1.0.2" - has-tostringtag "^1.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finalizationregistry@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" - integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== - dependencies: - call-bound "^1.0.3" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-generator-function@^1.0.10: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" - integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== - dependencies: - call-bound "^1.0.3" - get-proto "^1.0.0" - has-tostringtag "^1.0.2" - safe-regex-test "^1.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - -is-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" - integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== - -is-number-object@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" - integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== - dependencies: - call-bound "^1.0.3" - has-tostringtag "^1.0.2" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" - integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== - dependencies: - call-bound "^1.0.2" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - hasown "^2.0.2" - -is-set@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" - integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== - -is-shared-array-buffer@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" - integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== - dependencies: - call-bound "^1.0.3" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.7, is-string@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" - integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== - dependencies: - call-bound "^1.0.3" - has-tostringtag "^1.0.2" - -is-symbol@^1.0.4, is-symbol@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" - integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== - dependencies: - call-bound "^1.0.2" - has-symbols "^1.1.0" - safe-regex-test "^1.1.0" - -is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: - version "1.1.15" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" - integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== - dependencies: - which-typed-array "^1.1.16" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-weakmap@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" - integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== - -is-weakref@^1.0.2, is-weakref@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" - integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== - dependencies: - call-bound "^1.0.3" - -is-weakset@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" - integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== - dependencies: - call-bound "^1.0.3" - get-intrinsic "^1.2.6" - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== - -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@^5.0.4: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" - integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== - dependencies: - "@babel/core" "^7.23.9" - "@babel/parser" "^7.23.9" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -iterator.prototype@^1.1.4: - version "1.1.5" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" - integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== - dependencies: - define-data-property "^1.1.4" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.6" - get-proto "^1.0.0" - has-symbols "^1.1.0" - set-function-name "^2.0.2" - -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-node@^29.6.3, jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" - -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.6.3, jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - -jest-worker@^29.6.3, jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - -joi@^17.2.1: - version "17.13.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" - integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== - dependencies: - "@hapi/hoek" "^9.3.0" - "@hapi/topo" "^5.1.0" - "@sideway/address" "^4.1.5" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" - -js-message@1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/js-message/-/js-message-1.0.7.tgz#fbddd053c7a47021871bb8b2c95397cc17c20e47" - integrity sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA== - -js-queue@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/js-queue/-/js-queue-2.0.2.tgz#0be590338f903b36c73d33c31883a821412cd482" - integrity sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA== - dependencies: - easy-stack "^1.0.1" - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsc-android@^250231.0.0: - version "250231.0.0" - resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" - integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== - -jsc-safe-url@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz#141c14fbb43791e88d5dc64e85a374575a83477a" - integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== - -jscodeshift@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.14.0.tgz#7542e6715d6d2e8bde0b4e883f0ccea358b46881" - integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA== - dependencies: - "@babel/core" "^7.13.16" - "@babel/parser" "^7.13.16" - "@babel/plugin-proposal-class-properties" "^7.13.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" - "@babel/plugin-proposal-optional-chaining" "^7.13.12" - "@babel/plugin-transform-modules-commonjs" "^7.13.8" - "@babel/preset-flow" "^7.13.13" - "@babel/preset-typescript" "^7.13.0" - "@babel/register" "^7.13.16" - babel-core "^7.0.0-bridge.0" - chalk "^4.1.2" - flow-parser "0.*" - graceful-fs "^4.2.4" - micromatch "^4.0.4" - neo-async "^2.5.0" - node-dir "^0.1.17" - recast "^0.21.0" - temp "^0.8.4" - write-file-atomic "^2.3.0" - -jsesc@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - -jsesc@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-cycle@^1.3.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/json-cycle/-/json-cycle-1.5.0.tgz#b1f1d976eee16cef51d5f3d3b3caece3e90ba23a" - integrity sha512-GOehvd5PO2FeZ5T4c+RxobeT5a1PiGpF4u9/3+UvrMU4bhnVqzJY7hm39wg8PDCqkU91fWGH8qjWR4bn+wgq9w== - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -"jsx-ast-utils@^2.4.1 || ^3.0.0": - version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" - integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - object.assign "^4.1.4" - object.values "^1.1.6" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lighthouse-logger@^1.0.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa" - integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== - dependencies: - debug "^2.6.9" - marky "^1.2.2" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== - -lodash@^4.17.11, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -logkitty@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" - integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== - dependencies: - ansi-fragments "^0.2.1" - dayjs "^1.8.15" - yargs "^15.1.0" - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -marky@^1.2.2: - version "1.2.5" - resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" - integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== - -math-intrinsics@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== - -memoize-one@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -metro-babel-transformer@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz#ad02ade921dd4ced27b26b18ff31eb60608e3f56" - integrity sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg== - dependencies: - "@babel/core" "^7.20.0" - flow-enums-runtime "^0.0.6" - hermes-parser "0.23.1" - nullthrows "^1.1.1" - -metro-cache-key@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.12.tgz#52f5de698b85866503ace45d0ad76f75aaec92a4" - integrity sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA== - dependencies: - flow-enums-runtime "^0.0.6" - -metro-cache@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.12.tgz#bd81af02c4f17b5aeab19bb030566b14147cee8b" - integrity sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA== - dependencies: - exponential-backoff "^3.1.1" - flow-enums-runtime "^0.0.6" - metro-core "0.80.12" - -metro-config@0.80.12, metro-config@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.12.tgz#1543009f37f7ad26352ffc493fc6305d38bdf1c0" - integrity sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ== - dependencies: - connect "^3.6.5" - cosmiconfig "^5.0.5" - flow-enums-runtime "^0.0.6" - jest-validate "^29.6.3" - metro "0.80.12" - metro-cache "0.80.12" - metro-core "0.80.12" - metro-runtime "0.80.12" - -metro-core@0.80.12, metro-core@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.12.tgz#5ae337923ab19ff524077efa1aeacdf4480cfa28" - integrity sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw== - dependencies: - flow-enums-runtime "^0.0.6" - lodash.throttle "^4.1.1" - metro-resolver "0.80.12" - -metro-file-map@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.12.tgz#b03240166a68aa16c5a168c26e190d9da547eefb" - integrity sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw== - dependencies: - anymatch "^3.0.3" - debug "^2.2.0" - fb-watchman "^2.0.0" - flow-enums-runtime "^0.0.6" - graceful-fs "^4.2.4" - invariant "^2.2.4" - jest-worker "^29.6.3" - micromatch "^4.0.4" - node-abort-controller "^3.1.1" - nullthrows "^1.1.1" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" - -metro-minify-terser@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz#9951030e3bc52d7f3ac8664ce5862401c673e3c6" - integrity sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ== - dependencies: - flow-enums-runtime "^0.0.6" - terser "^5.15.0" - -metro-resolver@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.12.tgz#e3815914c21315b04db200032c3243a4cc22dfb6" - integrity sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw== - dependencies: - flow-enums-runtime "^0.0.6" - -metro-runtime@0.80.12, metro-runtime@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.12.tgz#a68af3a2a013f5372d3b8cee234fdd467455550b" - integrity sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw== - dependencies: - "@babel/runtime" "^7.25.0" - flow-enums-runtime "^0.0.6" - -metro-source-map@0.80.12, metro-source-map@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.12.tgz#36a2768c880f8c459d6d758e2d0975e36479f49c" - integrity sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw== - dependencies: - "@babel/traverse" "^7.20.0" - "@babel/types" "^7.20.0" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - metro-symbolicate "0.80.12" - nullthrows "^1.1.1" - ob1 "0.80.12" - source-map "^0.5.6" - vlq "^1.0.0" - -metro-symbolicate@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz#3a6aa783c6e494e2879342d88d5379fab69d1ed2" - integrity sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw== - dependencies: - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - metro-source-map "0.80.12" - nullthrows "^1.1.1" - source-map "^0.5.6" - through2 "^2.0.1" - vlq "^1.0.0" - -metro-transform-plugins@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz#4a3853630ad0f36cc2bffd53bae659ee171a389c" - integrity sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.20.0" - flow-enums-runtime "^0.0.6" - nullthrows "^1.1.1" - -metro-transform-worker@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz#80be8a185b7deb93402b682f58a1dd6724317ad1" - integrity sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/parser" "^7.20.0" - "@babel/types" "^7.20.0" - flow-enums-runtime "^0.0.6" - metro "0.80.12" - metro-babel-transformer "0.80.12" - metro-cache "0.80.12" - metro-cache-key "0.80.12" - metro-minify-terser "0.80.12" - metro-source-map "0.80.12" - metro-transform-plugins "0.80.12" - nullthrows "^1.1.1" - -metro@0.80.12, metro@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.12.tgz#29a61fb83581a71e50c4d8d5d8458270edfe34cc" - integrity sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/parser" "^7.20.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.20.0" - "@babel/types" "^7.20.0" - accepts "^1.3.7" - chalk "^4.0.0" - ci-info "^2.0.0" - connect "^3.6.5" - debug "^2.2.0" - denodeify "^1.2.1" - error-stack-parser "^2.0.6" - flow-enums-runtime "^0.0.6" - graceful-fs "^4.2.4" - hermes-parser "0.23.1" - image-size "^1.0.2" - invariant "^2.2.4" - jest-worker "^29.6.3" - jsc-safe-url "^0.2.2" - lodash.throttle "^4.1.1" - metro-babel-transformer "0.80.12" - metro-cache "0.80.12" - metro-cache-key "0.80.12" - metro-config "0.80.12" - metro-core "0.80.12" - metro-file-map "0.80.12" - metro-resolver "0.80.12" - metro-runtime "0.80.12" - metro-source-map "0.80.12" - metro-symbolicate "0.80.12" - metro-transform-plugins "0.80.12" - metro-transform-worker "0.80.12" - mime-types "^2.1.27" - nullthrows "^1.1.1" - serialize-error "^2.1.0" - source-map "^0.5.6" - strip-ansi "^6.0.0" - throat "^5.0.0" - ws "^7.5.10" - yargs "^17.6.2" - -micromatch@^4.0.4, micromatch@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -"mime-db@>= 1.43.0 < 2": - version "1.53.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" - integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== - -mime-types@^2.1.27, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -moment@^2.19.3: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.3, ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multi-sort-stream@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multi-sort-stream/-/multi-sort-stream-1.0.4.tgz#e4348edc9edc36e16333e531a90c0f166235cc99" - integrity sha512-hAZ8JOEQFbgdLe8HWZbb7gdZg0/yAIHF00Qfo3kd0rXFv96nXe+/bPTrKHZ2QMHugGX4FiAyET1Lt+jiB+7Qlg== - -multipipe@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-4.0.0.tgz#d302554ae664c1157dbfd1e8f98f03c517b3948a" - integrity sha512-jzcEAzFXoWwWwUbvHCNPwBlTz3WCWe/jPcXSmTfbo/VjRwRTfvLZ/bdvtiTdqCe8d4otCSsPCbhGYcX+eggpKQ== - dependencies: - duplexer2 "^0.1.2" - object-assign "^4.1.0" - -mv@~2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" - integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== - dependencies: - mkdirp "~0.5.1" - ncp "~2.0.0" - rimraf "~2.4.0" - -nan@^2.14.0: - version "2.22.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" - integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== - -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -ncp@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -negotiator@~0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" - integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== - -neo-async@^2.5.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nocache@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79" - integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== - -node-abort-controller@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - -node-dir@^0.1.17: - version "0.1.17" - resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== - dependencies: - minimatch "^3.0.2" - -node-fetch@^2.2.0, node-fetch@^2.6.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-ipc@9.2.1: - version "9.2.1" - resolved "https://registry.yarnpkg.com/node-ipc/-/node-ipc-9.2.1.tgz#b32f66115f9d6ce841dc4ec2009d6a733f98bb6b" - integrity sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ== - dependencies: - event-pubsub "4.3.0" - js-message "1.0.7" - js-queue "2.0.2" - -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== - -node-stream-zip@^1.9.1: - version "1.15.0" - resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" - integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== - -node-version@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.2.0.tgz#34fde3ffa8e1149bd323983479dda620e1b5060d" - integrity sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ== - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nullthrows@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" - integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== - -ob1@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.12.tgz#0451944ba6e5be225cc9751d8cd0d7309d2d1537" - integrity sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw== - dependencies: - flow-enums-runtime "^0.0.6" - -object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.3: - version "1.13.4" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" - integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4, object.assign@^4.1.7: - version "4.1.7" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" - integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - has-symbols "^1.1.0" - object-keys "^1.1.1" - -object.entries@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" - integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -object.fromentries@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" - integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.values@^1.1.6, object.values@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" - integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.0, onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^6.2.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" - integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== - dependencies: - is-wsl "^1.1.0" - -open@^7.0.3: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -optionator@^0.9.3: - version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.5" - -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -own-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" - integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== - dependencies: - get-intrinsic "^1.2.6" - object-keys "^1.1.1" - safe-push-apply "^1.0.0" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0, picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pirates@^4.0.4, pirates@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -possible-typed-array-names@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" - integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^2.8.8: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - -pretty-format@^26.5.2, pretty-format@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" - integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== - dependencies: - "@jest/types" "^26.6.2" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^17.0.1" - -pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise-polyfill@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-6.1.0.tgz#dfa96943ea9c121fca4de9b5868cb39d3472e057" - integrity sha512-g0LWaH0gFsxovsU7R5LrrhHhWAWiHRnh1GPrhXnPgYsDkIqjRYUYSZEsej/wtleDrz5xVSIDbeKfidztp2XHFQ== - -promise@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" - integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== - dependencies: - asap "~2.0.6" - -prompts@^2.0.1, prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proper-lockfile@^3.0.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-3.2.0.tgz#89ca420eea1d55d38ca552578851460067bcda66" - integrity sha512-iMghHHXv2bsxl6NchhEaFck8tvX3F9cknEEh1SUpguUOBjN7PAAW9BLzmbc1g/mCD1gY3EE2EABBHPJfFdHFmA== - dependencies: - graceful-fs "^4.1.11" - retry "^0.12.0" - signal-exit "^3.0.2" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -pure-rand@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" - integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -react-devtools-core@^4.27.7: - version "4.28.5" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508" - integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA== - dependencies: - shell-quote "^1.6.1" - ws "^7" - -"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -react-native-fs@^2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.20.0.tgz#05a9362b473bfc0910772c0acbb73a78dbc810f6" - integrity sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ== - dependencies: - base-64 "^0.1.0" - utf8 "^3.0.0" - -react-native@^0.73.11: - version "0.73.11" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.11.tgz#4661532efd146e1eab2abb69c252218795837ce5" - integrity sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg== - dependencies: - "@jest/create-cache-key-function" "^29.6.3" - "@react-native-community/cli" "12.3.7" - "@react-native-community/cli-platform-android" "12.3.7" - "@react-native-community/cli-platform-ios" "12.3.7" - "@react-native/assets-registry" "0.73.1" - "@react-native/codegen" "0.73.3" - "@react-native/community-cli-plugin" "0.73.18" - "@react-native/gradle-plugin" "0.73.5" - "@react-native/js-polyfills" "0.73.1" - "@react-native/normalize-colors" "0.73.2" - "@react-native/virtualized-lists" "0.73.4" - abort-controller "^3.0.0" - anser "^1.4.9" - ansi-regex "^5.0.0" - base64-js "^1.5.1" - chalk "^4.0.0" - deprecated-react-native-prop-types "^5.0.0" - event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - jest-environment-node "^29.6.3" - jsc-android "^250231.0.0" - memoize-one "^5.0.0" - metro-runtime "^0.80.3" - metro-source-map "^0.80.3" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - pretty-format "^26.5.2" - promise "^8.3.0" - react-devtools-core "^4.27.7" - react-refresh "^0.14.0" - react-shallow-renderer "^16.15.0" - regenerator-runtime "^0.13.2" - scheduler "0.24.0-canary-efb381bbf-20230505" - stacktrace-parser "^0.1.10" - whatwg-fetch "^3.0.0" - ws "^6.2.2" - yargs "^17.6.2" - -react-refresh@^0.14.0: - version "0.14.2" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" - integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== - -react-shallow-renderer@^16.15.0: - version "16.15.0" - resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" - integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== - dependencies: - object-assign "^4.1.1" - react-is "^16.12.0 || ^17.0.0 || ^18.0.0" - -react-test-renderer@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.2.0.tgz#1dd912bd908ff26da5b9fca4fd1c489b9523d37e" - integrity sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA== - dependencies: - react-is "^18.2.0" - react-shallow-renderer "^16.15.0" - scheduler "^0.23.0" - -react@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" - -readable-stream@^2.0.2, readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readline@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" - integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== - -recast@^0.21.0: - version "0.21.5" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.21.5.tgz#e8cd22bb51bcd6130e54f87955d33a2b2e57b495" - integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== - dependencies: - ast-types "0.15.2" - esprima "~4.0.0" - source-map "~0.6.1" - tslib "^2.0.1" - -reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" - integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.9" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.7" - get-proto "^1.0.1" - which-builtin-type "^1.2.1" - -regenerate-unicode-properties@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" - integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.2: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - -regexp.prototype.flags@^1.5.3: - version "1.5.4" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" - integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-errors "^1.3.0" - get-proto "^1.0.1" - gopd "^1.2.0" - set-function-name "^2.0.2" - -regexpu-core@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" - integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.2.0" - regjsgen "^0.8.0" - regjsparser "^0.12.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.1.0" - -regjsgen@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" - integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== - -regjsparser@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" - integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== - dependencies: - jsesc "~3.0.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" - integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== - -resolve@^1.14.2, resolve@^1.20.0: - version "1.22.10" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" - integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== - dependencies: - is-core-module "^2.16.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.5: - version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" - integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rimraf@~2.4.0: - version "2.4.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" - integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== - dependencies: - glob "^6.0.1" - -rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-array-concat@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" - integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - get-intrinsic "^1.2.6" - has-symbols "^1.1.0" - isarray "^2.0.5" - -safe-buffer@5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-json-stringify@~1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" - integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== - -safe-push-apply@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" - integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== - dependencies: - es-errors "^1.3.0" - isarray "^2.0.5" - -safe-regex-test@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" - integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - is-regex "^1.2.1" - -sanitize-filename@^1.6.1: - version "1.6.3" - resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" - integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== - dependencies: - truncate-utf8-bytes "^1.0.0" - -scheduler@0.24.0-canary-efb381bbf-20230505: - version "0.24.0-canary-efb381bbf-20230505" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz#5dddc60e29f91cd7f8b983d7ce4a99c2202d178f" - integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA== - dependencies: - loose-envify "^1.1.0" - -scheduler@^0.23.0: - version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" - -semver@^5.6.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.0.0, semver@^7.3.7, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== - -send@0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" - integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-error@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" - integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== - -serialize-error@^8.0.1: - version "8.1.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-8.1.0.tgz#3a069970c712f78634942ddd50fbbc0eaebe2f67" - integrity sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ== - dependencies: - type-fest "^0.20.2" - -serve-static@^1.13.1: - version "1.16.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" - integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== - dependencies: - encodeurl "~2.0.0" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.19.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-function-length@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -set-proto@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" - integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== - dependencies: - dunder-proto "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.6.1, shell-quote@^1.7.2, shell-quote@^1.7.3: - version "1.8.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" - integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== - -side-channel-list@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" - integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - -side-channel-map@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" - integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - -side-channel-weakmap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" - integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - side-channel-map "^1.0.1" - -side-channel@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" - integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - side-channel-list "^1.0.0" - side-channel-map "^1.0.1" - side-channel-weakmap "^1.0.2" - -signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@^0.5.16, source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.3: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -stackframe@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" - integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== - -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -stream-chain@^2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09" - integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== - -stream-json@^1.7.4: - version "1.9.1" - resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187" - integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== - dependencies: - stream-chain "^2.2.5" - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-natural-compare@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" - integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.matchall@^4.0.12: - version "4.0.12" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" - integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - es-abstract "^1.23.6" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.6" - gopd "^1.2.0" - has-symbols "^1.1.0" - internal-slot "^1.1.0" - regexp.prototype.flags "^1.5.3" - set-function-name "^2.0.2" - side-channel "^1.1.0" - -string.prototype.repeat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" - integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trim@^1.2.10: - version "1.2.10" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" - integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - define-data-property "^1.1.4" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-object-atoms "^1.0.0" - has-property-descriptors "^1.0.2" - -string.prototype.trimend@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" - integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^5.0.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== - -sudo-prompt@^9.0.0: - version "9.2.1" - resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" - integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -telnet-client@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/telnet-client/-/telnet-client-1.2.8.tgz#946c0dadc8daa3f19bb40a3e898cb870403a4ca4" - integrity sha512-W+w4k3QAmULVNhBVT2Fei369kGZCh/TH25M7caJAXW+hLxwoQRuw0di3cX4l0S9fgH3Mvq7u+IFMoBDpEw/eIg== - dependencies: - bluebird "^3.5.4" - -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== - -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -temp@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" - integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== - dependencies: - rimraf "~2.6.2" - -tempfile@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" - integrity sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA== - dependencies: - temp-dir "^1.0.0" - uuid "^3.0.1" - -terser@^5.15.0: - version "5.39.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.39.0.tgz#0e82033ed57b3ddf1f96708d123cca717d86ca3a" - integrity sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -throat@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" - integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== - -through2@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -trace-event-lib@^1.3.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/trace-event-lib/-/trace-event-lib-1.4.1.tgz#a749b8141650f56dcdecea760df4735f28d1ac6b" - integrity sha512-TOgFolKG8JFY+9d5EohGWMvwvteRafcyfPWWNIqcuD1W/FUvxWcy2MSCZ/beYHM63oYPHYHCd3tkbgCctHVP7w== - dependencies: - browser-process-hrtime "^1.0.0" - -truncate-utf8-bytes@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" - integrity sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ== - dependencies: - utf8-byte-length "^1.0.1" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.0.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -typed-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" - integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - is-typed-array "^1.1.14" - -typed-array-byte-length@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" - integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== - dependencies: - call-bind "^1.0.8" - for-each "^0.3.3" - gopd "^1.2.0" - has-proto "^1.2.0" - is-typed-array "^1.1.14" - -typed-array-byte-offset@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" - integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - for-each "^0.3.3" - gopd "^1.2.0" - has-proto "^1.2.0" - is-typed-array "^1.1.15" - reflect.getprototypeof "^1.0.9" - -typed-array-length@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" - integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - reflect.getprototypeof "^1.0.6" - -typescript@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" - integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== - -unbox-primitive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" - integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== - dependencies: - call-bound "^1.0.3" - has-bigints "^1.0.2" - has-symbols "^1.1.0" - which-boxed-primitive "^1.1.1" - -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" - integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" - integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" - integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - -unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" - integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -utf8-byte-length@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz#f9f63910d15536ee2b2d5dd4665389715eac5c1e" - integrity sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA== - -utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -uuid@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -v8-to-istanbul@^9.0.1: - version "9.3.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" - integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -vlq@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" - integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== - -walker@^1.0.7, walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== - dependencies: - defaults "^1.0.3" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-fetch@^3.0.0: - version "3.6.20" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" - integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" - integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== - dependencies: - is-bigint "^1.1.0" - is-boolean-object "^1.2.1" - is-number-object "^1.1.1" - is-string "^1.1.1" - is-symbol "^1.1.1" - -which-builtin-type@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" - integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== - dependencies: - call-bound "^1.0.2" - function.prototype.name "^1.1.6" - has-tostringtag "^1.0.2" - is-async-function "^2.0.0" - is-date-object "^1.1.0" - is-finalizationregistry "^1.1.0" - is-generator-function "^1.0.10" - is-regex "^1.2.1" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.1.0" - which-collection "^1.0.2" - which-typed-array "^1.1.16" - -which-collection@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" - integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== - dependencies: - is-map "^2.0.3" - is-set "^2.0.3" - is-weakmap "^2.0.2" - is-weakset "^2.0.3" - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which-typed-array@^1.1.16, which-typed-array@^1.1.18: - version "1.1.18" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad" - integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - call-bound "^1.0.3" - for-each "^0.3.3" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - -which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^2.3.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -ws@^6.2.2: - version "6.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" - integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== - dependencies: - async-limiter "~1.0.0" - -ws@^7, ws@^7.0.0, ws@^7.5.1, ws@^7.5.10: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - -xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yaml@^2.2.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" - integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^21.0.0, yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs-unparser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@^15.1.0: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yargs@^17.0.0, yargs@^17.3.1, yargs@^17.6.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/js/react_native/package-lock.json b/js/react_native/package-lock.json index 4b31128c92fd7..3c23bc1523bd8 100644 --- a/js/react_native/package-lock.json +++ b/js/react_native/package-lock.json @@ -1,28 +1,26 @@ { "name": "onnxruntime-react-native", - "version": "1.20.0", + "version": "1.22.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "onnxruntime-react-native", - "version": "1.20.0", + "version": "1.22.0", "license": "MIT", "dependencies": { - "@expo/config-plugins": "^7.2.4", - "buffer": "^6.0.3", - "onnxruntime-common": "file:../common" + "buffer": "^6.0.3" }, "devDependencies": { - "@types/jest": "^27.4.0", - "@types/react": "^18.0.9", - "@types/react-native": "^0.67.7", - "jest": "^27.4.7", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", "pod-install": "^0.1.36", - "prettier": "^2.6.2", - "react": "^18.1.0", - "react-native": "^0.75.3", - "react-native-builder-bob": "^0.18.2" + "prettier": "^2.8.8", + "react": "^18.2.0", + "react-native": "^0.73.11" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { "react": "*", @@ -31,7 +29,8 @@ }, "../common": { "name": "onnxruntime-common", - "version": "1.20.0", + "version": "1.22.0", + "extraneous": true, "license": "MIT", "devDependencies": { "typedoc": "^0.25.7" @@ -62,13 +61,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -145,29 +145,30 @@ "license": "MIT" }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", + "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -177,6 +178,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-explode-assignable-expression": "^7.16.7", "@babel/types": "^7.16.7" @@ -220,18 +222,18 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz", + "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.26.9", "semver": "^6.3.1" }, "engines": { @@ -260,6 +262,7 @@ "version": "0.3.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", @@ -278,6 +281,7 @@ "version": "4.3.4", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ms": "2.1.2" }, @@ -293,7 +297,8 @@ "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { "version": "2.1.2", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.2", @@ -307,6 +312,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -330,6 +336,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -338,28 +345,28 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -385,22 +392,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, "license": "MIT", "engines": { @@ -426,15 +433,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -458,14 +465,14 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -483,9 +490,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "license": "MIT", "engines": { @@ -493,9 +500,10 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -540,79 +548,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", + "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.26.9" }, "bin": { "parser": "bin/babel-parser.js" @@ -625,6 +568,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -639,6 +583,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", @@ -668,12 +613,15 @@ } }, "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.17.12", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -686,6 +634,7 @@ "version": "7.18.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.0", "@babel/helper-plugin-utils": "^7.17.12", @@ -702,6 +651,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -714,14 +664,13 @@ } }, "node_modules/@babel/plugin-proposal-export-default-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.24.7.tgz", - "integrity": "sha512-CcmFwUJ3tKhLjPdt4NP+SHMshebytF8ZTYOv5ZDpkzq2sin80Wb5vJrGt8fhPrORQCfoSa0LAxC/DW+GAC5+Hw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", + "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-export-default-from": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -734,6 +683,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -749,6 +699,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -764,6 +715,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -776,11 +728,14 @@ } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.17.12", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -806,15 +761,18 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.0", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.17.12" + "@babel/plugin-transform-parameters": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -839,12 +797,15 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.17.12", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -858,6 +819,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.17.12", "@babel/helper-plugin-utils": "^7.17.12" @@ -873,6 +835,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-create-class-features-plugin": "^7.17.12", @@ -890,6 +853,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.17.12", "@babel/helper-plugin-utils": "^7.17.12" @@ -912,21 +876,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -938,6 +892,7 @@ "version": "7.14.5", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -960,13 +915,13 @@ } }, "node_modules/@babel/plugin-syntax-export-default-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.24.7.tgz", - "integrity": "sha512-bTPz4/635WQ9WhwsyPdxUJDVpsi/X9BMmy/8Rf/UAlOO4jSql4CxUCjWI5PiM+jG+c4LVPTScoTw80geFj9+Bw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", + "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -979,6 +934,7 @@ "version": "7.8.3", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -1006,6 +962,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -1016,21 +973,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1056,6 +1003,7 @@ "version": "7.10.4", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1122,6 +1070,7 @@ "version": "7.14.5", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1136,6 +1085,7 @@ "version": "7.14.5", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1174,25 +1124,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", - "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-remap-async-to-generator": "^7.25.0", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", @@ -1215,6 +1146,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, @@ -1239,23 +1171,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", - "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-classes": { "version": "7.17.12", "dev": true, @@ -1311,6 +1226,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" @@ -1326,6 +1242,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -1340,6 +1257,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" @@ -1372,6 +1290,7 @@ "version": "7.18.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -1412,27 +1331,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, @@ -1447,6 +1350,7 @@ "version": "7.18.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.18.0", "@babel/helper-plugin-utils": "^7.17.12", @@ -1480,6 +1384,7 @@ "version": "7.18.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-module-transforms": "^7.18.0", @@ -1498,6 +1403,7 @@ "version": "7.18.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.18.0", "@babel/helper-plugin-utils": "^7.17.12" @@ -1528,6 +1434,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -1538,63 +1445,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7" @@ -1606,41 +1461,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-parameters": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", @@ -1658,14 +1478,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", - "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1675,16 +1495,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1697,6 +1516,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, @@ -1739,12 +1559,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1753,14 +1575,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1769,14 +1591,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { + "node_modules/@babel/plugin-transform-regenerator": { "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1785,12 +1609,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.0", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-plugin-utils": "^7.17.12" }, "engines": { @@ -1800,46 +1624,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz", + "integrity": "sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.17.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.4.tgz", - "integrity": "sha512-8hsyG+KUYGY0coX6KUCDancA0Vw225KJ2HJO0yCNr1vq5r+lJTleDaJf0K7iOhjw4SWhu03TMBzYTJ9krmzULQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", @@ -1853,9 +1646,9 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", "dev": true, "license": "MIT", "dependencies": { @@ -1870,14 +1663,14 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", + "@babel/helper-define-polyfill-provider": "^0.6.3", "semver": "^6.3.1" }, "peerDependencies": { @@ -1899,22 +1692,22 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "@babel/helper-define-polyfill-provider": "^0.6.3" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/plugin-transform-runtime/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { @@ -1983,6 +1776,7 @@ "version": "7.18.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -1997,6 +1791,7 @@ "version": "7.17.12", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -2027,6 +1822,7 @@ "version": "7.16.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, @@ -2056,6 +1852,7 @@ "version": "7.18.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/compat-data": "^7.17.10", "@babel/helper-compilation-targets": "^7.18.2", @@ -2160,6 +1957,7 @@ "version": "0.1.5", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", @@ -2171,25 +1969,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-react": { - "version": "7.17.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-react-display-name": "^7.16.7", - "@babel/plugin-transform-react-jsx": "^7.17.12", - "@babel/plugin-transform-react-jsx-development": "^7.16.7", - "@babel/plugin-transform-react-pure-annotations": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/preset-typescript": { "version": "7.17.12", "dev": true, @@ -2207,9 +1986,9 @@ } }, "node_modules/@babel/register": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", - "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", + "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", "dev": true, "license": "MIT", "dependencies": { @@ -2247,32 +2026,32 @@ "license": "MIT" }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", + "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2302,186 +2081,19 @@ "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", + "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@expo/config-plugins": { - "version": "7.2.5", - "license": "MIT", - "dependencies": { - "@expo/config-types": "^49.0.0-alpha.1", - "@expo/json-file": "~8.2.37", - "@expo/plist": "^0.0.20", - "@expo/sdk-runtime-versions": "^1.0.0", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.5.3", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.6.0" - } - }, - "node_modules/@expo/config-plugins/node_modules/@react-native/normalize-color": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/@expo/config-plugins/node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@expo/config-plugins/node_modules/find-up": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/glob": { - "version": "7.1.6", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/config-plugins/node_modules/locate-path": { - "version": "6.0.0", - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/ms": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/@expo/config-plugins/node_modules/p-limit": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/p-locate": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/semver": { - "version": "7.5.4", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/config-types": { - "version": "49.0.0", - "license": "MIT" - }, - "node_modules/@expo/json-file": { - "version": "8.2.37", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^2.2.2", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/json-file/node_modules/@babel/code-frame": { - "version": "7.10.4", - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/plist": { - "version": "0.0.20", - "license": "MIT", - "dependencies": { - "@xmldom/xmldom": "~0.7.7", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - } - }, - "node_modules/@expo/sdk-runtime-versions": { - "version": "1.0.0", - "license": "MIT" - }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -2509,91 +2121,6 @@ "node": ">=12" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/core": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, "node_modules/@jest/create-cache-key-function": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", @@ -2635,226 +2162,48 @@ "@types/yargs-parser": "*" } }, - "node_modules/@jest/environment": { - "version": "27.5.1", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/fake-timers": { - "version": "27.5.1", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.0.0" } }, - "node_modules/@jest/globals": { - "version": "27.5.1", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.0.0" } }, - "node_modules/@jest/reporters": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/transform/node_modules/write-file-atomic": { - "version": "3.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/@jest/types": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "license": "MIT", "engines": { @@ -2890,101 +2239,70 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@react-native-community/cli": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-14.1.0.tgz", - "integrity": "sha512-k7aTdKNZIec7WMSqMJn9bDVLWPPOaYmshXcnjWy6t5ItsJnREju9p2azMTR5tXY5uIeynose3cxettbhk2Tbnw==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.7.tgz", + "integrity": "sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-clean": "14.1.0", - "@react-native-community/cli-config": "14.1.0", - "@react-native-community/cli-debugger-ui": "14.1.0", - "@react-native-community/cli-doctor": "14.1.0", - "@react-native-community/cli-server-api": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", - "@react-native-community/cli-types": "14.1.0", + "@react-native-community/cli-clean": "12.3.7", + "@react-native-community/cli-config": "12.3.7", + "@react-native-community/cli-debugger-ui": "12.3.7", + "@react-native-community/cli-doctor": "12.3.7", + "@react-native-community/cli-hermes": "12.3.7", + "@react-native-community/cli-plugin-metro": "12.3.7", + "@react-native-community/cli-server-api": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "@react-native-community/cli-types": "12.3.7", "chalk": "^4.1.2", "commander": "^9.4.1", "deepmerge": "^4.3.0", "execa": "^5.0.0", - "find-up": "^5.0.0", + "find-up": "^4.1.0", "fs-extra": "^8.1.0", "graceful-fs": "^4.1.3", "prompts": "^2.4.2", "semver": "^7.5.2" }, "bin": { - "rnc-cli": "build/bin.js" + "react-native": "build/bin.js" }, "engines": { "node": ">=18" } }, "node_modules/@react-native-community/cli-clean": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-14.1.0.tgz", - "integrity": "sha512-/C4j1yntLo6faztNgZnsDtgpGqa6j0+GYrxOY8LqaKAN03OCnoeUUKO6w78dycbYSGglc1xjJg2RZI/M2oF2AA==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz", + "integrity": "sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-glob": "^3.3.2" + "execa": "^5.0.0" } }, "node_modules/@react-native-community/cli-config": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-14.1.0.tgz", - "integrity": "sha512-P3FK2rPUJBD1fmQHLgTqpHxsc111pnMdEEFR7KeqprCNz+Qr2QpPxfNy0V7s15tGL5rAv+wpbOGcioIV50EbxA==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.7.tgz", + "integrity": "sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", - "cosmiconfig": "^9.0.0", + "cosmiconfig": "^5.1.0", "deepmerge": "^4.3.0", - "fast-glob": "^3.3.2", + "glob": "^7.1.3", "joi": "^17.2.1" } }, "node_modules/@react-native-community/cli-debugger-ui": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.1.0.tgz", - "integrity": "sha512-+YbeCL0wLcBcqDwraJFGsqzcXu9S+bwTVrfImne/4mT6itfe3Oa93yrOVJgNbstrt5pJHuwpU76ZXfXoiuncsg==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz", + "integrity": "sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2992,22 +2310,22 @@ } }, "node_modules/@react-native-community/cli-doctor": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-14.1.0.tgz", - "integrity": "sha512-xIf0oQDRKt7lufUenRwcLYdINGc0x1FSXHaHjd7lQDGT5FJnCEYlIkYEDDgAl5tnVJSvM/IL2c6O+mffkNEPzQ==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz", + "integrity": "sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-config": "14.1.0", - "@react-native-community/cli-platform-android": "14.1.0", - "@react-native-community/cli-platform-apple": "14.1.0", - "@react-native-community/cli-platform-ios": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-config": "12.3.7", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-platform-ios": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", "command-exists": "^1.2.8", "deepmerge": "^4.3.0", - "envinfo": "^7.13.0", + "envinfo": "^7.10.0", "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", "node-stream-zip": "^1.9.1", "ora": "^5.4.1", "semver": "^7.5.2", @@ -3027,9 +2345,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -3053,9 +2371,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "dev": true, "license": "ISC", "bin": { @@ -3065,62 +2383,72 @@ "node": ">= 14" } }, - "node_modules/@react-native-community/cli-platform-android": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-14.1.0.tgz", - "integrity": "sha512-4JnXkAV+ca8XdUhZ7xjgDhXAMwTVjQs8JqiwP7FTYVrayShXy2cBXm/C3HNDoe+oQOF5tPT2SqsDAF2vYTnKiQ==", + "node_modules/@react-native-community/cli-hermes": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz", + "integrity": "sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-glob": "^3.3.2", - "fast-xml-parser": "^4.4.1", - "logkitty": "^0.7.1" + "hermes-profile-transformer": "^0.0.6" } }, - "node_modules/@react-native-community/cli-platform-apple": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.1.0.tgz", - "integrity": "sha512-DExd+pZ7hHxXt8I6BBmckeYUxxq7PQ+o4YSmGIeQx0xUpi+f82obBct2WNC3VWU72Jw6obwfoN6Fwe6F7Wxp5Q==", + "node_modules/@react-native-community/cli-platform-android": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz", + "integrity": "sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-tools": "12.3.7", "chalk": "^4.1.2", "execa": "^5.0.0", - "fast-glob": "^3.3.2", - "fast-xml-parser": "^4.4.1", - "ora": "^5.4.1" + "fast-xml-parser": "^4.2.4", + "glob": "^7.1.3", + "logkitty": "^0.7.1" } }, "node_modules/@react-native-community/cli-platform-ios": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.1.0.tgz", - "integrity": "sha512-ah/ZTiJXUdCVHujyRJ4OmCL5nTq8OWcURcE3UXa1z0sIIiA8io06n+v5n299T9rtPKMwRtVJlQjtO/nbODABPQ==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz", + "integrity": "sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-platform-apple": "14.1.0" + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.0.12", + "glob": "^7.1.3", + "ora": "^5.4.1" } }, + "node_modules/@react-native-community/cli-plugin-metro": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz", + "integrity": "sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg==", + "dev": true, + "license": "MIT" + }, "node_modules/@react-native-community/cli-server-api": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-14.1.0.tgz", - "integrity": "sha512-1k2LBQaYsy9RDWFIfKVne3frOye73O33MV6eYMoRPff7wqxHCrsX1CYJQkmwpgVigZHxYwalHj+Axtu3gpomCA==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz", + "integrity": "sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-debugger-ui": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", + "@react-native-community/cli-debugger-ui": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", "compression": "^1.7.1", "connect": "^3.6.5", "errorhandler": "^1.5.1", "nocache": "^3.0.1", "pretty-format": "^26.6.2", "serve-static": "^1.13.1", - "ws": "^6.2.3" + "ws": "^7.5.1" } }, "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { @@ -3166,28 +2494,18 @@ "node": ">= 10" } }, - "node_modules/@react-native-community/cli-server-api/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-limiter": "~1.0.0" - } - }, "node_modules/@react-native-community/cli-tools": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-14.1.0.tgz", - "integrity": "sha512-r1KxSu2+OSuhWFoE//1UR7aSTXMLww/UYWQprEw4bSo/kvutGX//4r9ywgXSWp+39udpNN4jQpNTHuWhGZd/Bg==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz", + "integrity": "sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw==", "dev": true, "license": "MIT", "dependencies": { "appdirsjs": "^1.2.4", "chalk": "^4.1.2", - "execa": "^5.0.0", "find-up": "^5.0.0", "mime": "^2.4.1", + "node-fetch": "^2.6.0", "open": "^6.2.0", "ora": "^5.4.1", "semver": "^7.5.2", @@ -3261,9 +2579,9 @@ } }, "node_modules/@react-native-community/cli-tools/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -3274,84 +2592,19 @@ } }, "node_modules/@react-native-community/cli-types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-14.1.0.tgz", - "integrity": "sha512-aJwZI9mGRx3HdP8U4CGhqjt3S4r8GmeOqv4kRagC1UHDk4QNMC+bZ8JgPA4W7FrGiPey+lJQHMDPAXOo51SOUw==", + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.7.tgz", + "integrity": "sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w==", "dev": true, "license": "MIT", "dependencies": { "joi": "^17.2.1" } }, - "node_modules/@react-native-community/cli/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@react-native-community/cli/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -3362,9 +2615,9 @@ } }, "node_modules/@react-native/assets-registry": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.75.3.tgz", - "integrity": "sha512-i7MaRbYR06WdpJWv3a0PQ2ScFBUeevwcJ0tVopnFwTg0tBWp3NFEMDIcU8lyXVy9Y59WmrP1V2ROaRDaPiESgg==", + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", + "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", "dev": true, "license": "MIT", "engines": { @@ -3372,52 +2625,50 @@ } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.75.3.tgz", - "integrity": "sha512-8JmXEKq+Efb9AffsV48l8gmKe/ZQ2PbBygZjHdIf8DNZZhO/z5mt27J4B43MWNdp5Ww1l59T0mEaf8l/uywQUg==", + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", + "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", "dev": true, "license": "MIT", "dependencies": { - "@react-native/codegen": "0.75.3" + "@react-native/codegen": "0.73.3" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.75.3.tgz", - "integrity": "sha512-VZQkQEj36DKEGApXFYdVcFtqdglbnoVr7aOZpjffURSgPcIA9vWTm1b+OL4ayOaRZXTZKiDBNQCXvBX5E5AgQg==", + "version": "0.73.21", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", + "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", "@babel/plugin-syntax-dynamic-import": "^7.8.0", "@babel/plugin-syntax-export-default-from": "^7.0.0", "@babel/plugin-syntax-flow": "^7.18.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-syntax-optional-chaining": "^7.0.0", "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", "@babel/plugin-transform-async-to-generator": "^7.20.0", "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-class-properties": "^7.24.1", "@babel/plugin-transform-classes": "^7.0.0", "@babel/plugin-transform-computed-properties": "^7.0.0", "@babel/plugin-transform-destructuring": "^7.20.0", "@babel/plugin-transform-flow-strip-types": "^7.20.0", - "@babel/plugin-transform-for-of": "^7.0.0", "@babel/plugin-transform-function-name": "^7.0.0", "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", "@babel/plugin-transform-modules-commonjs": "^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.5", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.5", "@babel/plugin-transform-parameters": "^7.0.0", "@babel/plugin-transform-private-methods": "^7.22.5", "@babel/plugin-transform-private-property-in-object": "^7.22.11", @@ -3425,7 +2676,6 @@ "@babel/plugin-transform-react-jsx": "^7.0.0", "@babel/plugin-transform-react-jsx-self": "^7.0.0", "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.20.0", "@babel/plugin-transform-runtime": "^7.0.0", "@babel/plugin-transform-shorthand-properties": "^7.0.0", "@babel/plugin-transform-spread": "^7.0.0", @@ -3433,7 +2683,7 @@ "@babel/plugin-transform-typescript": "^7.5.0", "@babel/plugin-transform-unicode-regex": "^7.0.0", "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.75.3", + "@react-native/babel-plugin-codegen": "0.73.4", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, @@ -3445,20 +2695,19 @@ } }, "node_modules/@react-native/codegen": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.75.3.tgz", - "integrity": "sha512-I0bz5jwOkiR7vnhYLGoV22RGmesErUg03tjsCiQgmsMpbyCYumudEtLNN5+DplHGK56bu8KyzBqKkWXGSKSCZQ==", + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", + "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.20.0", + "flow-parser": "^0.206.0", "glob": "^7.1.1", - "hermes-parser": "0.22.0", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" + "nullthrows": "^1.1.1" }, "engines": { "node": ">=18" @@ -3468,16 +2717,16 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.75.3.tgz", - "integrity": "sha512-njsYm+jBWzfLcJcxavAY5QFzYTrmPtjbxq/64GSqwcQYzy9qAkI7LNTK/Wprq1I/4HOuHJO7Km+EddCXB+ByRQ==", + "version": "0.73.18", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz", + "integrity": "sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww==", "dev": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-server-api": "14.1.0", - "@react-native-community/cli-tools": "14.1.0", - "@react-native/dev-middleware": "0.75.3", - "@react-native/metro-babel-transformer": "0.75.3", + "@react-native-community/cli-server-api": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "@react-native/dev-middleware": "0.73.8", + "@react-native/metro-babel-transformer": "0.73.15", "chalk": "^4.0.0", "execa": "^5.1.1", "metro": "^0.80.3", @@ -3491,9 +2740,9 @@ } }, "node_modules/@react-native/debugger-frontend": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.75.3.tgz", - "integrity": "sha512-99bLQsUwsxUMNR7Wa9eV2uyR38yfd6mOEqfN+JIm8/L9sKA926oh+CZkjDy1M8RmCB6spB5N9fVFVkrVdf2yFA==", + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", + "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -3501,23 +2750,22 @@ } }, "node_modules/@react-native/dev-middleware": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.75.3.tgz", - "integrity": "sha512-h2/6+UGmeMWjnT43axy27jNqoDRsE1C1qpjRC3sYpD4g0bI0jSTkY1kAgj8uqGGXLnHXiHOtjLDGdbAgZrsPaA==", + "version": "0.73.8", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", + "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", "dev": true, "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.75.3", + "@react-native/debugger-frontend": "0.73.3", "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", + "chromium-edge-launcher": "^1.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "node-fetch": "^2.2.0", - "nullthrows": "^1.1.1", "open": "^7.0.3", - "selfsigned": "^2.4.1", "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", "ws": "^6.2.2" }, "engines": { @@ -3552,9 +2800,9 @@ } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.75.3.tgz", - "integrity": "sha512-mSfa/Mq/AsALuG/kvXz5ECrc6HdY5waMHal2sSfa8KA0Gt3JqYQVXF9Pdwd4yR5ClPZDI2HRa1tdE8GVlhMvPA==", + "version": "0.73.5", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz", + "integrity": "sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA==", "dev": true, "license": "MIT", "engines": { @@ -3562,9 +2810,9 @@ } }, "node_modules/@react-native/js-polyfills": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.75.3.tgz", - "integrity": "sha512-+JVFJ351GSJT3V7LuXscMqfnpR/UxzsAjbBjfAHBR3kqTbVqrAmBccqPCA3NLzgb/RY8khLJklwMUVlWrn8iFg==", + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", + "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", "dev": true, "license": "MIT", "engines": { @@ -3572,15 +2820,15 @@ } }, "node_modules/@react-native/metro-babel-transformer": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.75.3.tgz", - "integrity": "sha512-gDlEl6C2mwQPLxFOR+yla5MpJpDPNOFD6J5Hd9JM9+lOdUq6MNujh1Xn4ZMvglW7rfViq3nMjg4xPQeGUhDG+w==", + "version": "0.73.15", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", + "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.75.3", - "hermes-parser": "0.22.0", + "@react-native/babel-preset": "0.73.21", + "hermes-parser": "0.15.0", "nullthrows": "^1.1.1" }, "engines": { @@ -3591,16 +2839,23 @@ } }, "node_modules/@react-native/normalize-colors": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.75.3.tgz", - "integrity": "sha512-3mhF8AJFfIN0E5bEs/DQ4U2LzMJYm+FPSwY5bJ1DZhrxW1PFAh24bAPrSd8PwS0iarQ7biLdr1lWf/8LFv8pDA==", + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", + "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@react-native/typescript-config": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/typescript-config/-/typescript-config-0.73.1.tgz", + "integrity": "sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w==", "dev": true, "license": "MIT" }, "node_modules/@react-native/virtualized-lists": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.75.3.tgz", - "integrity": "sha512-cTLm7k7Y//SvV8UK8esrDHEw5OrwwSJ4Fqc3x52Imi6ROuhshfGIPFwhtn4pmAg9nWHzHwwqiJ+9hCSVnXXX+g==", + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", + "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", "dev": true, "license": "MIT", "dependencies": { @@ -3611,14 +2866,7 @@ "node": ">=18" }, "peerDependencies": { - "@types/react": "^18.2.6", - "react": "*", "react-native": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, "node_modules/@sideway/address": { @@ -3652,103 +2900,25 @@ "dev": true, "license": "MIT" }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } + "license": "MIT" }, - "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^1.7.0" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/babel__core": { - "version": "7.1.19", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.17.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.3.0" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "dependencies": { + "@types/istanbul-lib-report": "*" } }, "node_modules/@types/node": { @@ -3756,26 +2926,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/prettier": { - "version": "2.6.1", - "dev": true, - "license": "MIT" - }, "node_modules/@types/prop-types": { "version": "15.7.5", "dev": true, @@ -3792,44 +2942,16 @@ "csstype": "^3.0.2" } }, - "node_modules/@types/react-native": { - "version": "0.67.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/stack-utils": { "version": "2.0.1", "dev": true, "license": "MIT" }, - "node_modules/@types/yargs": { - "version": "16.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@types/yargs-parser": { "version": "21.0.0", "dev": true, "license": "MIT" }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.11", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/abab": { - "version": "2.0.6", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/abort-controller": { "version": "3.0.0", "dev": true, @@ -3855,30 +2977,20 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" + "node": ">= 0.6" } }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "license": "MIT", "bin": { @@ -3888,88 +3000,11 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/anser": { "version": "1.4.10", "dev": true, "license": "MIT" }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-fragments": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", @@ -4015,6 +3050,7 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4053,14 +3089,6 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/array-union": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -4096,19 +3124,6 @@ "dev": true, "license": "MIT" }, - "node_modules/asynckit": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", @@ -4119,27 +3134,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-jest": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, "node_modules/babel-plugin-dynamic-import-node": { "version": "2.3.3", "dev": true, @@ -4148,39 +3142,11 @@ "object.assign": "^4.1.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.3.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/compat-data": "^7.13.11", "@babel/helper-define-polyfill-provider": "^0.3.1", @@ -4194,6 +3160,7 @@ "version": "0.5.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.3.1", "core-js-compat": "^3.21.0" @@ -4206,6 +3173,7 @@ "version": "0.3.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.3.1" }, @@ -4223,45 +3191,9 @@ "@babel/plugin-syntax-flow": "^7.12.1" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", + "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -4282,13 +3214,6 @@ ], "license": "MIT" }, - "node_modules/big-integer": { - "version": "1.6.51", - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -4326,47 +3251,26 @@ "ieee754": "^1.1.13" } }, - "node_modules/bplist-creator": { - "version": "0.1.0", + "node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, "license": "MIT", "dependencies": { - "stream-buffers": "2.2.x" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/bplist-parser": { - "version": "0.3.1", + "node_modules/braces": { + "version": "3.0.3", + "dev": true, "license": "MIT", "dependencies": { - "big-integer": "1.6.x" + "fill-range": "^7.1.1" }, "engines": { - "node": ">= 5.10.0" + "node": ">=8" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/browserslist": { "version": "4.23.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", @@ -4436,9 +3340,9 @@ "license": "MIT" }, "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { @@ -4493,14 +3397,6 @@ "node": ">=4" } }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/camelcase": { "version": "5.3.1", "dev": true, @@ -4532,6 +3428,7 @@ }, "node_modules/chalk": { "version": "4.1.2", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -4544,14 +3441,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/chrome-launcher": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", @@ -4585,9 +3474,9 @@ } }, "node_modules/chromium-edge-launcher": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", - "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4630,19 +3519,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4709,22 +3585,9 @@ "node": ">=6" } }, - "node_modules/co": { - "version": "4.6.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/color-convert": { "version": "2.0.1", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -4735,6 +3598,7 @@ }, "node_modules/color-name": { "version": "1.1.4", + "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -4744,17 +3608,6 @@ "dev": true, "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/command-exists": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", @@ -4793,26 +3646,48 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", + "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", + "negotiator": "~0.6.4", "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", + "dev": true, "license": "MIT" }, "node_modules/connect": { @@ -4831,14 +3706,6 @@ "node": ">= 0.10.0" } }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, "node_modules/core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -4861,54 +3728,63 @@ "license": "MIT" }, "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "license": "MIT", "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=4" } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "node_modules/cosmiconfig/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", "dev": true, - "license": "Python-2.0" + "license": "MIT", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/cross-spawn": { - "version": "7.0.3", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -4928,45 +3804,11 @@ "node": ">=8" } }, - "node_modules/cssom": { - "version": "0.4.4", - "dev": true, - "license": "MIT" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "dev": true, - "license": "MIT" - }, "node_modules/csstype": { "version": "3.1.0", "dev": true, "license": "MIT" }, - "node_modules/data-urls": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -4994,21 +3836,6 @@ "node": ">=0.10.0" } }, - "node_modules/decimal.js": { - "version": "10.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -5047,35 +3874,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/del": { - "version": "6.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/denodeify": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", @@ -5093,61 +3891,30 @@ "node": ">= 0.8" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", + "node_modules/deprecated-react-native-prop-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", + "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", "dev": true, "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "@react-native/normalize-colors": "^0.73.0", + "invariant": "^2.2.4", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/domexception": { - "version": "2.0.1", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "dev": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/ee-first": { @@ -5164,17 +3931,6 @@ "dev": true, "license": "ISC" }, - "node_modules/emittery": { - "version": "0.8.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "dev": true, @@ -5190,28 +3946,10 @@ "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/envinfo": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "dev": true, "license": "MIT", "bin": { @@ -5270,34 +4008,6 @@ "dev": true, "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, "node_modules/esprima": { "version": "4.0.1", "dev": true, @@ -5310,18 +4020,11 @@ "node": ">=4" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5378,92 +4081,32 @@ "node": ">=10.17.0" } }, - "node_modules/exit": { - "version": "0.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", + "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "dev": true, "license": "Apache-2.0" }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, "node_modules/fast-xml-parser": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", - "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" } }, - "node_modules/fastq": { - "version": "1.13.0", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/fb-watchman": { "version": "2.0.1", "dev": true, @@ -5600,28 +4243,15 @@ "license": "MIT" }, "node_modules/flow-parser": { - "version": "0.246.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.246.0.tgz", - "integrity": "sha512-WHRizzSrWFTcKo7cVcbP3wzZVhzsoYxoWqbnH4z+JXGqrjVmnsld6kBZWVlB200PwD5ur8r+HV3KUDxv3cHhOQ==", + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" } }, - "node_modules/form-data": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -5659,6 +4289,7 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -5707,14 +4338,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -5728,13 +4351,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getenv": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/glob": { "version": "7.2.3", "dev": true, @@ -5754,17 +4370,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/globals": { "version": "11.12.0", "dev": true, @@ -5773,27 +4378,9 @@ "node": ">=4" } }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.10", + "dev": true, "license": "ISC" }, "node_modules/has": { @@ -5809,6 +4396,7 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5837,37 +4425,44 @@ } }, "node_modules/hermes-estree": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.22.0.tgz", - "integrity": "sha512-FLBt5X9OfA8BERUdc6aZS36Xz3rRuB0Y/mfocSADWEJfomc1xfene33GdyAmtTkKTBXTN/EgAy+rjTKkkZJHlw==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", + "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", "dev": true, "license": "MIT" }, "node_modules/hermes-parser": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.22.0.tgz", - "integrity": "sha512-gn5RfZiEXCsIWsFGsKiykekktUoh0PdFWYocXsUdZIyWSckT6UIyPcyyUIPSR3kpnELWeK3n3ztAse7Mat6PSA==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", + "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", "dev": true, "license": "MIT", "dependencies": { - "hermes-estree": "0.22.0" + "hermes-estree": "0.15.0" } }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", + "node_modules/hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", "dev": true, "license": "MIT", "dependencies": { - "whatwg-encoding": "^1.0.5" + "source-map": "^0.7.3" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/html-escaper": { - "version": "2.0.2", + "node_modules/hermes-profile-transformer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } }, "node_modules/http-errors": { "version": "2.0.0", @@ -5896,92 +4491,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/human-signals": { - "version": "1.1.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "funding": [ @@ -6000,18 +4509,10 @@ ], "license": "BSD-3-Clause" }, - "node_modules/ignore": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", + "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", "dev": true, "license": "MIT", "dependencies": { @@ -6024,68 +4525,17 @@ "node": ">=16.x" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.8.19" } }, "node_modules/inflight": { "version": "1.0.6", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -6094,6 +4544,7 @@ }, "node_modules/inherits": { "version": "2.0.4", + "dev": true, "license": "ISC" }, "node_modules/invariant": { @@ -6106,20 +4557,8 @@ "loose-envify": "^1.0.0" } }, - "node_modules/is-absolute": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", + "node_modules/is-arrayish": { + "version": "0.2.1", "dev": true, "license": "MIT" }, @@ -6160,14 +4599,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "dev": true, @@ -6176,118 +4607,6 @@ "node": ">=8" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-git-dirty": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^4.0.3", - "is-git-repository": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/is-git-dirty/node_modules/execa": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/is-git-dirty/node_modules/get-stream": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-git-repository": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^4.0.3", - "is-absolute": "^1.0.0" - } - }, - "node_modules/is-git-repository/node_modules/execa": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/is-git-repository/node_modules/get-stream": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -6295,873 +4614,79 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-relative": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/istanbul-reports": { - "version": "3.1.4", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-circus": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-cli": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-cli/node_modules/cliui": { - "version": "7.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "16.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-cli/node_modules/yargs-parser": { - "version": "20.2.9", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-config": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-each": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-leak-detector": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.5.4", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-util": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=8" } }, - "node_modules/jest-validate": { - "version": "27.5.1", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" + "isobject": "^3.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", + "node_modules/is-stream": { + "version": "2.0.1", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-watcher": { - "version": "27.5.1", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-worker": { - "version": "27.5.1", + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "is-docker": "^2.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" }, - "node_modules/jetifier": { - "version": "1.6.8", + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", - "optional": true, - "bin": { - "jetifier": "bin/jetify", - "jetifier-standalone": "bin/jetifier-standalone", - "jetify": "bin/jetify" + "engines": { + "node": ">=0.10.0" } }, "node_modules/joi": { @@ -7180,6 +4705,7 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -7242,60 +4768,17 @@ "@babel/preset-env": "^7.1.6" } }, - "node_modules/jsdom": { - "version": "16.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jsesc": { - "version": "2.5.2", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-parse-better-errors": { @@ -7305,15 +4788,11 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -7358,18 +4837,6 @@ "node": ">=6" } }, - "node_modules/levn": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lighthouse-logger": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", @@ -7381,11 +4848,6 @@ "marky": "^1.2.2" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, "node_modules/locate-path": { "version": "5.0.0", "dev": true, @@ -7397,11 +4859,6 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "dev": true, @@ -7528,16 +4985,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -7587,14 +5034,6 @@ "dev": true, "license": "MIT" }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/metro": { "version": "0.80.12", "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.12.tgz", @@ -7787,36 +5226,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/metro-config/node_modules/cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "license": "MIT", - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "dev": true, - "license": "MIT", - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/metro-config/node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -7845,20 +5254,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/metro-config/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/metro-config/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -7881,16 +5276,6 @@ "dev": true, "license": "MIT" }, - "node_modules/metro-config/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/metro-core": { "version": "0.80.12", "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.12.tgz", @@ -8348,6 +5733,7 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -8356,8 +5742,20 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/mkdirp": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", "dependencies": { @@ -8367,11 +5765,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/mkdirp/node_modules/minimist": { - "version": "1.2.6", - "dev": true, - "license": "MIT" - }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -8379,15 +5772,10 @@ "dev": true, "license": "MIT" }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, "license": "MIT", "engines": { @@ -8477,16 +5865,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "dev": true, @@ -8547,11 +5925,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nwsapi": { - "version": "2.2.0", - "dev": true, - "license": "MIT" - }, "node_modules/ob1": { "version": "0.80.12", "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.12.tgz", @@ -8565,6 +5938,16 @@ "node": ">=18" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-keys": { "version": "1.1.1", "dev": true, @@ -8615,6 +5998,7 @@ }, "node_modules/once": { "version": "1.4.0", + "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -8634,10 +6018,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/onnxruntime-common": { - "resolved": "../common", - "link": true - }, "node_modules/open": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", @@ -8661,22 +6041,6 @@ "node": ">=4" } }, - "node_modules/optionator": { - "version": "0.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -8726,20 +6090,6 @@ "node": ">=8" } }, - "node_modules/p-map": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-try": { "version": "2.2.0", "dev": true, @@ -8748,39 +6098,6 @@ "node": ">=6" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -8793,6 +6110,7 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8800,6 +6118,7 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8808,20 +6127,13 @@ "node_modules/path-parse": { "version": "1.0.7", "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -8855,17 +6167,6 @@ "node": ">= 6" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/pod-install": { "version": "0.1.36", "dev": true, @@ -8874,15 +6175,10 @@ "pod-install": "build/index.js" } }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/prettier": { - "version": "2.6.2", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", "bin": { @@ -8895,30 +6191,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -8948,30 +6220,22 @@ "node": ">= 6" } }, - "node_modules/psl": { - "version": "1.8.0", - "dev": true, - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.0", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/querystringify": { - "version": "2.2.0", + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true, "license": "MIT" }, @@ -8985,25 +6249,6 @@ "inherits": "~2.0.3" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -9015,9 +6260,9 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9028,9 +6273,9 @@ } }, "node_modules/react-devtools-core": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.1.tgz", - "integrity": "sha512-7FSb9meX0btdBQLwdFOwt6bGqvRPabmVMMslv8fgoSPqXyuGpgQe36kx8gR86XPw7aV1yVouTp6fyZ0EH+NfUw==", + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", "dev": true, "license": "MIT", "dependencies": { @@ -9044,32 +6289,31 @@ "license": "MIT" }, "node_modules/react-native": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.75.3.tgz", - "integrity": "sha512-+Ne6u5H+tPo36sme19SCd1u2UID2uo0J/XzAJarxmrDj4Nsdi44eyUDKtQHmhgxjRGsuVJqAYrMK0abLSq8AHw==", + "version": "0.73.11", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.11.tgz", + "integrity": "sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg==", "dev": true, "license": "MIT", "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "14.1.0", - "@react-native-community/cli-platform-android": "14.1.0", - "@react-native-community/cli-platform-ios": "14.1.0", - "@react-native/assets-registry": "0.75.3", - "@react-native/codegen": "0.75.3", - "@react-native/community-cli-plugin": "0.75.3", - "@react-native/gradle-plugin": "0.75.3", - "@react-native/js-polyfills": "0.75.3", - "@react-native/normalize-colors": "0.75.3", - "@react-native/virtualized-lists": "0.75.3", + "@react-native-community/cli": "12.3.7", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-platform-ios": "12.3.7", + "@react-native/assets-registry": "0.73.1", + "@react-native/codegen": "0.73.3", + "@react-native/community-cli-plugin": "0.73.18", + "@react-native/gradle-plugin": "0.73.5", + "@react-native/js-polyfills": "0.73.1", + "@react-native/normalize-colors": "0.73.2", + "@react-native/virtualized-lists": "0.73.4", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "base64-js": "^1.5.1", "chalk": "^4.0.0", - "commander": "^9.4.1", + "deprecated-react-native-prop-types": "^5.0.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", - "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.6.3", "jsc-android": "^250231.0.0", @@ -9080,11 +6324,11 @@ "nullthrows": "^1.1.1", "pretty-format": "^26.5.2", "promise": "^8.3.0", - "react-devtools-core": "^5.3.1", + "react-devtools-core": "^4.27.7", "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.24.0-canary-efb381bbf-20230505", - "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.2", @@ -9097,123 +6341,7 @@ "node": ">=18" }, "peerDependencies": { - "@types/react": "^18.2.6", - "react": "^18.2.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-native-builder-bob": { - "version": "0.18.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-flow": "^7.12.1", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "browserslist": "^4.16.0", - "chalk": "^4.1.0", - "cosmiconfig": "^7.0.0", - "cross-spawn": "^7.0.3", - "dedent": "^0.7.0", - "del": "^6.0.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "is-git-dirty": "^2.0.1", - "json5": "^2.1.3", - "prompts": "^2.4.0", - "which": "^2.0.2", - "yargs": "^16.2.0" - }, - "bin": { - "bob": "bin/bob" - }, - "engines": { - "node": ">= 10.0.0" - }, - "optionalDependencies": { - "jetifier": "^1.6.6" - } - }, - "node_modules/react-native-builder-bob/node_modules/cliui": { - "version": "7.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/react-native-builder-bob/node_modules/cosmiconfig": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-builder-bob/node_modules/fs-extra": { - "version": "9.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-builder-bob/node_modules/jsonfile": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/react-native-builder-bob/node_modules/yargs": { - "version": "16.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-builder-bob/node_modules/yargs-parser": { - "version": "20.2.9", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "react": "18.2.0" } }, "node_modules/react-native/node_modules/@jest/environment": { @@ -9582,19 +6710,6 @@ "node": ">= 10" } }, - "node_modules/react-native/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/react-native/node_modules/ws": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", @@ -9615,6 +6730,20 @@ "node": ">=0.10.0" } }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -9680,6 +6809,7 @@ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -9738,11 +6868,6 @@ "dev": true, "license": "ISC" }, - "node_modules/requires-port": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.0", "dev": true, @@ -9759,32 +6884,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9799,15 +6898,6 @@ "node": ">=8" } }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -9825,53 +6915,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/safe-buffer": { "version": "5.1.2", "dev": true, "license": "MIT" }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/sax": { - "version": "1.2.4", - "license": "ISC" - }, - "node_modules/saxes": { - "version": "5.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/scheduler": { "version": "0.24.0-canary-efb381bbf-20230505", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", @@ -9882,20 +6930,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semver": { "version": "6.3.1", "dev": true, @@ -10055,45 +7089,22 @@ } }, "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/signal-exit": { "version": "3.0.7", - "license": "ISC" - }, - "node_modules/simple-plist": { - "version": "1.3.1", - "license": "MIT", - "dependencies": { - "bplist-creator": "0.1.0", - "bplist-parser": "0.3.1", - "plist": "^3.0.5" - } - }, - "node_modules/simple-plist/node_modules/plist": { - "version": "3.0.6", - "license": "MIT", - "dependencies": { - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/simple-plist/node_modules/xmlbuilder": { - "version": "15.1.1", - "license": "MIT", - "engines": { - "node": ">=8.0" - } + "dev": true, + "license": "ISC" }, "node_modules/sisteransi": { "version": "1.0.5", @@ -10102,6 +7113,7 @@ }, "node_modules/slash": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10231,13 +7243,6 @@ "node": ">= 0.6" } }, - "node_modules/stream-buffers": { - "version": "2.2.0", - "license": "Unlicense", - "engines": { - "node": ">= 0.10.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10269,18 +7274,6 @@ ], "license": "MIT" }, - "node_modules/string-length": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/string-width": { "version": "4.2.3", "dev": true, @@ -10305,14 +7298,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "dev": true, @@ -10321,48 +7306,33 @@ "node": ">=6" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "license": "MIT" }, "node_modules/sudo-prompt": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" @@ -10379,11 +7349,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "dev": true, - "license": "MIT" - }, "node_modules/temp": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", @@ -10397,6 +7362,16 @@ "node": ">=6.0.0" } }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/temp/node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -10411,25 +7386,10 @@ "rimraf": "bin.js" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", - "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", + "version": "5.39.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", + "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10452,24 +7412,6 @@ "dev": true, "license": "MIT" }, - "node_modules/test-exclude": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/throat": { - "version": "6.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -10512,14 +7454,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "dev": true, @@ -10549,57 +7483,13 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, - "node_modules/type-check": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "dev": true, @@ -10616,22 +7506,6 @@ "node": ">=8" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "dev": true, @@ -10668,14 +7542,6 @@ "node": ">=4" } }, - "node_modules/universalify": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -10717,15 +7583,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "dev": true, - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10743,34 +7600,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "7.0.3", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -10788,25 +7617,6 @@ "dev": true, "license": "MIT" }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/walker": { "version": "1.0.8", "dev": true, @@ -10825,45 +7635,11 @@ "defaults": "^1.0.3" } }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "iconv-lite": "0.4.24" - } - }, "node_modules/whatwg-fetch": { "version": "3.6.2", "dev": true, "license": "MIT" }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/which": { "version": "2.0.2", "dev": true, @@ -10885,14 +7661,6 @@ "dev": true, "license": "ISC" }, - "node_modules/word-wrap": { - "version": "1.2.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -10913,10 +7681,12 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { "version": "2.4.3", + "dev": true, "license": "ISC", "dependencies": { "graceful-fs": "^4.1.11", @@ -10946,52 +7716,6 @@ } } }, - "node_modules/xcode": { - "version": "3.0.1", - "license": "Apache-2.0", - "dependencies": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/xml2js": { - "version": "0.6.0", - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xml2js/node_modules/xmlbuilder": { - "version": "11.0.1", - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmlbuilder": { - "version": "14.0.0", - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "dev": true, - "license": "MIT" - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -11012,18 +7736,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "license": "ISC" - }, - "node_modules/yaml": { - "version": "1.10.2", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -11055,6 +7767,7 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" diff --git a/js/react_native/yarn.lock b/js/react_native/yarn.lock deleted file mode 100644 index ff7caa295bf93..0000000000000 --- a/js/react_native/yarn.lock +++ /dev/null @@ -1,3748 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== - dependencies: - "@babel/helper-validator-identifier" "^7.25.9" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== - -"@babel/core@^7.13.16", "@babel/core@^7.20.0": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" - integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.9" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.9" - "@babel/parser" "^7.26.9" - "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.9" - "@babel/types" "^7.26.9" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.20.0", "@babel/generator@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" - integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== - dependencies: - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/helper-annotate-as-pure@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" - integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== - dependencies: - "@babel/types" "^7.25.9" - -"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" - integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== - dependencies: - "@babel/compat-data" "^7.26.5" - "@babel/helper-validator-option" "^7.25.9" - browserslist "^4.24.0" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" - integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.26.9" - semver "^6.3.1" - -"@babel/helper-create-regexp-features-plugin@^7.25.9": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz#5169756ecbe1d95f7866b90bb555b022595302a0" - integrity sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - regexpu-core "^6.2.0" - semver "^6.3.1" - -"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": - version "0.6.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" - integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" - integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== - dependencies: - "@babel/types" "^7.24.7" - -"@babel/helper-member-expression-to-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" - integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-optimise-call-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" - integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== - dependencies: - "@babel/types" "^7.25.9" - -"@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" - integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== - -"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" - integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-wrap-function" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" - integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/traverse" "^7.26.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" - integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== - -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== - -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== - -"@babel/helper-wrap-function@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" - integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== - dependencies: - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helpers@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" - integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== - dependencies: - "@babel/template" "^7.26.9" - "@babel/types" "^7.26.9" - -"@babel/parser@^7.13.16", "@babel/parser@^7.20.0", "@babel/parser@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" - integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== - dependencies: - "@babel/types" "^7.26.9" - -"@babel/plugin-proposal-async-generator-functions@^7.0.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-export-default-from@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz#52702be6ef8367fc8f18b8438278332beeb8f87c" - integrity sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.20.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" - integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== - dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.20.7" - -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" - integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-dynamic-import@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-default-from@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz#86614767a9ff140366f0c3766ef218beb32a730a" - integrity sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz#96507595c21b45fccfc2bc758d5c45452e6164fa" - integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-jsx@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" - integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-typescript@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" - integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-arrow-functions@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" - integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-async-to-generator@^7.20.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" - integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-remap-async-to-generator" "^7.25.9" - -"@babel/plugin-transform-block-scoping@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" - integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-classes@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" - integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - "@babel/traverse" "^7.25.9" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" - integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/template" "^7.25.9" - -"@babel/plugin-transform-destructuring@^7.20.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" - integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.25.9": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz#2904c85a814e7abb1f4850b8baf4f07d0a2389d4" - integrity sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/plugin-syntax-flow" "^7.26.0" - -"@babel/plugin-transform-function-name@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" - integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== - dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-transform-literals@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" - integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.25.9": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" - integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== - dependencies: - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" - integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" - integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-private-methods@^7.22.5": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" - integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-private-property-in-object@^7.22.11": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" - integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-display-name@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" - integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx-self@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" - integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx-source@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" - integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" - integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/plugin-syntax-jsx" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/plugin-transform-runtime@^7.0.0": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" - integrity sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.26.5" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.6" - babel-plugin-polyfill-regenerator "^0.6.1" - semver "^6.3.1" - -"@babel/plugin-transform-shorthand-properties@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" - integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-spread@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" - integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-sticky-regex@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" - integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-typescript@^7.25.9", "@babel/plugin-transform-typescript@^7.5.0": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" - integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-syntax-typescript" "^7.25.9" - -"@babel/plugin-transform-unicode-regex@^7.0.0": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" - integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/preset-flow@^7.13.13": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.25.9.tgz#ef8b5e7e3f24a42b3711e77fb14919b87dffed0a" - integrity sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-transform-flow-strip-types" "^7.25.9" - -"@babel/preset-typescript@^7.13.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" - integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-syntax-jsx" "^7.25.9" - "@babel/plugin-transform-modules-commonjs" "^7.25.9" - "@babel/plugin-transform-typescript" "^7.25.9" - -"@babel/register@^7.13.16": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.25.9.tgz#1c465acf7dc983d70ccc318eb5b887ecb04f021b" - integrity sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA== - dependencies: - clone-deep "^4.0.1" - find-cache-dir "^2.0.0" - make-dir "^2.1.0" - pirates "^4.0.6" - source-map-support "^0.5.16" - -"@babel/runtime@^7.25.0": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" - integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.0.0", "@babel/template@^7.25.9", "@babel/template@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" - integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" - -"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" - integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.9" - "@babel/parser" "^7.26.9" - "@babel/template" "^7.26.9" - "@babel/types" "^7.26.9" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.20.0", "@babel/types@^7.24.7", "@babel/types@^7.25.9", "@babel/types@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" - integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== - dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - -"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" - integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== - -"@hapi/topo@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@isaacs/ttlcache@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" - integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== - -"@jest/create-cache-key-function@^29.6.3": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" - integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== - dependencies: - "@jest/types" "^29.6.3" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/types@^26.6.2": - version "26.6.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" - integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@react-native-community/cli-clean@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz#303ddf1c930918a8bdc4cc58fe0ac2dd05603cd5" - integrity sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - execa "^5.0.0" - -"@react-native-community/cli-config@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-12.3.7.tgz#feb8b93e8ccd6116ac1df0f1d8a0f06872388e51" - integrity sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - cosmiconfig "^5.1.0" - deepmerge "^4.3.0" - glob "^7.1.3" - joi "^17.2.1" - -"@react-native-community/cli-debugger-ui@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz#522aa11c7b4ff4a2ec86492fabee0366d5428b4c" - integrity sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q== - dependencies: - serve-static "^1.13.1" - -"@react-native-community/cli-doctor@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz#31e4784182d6bbfe62f2e728dca87ee23efe0564" - integrity sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg== - dependencies: - "@react-native-community/cli-config" "12.3.7" - "@react-native-community/cli-platform-android" "12.3.7" - "@react-native-community/cli-platform-ios" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - command-exists "^1.2.8" - deepmerge "^4.3.0" - envinfo "^7.10.0" - execa "^5.0.0" - hermes-profile-transformer "^0.0.6" - node-stream-zip "^1.9.1" - ora "^5.4.1" - semver "^7.5.2" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - yaml "^2.2.1" - -"@react-native-community/cli-hermes@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz#4a284e0091469f6cce8caad2fefcf6b45c0cf229" - integrity sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg== - dependencies: - "@react-native-community/cli-platform-android" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - hermes-profile-transformer "^0.0.6" - -"@react-native-community/cli-platform-android@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz#4826f5126f950e29d7ef1ac779c4eed56d251f98" - integrity sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.2.4" - glob "^7.1.3" - logkitty "^0.7.1" - -"@react-native-community/cli-platform-ios@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz#ef90e5c4d9ff5f15071b18179b17cf16699a70e5" - integrity sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow== - dependencies: - "@react-native-community/cli-tools" "12.3.7" - chalk "^4.1.2" - execa "^5.0.0" - fast-xml-parser "^4.0.12" - glob "^7.1.3" - ora "^5.4.1" - -"@react-native-community/cli-plugin-metro@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz#f9be724721a52d800a20f641a2241a7b4e6a9477" - integrity sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg== - -"@react-native-community/cli-server-api@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz#81e2a067c120391242740598010abb8d5d36a739" - integrity sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg== - dependencies: - "@react-native-community/cli-debugger-ui" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - compression "^1.7.1" - connect "^3.6.5" - errorhandler "^1.5.1" - nocache "^3.0.1" - pretty-format "^26.6.2" - serve-static "^1.13.1" - ws "^7.5.1" - -"@react-native-community/cli-tools@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz#65cf1c81d13662a1b0396c753e6ff916e3e92083" - integrity sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - find-up "^5.0.0" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - ora "^5.4.1" - semver "^7.5.2" - shell-quote "^1.7.3" - sudo-prompt "^9.0.0" - -"@react-native-community/cli-types@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-12.3.7.tgz#6f55becdc41bb5ebf1a8f6fd27ad0d198831169d" - integrity sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w== - dependencies: - joi "^17.2.1" - -"@react-native-community/cli@12.3.7": - version "12.3.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-12.3.7.tgz#8f53ec9310367a0204d859005e9cd137f9888382" - integrity sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ== - dependencies: - "@react-native-community/cli-clean" "12.3.7" - "@react-native-community/cli-config" "12.3.7" - "@react-native-community/cli-debugger-ui" "12.3.7" - "@react-native-community/cli-doctor" "12.3.7" - "@react-native-community/cli-hermes" "12.3.7" - "@react-native-community/cli-plugin-metro" "12.3.7" - "@react-native-community/cli-server-api" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - "@react-native-community/cli-types" "12.3.7" - chalk "^4.1.2" - commander "^9.4.1" - deepmerge "^4.3.0" - execa "^5.0.0" - find-up "^4.1.0" - fs-extra "^8.1.0" - graceful-fs "^4.1.3" - prompts "^2.4.2" - semver "^7.5.2" - -"@react-native/assets-registry@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.73.1.tgz#e2a6b73b16c183a270f338dc69c36039b3946e85" - integrity sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg== - -"@react-native/babel-plugin-codegen@0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz#8a2037d5585b41877611498ae66adbf1dddfec1b" - integrity sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ== - dependencies: - "@react-native/codegen" "0.73.3" - -"@react-native/babel-preset@0.73.21": - version "0.73.21" - resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.73.21.tgz#174c16493fa4e311b2f5f0c58d4f3c6a5a68bbea" - integrity sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-class-properties" "^7.18.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" - "@babel/plugin-proposal-numeric-separator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.20.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.18.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.20.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.20.0" - "@babel/plugin-transform-flow-strip-types" "^7.20.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-private-methods" "^7.22.5" - "@babel/plugin-transform-private-property-in-object" "^7.22.11" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-self" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.5.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - "@react-native/babel-plugin-codegen" "0.73.4" - babel-plugin-transform-flow-enums "^0.0.2" - react-refresh "^0.14.0" - -"@react-native/codegen@0.73.3": - version "0.73.3" - resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.73.3.tgz#cc984a8b17334d986cc600254a0d4b7fa7d68a94" - integrity sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg== - dependencies: - "@babel/parser" "^7.20.0" - flow-parser "^0.206.0" - glob "^7.1.1" - invariant "^2.2.4" - jscodeshift "^0.14.0" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - -"@react-native/community-cli-plugin@0.73.18": - version "0.73.18" - resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz#ba2a0933fad574684534eea29f1c5d2cab494854" - integrity sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww== - dependencies: - "@react-native-community/cli-server-api" "12.3.7" - "@react-native-community/cli-tools" "12.3.7" - "@react-native/dev-middleware" "0.73.8" - "@react-native/metro-babel-transformer" "0.73.15" - chalk "^4.0.0" - execa "^5.1.1" - metro "^0.80.3" - metro-config "^0.80.3" - metro-core "^0.80.3" - node-fetch "^2.2.0" - readline "^1.3.0" - -"@react-native/debugger-frontend@0.73.3": - version "0.73.3" - resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz#033757614d2ada994c68a1deae78c1dd2ad33c2b" - integrity sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw== - -"@react-native/dev-middleware@0.73.8": - version "0.73.8" - resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz#2e43722a00c7b8db753f747f40267cbad6caba4d" - integrity sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg== - dependencies: - "@isaacs/ttlcache" "^1.4.1" - "@react-native/debugger-frontend" "0.73.3" - chrome-launcher "^0.15.2" - chromium-edge-launcher "^1.0.0" - connect "^3.6.5" - debug "^2.2.0" - node-fetch "^2.2.0" - open "^7.0.3" - serve-static "^1.13.1" - temp-dir "^2.0.0" - ws "^6.2.2" - -"@react-native/gradle-plugin@0.73.5": - version "0.73.5" - resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz#900126b4e5737eaac22a0fddb2fc5b4cc20da41c" - integrity sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA== - -"@react-native/js-polyfills@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz#730b0a7aaab947ae6f8e5aa9d995e788977191ed" - integrity sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g== - -"@react-native/metro-babel-transformer@0.73.15": - version "0.73.15" - resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz#c516584dde62d65a46668074084359c03e6a50f1" - integrity sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw== - dependencies: - "@babel/core" "^7.20.0" - "@react-native/babel-preset" "0.73.21" - hermes-parser "0.15.0" - nullthrows "^1.1.1" - -"@react-native/normalize-colors@0.73.2", "@react-native/normalize-colors@^0.73.0": - version "0.73.2" - resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz#cc8e48fbae2bbfff53e12f209369e8d2e4cf34ec" - integrity sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w== - -"@react-native/typescript-config@0.73.1": - version "0.73.1" - resolved "https://registry.yarnpkg.com/@react-native/typescript-config/-/typescript-config-0.73.1.tgz#c97a42f5cd264069bfe86b737c531ed2f042ae6d" - integrity sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w== - -"@react-native/virtualized-lists@0.73.4": - version "0.73.4" - resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz#640e594775806f63685435b5d9c3d05c378ccd8c" - integrity sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog== - dependencies: - invariant "^2.2.4" - nullthrows "^1.1.1" - -"@sideway/address@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" - integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" - integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== - -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/node@*": - version "22.13.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.4.tgz#3fe454d77cd4a2d73c214008b3e331bfaaf5038a" - integrity sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg== - dependencies: - undici-types "~6.20.0" - -"@types/prop-types@*": - version "15.7.14" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" - integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== - -"@types/react@^18.2.6": - version "18.3.18" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" - integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^15.0.0": - version "15.0.19" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.19.tgz#328fb89e46109ecbdb70c295d96ff2f46dfd01b9" - integrity sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA== - dependencies: - "@types/yargs-parser" "*" - -"@types/yargs@^17.0.8": - version "17.0.33" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" - integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== - dependencies: - "@types/yargs-parser" "*" - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -accepts@^1.3.7, accepts@~1.3.7: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn@^8.8.2: - version "8.14.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== - -anser@^1.4.9: - version "1.4.10" - resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" - integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== - -ansi-fragments@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" - integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== - dependencies: - colorette "^1.0.7" - slice-ansi "^2.0.0" - strip-ansi "^5.0.0" - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-regex@^5.0.0, ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -appdirsjs@^1.2.4: - version "1.2.7" - resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" - integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -ast-types@0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d" - integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== - dependencies: - tslib "^2.0.1" - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -babel-core@^7.0.0-bridge.0: - version "7.0.0-bridge.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" - integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== - -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.12" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" - integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.3" - semver "^6.3.1" - -babel-plugin-polyfill-corejs3@^0.10.6: - version "0.10.6" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" - integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.2" - core-js-compat "^3.38.0" - -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" - integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.3" - -babel-plugin-transform-flow-enums@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25" - integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ== - dependencies: - "@babel/plugin-syntax-flow" "^7.12.1" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1, base64-js@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.24.0, browserslist@^4.24.3: - version "4.24.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== - dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" - node-releases "^2.0.19" - update-browserslist-db "^1.1.1" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001688: - version "1.0.30001700" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" - integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== - -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chrome-launcher@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" - integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== - dependencies: - "@types/node" "*" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - -chromium-edge-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#0443083074715a13c669530b35df7bfea33b1509" - integrity sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA== - dependencies: - "@types/node" "*" - escape-string-regexp "^4.0.0" - is-wsl "^2.2.0" - lighthouse-logger "^1.0.0" - mkdirp "^1.0.4" - rimraf "^3.0.2" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.5.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^1.0.7: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - -command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^9.4.1: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - -compressible@~2.0.18: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.1: - version "1.8.0" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.0.tgz#09420efc96e11a0f44f3a558de59e321364180f7" - integrity sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA== - dependencies: - bytes "3.1.2" - compressible "~2.0.18" - debug "2.6.9" - negotiator "~0.6.4" - on-headers "~1.0.2" - safe-buffer "5.2.1" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -connect@^3.6.5: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -core-js-compat@^3.38.0: - version "3.40.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" - integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== - dependencies: - browserslist "^4.24.3" - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cross-spawn@^7.0.3: - version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -dayjs@^1.8.15: - version "1.11.13" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" - integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== - -debug@2.6.9, debug@^2.2.0, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -deepmerge@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -defaults@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" - integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== - dependencies: - clone "^1.0.2" - -denodeify@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" - integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -deprecated-react-native-prop-types@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz#02a12f090da7bd9e8c3ac53c31cf786a1315d302" - integrity sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ== - dependencies: - "@react-native/normalize-colors" "^0.73.0" - invariant "^2.2.4" - prop-types "^15.8.1" - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.5.73: - version "1.5.102" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz#81a452ace8e2c3fa7fba904ea4fed25052c53d3f" - integrity sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -encodeurl@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" - integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== - -envinfo@^7.10.0: - version "7.14.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" - integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -error-stack-parser@^2.0.6: - version "2.1.4" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" - integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== - dependencies: - stackframe "^1.3.4" - -errorhandler@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" - integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== - dependencies: - accepts "~1.3.7" - escape-html "~1.0.3" - -escalade@^3.1.1, escalade@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -esprima@^4.0.0, esprima@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -event-target-shim@^5.0.0, event-target-shim@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -execa@^5.0.0, execa@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exponential-backoff@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91" - integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA== - -fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: - version "4.5.1" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz#a7e665ff79b7919100a5202f23984b6150f9b31e" - integrity sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w== - dependencies: - strnum "^1.0.5" - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flow-enums-runtime@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" - integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== - -flow-parser@0.*: - version "0.261.1" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.261.1.tgz#1ce84a0ea0f51f263be779c4988bf6ddd8e7aafb" - integrity sha512-2l5bBKeVtT+d+1CYSsTLJ+iP2FuoR7zjbDQI/v6dDRiBpx3Lb20Z/tLS37ReX/lcodyGSHC2eA/Nk63hB+mkYg== - -flow-parser@^0.206.0: - version "0.206.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef" - integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1, get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -glob@^7.1.1, glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -hermes-estree@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba" - integrity sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ== - -hermes-estree@0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb" - integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg== - -hermes-parser@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.15.0.tgz#f611a297c2a2dbbfbce8af8543242254f604c382" - integrity sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q== - dependencies: - hermes-estree "0.15.0" - -hermes-parser@0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205" - integrity sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA== - dependencies: - hermes-estree "0.23.1" - -hermes-profile-transformer@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" - integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== - dependencies: - source-map "^0.7.3" - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ieee754@^1.1.13, ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -image-size@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.2.0.tgz#312af27a2ff4ff58595ad00b9344dd684c910df6" - integrity sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w== - dependencies: - queue "6.0.2" - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-core-module@^2.16.0: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" - integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== - dependencies: - hasown "^2.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== - -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -jest-environment-node@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-worker@^29.6.3: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -joi@^17.2.1: - version "17.13.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" - integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== - dependencies: - "@hapi/hoek" "^9.3.0" - "@hapi/topo" "^5.1.0" - "@sideway/address" "^4.1.5" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsc-android@^250231.0.0: - version "250231.0.0" - resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" - integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== - -jsc-safe-url@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz#141c14fbb43791e88d5dc64e85a374575a83477a" - integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== - -jscodeshift@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.14.0.tgz#7542e6715d6d2e8bde0b4e883f0ccea358b46881" - integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA== - dependencies: - "@babel/core" "^7.13.16" - "@babel/parser" "^7.13.16" - "@babel/plugin-proposal-class-properties" "^7.13.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" - "@babel/plugin-proposal-optional-chaining" "^7.13.12" - "@babel/plugin-transform-modules-commonjs" "^7.13.8" - "@babel/preset-flow" "^7.13.13" - "@babel/preset-typescript" "^7.13.0" - "@babel/register" "^7.13.16" - babel-core "^7.0.0-bridge.0" - chalk "^4.1.2" - flow-parser "0.*" - graceful-fs "^4.2.4" - micromatch "^4.0.4" - neo-async "^2.5.0" - node-dir "^0.1.17" - recast "^0.21.0" - temp "^0.8.4" - write-file-atomic "^2.3.0" - -jsesc@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - -jsesc@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -lighthouse-logger@^1.0.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa" - integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== - dependencies: - debug "^2.6.9" - marky "^1.2.2" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -logkitty@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" - integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== - dependencies: - ansi-fragments "^0.2.1" - dayjs "^1.8.15" - yargs "^15.1.0" - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -marky@^1.2.2: - version "1.2.5" - resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" - integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== - -memoize-one@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -metro-babel-transformer@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz#ad02ade921dd4ced27b26b18ff31eb60608e3f56" - integrity sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg== - dependencies: - "@babel/core" "^7.20.0" - flow-enums-runtime "^0.0.6" - hermes-parser "0.23.1" - nullthrows "^1.1.1" - -metro-cache-key@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.12.tgz#52f5de698b85866503ace45d0ad76f75aaec92a4" - integrity sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA== - dependencies: - flow-enums-runtime "^0.0.6" - -metro-cache@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.12.tgz#bd81af02c4f17b5aeab19bb030566b14147cee8b" - integrity sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA== - dependencies: - exponential-backoff "^3.1.1" - flow-enums-runtime "^0.0.6" - metro-core "0.80.12" - -metro-config@0.80.12, metro-config@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.12.tgz#1543009f37f7ad26352ffc493fc6305d38bdf1c0" - integrity sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ== - dependencies: - connect "^3.6.5" - cosmiconfig "^5.0.5" - flow-enums-runtime "^0.0.6" - jest-validate "^29.6.3" - metro "0.80.12" - metro-cache "0.80.12" - metro-core "0.80.12" - metro-runtime "0.80.12" - -metro-core@0.80.12, metro-core@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.12.tgz#5ae337923ab19ff524077efa1aeacdf4480cfa28" - integrity sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw== - dependencies: - flow-enums-runtime "^0.0.6" - lodash.throttle "^4.1.1" - metro-resolver "0.80.12" - -metro-file-map@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.12.tgz#b03240166a68aa16c5a168c26e190d9da547eefb" - integrity sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw== - dependencies: - anymatch "^3.0.3" - debug "^2.2.0" - fb-watchman "^2.0.0" - flow-enums-runtime "^0.0.6" - graceful-fs "^4.2.4" - invariant "^2.2.4" - jest-worker "^29.6.3" - micromatch "^4.0.4" - node-abort-controller "^3.1.1" - nullthrows "^1.1.1" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" - -metro-minify-terser@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz#9951030e3bc52d7f3ac8664ce5862401c673e3c6" - integrity sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ== - dependencies: - flow-enums-runtime "^0.0.6" - terser "^5.15.0" - -metro-resolver@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.12.tgz#e3815914c21315b04db200032c3243a4cc22dfb6" - integrity sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw== - dependencies: - flow-enums-runtime "^0.0.6" - -metro-runtime@0.80.12, metro-runtime@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.12.tgz#a68af3a2a013f5372d3b8cee234fdd467455550b" - integrity sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw== - dependencies: - "@babel/runtime" "^7.25.0" - flow-enums-runtime "^0.0.6" - -metro-source-map@0.80.12, metro-source-map@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.12.tgz#36a2768c880f8c459d6d758e2d0975e36479f49c" - integrity sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw== - dependencies: - "@babel/traverse" "^7.20.0" - "@babel/types" "^7.20.0" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - metro-symbolicate "0.80.12" - nullthrows "^1.1.1" - ob1 "0.80.12" - source-map "^0.5.6" - vlq "^1.0.0" - -metro-symbolicate@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz#3a6aa783c6e494e2879342d88d5379fab69d1ed2" - integrity sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw== - dependencies: - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - metro-source-map "0.80.12" - nullthrows "^1.1.1" - source-map "^0.5.6" - through2 "^2.0.1" - vlq "^1.0.0" - -metro-transform-plugins@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz#4a3853630ad0f36cc2bffd53bae659ee171a389c" - integrity sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.20.0" - flow-enums-runtime "^0.0.6" - nullthrows "^1.1.1" - -metro-transform-worker@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz#80be8a185b7deb93402b682f58a1dd6724317ad1" - integrity sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA== - dependencies: - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/parser" "^7.20.0" - "@babel/types" "^7.20.0" - flow-enums-runtime "^0.0.6" - metro "0.80.12" - metro-babel-transformer "0.80.12" - metro-cache "0.80.12" - metro-cache-key "0.80.12" - metro-minify-terser "0.80.12" - metro-source-map "0.80.12" - metro-transform-plugins "0.80.12" - nullthrows "^1.1.1" - -metro@0.80.12, metro@^0.80.3: - version "0.80.12" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.12.tgz#29a61fb83581a71e50c4d8d5d8458270edfe34cc" - integrity sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/core" "^7.20.0" - "@babel/generator" "^7.20.0" - "@babel/parser" "^7.20.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.20.0" - "@babel/types" "^7.20.0" - accepts "^1.3.7" - chalk "^4.0.0" - ci-info "^2.0.0" - connect "^3.6.5" - debug "^2.2.0" - denodeify "^1.2.1" - error-stack-parser "^2.0.6" - flow-enums-runtime "^0.0.6" - graceful-fs "^4.2.4" - hermes-parser "0.23.1" - image-size "^1.0.2" - invariant "^2.2.4" - jest-worker "^29.6.3" - jsc-safe-url "^0.2.2" - lodash.throttle "^4.1.1" - metro-babel-transformer "0.80.12" - metro-cache "0.80.12" - metro-cache-key "0.80.12" - metro-config "0.80.12" - metro-core "0.80.12" - metro-file-map "0.80.12" - metro-resolver "0.80.12" - metro-runtime "0.80.12" - metro-source-map "0.80.12" - metro-symbolicate "0.80.12" - metro-transform-plugins "0.80.12" - metro-transform-worker "0.80.12" - mime-types "^2.1.27" - nullthrows "^1.1.1" - serialize-error "^2.1.0" - source-map "^0.5.6" - strip-ansi "^6.0.0" - throat "^5.0.0" - ws "^7.5.10" - yargs "^17.6.2" - -micromatch@^4.0.4: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -"mime-db@>= 1.43.0 < 2": - version "1.53.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" - integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== - -mime-types@^2.1.27, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.2, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp@^0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.3, ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -negotiator@~0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" - integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== - -neo-async@^2.5.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nocache@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79" - integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== - -node-abort-controller@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - -node-dir@^0.1.17: - version "0.1.17" - resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== - dependencies: - minimatch "^3.0.2" - -node-fetch@^2.2.0, node-fetch@^2.6.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== - -node-stream-zip@^1.9.1: - version "1.15.0" - resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" - integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nullthrows@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" - integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== - -ob1@0.80.12: - version "0.80.12" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.12.tgz#0451944ba6e5be225cc9751d8cd0d7309d2d1537" - integrity sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw== - dependencies: - flow-enums-runtime "^0.0.6" - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.0, onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^6.2.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" - integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== - dependencies: - is-wsl "^1.1.0" - -open@^7.0.3: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -picocolors@^1.0.0, picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pirates@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pod-install@^0.1.36: - version "0.1.39" - resolved "https://registry.yarnpkg.com/pod-install/-/pod-install-0.1.39.tgz#853a0585bafbd332c2ca6543854fd4919958cfb3" - integrity sha512-0kVvdLYe0CtfJEr+ISvTMxAEB0UF4JMRToPjuu9xAAq1mEqA2Ql5u7uLWX1m45BMM+7NfU4LnBbnfNjmQE9GCw== - -prettier@^2.8.8: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - -pretty-format@^26.5.2, pretty-format@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" - integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== - dependencies: - "@jest/types" "^26.6.2" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^17.0.1" - -pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" - integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== - dependencies: - asap "~2.0.6" - -prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -react-devtools-core@^4.27.7: - version "4.28.5" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508" - integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA== - dependencies: - shell-quote "^1.6.1" - ws "^7" - -"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -react-native@^0.73.11: - version "0.73.11" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.11.tgz#4661532efd146e1eab2abb69c252218795837ce5" - integrity sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg== - dependencies: - "@jest/create-cache-key-function" "^29.6.3" - "@react-native-community/cli" "12.3.7" - "@react-native-community/cli-platform-android" "12.3.7" - "@react-native-community/cli-platform-ios" "12.3.7" - "@react-native/assets-registry" "0.73.1" - "@react-native/codegen" "0.73.3" - "@react-native/community-cli-plugin" "0.73.18" - "@react-native/gradle-plugin" "0.73.5" - "@react-native/js-polyfills" "0.73.1" - "@react-native/normalize-colors" "0.73.2" - "@react-native/virtualized-lists" "0.73.4" - abort-controller "^3.0.0" - anser "^1.4.9" - ansi-regex "^5.0.0" - base64-js "^1.5.1" - chalk "^4.0.0" - deprecated-react-native-prop-types "^5.0.0" - event-target-shim "^5.0.1" - flow-enums-runtime "^0.0.6" - invariant "^2.2.4" - jest-environment-node "^29.6.3" - jsc-android "^250231.0.0" - memoize-one "^5.0.0" - metro-runtime "^0.80.3" - metro-source-map "^0.80.3" - mkdirp "^0.5.1" - nullthrows "^1.1.1" - pretty-format "^26.5.2" - promise "^8.3.0" - react-devtools-core "^4.27.7" - react-refresh "^0.14.0" - react-shallow-renderer "^16.15.0" - regenerator-runtime "^0.13.2" - scheduler "0.24.0-canary-efb381bbf-20230505" - stacktrace-parser "^0.1.10" - whatwg-fetch "^3.0.0" - ws "^6.2.2" - yargs "^17.6.2" - -react-refresh@^0.14.0: - version "0.14.2" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" - integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== - -react-shallow-renderer@^16.15.0: - version "16.15.0" - resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" - integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== - dependencies: - object-assign "^4.1.1" - react-is "^16.12.0 || ^17.0.0 || ^18.0.0" - -react@^18.2.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" - -readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readline@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" - integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== - -recast@^0.21.0: - version "0.21.5" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.21.5.tgz#e8cd22bb51bcd6130e54f87955d33a2b2e57b495" - integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== - dependencies: - ast-types "0.15.2" - esprima "~4.0.0" - source-map "~0.6.1" - tslib "^2.0.1" - -regenerate-unicode-properties@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" - integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.2: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regexpu-core@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" - integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.2.0" - regjsgen "^0.8.0" - regjsparser "^0.12.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.1.0" - -regjsgen@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" - integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== - -regjsparser@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" - integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== - dependencies: - jsesc "~3.0.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - -resolve@^1.14.2: - version "1.22.10" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" - integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== - dependencies: - is-core-module "^2.16.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -safe-buffer@5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -scheduler@0.24.0-canary-efb381bbf-20230505: - version "0.24.0-canary-efb381bbf-20230505" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz#5dddc60e29f91cd7f8b983d7ce4a99c2202d178f" - integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA== - dependencies: - loose-envify "^1.1.0" - -semver@^5.6.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.2: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== - -send@0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" - integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-error@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" - integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== - -serve-static@^1.13.1: - version "1.16.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" - integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== - dependencies: - encodeurl "~2.0.0" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.19.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.6.1, shell-quote@^1.7.3: - version "1.8.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" - integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -source-map-support@^0.5.16, source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - -source-map@^0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.3: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -stackframe@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" - integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== - -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^5.0.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== - -sudo-prompt@^9.0.0: - version "9.2.1" - resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" - integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -temp@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" - integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== - dependencies: - rimraf "~2.6.2" - -terser@^5.15.0: - version "5.39.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.39.0.tgz#0e82033ed57b3ddf1f96708d123cca717d86ca3a" - integrity sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -throat@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" - integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== - -through2@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -tslib@^2.0.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" - integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" - integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" - integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" - integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -vlq@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" - integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== - -walker@^1.0.7: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== - dependencies: - defaults "^1.0.3" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-fetch@^3.0.0: - version "3.6.20" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" - integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^2.3.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -ws@^6.2.2: - version "6.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" - integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== - dependencies: - async-limiter "~1.0.0" - -ws@^7, ws@^7.5.1, ws@^7.5.10: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - -xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yaml@^2.2.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" - integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^15.1.0: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yargs@^17.6.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json index 891b40710ff99..ddb49f8e2f062 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json @@ -62,9 +62,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", + "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", "cpu": [ "ppc64" ], @@ -79,9 +79,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", + "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", "cpu": [ "arm" ], @@ -96,9 +96,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", + "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", "cpu": [ "arm64" ], @@ -113,9 +113,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", + "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", "cpu": [ "x64" ], @@ -130,9 +130,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", + "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", "cpu": [ "arm64" ], @@ -147,9 +147,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", + "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", "cpu": [ "x64" ], @@ -164,9 +164,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", + "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", "cpu": [ "arm64" ], @@ -181,9 +181,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", + "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", "cpu": [ "x64" ], @@ -198,9 +198,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", + "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", "cpu": [ "arm" ], @@ -215,9 +215,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", + "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", "cpu": [ "arm64" ], @@ -232,9 +232,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", + "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", "cpu": [ "ia32" ], @@ -249,9 +249,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", + "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", "cpu": [ "loong64" ], @@ -266,9 +266,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", + "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", "cpu": [ "mips64el" ], @@ -283,9 +283,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", + "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", "cpu": [ "ppc64" ], @@ -300,9 +300,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", + "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", "cpu": [ "riscv64" ], @@ -317,9 +317,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", + "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", "cpu": [ "s390x" ], @@ -334,9 +334,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", + "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", "cpu": [ "x64" ], @@ -351,9 +351,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", + "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", "cpu": [ "arm64" ], @@ -368,9 +368,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", + "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", "cpu": [ "x64" ], @@ -385,9 +385,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", + "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", "cpu": [ "arm64" ], @@ -402,9 +402,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", + "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", "cpu": [ "x64" ], @@ -419,9 +419,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", + "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", "cpu": [ "x64" ], @@ -436,9 +436,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", + "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", "cpu": [ "arm64" ], @@ -453,9 +453,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", + "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", "cpu": [ "ia32" ], @@ -470,9 +470,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", + "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", "cpu": [ "x64" ], @@ -493,9 +493,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.2.tgz", - "integrity": "sha512-s/8RiF4bdmGnc/J0N7lHAr5ZFJj+NdJqJ/Hj29K+c4lEdoVlukzvWXB9XpWZCdakVT0YAw8iyIqUP2iFRz5/jA==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz", + "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==", "cpu": [ "arm" ], @@ -507,9 +507,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.2.tgz", - "integrity": "sha512-mKRlVj1KsKWyEOwR6nwpmzakq6SgZXW4NUHNWlYSiyncJpuXk7wdLzuKdWsRoR1WLbWsZBKvsUCdCTIAqRn9cA==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz", + "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==", "cpu": [ "arm64" ], @@ -521,9 +521,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.2.tgz", - "integrity": "sha512-vJX+vennGwygmutk7N333lvQ/yKVAHnGoBS2xMRQgXWW8tvn46YWuTDOpKroSPR9BEW0Gqdga2DHqz8Pwk6X5w==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz", + "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==", "cpu": [ "arm64" ], @@ -535,9 +535,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.2.tgz", - "integrity": "sha512-e2rW9ng5O6+Mt3ht8fH0ljfjgSCC6ffmOipiLUgAnlK86CHIaiCdHCzHzmTkMj6vEkqAiRJ7ss6Ibn56B+RE5w==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz", + "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==", "cpu": [ "x64" ], @@ -549,9 +549,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.2.tgz", - "integrity": "sha512-/xdNwZe+KesG6XJCK043EjEDZTacCtL4yurMZRLESIgHQdvtNyul3iz2Ab03ZJG0pQKbFTu681i+4ETMF9uE/Q==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz", + "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.2.tgz", - "integrity": "sha512-eXKvpThGzREuAbc6qxnArHh8l8W4AyTcL8IfEnmx+bcnmaSGgjyAHbzZvHZI2csJ+e0MYddl7DX0X7g3sAuXDQ==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz", + "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==", "cpu": [ "x64" ], @@ -577,9 +577,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.2.tgz", - "integrity": "sha512-h4VgxxmzmtXLLYNDaUcQevCmPYX6zSj4SwKuzY7SR5YlnCBYsmvfYORXgiU8axhkFCDtQF3RW5LIXT8B14Qykg==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz", + "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==", "cpu": [ "arm" ], @@ -591,9 +591,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.2.tgz", - "integrity": "sha512-EObwZ45eMmWZQ1w4N7qy4+G1lKHm6mcOwDa+P2+61qxWu1PtQJ/lz2CNJ7W3CkfgN0FQ7cBUy2tk6D5yR4KeXw==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz", + "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==", "cpu": [ "arm" ], @@ -605,9 +605,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.2.tgz", - "integrity": "sha512-Z7zXVHEXg1elbbYiP/29pPwlJtLeXzjrj4241/kCcECds8Zg9fDfURWbZHRIKrEriAPS8wnVtdl4ZJBvZr325w==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz", + "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==", "cpu": [ "arm64" ], @@ -619,9 +619,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.2.tgz", - "integrity": "sha512-TF4kxkPq+SudS/r4zGPf0G08Bl7+NZcFrUSR3484WwsHgGgJyPQRLCNrQ/R5J6VzxfEeQR9XRpc8m2t7lD6SEQ==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz", + "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==", "cpu": [ "arm64" ], @@ -633,9 +633,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.2.tgz", - "integrity": "sha512-kO9Fv5zZuyj2zB2af4KA29QF6t7YSxKrY7sxZXfw8koDQj9bx5Tk5RjH+kWKFKok0wLGTi4bG117h31N+TIBEg==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz", + "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==", "cpu": [ "loong64" ], @@ -647,9 +647,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.2.tgz", - "integrity": "sha512-gIh776X7UCBaetVJGdjXPFurGsdWwHHinwRnC5JlLADU8Yk0EdS/Y+dMO264OjJFo7MXQ5PX4xVFbxrwK8zLqA==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz", + "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==", "cpu": [ "ppc64" ], @@ -661,9 +661,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.2.tgz", - "integrity": "sha512-YgikssQ5UNq1GoFKZydMEkhKbjlUq7G3h8j6yWXLBF24KyoA5BcMtaOUAXq5sydPmOPEqB6kCyJpyifSpCfQ0w==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz", + "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==", "cpu": [ "riscv64" ], @@ -675,9 +675,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.2.tgz", - "integrity": "sha512-9ouIR2vFWCyL0Z50dfnon5nOrpDdkTG9lNDs7MRaienQKlTyHcDxplmk3IbhFlutpifBSBr2H4rVILwmMLcaMA==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz", + "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==", "cpu": [ "s390x" ], @@ -689,9 +689,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.2.tgz", - "integrity": "sha512-ckBBNRN/F+NoSUDENDIJ2U9UWmIODgwDB/vEXCPOMcsco1niTkxTXa6D2Y/pvCnpzaidvY2qVxGzLilNs9BSzw==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz", + "integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==", "cpu": [ "x64" ], @@ -703,9 +703,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.2.tgz", - "integrity": "sha512-jycl1wL4AgM2aBFJFlpll/kGvAjhK8GSbEmFT5v3KC3rP/b5xZ1KQmv0vQQ8Bzb2ieFQ0kZFPRMbre/l3Bu9JA==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz", + "integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==", "cpu": [ "x64" ], @@ -717,9 +717,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.2.tgz", - "integrity": "sha512-S2V0LlcOiYkNGlRAWZwwUdNgdZBfvsDHW0wYosYFV3c7aKgEVcbonetZXsHv7jRTTX+oY5nDYT4W6B1oUpMNOg==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz", + "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==", "cpu": [ "arm64" ], @@ -731,9 +731,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.2.tgz", - "integrity": "sha512-pW8kioj9H5f/UujdoX2atFlXNQ9aCfAxFRaa+mhczwcsusm6gGrSo4z0SLvqLF5LwFqFTjiLCCzGkNK/LE0utQ==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz", + "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==", "cpu": [ "ia32" ], @@ -745,9 +745,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.2.tgz", - "integrity": "sha512-p6fTArexECPf6KnOHvJXRpAEq0ON1CBtzG/EY4zw08kCHk/kivBc5vUEtnCFNCHOpJZ2ne77fxwRLIKD4wuW2Q==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz", + "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==", "cpu": [ "x64" ], @@ -898,9 +898,9 @@ } }, "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -911,31 +911,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.1", + "@esbuild/android-arm": "0.25.1", + "@esbuild/android-arm64": "0.25.1", + "@esbuild/android-x64": "0.25.1", + "@esbuild/darwin-arm64": "0.25.1", + "@esbuild/darwin-x64": "0.25.1", + "@esbuild/freebsd-arm64": "0.25.1", + "@esbuild/freebsd-x64": "0.25.1", + "@esbuild/linux-arm": "0.25.1", + "@esbuild/linux-arm64": "0.25.1", + "@esbuild/linux-ia32": "0.25.1", + "@esbuild/linux-loong64": "0.25.1", + "@esbuild/linux-mips64el": "0.25.1", + "@esbuild/linux-ppc64": "0.25.1", + "@esbuild/linux-riscv64": "0.25.1", + "@esbuild/linux-s390x": "0.25.1", + "@esbuild/linux-x64": "0.25.1", + "@esbuild/netbsd-arm64": "0.25.1", + "@esbuild/netbsd-x64": "0.25.1", + "@esbuild/openbsd-arm64": "0.25.1", + "@esbuild/openbsd-x64": "0.25.1", + "@esbuild/sunos-x64": "0.25.1", + "@esbuild/win32-arm64": "0.25.1", + "@esbuild/win32-ia32": "0.25.1", + "@esbuild/win32-x64": "0.25.1" } }, "node_modules/estree-walker": { @@ -993,9 +993,9 @@ "license": "ISC" }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -1012,7 +1012,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -1021,9 +1021,9 @@ } }, "node_modules/rollup": { - "version": "4.29.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.2.tgz", - "integrity": "sha512-tJXpsEkzsEzyAKIaB3qv3IuvTVcTN7qBw1jL4SPPXM3vzDrJgiLGFY6+HodgFaUHAJ2RYJ94zV5MKRJCoQzQeA==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz", + "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==", "dev": true, "license": "MIT", "dependencies": { @@ -1037,25 +1037,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.29.2", - "@rollup/rollup-android-arm64": "4.29.2", - "@rollup/rollup-darwin-arm64": "4.29.2", - "@rollup/rollup-darwin-x64": "4.29.2", - "@rollup/rollup-freebsd-arm64": "4.29.2", - "@rollup/rollup-freebsd-x64": "4.29.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.29.2", - "@rollup/rollup-linux-arm-musleabihf": "4.29.2", - "@rollup/rollup-linux-arm64-gnu": "4.29.2", - "@rollup/rollup-linux-arm64-musl": "4.29.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.29.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.29.2", - "@rollup/rollup-linux-riscv64-gnu": "4.29.2", - "@rollup/rollup-linux-s390x-gnu": "4.29.2", - "@rollup/rollup-linux-x64-gnu": "4.29.2", - "@rollup/rollup-linux-x64-musl": "4.29.2", - "@rollup/rollup-win32-arm64-msvc": "4.29.2", - "@rollup/rollup-win32-ia32-msvc": "4.29.2", - "@rollup/rollup-win32-x64-msvc": "4.29.2", + "@rollup/rollup-android-arm-eabi": "4.35.0", + "@rollup/rollup-android-arm64": "4.35.0", + "@rollup/rollup-darwin-arm64": "4.35.0", + "@rollup/rollup-darwin-x64": "4.35.0", + "@rollup/rollup-freebsd-arm64": "4.35.0", + "@rollup/rollup-freebsd-x64": "4.35.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", + "@rollup/rollup-linux-arm-musleabihf": "4.35.0", + "@rollup/rollup-linux-arm64-gnu": "4.35.0", + "@rollup/rollup-linux-arm64-musl": "4.35.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", + "@rollup/rollup-linux-riscv64-gnu": "4.35.0", + "@rollup/rollup-linux-s390x-gnu": "4.35.0", + "@rollup/rollup-linux-x64-gnu": "4.35.0", + "@rollup/rollup-linux-x64-musl": "4.35.0", + "@rollup/rollup-win32-arm64-msvc": "4.35.0", + "@rollup/rollup-win32-ia32-msvc": "4.35.0", + "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" } }, @@ -1069,15 +1069,15 @@ } }, "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz", + "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "esbuild": "^0.25.0", + "postcss": "^8.5.3", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" From 644362650470ba4ae9af9a08e656023a3e0c5533 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:22:13 -0700 Subject: [PATCH 073/266] Suppress some warnings in WebGPU EP generated by GCC 13 (#23984) ### Description Replace #23445, resolve conflicts and add one new file. --------- Co-authored-by: Changming Sun --- .../core/providers/webgpu/buffer_manager.h | 2 +- .../core/providers/webgpu/compute_context.h | 2 +- .../core/providers/webgpu/program_manager.h | 2 +- .../core/providers/webgpu/shader_helper.h | 2 +- .../core/providers/webgpu/tensor/pad.cc | 18 ++++++------------ .../core/providers/webgpu/webgpu_context.h | 2 +- .../webgpu/webgpu_pix_frame_generator.h | 2 +- 7 files changed, 12 insertions(+), 18 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.h b/onnxruntime/core/providers/webgpu/buffer_manager.h index 20bee52835c02..a5bba53c6798b 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.h +++ b/onnxruntime/core/providers/webgpu/buffer_manager.h @@ -5,7 +5,7 @@ #include -#include +#include "core/providers/webgpu/webgpu_external_header.h" #include "core/framework/execution_provider.h" diff --git a/onnxruntime/core/providers/webgpu/compute_context.h b/onnxruntime/core/providers/webgpu/compute_context.h index 680e03aef0aa3..23fa10a0d5489 100644 --- a/onnxruntime/core/providers/webgpu/compute_context.h +++ b/onnxruntime/core/providers/webgpu/compute_context.h @@ -3,7 +3,7 @@ #pragma once -#include +#include "core/providers/webgpu/webgpu_external_header.h" #include diff --git a/onnxruntime/core/providers/webgpu/program_manager.h b/onnxruntime/core/providers/webgpu/program_manager.h index 55721770014d2..feeb703b95aa2 100644 --- a/onnxruntime/core/providers/webgpu/program_manager.h +++ b/onnxruntime/core/providers/webgpu/program_manager.h @@ -6,7 +6,7 @@ #include #include -#include +#include "core/providers/webgpu/webgpu_external_header.h" #include "core/common/common.h" diff --git a/onnxruntime/core/providers/webgpu/shader_helper.h b/onnxruntime/core/providers/webgpu/shader_helper.h index dac08f3bd9368..64b4c054f93d4 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.h +++ b/onnxruntime/core/providers/webgpu/shader_helper.h @@ -5,7 +5,7 @@ #include -#include +#include "core/providers/webgpu/webgpu_external_header.h" #include "core/framework/tensor_shape.h" diff --git a/onnxruntime/core/providers/webgpu/tensor/pad.cc b/onnxruntime/core/providers/webgpu/tensor/pad.cc index 6a8bc6554b772..cb019892b006f 100644 --- a/onnxruntime/core/providers/webgpu/tensor/pad.cc +++ b/onnxruntime/core/providers/webgpu/tensor/pad.cc @@ -146,27 +146,21 @@ Status Pad::ComputeInternal(ComputeContext& context) const { uint16_t value = math::floatToHalf(value_); std::memcpy(&value_uint32, &value, sizeof(value)); } else { - value_uint32 = *reinterpret_cast(&value_); + std::memcpy(&value_uint32, &value_, sizeof(value_uint32)); } } else if (value_tensor) { ORT_ENFORCE(value_tensor->DataType() == input_tensor->DataType() && value_tensor->Shape().Size() == 1, "Value tensor should be a 1D tensor of size 1 with the same type as that of the input tensor"); switch (data_type) { - case ONNX_NAMESPACE::TensorProto_DataType_INT32: { - int32_t value = value_tensor->Data()[0]; - value_uint32 = *reinterpret_cast(&value); - } break; - case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: { - float value = value_tensor->Data()[0]; - value_uint32 = *reinterpret_cast(&value); - } break; case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: { uint16_t value = value_tensor->Data()[0].val; std::memcpy(&value_uint32, &value, sizeof(value)); } break; - case ONNX_NAMESPACE::TensorProto_DataType_UINT32: { - value_uint32 = value_tensor->Data()[0]; - } break; + case ONNX_NAMESPACE::TensorProto_DataType_INT32: + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: + std::memcpy(&value_uint32, value_tensor->DataRaw(), sizeof(value_uint32)); + break; default: return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported input type: ", static_cast(data_type)); } diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index cb0e14f82610b..15819033d2573 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -6,7 +6,7 @@ #include #include -#include +#include "core/providers/webgpu/webgpu_external_header.h" #include "core/common/common.h" #include "core/framework/library_handles.h" diff --git a/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h b/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h index 0d9393321284d..16d5420191dc1 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h +++ b/onnxruntime/core/providers/webgpu/webgpu_pix_frame_generator.h @@ -14,7 +14,7 @@ #include -#include +#include "core/providers/webgpu/webgpu_external_header.h" namespace onnxruntime { From d010acb546fbfab7070716366d50650559bb7668 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 11 Mar 2025 16:34:54 -0400 Subject: [PATCH 074/266] Fix NPM audit in js/react-native (#23974) ### Description ### Motivation and Context From 9118b1de37275481a4b171562f63e7219174f1a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 23:06:34 +0000 Subject: [PATCH 075/266] Bump axios from 1.7.9 to 1.8.2 in /js/node (#23963) --- js/node/package-lock.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/js/node/package-lock.json b/js/node/package-lock.json index b0cc8a307bd35..41ffb071b9ced 100644 --- a/js/node/package-lock.json +++ b/js/node/package-lock.json @@ -277,10 +277,11 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz", + "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==", "dev": true, + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -1782,9 +1783,9 @@ "dev": true }, "axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz", + "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==", "dev": true, "requires": { "follow-redirects": "^1.15.6", From 5672cf7dd666c320813e475b278ce1141162ffab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20Talpalaru?= Date: Wed, 12 Mar 2025 01:40:12 +0100 Subject: [PATCH 076/266] GCC 14: fix insert_or_assign() call (#23955) Resolve #23954 --- onnxruntime/core/framework/resource_accountant.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/framework/resource_accountant.cc b/onnxruntime/core/framework/resource_accountant.cc index 17f1fd0c3898e..b1bf9aa6d120b 100644 --- a/onnxruntime/core/framework/resource_accountant.cc +++ b/onnxruntime/core/framework/resource_accountant.cc @@ -147,8 +147,8 @@ static Status LoadNodeAllocationStats( size_t initializers_sizes = SafeInt(std::stoull(std::string{splits[2]})); size_t total_dynamic_sizes = SafeInt(std::stoull(std::string{splits[3]})); size_t total_temp_allocations = SafeInt(std::stoull(std::string{splits[4]})); - node_stats.insert_or_assign(std::move(node_name), {input_sizes, initializers_sizes, - total_dynamic_sizes, total_temp_allocations}); + const NodeAllocationStats stats = {input_sizes, initializers_sizes, total_dynamic_sizes, total_temp_allocations}; + node_stats.insert_or_assign(std::move(node_name), stats); } result.swap(node_stats); @@ -224,4 +224,4 @@ std::string IResourceAccountant::MakeUniqueNodeName(const Node& node) { return result; } -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime From d2bf9a797b5880c46b8a6cb58a457348e75627e9 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Tue, 11 Mar 2025 21:04:42 -0700 Subject: [PATCH 077/266] ADD emsdk env vars to VCPKG_KEEP_ENV_VARS (#23997) ### Description The vars are set by cmake\external\emsdk\emsdk_env.bat ### Motivation and Context By default they are filtered by vcpkg to make build reproducible. However, emscripten's cmake toolchain file needs this information. emcc.bat has the following code: ``` @set EM_PY=%EMSDK_PYTHON% @if "%EM_PY%"=="" ( set EM_PY=python ) ``` Actually, it doesn't work as expected. the line ``` set EM_PY=python ``` should be changed to ``` set EM_PY=python.exe ``` We haven't hit this issue because usually the var EM_PY is set. --- tools/ci_build/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index db7dbed23a2d2..c20ea159943fe 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -1952,7 +1952,7 @@ def generate_build_tree( ] env = {} if args.use_vcpkg: - env["VCPKG_KEEP_ENV_VARS"] = "TRT_UPLOAD_AUTH_TOKEN" + env["VCPKG_KEEP_ENV_VARS"] = "TRT_UPLOAD_AUTH_TOKEN;EMSDK;EMSDK_NODE;EMSDK_PYTHON" if args.build_wasm: env["EMSDK"] = emsdk_dir From fe4353714cebb1a639438af06f749bbb29097fd9 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 12 Mar 2025 03:09:13 -0400 Subject: [PATCH 078/266] Fix ONNX Runtime Python Test Pipeline (#23990) ### Description [Fix ONNX Runtime Python Test Pipeline ](https://aiinfra.visualstudio.com/Lotus/_build?definitionId=1164&_a=summary) ### Motivation and Context --- .../azure-pipelines/templates/py-package-smoking-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml b/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml index c0bd740b2d483..be9707e8f3f65 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-package-smoking-test.yml @@ -57,6 +57,6 @@ jobs: python3 -m pip install --find-links "$(Pipeline.Workspace)/build/onnxruntime-${{ parameters.arch }}-${{ parameters.ep }}" $PYTHON_PACKAGE_NAME python3 -m pip show $PYTHON_PACKAGE_NAME python3 -c "import onnxruntime as ort; print(ort.__version__)" - workingDirectory: $(Pipeline.Workspace)/build/onnxruntime + workingDirectory: $(Pipeline.Workspace)/build/onnxruntime-${{ parameters.arch }}-${{ parameters.ep }} displayName: Test Package Installation From 16d6f397d1e1205ab9856902270176b6c143f249 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Wed, 12 Mar 2025 23:44:40 +0800 Subject: [PATCH 079/266] [webgpu] Fix the continuation issue (#23999) ### Description ### Motivation and Context --- onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc | 3 ++- onnxruntime/contrib_ops/webgpu/bert/flash_attention.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 1e95d3d9610ff..5759e7c1232de 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -300,7 +300,7 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { qk_4 = qk_4 * q_element_t(uniforms.alpha) + loadAttentionBias(q_idx_global, k_start+12, head_idx); } - let seq_causal_length = select(uniforms.total_sequence_length, q_idx_global + 1, uniforms.is_gqa > 0); + let seq_causal_length = select(uniforms.total_sequence_length, uniforms.past_sequence_length + q_idx_global + 1, uniforms.is_gqa > 0); // Neuter qk values where K is out of bounds. qk_1[0] = select(min_value, qk_1[0], k_start+0 < seq_causal_length); qk_1[1] = select(min_value, qk_1[1], k_start+1 < seq_causal_length); @@ -451,6 +451,7 @@ Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, co .AddUniformVariables({{static_cast(parameters.sequence_length_)}, {static_cast(parameters.total_sequence_length_)}, {static_cast(parameters.past_present_share_buffer_ ? parameters.past_sequence_length_ : parameters.total_sequence_length_)}, + {static_cast(parameters.total_sequence_length_ - parameters.kv_sequence_length_)}, {static_cast(parameters.is_gqa_ ? 1 : 0)}, {static_cast(parameters.n_reps)}, {alpha}}); diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h index c31a3bf9b7907..2c2b888538843 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h @@ -49,6 +49,7 @@ class FlashAttentionProgram final : public Program { WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"new_sequence_length", ProgramUniformVariableDataType::Uint32}, {"total_sequence_length", ProgramUniformVariableDataType::Uint32}, {"present_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"past_sequence_length", ProgramUniformVariableDataType::Uint32}, {"is_gqa", ProgramUniformVariableDataType::Uint32}, {"n_reps", ProgramUniformVariableDataType::Uint32}, {"alpha", ProgramUniformVariableDataType::Float32}); From 9891eb3d7cc5fa050021b36de8bdf31a5ef13237 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 12 Mar 2025 08:47:13 -0700 Subject: [PATCH 080/266] [WebGPU EP] Implements Gelu, BiasSplitGelu, and QuickGelu (#23981) Increases WebGPU operator coverage --- .../webgpu/bert/bias_split_gelu.cc | 80 +++++++++++++++++++ .../contrib_ops/webgpu/bert/bias_split_gelu.h | 32 ++++++++ onnxruntime/contrib_ops/webgpu/bert/gelu.cc | 27 +++++++ .../contrib_ops/webgpu/bert/quick_gelu.cc | 27 +++++++ .../webgpu/webgpu_contrib_kernels.cc | 6 +- .../webgpu/math/unary_elementwise_ops.cc | 44 +++------- .../webgpu/math/unary_elementwise_ops.h | 50 +++++++++++- .../core/providers/webgpu/webgpu_utils.h | 20 +++++ 8 files changed, 250 insertions(+), 36 deletions(-) create mode 100644 onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc create mode 100644 onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.h create mode 100644 onnxruntime/contrib_ops/webgpu/bert/gelu.cc create mode 100644 onnxruntime/contrib_ops/webgpu/bert/quick_gelu.cc create mode 100644 onnxruntime/core/providers/webgpu/webgpu_utils.h diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc b/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc new file mode 100644 index 0000000000000..99cd643423400 --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "contrib_ops/webgpu/bert/bias_split_gelu.h" +#include "contrib_ops/webgpu/webgpu_contrib_kernels.h" +#include "core/providers/webgpu/webgpu_utils.h" +#include "core/providers/webgpu/math/unary_elementwise_ops.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +ONNX_OPERATOR_KERNEL_EX( + BiasSplitGelu, + kMSDomain, + 1, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()), + BiasSplitGelu); + +Status BiasSplitGeluProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input"); + const ShaderVariableHelper& bias = shader.AddInput("bias"); + const ShaderVariableHelper& output = shader.AddOutput("output"); + + shader.AdditionalImplementation() << ErfImpl; + + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "const M_SQRT2: f32 = sqrt(2.0);\n" + << "const halfChannels = uniforms.channels / 2u;\n" + << "let biasIdx = global_idx % halfChannels;\n" + << "let batchIndex = global_idx / halfChannels;\n" + << "let inputOffset = biasIdx + batchIndex * halfChannels * 2;\n" + << "let valueLeft = " << input.GetByOffset("inputOffset") << " + " << bias.GetByOffset("biasIdx") << ";\n" + << "let valueRight = " << input.GetByOffset("inputOffset + halfChannels") << " + " << bias.GetByOffset("biasIdx + halfChannels") << ";\n" + << "let geluRight = valueRight * 0.5 * (erf_v(valueRight / M_SQRT2) + 1);\n" + << output.SetByOffset("global_idx", "valueLeft * geluRight"); + + return Status::OK(); +} + +Status BiasSplitGelu::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) const { + const auto* input = context.Input(0); + const auto* bias = context.Input(1); + + TensorShape input_shape = input->Shape(); + + if (input_shape.NumDimensions() != 3) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "BiasSplitGelu input should have 3 dimensions."); + } + + int64_t channels = input_shape[2]; + int64_t components = GetMaxComponents(channels); + channels /= components; + input_shape[2] = channels / 2; // for output shape calculation (N,S,D) -> (N,S,D/2) + + TensorShape bias_shape = bias->Shape(); + if (bias_shape.NumDimensions() != 1 || bias_shape[0] != channels) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "BiasSplitGelu bias should have 1 dimension with size equal to the number of channels."); + } + + auto* output = context.Output(0, input_shape); + int64_t output_size = output->Shape().Size() / components; + + BiasSplitGeluProgram program{}; + program.AddInputs({{input, ProgramTensorMetadataDependency::TypeAndRank}, + {bias}}) + .AddOutput({output}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({{static_cast(output_size)}, + {static_cast(channels)}}); + return context.RunProgram(program); +} + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.h b/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.h new file mode 100644 index 0000000000000..ccc3dd8c89b7b --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/webgpu_kernel.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +using namespace onnxruntime::webgpu; +using onnxruntime::webgpu::ComputeContext; + +class BiasSplitGeluProgram final : public Program { + public: + BiasSplitGeluProgram() : Program{"BiasSplitGelu"} {} + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, + {"channels", ProgramUniformVariableDataType::Uint32}); +}; + +class BiasSplitGelu final : public WebGpuKernel { + public: + BiasSplitGelu(const OpKernelInfo& info) : WebGpuKernel(info) {} + Status ComputeInternal(ComputeContext& context) const override; +}; + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/contrib_ops/webgpu/bert/gelu.cc b/onnxruntime/contrib_ops/webgpu/bert/gelu.cc new file mode 100644 index 0000000000000..8dafecfae83e5 --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/bert/gelu.cc @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/math/unary_elementwise_ops.h" // contains Gelu definition +#include "contrib_ops/webgpu/webgpu_contrib_kernels.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +using namespace onnxruntime::webgpu; +using onnxruntime::webgpu::ComputeContext; + +ONNX_OPERATOR_KERNEL_EX( + Gelu, + kMSDomain, + 1, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()), + Gelu); + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/contrib_ops/webgpu/bert/quick_gelu.cc b/onnxruntime/contrib_ops/webgpu/bert/quick_gelu.cc new file mode 100644 index 0000000000000..7d669e140ef23 --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/bert/quick_gelu.cc @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/math/unary_elementwise_ops.h" // contained Gelu definition +#include "contrib_ops/webgpu/webgpu_contrib_kernels.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { + +using namespace onnxruntime::webgpu; +using onnxruntime::webgpu::ComputeContext; + +ONNX_OPERATOR_KERNEL_EX( + QuickGelu, + kMSDomain, + 1, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()), + QuickGelu); + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc b/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc index 068a94c7390e2..6e63ba3a0caa4 100644 --- a/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc @@ -38,14 +38,14 @@ Status RegisterWebGpuContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, // default entry to avoid the list become empty after ops-reducing // BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, // LayerNormalization used to be a contrib op that (incorrectly) used kOnnxDomain so we need to version it diff --git a/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc index 189d7baafce6a..e16327b9facad 100644 --- a/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc @@ -256,26 +256,6 @@ WEBGPU_CLIP_KERNEL(MLFloat16) // activation // -class LinearUnit : public UnaryElementwise { - public: - LinearUnit(const OpKernelInfo& info, - const std::string& kernel_name, - const std::string& expression, - const std::string& additional_impl, - float default_alpha) - : UnaryElementwise{info, kernel_name, expression, additional_impl, ShaderUsage::UseElementTypeAlias} { - info.GetAttrOrDefault("alpha", &alpha_, default_alpha); - } - - Status ConfigureProgram(const ComputeContext& /*context*/, UnaryElementwiseProgram& program) const override { - program.AddUniformVariables({alpha_}); - return Status::OK(); - } - - protected: - float alpha_; -}; - #define WEBGPU_LU_IMPL(OP_TYPE, ...) \ class OP_TYPE final : public LinearUnit { \ public: \ @@ -285,17 +265,17 @@ class LinearUnit : public UnaryElementwise { WEBGPU_LU_IMPL(Elu, "elu_v(a)", EluImpl, 1.0) WEBGPU_ELEMENTWISE_KERNEL(Elu, 6, WebGpuSupportedFloatTypes()) -class Gelu : public UnaryElementwise { - public: - Gelu(const OpKernelInfo& info) - : UnaryElementwise{info, - "Gelu", - info.GetAttrOrDefault("approximate", "none") == "tanh" ? FastGeluExpr : GeluExpr, - info.GetAttrOrDefault("approximate", "none") == "tanh" ? TanhImpl : ErfImpl, - ShaderUsage::UseValueTypeAlias} { - cache_hint = info.GetAttrOrDefault("approximate", "none"); - } -}; +Gelu::Gelu(const OpKernelInfo& info) + : UnaryElementwise{info, + "Gelu", + info.GetAttrOrDefault("approximate", "none") == "tanh" ? FastGeluExpr : GeluExpr, + info.GetAttrOrDefault("approximate", "none") == "tanh" ? TanhImpl : ErfImpl, + ShaderUsage::UseValueTypeAlias} { + cache_hint = info.GetAttrOrDefault("approximate", "none"); +} + +QuickGelu::QuickGelu(const OpKernelInfo& info) + : LinearUnit{info, "QuickGelu", "quick_gelu_v(a)", QuickGeluImpl, 1.702f} {} WEBGPU_ELEMENTWISE_KERNEL(Gelu, 20, WebGpuSupportedFloatTypes()) @@ -312,4 +292,4 @@ WEBGPU_LU_IMPL(ThresholdedRelu, "select(vec4(0), a, a > vec4) -> vec4 { } )"; +constexpr const char QuickGeluImpl[] = R"( +fn quick_gelu_v(a: vec4) -> vec4 { + let one = 1.0; + let zero = 0.0; + let alpha_vec = vec4(uniforms.attr); + let v = a * alpha_vec; + var x1 : vec4; + for (var i = 0; i < 4; i = i + 1) { + if (v[i] >= zero) { + x1[i] = one / (one + exp(-v[i])); + } else { + x1[i] = one - one / (one + exp(v[i])); + } + } + return a * x1; +} +)"; + // default GELU expression, depending on ErfImpl constexpr const char GeluExpr[] = "0.5 * a * (1.0 + erf_v(a * 0.7071067811865475))"; @@ -111,4 +159,4 @@ constexpr const char GeluExpr[] = "0.5 * a * (1.0 + erf_v(a * 0.7071067811865475 constexpr const char FastGeluExpr[] = "a * (0.5 + 0.5 * tanh_v(a * (0.035677408136300125 * a * a + 0.7978845608028654)))"; } // namespace webgpu -} // namespace onnxruntime +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/webgpu_utils.h b/onnxruntime/core/providers/webgpu/webgpu_utils.h new file mode 100644 index 0000000000000..4f9018646905d --- /dev/null +++ b/onnxruntime/core/providers/webgpu/webgpu_utils.h @@ -0,0 +1,20 @@ +// Licensed under the MIT License. + +#pragma once + +#include + +namespace onnxruntime { +namespace webgpu { + +inline int64_t GetMaxComponents(int64_t size) { + if (size % 4 == 0) { + return 4; + } else if (size % 2 == 0) { + return 2; + } + return 1; +} + +} // namespace webgpu +} // namespace onnxruntime \ No newline at end of file From 6dd6ef93f01e248f57d7a0d4d98377887a2ad0ff Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Wed, 12 Mar 2025 11:58:12 -0700 Subject: [PATCH 081/266] [Native WebGPU] Added ReduceMax and ReduceSum (#23934) ### Description Added ReduceMax and ReduceSum ### Motivation and Context --- .../webgpu/reduction/reduction_ops.cc | 94 +++++++++++++++---- .../webgpu/reduction/reduction_ops.h | 39 ++++++-- .../webgpu/webgpu_execution_provider.cc | 16 ++-- 3 files changed, 112 insertions(+), 37 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index eb7903e7903b6..255ad9cdf66c6 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -34,11 +34,28 @@ REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 11, 12); REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 13, 17); REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMean, 18); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 11, 11); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 12, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMax, 18); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSum, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSum, 11, 12); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceSum, 13); + Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { - const auto& input = shader.AddInput("input", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + if (is_input_empty_) { + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << code_[0] + << code_[2] + << output.SetByOffset("global_idx", "output_value"); + return Status::OK(); + } + const auto& input = shader.AddInput("input", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); bool reduce_on_all_axes = no_op_with_empty_axes_ == false && axes_.empty(); - std::string loop_header = code_[0]; + std::string loop_header = code_[0].find("first_element") == std::string::npos ? code_[0] : "let first_element = " + input.GetByIndices("input_indices") + ";\n" + code_[0] + "\n"; std::string loop_body = "let current_element: input_value_t = " + input.GetByIndices("input_indices") + ";\n" + code_[1]; std::string loop_footer = code_[2]; const auto input_rank = input.Rank(); @@ -56,10 +73,10 @@ Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { loop_body = ss.str(); } else { std::stringstream ss; - ss << loop_header << "\n"; std::string index = "i" + std::to_string(i); ss << "let " << index << " = " << output.IndicesGet("output_indices", l) << ";\n"; ss << input.IndicesSet("input_indices", i, index) << ";\n"; + ss << loop_header << "\n"; loop_header = ss.str(); l++; } @@ -80,6 +97,7 @@ Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { template Status ReduceKernel::ComputeInternal(ComputeContext& context) const { const auto* input_tensor = context.Input(0); + ORT_RETURN_IF_ERROR(CheckInput(input_tensor)); InlinedVector input_axes; auto rank = input_tensor->Shape().NumDimensions(); auto transform_axis = [rank](int64_t axis) { @@ -95,10 +113,12 @@ Status ReduceKernel::ComputeInternal(ComputeContext& context) if (context.InputCount() > 1) { ORT_ENFORCE(axes_.empty(), "Axes attribute may not be specified when axes input is also provided."); const Tensor* axes_tensor = context.Input(1); - auto size = static_cast(axes_tensor->Shape()[0]); - const auto* data = axes_tensor->Data(); - input_axes.reserve(size); - std::transform(data, data + size, std::back_inserter(input_axes), transform_axis); + if (nullptr != axes_tensor) { + auto size = static_cast(axes_tensor->Shape()[0]); + const auto* data = axes_tensor->Data(); + input_axes.reserve(size); + std::transform(data, data + size, std::back_inserter(input_axes), transform_axis); + } } else { input_axes.reserve(axes_.size()); std::transform(axes_.begin(), axes_.end(), std::back_inserter(input_axes), transform_axis); @@ -120,10 +140,12 @@ Status ReduceKernel::ComputeInternal(ComputeContext& context) std::iota(input_axes.begin(), input_axes.end(), 0); } } - const auto code = GetOpSpecificCode(input_tensor, input_axes.size()); + const auto code = GetOpSpecificCode(input_tensor); // Compute output shape std::vector output_shape; + bool is_input_empty = false; for (size_t i = 0; i < input_tensor->Shape().NumDimensions(); ++i) { + is_input_empty |= input_tensor->Shape()[i] == 0; if (std::find(input_axes.begin(), input_axes.end(), i) != input_axes.end()) { if (keepdims_) { output_shape.push_back(1); @@ -134,34 +156,68 @@ Status ReduceKernel::ComputeInternal(ComputeContext& context) } TensorShape output_tensor_shape(output_shape); int64_t output_size = output_tensor_shape.Size(); - ReduceKernelProgram program("ReduceMean", keepdims_, noop_with_empty_axes_, input_axes, code); - program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + if (output_size == 0) { + ORT_IGNORE_RETURN_VALUE(context.Output(0, output_tensor_shape)); + return Status::OK(); + } + + auto input_rank = input_tensor->Shape().NumDimensions(); + // reduce_axes element is either 1 or 0 depending on whether the axis is reduced or not + std::vector reduce_axes; + reduce_axes.resize(input_rank, 0); + for (auto axis : input_axes) { + reduce_axes[axis] = 1; + } + + ReduceKernelProgram program(name_, keepdims_, noop_with_empty_axes_, input_axes, code, is_input_empty); + if (!is_input_empty) { + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}); + } + + program.CacheHint(is_input_empty) .AddOutput({context.Output(0, output_shape), ProgramTensorMetadataDependency::TypeAndRank}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) .AddUniformVariables({{static_cast(output_size)}, {static_cast(noop_with_empty_axes_ ? 1 : 0)}, - {input_axes}, - {static_cast(input_axes.size())}}); + {reduce_axes}}); return context.RunProgram(program); } -ReduceOpSpecificCode ReduceMean::GetOpSpecificCode(const Tensor* input_tensor, size_t axes_size) const { +ReduceOpSpecificCode ReduceMean::GetOpSpecificCode(const Tensor* input_tensor) const { const TensorShape& input_shape = input_tensor->Shape(); size_t input_rank = input_shape.NumDimensions(); + std::string loop_header = "var sum = f32(0);"; + std::string loop_body = "sum += f32(current_element);"; std::stringstream ss; ss << "var size: u32 = 1;\n" - << "for (var i: u32 = 0; i < uniforms.axes_size; i += 1) { \n" - << " let index = " << GetElementAt("uniforms.axes", "i", axes_size) << ";\n" - << " size = size * " << GetElementAt("uniforms.input_shape", "index", input_rank) << ";\n" + << "for (var i: u32 = 0; i < " << input_rank << "; i += 1) { \n" + << " let index_reduced_or_not = " << GetElementAt("uniforms.reduce_axes", "i", input_rank) << ";\n" + << " if (index_reduced_or_not == 1) { \n" + << " size = size * " << GetElementAt("uniforms.input_shape", "i", input_rank) << ";\n" + << " }\n" << "}\n" << "let output_value = output_value_t(sum / f32(size));"; - ReduceOpSpecificCode code({"var sum = f32(0);", "sum += f32(current_element);", ss.str()}); + std::string loop_footer = ss.str(); + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); return code; } -Status ReduceMean::ComputeInternal(ComputeContext& ctx) const { - return ReduceKernel::ComputeInternal(ctx); +ReduceOpSpecificCode ReduceMax::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var max_element = first_element;"; + std::string loop_body = "max_element = max(max_element, current_element);"; + std::string loop_footer = "let output_value = output_value_t(max_element);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} +ReduceOpSpecificCode ReduceSum::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var sum = f32(0);"; + std::string loop_body = "sum += f32(current_element);"; + std::string loop_footer = "let output_value = output_value_t(sum);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; } } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h index e93eb06f20886..1c7dba89b7144 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h @@ -13,22 +13,23 @@ namespace webgpu { // reduceOpSpecificCode is a 3-element array of strings that represent the op specific code for the reduce operation. // The first element is the loop header, the second element is the loop body, and the third element is the loop footer. // The loop header is the code that is executed before the loop starts. The loop body is the code that is executed for each element in the loop. -// The loop footer is the code that is executed after the loop ends. +// The loop footer is the code that is executed after the loop ends. The loop body should contain the code that accumulates the result of the reduction and +// the loop footer should contain the code that assigins output_value the result of the reduction. typedef std::array ReduceOpSpecificCode; class ReduceKernelProgram final : public Program { public: - ReduceKernelProgram(std::string name, bool keepdims, bool no_op_with_empty_axes, const InlinedVector& axes, ReduceOpSpecificCode code) : Program{name}, keepdims_(keepdims), no_op_with_empty_axes_(no_op_with_empty_axes), axes_(axes.begin(), axes.end()), code_(code) {} + ReduceKernelProgram(std::string name, bool keepdims, bool no_op_with_empty_axes, const InlinedVector& axes, ReduceOpSpecificCode code, bool is_input_empty) : Program{name}, keepdims_(keepdims), no_op_with_empty_axes_(no_op_with_empty_axes), axes_(axes.begin(), axes.end()), code_(code), is_input_empty_(is_input_empty) {} Status GenerateShaderCode(ShaderHelper& wgpuShaderModuleAddRef) const override; WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, {"no_op_with_empty_axes", ProgramUniformVariableDataType::Uint32}, - {"axes", ProgramUniformVariableDataType::Uint32}, - {"axes_size", ProgramUniformVariableDataType::Uint32}); + {"reduce_axes", ProgramUniformVariableDataType::Uint32}); private: const bool keepdims_; const bool no_op_with_empty_axes_; InlinedVector axes_; ReduceOpSpecificCode code_; + bool is_input_empty_; }; template @@ -39,23 +40,41 @@ class ReduceKernel : public WebGpuKernel, public ReduceKernelBase::keepdims_; using ReduceKernelBase::select_last_index_; - ReduceKernel(const OpKernelInfo& info, std::string name, optional keepdims_override = {}) + ReduceKernel(const OpKernelInfo& info, std::string name, bool allow_empty_input = false, optional keepdims_override = {}) : WebGpuKernel(info), ReduceKernelBase(info, keepdims_override), - name_(name) { + name_(name), + allow_empty_input_(allow_empty_input) { } Status ComputeInternal(ComputeContext& ctx) const; - virtual ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor, size_t axes_size) const = 0; + virtual ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const = 0; + + Status CheckInput(const Tensor* input_tensor) const { + ORT_ENFORCE(input_tensor != nullptr && (input_tensor->Shape().Size() > 0 || allow_empty_input_), "Input tensor cannot be null or empty"); + return Status::OK(); + } private: std::string name_; + bool allow_empty_input_; }; class ReduceMean final : public ReduceKernel { public: - ReduceMean(const OpKernelInfo& info) : ReduceKernel(info, "ReduceMean") {} - ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor, size_t axes_size) const override; - Status ComputeInternal(ComputeContext& ctx) const override; + ReduceMean(const OpKernelInfo& info) : ReduceKernel(info, "ReduceMean", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceMax final : public ReduceKernel { + public: + ReduceMax(const OpKernelInfo& info) : ReduceKernel(info, "ReduceMax") {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceSum final : public ReduceKernel { + public: + ReduceSum(const OpKernelInfo& info) : ReduceKernel(info, "ReduceSum", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; }; } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index df7f2d6dcdeab..0ff07f0581475 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -513,11 +513,11 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -539,9 +539,9 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, From 47bd0468ff7ae52aeb5141b2bdff04108ccce8cc Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Wed, 12 Mar 2025 12:00:05 -0700 Subject: [PATCH 082/266] Convert Windows CPU CI Pipeline to Github Actions (#23996) --- .../locate-vcvarsall-and-setup-env/action.yml | 63 +++++ .../locate_vcvarsall.bat | 30 ++ .../update_environment.py | 37 +++ .github/workflows/ios.yml | 59 ++++ .github/workflows/mac.yml | 96 ++++++- .github/workflows/macos_coreml.yml | 51 ++++ .github/workflows/windows.yml | 44 --- .github/workflows/windows_build_x64_asan.yml | 49 ++++ .../windows_x64_debug_build_x64_debug.yml | 129 +++++++++ .../windows_x64_release_build_x64_release.yml | 126 +++++++++ ...build_x64_release_ep_generic_interface.yml | 117 ++++++++ ..._x64_release_vitisai_build_x64_release.yml | 113 ++++++++ .../workflows/windows_x64_release_xnnpack.yml | 119 ++++++++ .github/workflows/windows_x86.yml | 127 +++++++++ tools/ci_build/build.py | 4 + .../azure-pipelines/mac-ci-pipeline.yml | 37 --- .../mac-coreml-ci-pipeline.yml | 68 ----- .../azure-pipelines/mac-ios-ci-pipeline.yml | 81 ------ .../azure-pipelines/win-ci-pipeline.yml | 261 ------------------ 19 files changed, 1119 insertions(+), 492 deletions(-) create mode 100644 .github/actions/locate-vcvarsall-and-setup-env/action.yml create mode 100644 .github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat create mode 100644 .github/actions/locate-vcvarsall-and-setup-env/update_environment.py create mode 100644 .github/workflows/ios.yml create mode 100644 .github/workflows/macos_coreml.yml delete mode 100644 .github/workflows/windows.yml create mode 100644 .github/workflows/windows_build_x64_asan.yml create mode 100644 .github/workflows/windows_x64_debug_build_x64_debug.yml create mode 100644 .github/workflows/windows_x64_release_build_x64_release.yml create mode 100644 .github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml create mode 100644 .github/workflows/windows_x64_release_vitisai_build_x64_release.yml create mode 100644 .github/workflows/windows_x64_release_xnnpack.yml create mode 100644 .github/workflows/windows_x86.yml delete mode 100644 tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml diff --git a/.github/actions/locate-vcvarsall-and-setup-env/action.yml b/.github/actions/locate-vcvarsall-and-setup-env/action.yml new file mode 100644 index 0000000000000..b1e09e7d17f9e --- /dev/null +++ b/.github/actions/locate-vcvarsall-and-setup-env/action.yml @@ -0,0 +1,63 @@ +name: 'Locate vcvarsall and Setup Environment' +description: 'Locates vcvarsall.bat, sets up the environment, and handles PATH updates.' +inputs: + architecture: + description: 'Target architecture (x64 or x86)' + required: true + default: 'x64' +outputs: + vcvarsall_path: + description: "Path to vcvarsall.bat" + value: ${{ steps.find-vcvarsall.outputs.vcvarsall_path }} +runs: + using: "composite" + steps: + - name: Find vcvarsall.bat + id: find-vcvarsall + shell: python # Use Python shell + run: | + import os + import subprocess + + vswhere_path = os.path.join(os.environ["ProgramFiles(x86)"], "Microsoft Visual Studio", "Installer", "vswhere.exe") + + try: + process = subprocess.run([vswhere_path, "-latest", "-property", "installationPath"], capture_output=True, text=True, check=True) + vs_install_path = process.stdout.strip() + vcvarsall_path = os.path.join(vs_install_path, "VC", "Auxiliary", "Build", "vcvarsall.bat") + + if os.path.exists(vcvarsall_path): + print(f"vcvarsall found at: {vcvarsall_path}") + # Use GITHUB_OUTPUT environment variable + with open(os.environ['GITHUB_OUTPUT'], 'a') as f: + f.write(f"vcvarsall_path={vcvarsall_path}\n") + else: + print(f"vcvarsall.bat not found at expected path: {vcvarsall_path}") + # Use 'exit(1)' for Python to properly signal failure to GitHub Actions + exit(1) + + + except subprocess.CalledProcessError as e: + print(f"Error running vswhere.exe: {e}") + print(f"vswhere output: {e.stdout}") + print(f"vswhere stderr: {e.stderr}") + exit(1) # Exit with a non-zero code on error + except FileNotFoundError: + print(f"vswhere.exe not found at: {vswhere_path}") + exit(1) + + + - name: Setup Environment + shell: cmd + run: | + REM Get initial environment variables + set > initial_env.txt + + REM Call vcvarsall.bat using the output from the previous step + call "${{ steps.find-vcvarsall.outputs.vcvarsall_path }}" ${{ inputs.architecture }} + + REM Get environment variables after calling vcvarsall.bat + set > final_env.txt + + REM Call the Python script to update the GitHub Actions environment + python ${{ github.action_path }}\update_environment.py \ No newline at end of file diff --git a/.github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat b/.github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat new file mode 100644 index 0000000000000..df900e5cd0995 --- /dev/null +++ b/.github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat @@ -0,0 +1,30 @@ +@echo off +setlocal + +set vswherepath="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +set vcvarsall_arch=%1 +if "%vcvarsall_arch%" == "x86" ( + set vcvarsall_arch=x86 +) else ( + set vcvarsall_arch=x64 +) + +for /f "usebackq delims=" %%i in (`%vswherepath% -latest -property installationPath`) do ( + if exist "%%i\VC\Auxiliary\Build\vcvars%vcvarsall_arch%.bat" ( + set "vcvarsall=%%i\VC\Auxiliary\Build\vcvars%vcvarsall_arch%.bat" + ) +) + +echo "Get initial environment variables" +set > initial_env.txt + +echo "Call vcvarsall.bat" +call "%vcvarsall%" + +echo "Get environment variables after calling vcvarsall.bat" +set > final_env.txt + +echo "Call the Python script to update the GitHub Actions environment" +python "%~dp0\update_environment.py" + +endlocal \ No newline at end of file diff --git a/.github/actions/locate-vcvarsall-and-setup-env/update_environment.py b/.github/actions/locate-vcvarsall-and-setup-env/update_environment.py new file mode 100644 index 0000000000000..9b63b26042562 --- /dev/null +++ b/.github/actions/locate-vcvarsall-and-setup-env/update_environment.py @@ -0,0 +1,37 @@ +import os +import re + + +def read_env_file(filepath): + env_vars = {} + with open(filepath) as f: + for line in f: + match = re.match(r"^(.*?)=(.*)$", line.strip()) + if match: + env_vars[match.group(1).upper()] = match.group(2) + return env_vars + + +initial_env = read_env_file("initial_env.txt") +final_env = read_env_file("final_env.txt") + +for key, value in final_env.items(): + if key not in initial_env or initial_env[key] != value: + if key.startswith("_"): + continue + if key.upper() == "PATH": + new_paths = value.split(";") + initial_paths = initial_env.get("PATH", "").split(";") + added_paths = [p for p in new_paths if p not in initial_paths and p] + + if added_paths: + print("Adding paths") + with open(os.environ["GITHUB_PATH"], "a") as f: + for path in added_paths: + print(f"Adding PATH: {path}") + f.write(path + os.linesep) + else: + # Use GITHUB_ENV + with open(os.environ["GITHUB_ENV"], "a") as f: + print(f"Setting {key}={value}\n") + f.write(f"{key}={value}\n") diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml new file mode 100644 index 0000000000000..b4cb0adc47b66 --- /dev/null +++ b/.github/workflows/ios.yml @@ -0,0 +1,59 @@ +name: iOS_CI_on_Mac + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + iOS_CI_on_Mac: + runs-on: macos-13 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + - name: Use Xcode ${{ env.XCODE_VERSION }} + shell: bash + run: | + set -e -x + XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: (CPU, CoreML, XNNPACK EPs) Build onnxruntime for iOS x86_64 and run tests using simulator + shell: bash + run: | + python3 ${{ github.workspace }}/tools/ci_build/build.py \ + --skip_submodule_sync \ + --build_dir ${{ github.workspace }}/iOS \ + --build_shared_lib \ + --use_coreml \ + --use_xnnpack \ + --ios \ + --apple_sysroot iphonesimulator \ + --osx_arch x86_64 \ + --apple_deploy_target=15.1 \ + --use_xcode \ + --config RelWithDebInfo \ + --build_apple_framework \ + --parallel \ + --use_binskim_compliant_compile_flags + env: + ORT_GET_SIMULATOR_DEVICE_INFO_REQUESTED_RUNTIME_VERSION: ${{ env.IOS_SIMULATOR_RUNTIME_VERSION }} + + timeout-minutes: 150 + env: + XCODE_VERSION: 14.3.1 + IOS_SIMULATOR_RUNTIME_VERSION: 16.4 \ No newline at end of file diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 3218afe11edfd..eb4befaa34244 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -1,4 +1,4 @@ -name: Mac_CI +name: "MacOS CI Pipeline" on: push: @@ -19,6 +19,100 @@ env: python_version: 3.11 jobs: + MacOS_C_API_Packaging_CPU_x86_64: + runs-on: macos-13 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Use Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.python_version }} + + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: Install Java 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: Set version number variables for Unix + shell: bash + run: | + # Do not output ##vso[] commands with `set -x` or they may be parsed again and include a trailing quote. + set +x + + _OnnxRuntimeVersion=$(head -1 ${{ github.workspace }}/VERSION_NUMBER) + echo "OnnxRuntimeVersion=$_OnnxRuntimeVersion" + + _OnnxRuntimeGitCommitHash=$(git rev-parse HEAD) + echo "OnnxRuntimeGitCommitHash=$_OnnxRuntimeGitCommitHash" + + _OnnxRuntimeGitCommitHash=$(git rev-parse --short=8 HEAD) + echo "OnnxRuntimeGitCommitHashShort=$_OnnxRuntimeGitCommitHash" + working-directory: ${{ github.workspace }} + + - name: Use Xcode 14.3.1 + shell: bash + run: | + set -e -x + XCODE_DEVELOPER_DIR="/Applications/Xcode_14.3.1.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: Setup environment variables + shell: bash + run: | + set -e -x + export PATH=${{ github.workspace }}/installed/bin:$PATH + export ONNX_ML=1 + export CMAKE_ARGS="-DONNX_GEN_PB_TYPE_STUBS=ON -DONNX_WERROR=OFF" + python3 -m pip install -r '${{ github.workspace }}/tools/ci_build/github/linux/docker/scripts/requirements.txt' + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Configure Build (build.py --update) + shell: bash + run: | + set -e -x + rm -rf ${{ github.workspace }}/Release + python3 ${{ github.workspace }}/tools/ci_build/build.py --update --build_objc --build_wheel --use_xnnpack --build_nodejs --build_java --use_coreml --use_webgpu --build_dir ${{ github.workspace }} --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --build_shared_lib --config Release --use_vcpkg --use_vcpkg_ms_internal_asset_cache + + - name: Build (build.py --build) + shell: bash + run: | + set -e -x + python3 ${{ github.workspace }}/tools/ci_build/build.py --build --build_objc --build_wheel --use_xnnpack --build_nodejs --build_java --use_coreml --use_webgpu --build_dir ${{ github.workspace }} --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --build_shared_lib --config Release --use_vcpkg --use_vcpkg_ms_internal_asset_cache + + - name: Install + shell: bash + run: | + set -e -x + cd ${{ github.workspace }}/Release + make install DESTDIR=${{ github.workspace }}/installed + + - name: Running Tests (build.py --test) + shell: bash + run: | + set -e -x + python3 ${{ github.workspace }}/tools/ci_build/build.py --test --build_objc --build_wheel --use_xnnpack --build_nodejs --build_java --use_coreml --use_webgpu --build_dir ${{ github.workspace }} --skip_submodule_sync --parallel --use_binskim_compliant_compile_flags --build_shared_lib --config Release --use_vcpkg --use_vcpkg_ms_internal_asset_cache + timeout-minutes: 300 + env: + MACOSX_DEPLOYMENT_TARGET: '13.3' + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + ARM64-Xcode16: runs-on: macos-15 diff --git a/.github/workflows/macos_coreml.yml b/.github/workflows/macos_coreml.yml new file mode 100644 index 0000000000000..42b9ec702661b --- /dev/null +++ b/.github/workflows/macos_coreml.yml @@ -0,0 +1,51 @@ +name: "CoreML CI Pipeline" + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_with_coreml: + runs-on: macos-13 + strategy: + matrix: + use_coreml: [true, false] + + env: + MACOSX_DEPLOYMENT_TARGET: '13.3' + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install coreutils and ninja + run: brew install coreutils ninja + + - name: Use Xcode 14.3.1 + run: | + XCODE_DEVELOPER_DIR="/Applications/Xcode_14.3.1.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: CoreML EP, Build and Test on macOS + run: | + python3 tools/ci_build/build.py \ + --build_dir build \ + --skip_submodule_sync \ + --cmake_generator=Ninja \ + --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags \ + --build_shared_lib \ + --config Debug \ + ${{ matrix.use_coreml && '--use_coreml' || '' }} \ No newline at end of file diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 593ca85e8ea4b..0000000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Windows_CI -on: - push: - branches: - - main - - rel-* - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - AZCOPY_AUTO_LOGIN_TYPE: MSI - AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 - -jobs: - Windows-CUDA-12: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] - steps: - - uses: actions/checkout@v4 - with: - submodules: false - - uses: actions/setup-python@v5 - with: - python-version: '3.11.x' - architecture: 'x64' - - - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: Download cuda - run: azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.2" cuda_sdk - - - - name: Delete build folder - run: | - if (Test-Path D:\b) { Remove-Item -Recurse -Force D:\b } - - - # The build machine doesn't have a GPU. So the value of CMAKE_CUDA_ARCHITECTURES doesn't matter. - - name: Build code - run: python tools\ci_build\build.py --windows_sdk_version 10.0.22621.0 --enable_training --build_java --config Debug --build_dir D:\b --skip_submodule_sync --build_csharp --update --build --parallel --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_pybind --use_cuda --cuda_home=${{ github.workspace }}\cuda_sdk\v12.2 --enable_cuda_profiling --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=75 \ No newline at end of file diff --git a/.github/workflows/windows_build_x64_asan.yml b/.github/workflows/windows_build_x64_asan.yml new file mode 100644 index 0000000000000..6be647c86eab8 --- /dev/null +++ b/.github/workflows/windows_build_x64_asan.yml @@ -0,0 +1,49 @@ +# .github/workflows/build_x64_asan.yml +name: windows_x64_asan + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env # Use the composite action + with: + architecture: x64 + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test (Combined) + shell: cmd + run: | + @echo off + echo %PATH% + python -m pip install -r "%GITHUB_WORKSPACE%\tools\ci_build/github/windows\python\requirements.txt" + python "%GITHUB_WORKSPACE%\tools\ci_build\build.py" --config Debug --build_dir "%RUNNER_TEMP%\build" --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_generator "Visual Studio 17 2022" --disable_memleak_checker --enable_address_sanitizer \ No newline at end of file diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml new file mode 100644 index 0000000000000..081f8dc57a107 --- /dev/null +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -0,0 +1,129 @@ +name: windows_x64_debug + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_debug: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env # Use the composite action + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\Debug\Debug + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v1 # Use the official NuGet setup action + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\Debug -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config Debug --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_java --build_nodejs --build_wheel --disable_memleak_checker --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\Debug" -Include "*.obj" -Recurse + env: # Set environment variables here, applies to this step only + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' # Can be set dynamically based on build output if needed + + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\Debug\\Debug" + + # Publish artifacts only on failure and if DocUpdateNeeded is true (example) + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' # Use env. for step-level vars + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + # These variables will persist for the entire job + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' \ No newline at end of file diff --git a/.github/workflows/windows_x64_release_build_x64_release.yml b/.github/workflows/windows_x64_release_build_x64_release.yml new file mode 100644 index 0000000000000..9f8f650e906dc --- /dev/null +++ b/.github/workflows/windows_x64_release_build_x64_release.yml @@ -0,0 +1,126 @@ +name: windows_x64_release + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_release: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v1 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --build_java --build_nodejs --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml b/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml new file mode 100644 index 0000000000000..9c280da27e8bc --- /dev/null +++ b/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml @@ -0,0 +1,117 @@ +name: windows_x64_release_ep_generic_interface + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_release_ep_generic_interface: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v1 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --enable_generic_interface --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml new file mode 100644 index 0000000000000..ec4ccef5390d2 --- /dev/null +++ b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml @@ -0,0 +1,113 @@ +name: windows_x64_release_vitisai + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_release_vitisai: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v1 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --build_wheel --use_vitisai --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_xnnpack.yml b/.github/workflows/windows_x64_release_xnnpack.yml new file mode 100644 index 0000000000000..13e830505513d --- /dev/null +++ b/.github/workflows/windows_x64_release_xnnpack.yml @@ -0,0 +1,119 @@ +name: windows_x64_release_xnnpack + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_release_xnnpack: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v1 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --use_xnnpack --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --disable_rtti --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x86.yml b/.github/workflows/windows_x86.yml new file mode 100644 index 0000000000000..20f1bcd54cb1a --- /dev/null +++ b/.github/workflows/windows_x86.yml @@ -0,0 +1,127 @@ +name: Windows CPU CI Pipeline + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x86_release: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + architecture: x86 # x86 Python + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x86 # x86 architecture for vcvarsall + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + architecture: x86 #Add architecture + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + architecture: x86 # x86 Java + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x86 # x86 .NET + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v1 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' \ No newline at end of file diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index c20ea159943fe..e6c3d9faf4a3f 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -1069,6 +1069,10 @@ def generate_vcpkg_install_options(build_dir, args): if "AGENT_TEMPDIRECTORY" in os.environ: temp_dir = os.environ["AGENT_TEMPDIRECTORY"] vcpkg_install_options.append(f"--x-buildtrees-root={temp_dir}") + elif "RUNNER_TEMP" in os.environ: + temp_dir = os.environ["RUNNER_TEMP"] + vcpkg_install_options.append(f"--x-buildtrees-root={temp_dir}") + vcpkg_install_options.append("--binarysource=clear\\;x-gha,readwrite") # Config asset cache if args.use_vcpkg_ms_internal_asset_cache: diff --git a/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml deleted file mode 100644 index f3465a8eea8b5..0000000000000 --- a/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml +++ /dev/null @@ -1,37 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -stages: -- template: templates/mac-cpu-packaging-pipeline.yml - parameters: - AllowReleasedOpsetOnly: 0 - BuildForAllArchs: false - AdditionalBuildFlags: --build_objc --build_wheel --use_xnnpack - WithCache: true diff --git a/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml deleted file mode 100644 index 42f5340730a69..0000000000000 --- a/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml +++ /dev/null @@ -1,68 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -jobs: -- job: CoreML_CI - workspace: - clean: all - pool: - vmImage: 'macOS-13' - variables: - MACOSX_DEPLOYMENT_TARGET: '13.3' - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - CCACHE_DIR: '$(Pipeline.Workspace)/ccache' - timeoutInMinutes: 120 - steps: - - script: brew install coreutils ninja - displayName: Install coreutils and ninja - - - template: templates/use-xcode-version.yml - - - template: templates/mac-build-step-with-cache.yml - parameters: - WithCache: true - Today: $(TODAY) - AdditionalKey: coreml - CacheDir: $(CCACHE_DIR) - BuildStep: - - script: | - set -e - python3 tools/ci_build/build.py \ - --build_dir build \ - --skip_submodule_sync \ - --cmake_generator=Ninja \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags \ - --build_shared_lib \ - --config Debug \ - --use_cache \ - --use_coreml - displayName: CoreML EP, Build and Test on macOS - env: - CCACHE_COMPILERCHECK: content diff --git a/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml deleted file mode 100644 index 26b072ed55b04..0000000000000 --- a/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml +++ /dev/null @@ -1,81 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -jobs: -- job: iOS_CI_on_Mac - pool: - vmImage: 'macOS-13' - variables: - PROTO_CACHE_DIR: $(Pipeline.Workspace)/proto_ccache - ORT_CACHE_DIR: $(Pipeline.Workspace)/ort_ccache - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - # Note: Keep the Xcode version and iOS simulator version compatible. - # Check the table here to see what iOS simulator versions are supported by a particular Xcode version: - # https://developer.apple.com/support/xcode/ - XCODE_VERSION: 14.3.1 - IOS_SIMULATOR_RUNTIME_VERSION: 16.4 - timeoutInMinutes: 150 - steps: - - template: templates/use-xcode-version.yml - parameters: - xcodeVersion: $(XCODE_VERSION) - - - template: templates/mac-build-step-with-cache.yml - parameters: - WithCache: true - Today: $(TODAY) - AdditionalKey: onnxruntime - CacheDir: $(ORT_CACHE_DIR) - ChangeEveryCommit: true - BuildStep: - - script: | - python3 $(Build.SourcesDirectory)/tools/ci_build/build.py \ - --skip_submodule_sync \ - --build_dir $(Build.BinariesDirectory)/iOS \ - --build_shared_lib \ - --use_coreml \ - --use_xnnpack \ - --ios \ - --apple_sysroot iphonesimulator \ - --osx_arch x86_64 \ - --apple_deploy_target=15.1 \ - --use_xcode \ - --config RelWithDebInfo \ - --build_apple_framework \ - --parallel --use_binskim_compliant_compile_flags - displayName: (CPU, CoreML, XNNPACK EPs) Build onnxruntime for iOS x86_64 and run tests using simulator - env: - CC: clang - CXX: clang++ - CCACHE_CPP2: 1 - CCACHE_DEPEND: 1 - CCACHE_SLOPPINESS: modules - CCACHE_DIR: $(ORT_CACHE_DIR) - ORT_GET_SIMULATOR_DEVICE_INFO_REQUESTED_RUNTIME_VERSION: $(IOS_SIMULATOR_RUNTIME_VERSION) diff --git a/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml deleted file mode 100644 index 54c2e51c2a09b..0000000000000 --- a/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml +++ /dev/null @@ -1,261 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -parameters: -- name: RunOnnxRuntimeTests - displayName: Run Tests? - type: boolean - default: true - -stages: -- stage: x64_debug - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'Debug' - buildArch: x64 - additionalBuildFlags: --build_java --build_nodejs --build_wheel --disable_memleak_checker --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_debug - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - isTraining: false - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - - - job: build_x64_asan - pool: 'onnxruntime-Win-CPU-2022' - timeoutInMinutes: 300 - steps: - - checkout: self - clean: true - submodules: none - - - template: templates/jobs/win-ci-prebuild-steps.yml - parameters: - EnvSetupScript: setup_env.bat - DownloadCUDA: false - BuildArch: x64 - BuildConfig: Debug - MachinePool: 'onnxruntime-Win-CPU-2022' - WithCache: false - Today: $(TODAY) - - - task: PythonScript@0 - displayName: 'Build and Test' - inputs: - scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: --config Debug --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_generator "Visual Studio 17 2022" --disable_memleak_checker --enable_address_sanitizer - workingDirectory: '$(Build.BinariesDirectory)' - - -- stage: x64_release - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - # Compare to our Nuget packaging pipeline, this job has "--build_wheel" but doesn't have "--enable_lto --disable_rtti --use_telemetry --enable_wcos" - # Python bindings use typeid so I can't disable RTTI here. If it causes a problem, we will need to split this job to two jobs. - additionalBuildFlags: --build_wheel --build_java --build_nodejs --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - isTraining: false - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - -- stage: x64_release_dnnl - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --build_wheel --use_dnnl --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - isTraining: false - ORT_EP_NAME: DNNL - GenerateDocumentation: false - WITH_CACHE: false - # Intel EPs require Intel CPUs - MachinePool: 'onnxruntime-Win2022-Intel-CPU' - -# Tests doesn't work on AMD CPUs -- stage: x64_release_xnnpack - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --build_wheel --use_xnnpack --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - isTraining: false - ORT_EP_NAME: XNNPACK - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - -# Build only. Does not run any tests. -- stage: x64_release_vitisai - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --build_wheel --use_vitisai --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release - RunOnnxRuntimeTests: false - isTraining: false - ORT_EP_NAME: VITISAI - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - -- stage: x64_release_winml - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --use_winml --enable_wcos --disable_rtti --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release_winml - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - # WinML has many warnings - EnablePython: false - isTraining: false - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - -- stage: x64_release_ep_generic_interface - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --enable_generic_interface --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release_ep_generic_interface - RunOnnxRuntimeTests: false # --enable_generic_interface does not build tests - EnablePython: false - isTraining: false - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - -- stage: x86_release - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - EnvSetupScript: setup_env_x86.bat - buildArch: x86 - additionalBuildFlags: --build_wheel --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: Win32 - isX86: true - job_name_suffix: x86_release - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - isTraining: false - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' - -- stage: ort_training_apis_x64_release - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --enable_training_apis --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: ort_training_apis_x64_release - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - EnablePython: false - isTraining: true - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win2022-CPU-training-AMD' - -- stage: x64_release_azure - dependsOn: [] - jobs: - - job: x64_release_azure - steps: - - powershell: | - Write-Host "##vso[task.prependpath]$(Build.BinariesDirectory)\RelWithDebInfo\_deps\vcpkg-src\installed\x86-windows\bin" - $env:PATH - Write-Host "##vso[task.prependpath]$(Build.BinariesDirectory)\RelWithDebInfo\_deps\vcpkg-src\installed\x64-windows\bin" - $env:PATH - displayName: 'Append x64-windows and x86-windows to PATH' - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - buildArch: x64 - additionalBuildFlags: --use_azure --use_lock_free_queue --msbuild_extra_options IncludeMobileTargets=false --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_release_azure - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - EnablePython: false - isTraining: false - ORT_EP_NAME: CPU - GenerateDocumentation: false - WITH_CACHE: false - MachinePool: 'onnxruntime-Win-CPU-2022' From 06482c2644bb0705e71db084619c26937f08df76 Mon Sep 17 00:00:00 2001 From: mingyue <131847423+mingyueliuh@users.noreply.github.com> Date: Wed, 12 Mar 2025 14:01:14 -0500 Subject: [PATCH 083/266] [Fix] Dependencies find_package Eigen error (#23939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description To fix the CMake configuration error when a dependency brought in via FetchContent uses find_package(Eigen3 REQUIRED) Major Changes: - enable EIGEN_BUILD_CMAKE_PACKAGE - [optional] rename eigen to Eigen3 ### Motivation and Context Get the following build error when Dependencies use find_package(Eigen3 REQUIRED) ``` By not providing "FindEigen3.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "Eigen3", but CMake did not find one. Could not find a package configuration file provided by "Eigen3" with any of the following names: Eigen3Config.cmake eigen3-config.cmake Add the installation prefix of "Eigen3" to CMAKE_PREFIX_PATH or set "Eigen3_DIR" to a directory containing one of the above files. If "Eigen3" provides a separate development package or SDK, be sure it has been installed. ``` Eigen need enable **EIGEN_BUILD_CMAKE_PACKAGE** when FetchContent for generate **Eigen3Config.cmake** https://gitlab.com/libeigen/eigen/-/blob/master/CMakeLists.txt?ref_type=heads#L213 in addition , the eigen‘s project name is "Eigen3" and providing the cmake configuration file is "Eigen3Config.cmake" : https://gitlab.com/libeigen/eigen/-/blob/master/CMakeLists.txt?ref_type=heads#L36 https://gitlab.com/libeigen/eigen/-/blob/master/CMakeLists.txt?ref_type=heads#L252 So I think it's best for FetchContent_Declare Name to be consistent with the project name to avoid potential errors. Co-authored-by: mingyue --- cmake/external/eigen.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/external/eigen.cmake b/cmake/external/eigen.cmake index f8856069733a2..9b5ca601df8d4 100644 --- a/cmake/external/eigen.cmake +++ b/cmake/external/eigen.cmake @@ -2,11 +2,12 @@ set(EIGEN_BUILD_DOC OFF CACHE BOOL "" FORCE) set(EIGEN_BUILD_BLAS OFF CACHE BOOL "" FORCE) set(EIGEN_BUILD_LAPACK OFF CACHE BOOL "" FORCE) set(EIGEN_BUILD_PKGCONFIG OFF CACHE BOOL "" FORCE) +set(EIGEN_BUILD_CMAKE_PACKAGE ON CACHE BOOL "" FORCE) onnxruntime_fetchcontent_declare( - eigen + Eigen3 URL ${DEP_URL_eigen} URL_HASH SHA1=${DEP_SHA1_eigen} EXCLUDE_FROM_ALL ) -onnxruntime_fetchcontent_makeavailable(eigen) +onnxruntime_fetchcontent_makeavailable(Eigen3) From 5e057292466ad8451467a66d96e2e59ce54693b0 Mon Sep 17 00:00:00 2001 From: Haik Silm <57659827+hsilm@users.noreply.github.com> Date: Wed, 12 Mar 2025 23:55:37 +0100 Subject: [PATCH 084/266] Update onnxruntime_c_api.h to work with MinGW (#24006) ### Description Same as #23169 ### Motivation and Context Same as #23169 --- include/onnxruntime/core/session/onnxruntime_c_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 098de14bdfd61..d0eab46ea1bbd 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -310,7 +310,7 @@ ORT_RUNTIME_CLASS(Node); ORT_RUNTIME_CLASS(Graph); ORT_RUNTIME_CLASS(Model); -#ifdef _WIN32 +#ifdef _MSC_VER typedef _Return_type_success_(return == 0) OrtStatus* OrtStatusPtr; #else typedef OrtStatus* OrtStatusPtr; From 57ddd026fd88007ac6f0d48db4251eae68e11e13 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Wed, 12 Mar 2025 19:38:36 -0700 Subject: [PATCH 085/266] Add DNNL github workflow (#24011) ### Description Add DNNL github workflow which is migrated from "Windows CPU CI pipeline" from Azure DevOps. This PR also adds "--build_nuget" to test the C# part. However, then I hit an error when building the tests in "test\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj". The error message was: ``` D:\a\_work\onnxruntime\onnxruntime\csharp\test\Microsoft.ML.OnnxRuntime.Tests.Common\TrainingTest.cs(34,81): error CS0103: The name 'CheckpointState' does not exist in the current context [D:\a\_work\onnxruntime\onnxruntime\csharp\test\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj] ``` Then I checked the code. I couldn't understand how it worked before. In this build, `__TRAINING_ENABLED_NATIVE_BUILD__` is not defined. But the "CheckpointState" class is defined in https://github.com/microsoft/onnxruntime/blob/main/csharp/src/Microsoft.ML.OnnxRuntime/Training/CheckpointState.shared.cs#L21 And the file is empty when __TRAINING_ENABLED_NATIVE_BUILD__ is not defined. So I don't understand how it could work in a normal build without dnnl. Here is my build command: ``` python tools\ci_build\build.py --config RelWithDebInfo --build_dir dnnlbuild --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_dnnl ``` This PR removes the failed test. --- .github/workflows/ios.yml | 2 +- .github/workflows/mac.yml | 2 +- .github/workflows/macos_coreml.yml | 2 +- .github/workflows/windows_build_x64_asan.yml | 4 +- .../windows_x64_debug_build_x64_debug.yml | 12 +- .../windows_x64_release_build_x64_release.yml | 12 +- ...ows_x64_release_dnnl_build_x64_release.yml | 125 ++++++++++++++++++ ...build_x64_release_ep_generic_interface.yml | 12 +- ..._x64_release_vitisai_build_x64_release.yml | 12 +- .../workflows/windows_x64_release_xnnpack.yml | 12 +- .github/workflows/windows_x86.yml | 12 +- .../TrainingTest.cs | 10 -- tools/ci_build/build.py | 14 +- 13 files changed, 173 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/windows_x64_release_dnnl_build_x64_release.yml diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index b4cb0adc47b66..063b5488499e1 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -15,7 +15,7 @@ jobs: runs-on: macos-13 steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Use Xcode ${{ env.XCODE_VERSION }} diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index eb4befaa34244..143f0b9eaea5b 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -23,7 +23,7 @@ jobs: runs-on: macos-13 steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false diff --git a/.github/workflows/macos_coreml.yml b/.github/workflows/macos_coreml.yml index 42b9ec702661b..f0acbd54a3fb1 100644 --- a/.github/workflows/macos_coreml.yml +++ b/.github/workflows/macos_coreml.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install coreutils and ninja run: brew install coreutils ninja diff --git a/.github/workflows/windows_build_x64_asan.yml b/.github/workflows/windows_build_x64_asan.yml index 6be647c86eab8..22c62f1c39411 100644 --- a/.github/workflows/windows_build_x64_asan.yml +++ b/.github/workflows/windows_build_x64_asan.yml @@ -18,12 +18,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x64 diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml index 081f8dc57a107..b8d1bdf228261 100644 --- a/.github/workflows/windows_x64_debug_build_x64_debug.yml +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x64 @@ -37,12 +37,12 @@ jobs: run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -59,14 +59,14 @@ jobs: working-directory: ${{ github.workspace }} - name: Use .NET 8.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.x' env: PROCESSOR_ARCHITECTURE: x64 - name: Use Nuget 6.x - uses: nuget/setup-nuget@v1 # Use the official NuGet setup action + uses: nuget/setup-nuget@v2 # Use the official NuGet setup action with: nuget-version: '6.x' diff --git a/.github/workflows/windows_x64_release_build_x64_release.yml b/.github/workflows/windows_x64_release_build_x64_release.yml index 9f8f650e906dc..c0e8fb24bc615 100644 --- a/.github/workflows/windows_x64_release_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_build_x64_release.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x64 @@ -37,12 +37,12 @@ jobs: run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -59,14 +59,14 @@ jobs: working-directory: ${{ github.workspace }} - name: Use .NET 8.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.x' env: PROCESSOR_ARCHITECTURE: x64 - name: Use Nuget 6.x - uses: nuget/setup-nuget@v1 + uses: nuget/setup-nuget@v2 with: nuget-version: '6.x' diff --git a/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml b/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml new file mode 100644 index 0000000000000..2ac7a4a646eb0 --- /dev/null +++ b/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml @@ -0,0 +1,125 @@ +name: windows_x64_dnnl_release + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_dnnl_release: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --build_java --build_nodejs --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_dnnl + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v4 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' \ No newline at end of file diff --git a/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml b/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml index 9c280da27e8bc..a0bf348a7dba0 100644 --- a/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml +++ b/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x64 @@ -37,12 +37,12 @@ jobs: run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -59,14 +59,14 @@ jobs: working-directory: ${{ github.workspace }} - name: Use .NET 8.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.x' env: PROCESSOR_ARCHITECTURE: x64 - name: Use Nuget 6.x - uses: nuget/setup-nuget@v1 + uses: nuget/setup-nuget@v2 with: nuget-version: '6.x' diff --git a/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml index ec4ccef5390d2..10c1f6858dc2f 100644 --- a/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x64 @@ -37,12 +37,12 @@ jobs: run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -59,14 +59,14 @@ jobs: working-directory: ${{ github.workspace }} - name: Use .NET 8.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.x' env: PROCESSOR_ARCHITECTURE: x64 - name: Use Nuget 6.x - uses: nuget/setup-nuget@v1 + uses: nuget/setup-nuget@v2 with: nuget-version: '6.x' diff --git a/.github/workflows/windows_x64_release_xnnpack.yml b/.github/workflows/windows_x64_release_xnnpack.yml index 13e830505513d..970f94371b905 100644 --- a/.github/workflows/windows_x64_release_xnnpack.yml +++ b/.github/workflows/windows_x64_release_xnnpack.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x64 @@ -37,12 +37,12 @@ jobs: run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -59,14 +59,14 @@ jobs: working-directory: ${{ github.workspace }} - name: Use .NET 8.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.x' env: PROCESSOR_ARCHITECTURE: x64 - name: Use Nuget 6.x - uses: nuget/setup-nuget@v1 + uses: nuget/setup-nuget@v2 with: nuget-version: '6.x' diff --git a/.github/workflows/windows_x86.yml b/.github/workflows/windows_x86.yml index 20f1bcd54cb1a..c0aaaf30974a5 100644 --- a/.github/workflows/windows_x86.yml +++ b/.github/workflows/windows_x86.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: false - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' architecture: x86 # x86 Python @@ -37,13 +37,13 @@ jobs: run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' architecture: x86 #Add architecture - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -60,14 +60,14 @@ jobs: working-directory: ${{ github.workspace }} - name: Use .NET 8.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.x' env: PROCESSOR_ARCHITECTURE: x86 # x86 .NET - name: Use Nuget 6.x - uses: nuget/setup-nuget@v1 + uses: nuget/setup-nuget@v2 with: nuget-version: '6.x' diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs index 9b72326201322..455b48ec81a5c 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs @@ -26,16 +26,6 @@ public TrainingTest(ITestOutputHelper o) this.output = o; } -#if !__TRAINING_ENABLED_NATIVE_BUILD__ - [Fact(DisplayName = "TestLoadCheckpointThrows")] - public void TestLoadCheckpointThrows() - { - string path = Path.Combine(Directory.GetCurrentDirectory(), "checkpoint.ckpt"); - var ex = Assert.Throws(() => { var opt = CheckpointState.LoadCheckpoint(path); }); - Assert.Contains("Please install the Microsoft.ML.OnnxRuntime.Training NuGet package.", ex.Message); - } -#endif - #if __TRAINING_ENABLED_NATIVE_BUILD__ [Fact(DisplayName = "TestLoadCheckpoint")] public void TestLoadCheckpoint() diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index e6c3d9faf4a3f..987407b278448 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -2788,21 +2788,21 @@ def run_csharp_tests( csharp_source_dir = os.path.join(source_dir, "csharp") # define macros based on build args - macros = "" + macros = [] if use_openvino: - macros += "USE_OPENVINO;" + macros.append("USE_OPENVINO") if use_tensorrt: - macros += "USE_TENSORRT;" + macros.append("USE_TENSORRT") if use_dnnl: - macros += "USE_DNNL;" + macros.append("USE_DNNL") if use_cuda: - macros += "USE_CUDA;" + macros.append("USE_CUDA") if enable_training_apis: - macros += "__TRAINING_ENABLED_NATIVE_BUILD__;__ENABLE_TRAINING_APIS__" + macros += ["__TRAINING_ENABLED_NATIVE_BUILD__", "__ENABLE_TRAINING_APIS__"] define_constants = "" if macros: - define_constants = '/p:DefineConstants="' + macros + '"' + define_constants = '/p:DefineConstants="' + ";".join(macros) + '"' # set build directory based on build_dir arg native_build_dir = os.path.normpath(os.path.join(source_dir, build_dir)) From 7ae606f71f3e057e5db8bf87e7e520df1df04425 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Thu, 13 Mar 2025 08:13:14 -0700 Subject: [PATCH 086/266] Qnn weight sharing improvement (#23945) ### Description Qnn weight sharing improvement so that only the last session in the weight sharing group (the session that has both share_ep_contexts and stop_share_ep_contexts enabled) generates the .bin file. The .bin file name is decided from the 1st session. And all generated *_ctx.onnx models point to this single .bin to avoid post-processing work. Previously each session generates a _ctx.onnx model with a .bin file. So it requires post-processing work to go through generated *_ctx.onnx models to get the last generated *_ctx.bin file and update all *_ctx.onnx to point to the same .bin file and remove the .bin files not used. --- .../core/session/onnxruntime_c_api.h | 3 - .../qnn/builder/onnx_ctx_model_helper.cc | 40 +++- .../qnn/builder/onnx_ctx_model_helper.h | 4 +- .../qnn/builder/qnn_backend_manager.cc | 18 +- .../qnn/builder/qnn_backend_manager.h | 10 +- .../providers/qnn/qnn_execution_provider.cc | 26 +-- .../core/providers/qnn/shared_context.h | 18 ++ .../command_args_parser.cc | 7 +- .../test/ep_weight_sharing_ctx_gen/main.cc | 79 +++---- .../test/providers/qnn/qnn_ep_context_test.cc | 210 ++++-------------- 10 files changed, 158 insertions(+), 257 deletions(-) diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index d0eab46ea1bbd..6481592232a58 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -3674,9 +3674,6 @@ struct OrtApi { * Enable the float32 model to be inferenced with fp16 precision. Otherwise, it will be fp32 precision. * - "0": With fp32 precision. * - "1": Default. With fp16 precision. - * "enable_htp_weight_sharing": Enable QNN weight sharing feature while compiling multiple graphs into one QNN context. - * - "0": Default. Disabled. - * - "1": Enabled. * "offload_graph_io_quantization": Offload graph input quantization and graph output dequantization to another * execution provider (typically CPU EP). * - "0": Disabled. QNN EP will handle quantization and dequantization of graph I/O. diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc index d85277627a3de..93b2acb5b002c 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc @@ -10,6 +10,7 @@ #include "core/providers/qnn/ort_api.h" #include "core/providers/qnn/builder/qnn_utils.h" #include "core/providers/qnn/builder/qnn_model.h" +#include "core/providers/qnn/shared_context.h" namespace onnxruntime { namespace qnn { @@ -207,7 +208,9 @@ Status CreateEPContextNodes(Model* model, const onnxruntime::PathString& context_model_path, bool qnn_context_embed_mode, uint64_t max_spill_fill_buffer_size, - const logging::Logger& logger) { + const logging::Logger& logger, + bool share_ep_contexts, + bool stop_share_ep_contexts) { auto& graph = model->MainGraph(); using namespace ONNX_NAMESPACE; @@ -241,6 +244,7 @@ Status CreateEPContextNodes(Model* model, ep_node.AddAttribute(EP_CACHE_CONTEXT, cache_payload); } else { onnxruntime::PathString context_bin_path; + std::string context_cache_name; auto pos = context_model_path.find_last_of(ORT_TSTR(".")); if (pos != std::string::npos) { context_bin_path = context_model_path.substr(0, pos); @@ -253,14 +257,36 @@ Status CreateEPContextNodes(Model* model, graph_name_in_file.replace(name_pos, strlen(kQnnExecutionProvider), ""); } context_bin_path = context_bin_path + ToPathString(graph_name_in_file + ".bin"); - std::string context_cache_name(std::filesystem::path(context_bin_path).filename().string()); - std::ofstream of_stream(context_bin_path.c_str(), std::ofstream::binary); - if (!of_stream) { - LOGS(logger, ERROR) << "Failed to open create context file."; - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to open context cache file."); + context_cache_name = std::filesystem::path(context_bin_path).filename().string(); + + // If generate ctx.onnx with share_ep_context enabled, all ctx.onnx should point to the same ctx.bin + if (share_ep_contexts) { + auto shared_ctx_bin_name = SharedContext::GetInstance().GetSharedCtxBinFileName(); + if (shared_ctx_bin_name.empty()) { + SharedContext::GetInstance().SetSharedCtxBinFileName(context_cache_name); + } else { + context_cache_name = shared_ctx_bin_name; + auto model_folder_path = std::filesystem::path(context_bin_path).parent_path().string(); + context_bin_path = ToPathString(model_folder_path + "/" + context_cache_name); + } + } + + // Write the ctx.bin file for the case: 1. no share_ep_context enabled, write for every session + // 2. share_ep_context enabled, only write for the last session which has stop_share_ep_contexts enabled + if (!share_ep_contexts || (share_ep_contexts && stop_share_ep_contexts)) { + std::ofstream of_stream(context_bin_path.c_str(), std::ofstream::binary); + if (!of_stream) { + LOGS(logger, ERROR) << "Failed to open create context file."; + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to open context cache file."); + } + of_stream.write(reinterpret_cast(buffer), buffer_size); } - of_stream.write(reinterpret_cast(buffer), buffer_size); + ep_node.AddAttribute(EP_CACHE_CONTEXT, context_cache_name); + if (share_ep_contexts && stop_share_ep_contexts) { + SharedContext::GetInstance().ResetSharedCtxBinFileName(); + } + ep_node.AddAttribute(MAX_SIZE, static_cast(max_spill_fill_buffer_size)); } } else { diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h index c54cd3ca6e90c..b037d5c3d2336 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h @@ -65,6 +65,8 @@ Status CreateEPContextNodes(Model* model, const onnxruntime::PathString& context_model_path, bool qnn_context_embed_mode, uint64_t max_spill_fill_buffer_size, - const logging::Logger& logger); + const logging::Logger& logger, + bool share_ep_contexts, + bool stop_share_ep_contexts); } // namespace qnn } // namespace onnxruntime diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc index 26d792c008edc..0328f6c2014fa 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc @@ -538,7 +538,7 @@ Status SetQnnContextConfig(ContextPriority context_priority, QnnContext_Config_t return Status::OK(); } -Status QnnBackendManager::CreateContext() { +Status QnnBackendManager::CreateContext(bool enable_htp_weight_sharing) { if (true == context_created_) { LOGS_DEFAULT(INFO) << "Context created already."; return Status::OK(); @@ -547,7 +547,7 @@ Status QnnBackendManager::CreateContext() { QnnContext_Config_t context_config_weight_sharing = QNN_CONTEXT_CONFIG_INIT; QnnHtpContext_CustomConfig_t custom_config; custom_config.option = QNN_HTP_CONTEXT_CONFIG_OPTION_WEIGHT_SHARING_ENABLED; - custom_config.weightSharingEnabled = enable_htp_weight_sharing_; + custom_config.weightSharingEnabled = enable_htp_weight_sharing; context_config_weight_sharing.option = QNN_CONTEXT_CONFIG_OPTION_CUSTOM; context_config_weight_sharing.customConfig = &custom_config; @@ -810,7 +810,8 @@ Status QnnBackendManager::LoadCachedQnnContextFromBuffer(char* buffer, uint64_t // or generate Qnn context binary is enabled -- to get the max spill fill buffer size Status QnnBackendManager::SetupBackend(const logging::Logger& logger, bool load_from_cached_context, - bool need_load_system_lib) { + bool need_load_system_lib, + bool share_ep_contexts) { std::lock_guard lock(logger_recursive_mutex_); if (backend_setup_completed_) { LOGS(logger, VERBOSE) << "Backend setup already!"; @@ -865,9 +866,18 @@ Status QnnBackendManager::SetupBackend(const logging::Logger& logger, LOGS(logger, VERBOSE) << "InitializeProfiling succeed."; } + bool enable_htp_weight_sharing = false; + if (share_ep_contexts && !load_from_cached_context) { +#if defined(__aarch64__) || defined(_M_ARM64) + LOGS(logger, WARNING) << "Weight sharing only available with offline generation on x64 platform, not work on real device."; +#else + enable_htp_weight_sharing = true; +#endif + } + if (!load_from_cached_context) { if (status.IsOK()) { - status = CreateContext(); + status = CreateContext(enable_htp_weight_sharing); } if (status.IsOK()) { LOGS(logger, VERBOSE) << "CreateContext succeed."; diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h index 3592af41f03df..bd451d9ba9c1d 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h @@ -43,7 +43,6 @@ struct QnnBackendManagerConfig { uint32_t device_id; QnnHtpDevice_Arch_t htp_arch; uint32_t soc_model; - bool enable_htp_weight_sharing; }; class QnnBackendManager : public std::enable_shared_from_this { @@ -67,8 +66,7 @@ class QnnBackendManager : public std::enable_shared_from_this qnn_saver_path_(config.qnn_saver_path), device_id_(config.device_id), htp_arch_(config.htp_arch), - soc_model_(config.soc_model), - enable_htp_weight_sharing_(config.enable_htp_weight_sharing) { + soc_model_(config.soc_model) { } ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(QnnBackendManager); @@ -84,7 +82,8 @@ class QnnBackendManager : public std::enable_shared_from_this // Initializes handles to QNN resources (device, logger, etc.). // NOTE: This function locks the internal `logger_recursive_mutex_`. - Status SetupBackend(const logging::Logger& logger, bool load_from_cached_context, bool need_load_system_lib); + Status SetupBackend(const logging::Logger& logger, bool load_from_cached_context, + bool need_load_system_lib, bool share_ep_contexts); Status CreateHtpPowerCfgId(uint32_t deviceId, uint32_t coreId, uint32_t& htp_power_config_id); @@ -155,7 +154,7 @@ class QnnBackendManager : public std::enable_shared_from_this Status ReleaseProfilehandle(); - Status CreateContext(); + Status CreateContext(bool enable_htp_weight_sharing); Status ReleaseContext(); @@ -298,7 +297,6 @@ class QnnBackendManager : public std::enable_shared_from_this uint32_t device_id_ = 0; QnnHtpDevice_Arch_t htp_arch_ = QNN_HTP_DEVICE_ARCH_NONE; uint32_t soc_model_ = QNN_SOC_MODEL_UNKNOWN; - bool enable_htp_weight_sharing_ = false; }; } // namespace qnn diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index a5813dc2a4adc..e5b88a77b334c 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -337,19 +337,8 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio LOGS_DEFAULT(VERBOSE) << "User specified enable_htp_fp16_precision: " << enable_HTP_FP16_precision_; } - bool enable_htp_weight_sharing = false; - static const std::string QNN_HTP_WEIGHT_SHARING_ENABLED = "enable_htp_weight_sharing"; - auto htp_weight_sharing_enabled_pos = provider_options_map.find(QNN_HTP_WEIGHT_SHARING_ENABLED); - if (htp_weight_sharing_enabled_pos != provider_options_map.end()) { - if ("1" == htp_weight_sharing_enabled_pos->second) { - enable_htp_weight_sharing = true; - } else if ("0" == htp_weight_sharing_enabled_pos->second) { - enable_htp_weight_sharing = false; - } else { - LOGS_DEFAULT(VERBOSE) << "Invalid enable_htp_weight_sharing: " << enable_htp_weight_sharing - << " only 0 or 1 allowed. Set to 0."; - } - LOGS_DEFAULT(VERBOSE) << "User specified enable_htp_weight_sharing: " << enable_htp_weight_sharing; + if (qnn_context_embed_mode_ && share_ep_contexts_) { + LOGS_DEFAULT(ERROR) << "[EP context generation:] Weight sharing enabled conflict with EP context embed mode. Inference will not work as expected!"; } // Add this option because this feature requires QnnSystem lib and it's no supported for Windows x86_64 platform @@ -406,8 +395,7 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio qnn_saver_path, device_id_, htp_arch, - soc_model, - enable_htp_weight_sharing}); + soc_model}); } #if defined(_WIN32) @@ -701,7 +689,9 @@ QNNExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer // It will load the QnnSystem lib if is_qnn_ctx_model=true, and // delay the Qnn context creation to Compile() using the cached context binary // or generate context cache enable, need to use use QnnSystem lib to parse the binary to get the max spill fill buffer size - auto rt = qnn_backend_manager_->SetupBackend(logger, is_qnn_ctx_model, context_cache_enabled_ && enable_spill_fill_buffer_); + auto rt = qnn_backend_manager_->SetupBackend(logger, is_qnn_ctx_model, + context_cache_enabled_ && enable_spill_fill_buffer_, + share_ep_contexts_); if (Status::OK() != rt) { LOGS(logger, ERROR) << "QNN SetupBackend failed " << rt.ErrorMessage(); return result; @@ -1051,7 +1041,9 @@ Status QNNExecutionProvider::Compile(const std::vector& fused context_model_path, qnn_context_embed_mode_, max_spill_fill_buffer_size, - logger)); + logger, + share_ep_contexts_, + stop_share_ep_contexts_)); if (share_ep_contexts_ && !stop_share_ep_contexts_ && nullptr == SharedContext::GetInstance().GetSharedQnnBackendManager()) { diff --git a/onnxruntime/core/providers/qnn/shared_context.h b/onnxruntime/core/providers/qnn/shared_context.h index 277a484ad8528..1402dc30fd37a 100644 --- a/onnxruntime/core/providers/qnn/shared_context.h +++ b/onnxruntime/core/providers/qnn/shared_context.h @@ -84,6 +84,21 @@ class SharedContext { qnn_backend_manager_.reset(); } + void SetSharedCtxBinFileName(std::string& shared_ctx_bin_file_name) { + const std::lock_guard lock(mtx_); + shared_ctx_bin_file_name_ = shared_ctx_bin_file_name; + } + + const std::string& GetSharedCtxBinFileName() { + const std::lock_guard lock(mtx_); + return shared_ctx_bin_file_name_; + } + + void ResetSharedCtxBinFileName() { + const std::lock_guard lock(mtx_); + shared_ctx_bin_file_name_.clear(); + } + private: SharedContext() = default; ~SharedContext() = default; @@ -94,6 +109,9 @@ class SharedContext { std::vector> shared_qnn_models_; // Used for compiling multiple models into same QNN context binary std::shared_ptr qnn_backend_manager_; + // Track the shared ctx binary .bin file name, all _ctx.onnx point to this .bin file + // only the last session generate the .bin file since it contains all graphs from all sessions. + std::string shared_ctx_bin_file_name_; // Producer sessions can be in parallel // Consumer sessions have to be after producer sessions initialized std::mutex mtx_; diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc index bf21d54ccde41..ccfccf2e08dfc 100644 --- a/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc @@ -48,7 +48,6 @@ namespace qnnctxgen { "\t [QNN only] [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). \n" "\t [QNN only] [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. \n" "\t Otherwise, it will be fp32 precision. Works for float32 model for HTP backend. Defaults to '1' (with FP16 precision.). \n" - "\t [QNN only] [enable_htp_weight_sharing]: Allows common weights across graphs to be shared and stored in a single context binary. Defaults to '1' (enabled).\n" "\t [QNN only] [offload_graph_io_quantization]: Offload graph input quantization and graph output dequantization to another EP (typically CPU EP). \n" "\t Defaults to '1' (QNN EP handles the graph I/O quantization and dequantization). \n" "\t [QNN only] [enable_htp_spill_fill_buffer]: Enable HTP spill file buffer, used while generating QNN context binary." @@ -161,8 +160,8 @@ static bool ParseSessionConfigs(const std::string& configs_string, std::string str = str_stream.str(); ORT_THROW("Wrong value for htp_graph_finalization_optimization_mode. select from: " + str); } - } else if (key == "enable_htp_fp16_precision" || key == "enable_htp_weight_sharing" || - key == "offload_graph_io_quantization" || key == "enable_htp_spill_fill_buffer") { + } else if (key == "enable_htp_fp16_precision" || key == "offload_graph_io_quantization" || + key == "enable_htp_spill_fill_buffer") { std::unordered_set supported_options = {"0", "1"}; if (supported_options.find(value) == supported_options.end()) { std::ostringstream str_stream; @@ -173,7 +172,7 @@ static bool ParseSessionConfigs(const std::string& configs_string, } } else { ORT_THROW(R"(Wrong key type entered. Choose from options: ['backend_path', 'vtcm_mb', 'htp_performance_mode', - 'htp_graph_finalization_optimization_mode', 'soc_model', 'htp_arch', 'enable_htp_fp16_precision', 'enable_htp_weight_sharing', + 'htp_graph_finalization_optimization_mode', 'soc_model', 'htp_arch', 'enable_htp_fp16_precision', 'offload_graph_io_quantization', 'enable_htp_spill_fill_buffer'])"); } diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc b/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc index 104cdbdfd5abc..92671e52f62f9 100644 --- a/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc @@ -16,11 +16,9 @@ using namespace onnxruntime; using ProviderOptions = std::unordered_map; // from the last context cache Onnx model, find the EPContext node with main_context=1, -// and get the QNN context binary file name, this context binary contains all graphs from all Onnx models // get the max spill fill buffer size -static void GetLastContextBinaryFileName(const std::basic_string last_onnx_ctx_file, - std::string& last_ctx_bin_file, - int64_t& max_size) { +static void GetEpContextInfoFromLastContextModel(const std::basic_string last_onnx_ctx_file, + int64_t& max_size) { max_size = 0; onnx::ModelProto model; @@ -37,9 +35,6 @@ static void GetLastContextBinaryFileName(const std::basic_string last if (attr.name() == "max_size") { max_size = attr.i(); } - if (attr.name() == "ep_cache_context") { - last_ctx_bin_file = attr.s(); - } } if (is_main_context) { return; @@ -50,11 +45,8 @@ static void GetLastContextBinaryFileName(const std::basic_string last onnx_file_stream.close(); } -// Update generated context cache Onnx model to make the main EPContext node point to -// the last QNN context binary file -// Remove not used QNN context binary file, only keep the last one which contains all graphs +// Update generated context cache Onnx model to have the same max_size (align with the last generated model) static void UpdateEpContextModel(const std::vector>& ep_ctx_files, - const std::string& last_qnn_ctx_binary_file_name, int64_t max_size) { for (auto ep_ctx_file : ep_ctx_files) { onnx::ModelProto model; @@ -65,9 +57,7 @@ static void UpdateEpContextModel(const std::vector> for (auto& node : *(model.mutable_graph()->mutable_node())) { if (node.op_type() == "EPContext") { int64_t is_main_context = 0; - std::string old_qnn_ctx_binary_file_name; int max_size_index = 0; - int ep_context_index = 0; for (auto i = 0; i < node.attribute_size(); ++i) { auto& attr = node.attribute()[i]; if (attr.name() == "main_context") { @@ -77,19 +67,9 @@ static void UpdateEpContextModel(const std::vector> max_size = attr.i(); max_size_index = i; } - if (attr.name() == "ep_cache_context") { - old_qnn_ctx_binary_file_name = attr.s(); - ep_context_index = 0; - } } if (is_main_context) { - auto path_str = ToPathString(ep_ctx_file); - auto path = std::filesystem::path(path_str); - auto file_path = path.replace_filename(old_qnn_ctx_binary_file_name); - std::remove(file_path.string().c_str()); - node.mutable_attribute(max_size_index)->set_i(max_size); - node.mutable_attribute(ep_context_index)->set_s(last_qnn_ctx_binary_file_name); } } } @@ -164,11 +144,6 @@ int real_main(int argc, char* argv[]) { provider_options["backend_path"] = "libQnnHtp.so"; #endif - // set default QNN EP option to enable weight sharing if not set by user - const std::string enable_htp_weight_sharing = "enable_htp_weight_sharing"; - if (provider_options.find(enable_htp_weight_sharing) == provider_options.end()) { - provider_options[enable_htp_weight_sharing] = "1"; - } so.AppendExecutionProvider("QNN", provider_options); #else ORT_THROW("QNN is not supported in this build\n"); @@ -188,33 +163,33 @@ int real_main(int argc, char* argv[]) { } } - std::cout << "Start to update the generated Onnx model." << std::endl; - std::vector> ep_ctx_files; - ep_ctx_files.reserve(test_config.model_file_paths.size()); - for (auto model_path : test_config.model_file_paths) { - auto pos = model_path.find_last_of(ORT_TSTR(".")); - if (pos != std::string::npos) { - model_path = model_path.substr(0, pos) + ORT_TSTR("_ctx.onnx"); - } else { - model_path = model_path + ORT_TSTR("_ctx.onnx"); + // Only with enable_htp_spill_fill_buffer enabled: + // Update generated context cache Onnx model to have the same max_size (align with the last generated model) + // so that the inference session can be created with any order of the ctx.onnx models + const std::string enable_htp_spill_fill_buffer = "enable_htp_spill_fill_buffer"; + auto pos = provider_options.find(enable_htp_spill_fill_buffer); + if (pos != provider_options.end() && pos->second == "1") { + std::cout << "Start to update the generated Onnx model to reflect the max_size." << std::endl; + + // The steps below only used for spill fill buffer enabled + std::vector> ep_ctx_files; + ep_ctx_files.reserve(test_config.model_file_paths.size()); + for (auto model_path : test_config.model_file_paths) { + auto dot_pos = model_path.find_last_of(ORT_TSTR(".")); + if (dot_pos != std::string::npos) { + model_path = model_path.substr(0, dot_pos) + ORT_TSTR("_ctx.onnx"); + } else { + model_path = model_path + ORT_TSTR("_ctx.onnx"); + } + ep_ctx_files.push_back(model_path); } - ep_ctx_files.push_back(model_path); - } - // Get the last context binary file name - std::string last_qnn_ctx_binary_file_name; - int64_t max_size = 0; - GetLastContextBinaryFileName(ep_ctx_files.back(), last_qnn_ctx_binary_file_name, max_size); - std::cout << "The last context binary file: " << last_qnn_ctx_binary_file_name << std::endl; - if (last_qnn_ctx_binary_file_name.empty()) { - throw Ort::Exception("Can't find QNN context binary file from the Onnx model.", OrtErrorCode::ORT_FAIL); - } - ep_ctx_files.pop_back(); + int64_t max_size = 0; + GetEpContextInfoFromLastContextModel(ep_ctx_files.back(), max_size); + ep_ctx_files.pop_back(); - // Update generated context cache Onnx model to make the main EPContext node point to - // the last QNN context binary file - // Remove not used QNN context binary file, only keep the last one only which contains all graphs - UpdateEpContextModel(ep_ctx_files, last_qnn_ctx_binary_file_name, max_size); + UpdateEpContextModel(ep_ctx_files, max_size); + } } ORT_CATCH(const Ort::Exception& e) { std::cerr << "Failed to generate context cache file: " << e.what(); diff --git a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc index 3dec74599abdf..e39102a21dd1c 100644 --- a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc @@ -1088,7 +1088,7 @@ static void CreateQdqModel(const std::string& model_file_name, const Logger& log ASSERT_STATUS_OK(onnxruntime::Model::Save(model, ToPathString(model_file_name))); } -static void DumpModelWithSharedCtx(const ProviderOptions& provider_options, +static void DumpModelWithSharedCtx(ProviderOptions provider_options, const std::string& onnx_model_path1, const std::string& onnx_model_path2) { Ort::SessionOptions so; @@ -1097,6 +1097,13 @@ static void DumpModelWithSharedCtx(const ProviderOptions& provider_options, // enable ep.share_ep_contexts so that QNNEP share the QnnBackendManager across sessions so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); +#ifndef __aarch64__ +#ifndef _M_ARM64 + // weight sharing only available for v73 and higher + provider_options["soc_model"] = "60"; +#endif // !_M_ARM64 +#endif // !__aarch64__ + so.AppendExecutionProvider("QNN", provider_options); // Create 2 sessions to generate context binary models, the 1st session will share the QnnBackendManager @@ -1107,37 +1114,7 @@ static void DumpModelWithSharedCtx(const ProviderOptions& provider_options, Ort::Session session2(*ort_env, ToPathString(onnx_model_path2).c_str(), so); } -// Update generated context cache Onnx model to make the main EPContext node point to -// the last QNN context binary file -// Remove not used QNN context binary file, only keep the last one which contains all graphs -static void UpdateEpContextModel(const std::vector& ep_ctx_files, - const std::string& last_qnn_ctx_binary_file_name, - const Logger& logger) { - for (auto ep_ctx_file : ep_ctx_files) { - std::shared_ptr ctx_model; - auto path_str = ToPathString(ep_ctx_file); - ASSERT_STATUS_OK(Model::Load(path_str, ctx_model, nullptr, logger)); - auto& ctx_graph = ctx_model->MainGraph(); - GraphViewer graph_viewer(ctx_graph); - auto path = std::filesystem::path(path_str); - - for (auto& node : ctx_graph.Nodes()) { - if (node.OpType() == "EPContext") { - int64_t is_main_context = GetNodeAttr(node, "main_context", static_cast(0)); - if (1 == is_main_context) { - std::string old_qnn_ctx_binary_file_name = GetNodeAttr(node, "ep_cache_context", ""); - auto file_path = path.replace_filename(old_qnn_ctx_binary_file_name); - std::remove(file_path.string().c_str()); - node.ClearAttribute("ep_cache_context"); - node.AddAttribute("ep_cache_context", last_qnn_ctx_binary_file_name); - } - } - } - std::remove(ep_ctx_file.c_str()); - ASSERT_STATUS_OK(Model::Save(*ctx_model.get(), ToPathString(ep_ctx_file))); - } -} - +#if defined(__aarch64__) || defined(_M_ARM64) static void GetModelInputNames(const std::string& model_path, std::vector& input_names, std::vector& output_names, @@ -1157,16 +1134,16 @@ static void GetModelInputNames(const std::string& model_path, output_names.push_back(output->Name()); } } +#endif // 1. Create 2 QDQ models // 2. Initialize 2 Ort sessions which share the same QNN EP from these 2 QDQ models // with EpContextEnable = 1, to dump the context binary // so, the 2nd context binary contains the graph from the 1st model -// 3. Change the 1st context model to point to the 2nd context binary file -// 4. Start 2 ort session from the dumped context model, +// 3. Start 2 ort session from the dumped context model, // The 2nd session uses graph from 1st session -// 5. Run the 2nd session -TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { +// 4. Run the 2nd session +TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions) { ProviderOptions provider_options; #if defined(_WIN32) provider_options["backend_path"] = "QnnHtp.dll"; @@ -1177,6 +1154,11 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { // Create QDQ models std::vector onnx_model_paths{"./weight_share1.onnx", "./weight_share2.onnx"}; + // cleanup in case some failure test doesn't remove them + for (auto model_path : onnx_model_paths) { + std::remove(model_path.c_str()); + } + std::vector ctx_model_paths; for (auto model_path : onnx_model_paths) { CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); @@ -1189,23 +1171,28 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { } ctx_model_paths.push_back(model_path); } + for (auto ctx_model_path : ctx_model_paths) { + std::remove(ctx_model_path.c_str()); + } DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); - // Get the last context binary file name, the latest context binary file holds all graphs generated from all models - std::string last_qnn_ctx_binary_file_name; - GetContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, + std::string qnn_ctx_binary_file_name1; + GetContextBinaryFileName(ctx_model_paths[0], qnn_ctx_binary_file_name1, DefaultLoggingManager().DefaultLogger()); - EXPECT_TRUE(!last_qnn_ctx_binary_file_name.empty()); + EXPECT_TRUE(!qnn_ctx_binary_file_name1.empty()); - // Update generated context cache Onnx model to make the main EPContext node point to - // the last QNN context binary file - // Remove not used QNN context binary file, only keep the last one which contains all graphs - std::vector ctx_model_paths_to_update(ctx_model_paths); - ctx_model_paths_to_update.pop_back(); - UpdateEpContextModel(ctx_model_paths_to_update, last_qnn_ctx_binary_file_name, - DefaultLoggingManager().DefaultLogger()); + std::string qnn_ctx_binary_file_name2; + GetContextBinaryFileName(ctx_model_paths[1], qnn_ctx_binary_file_name2, + DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(!qnn_ctx_binary_file_name2.empty()); + // 2 *_ctx.onn point to same .bin file + EXPECT_TRUE(qnn_ctx_binary_file_name1 == qnn_ctx_binary_file_name2); + auto file_size_1 = std::filesystem::file_size(qnn_ctx_binary_file_name1); + EXPECT_TRUE(file_size_1 > 0); + // only load and run the session on real device +#if defined(__aarch64__) || defined(_M_ARM64) Ort::SessionOptions so1; so1.SetLogId("so1"); so1.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); @@ -1251,108 +1238,7 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { auto ort_outputs1 = session1.Run(Ort::RunOptions{}, input_names_c.data(), ort_inputs.data(), ort_inputs.size(), output_names_c.data(), 1); - - for (auto model_path : onnx_model_paths) { - std::remove(model_path.c_str()); - } - for (auto ctx_model_path : ctx_model_paths) { - std::remove(ctx_model_path.c_str()); - } - std::remove(last_qnn_ctx_binary_file_name.c_str()); -} - -// 1. Create 2 QDQ models -// 2. Initialize 2 Ort sessions which share the same QNN EP from these 2 QDQ models -// with EpContextEnable = 1, to dump the context binary -// so, the 2nd context binary contains the graph from the 1st model -// 3. Change the 1st context model to point to a context binary file which is not exist -// 4. Start 2 ort session from the dumped context model, -// The 1st session uses the 2nd model, the 2nd session uses the 1st model -// so the 2nd session uses graph from the 1st session -// 6. Run the 2nd session -TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions2) { - ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif - provider_options["offload_graph_io_quantization"] = "0"; - - // Create QDQ models - std::vector onnx_model_paths{"./weight_share21.onnx", "./weight_share22.onnx"}; - std::vector ctx_model_paths; - for (auto model_path : onnx_model_paths) { - CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); - EXPECT_TRUE(std::filesystem::exists(model_path.c_str())); - auto pos = model_path.find_last_of("."); - if (pos != std::string::npos) { - model_path = model_path.substr(0, pos) + "_ctx.onnx"; - } else { - model_path = model_path + "_ctx.onnx"; - } - ctx_model_paths.push_back(model_path); - } - - DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); - - // Get the last context binary file name - std::string last_qnn_ctx_binary_file_name; - GetContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, - DefaultLoggingManager().DefaultLogger()); - EXPECT_TRUE(!last_qnn_ctx_binary_file_name.empty()); - - // Update generated context cache Onnx model to make the main EPContext node point to - // the last QNN context binary file - // Remove not used QNN context binary file, only keep the last one which contains all graphs - std::vector ctx_model_paths_to_update(ctx_model_paths); - ctx_model_paths_to_update.pop_back(); - // The 2nd model still point to the context binary which includes all graphs - // The 1st model point to file not exists - UpdateEpContextModel(ctx_model_paths_to_update, "file_not_exist.bin", - DefaultLoggingManager().DefaultLogger()); - - Ort::SessionOptions so; - so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); - so.AppendExecutionProvider("QNN", provider_options); - - EXPECT_TRUE(2 == ctx_model_paths.size()); -#ifdef _WIN32 - std::wstring ctx_model_file1(ctx_model_paths[0].begin(), ctx_model_paths[0].end()); - std::wstring ctx_model_file2(ctx_model_paths[1].begin(), ctx_model_paths[1].end()); -#else - std::string ctx_model_file1(ctx_model_paths[0].begin(), ctx_model_paths[0].end()); - std::string ctx_model_file2(ctx_model_paths[1].begin(), ctx_model_paths[1].end()); #endif - // Create session from the 2nd model first - Ort::Session session1(*ort_env, ctx_model_file2.c_str(), so); - Ort::Session session2(*ort_env, ctx_model_file1.c_str(), so); - - std::vector input_names; - std::vector output_names; - GetModelInputNames(ctx_model_paths[1], input_names, output_names, - DefaultLoggingManager().DefaultLogger()); - - // Run sessions - // prepare input - std::vector input_dim{2, 3}; - std::vector input_value(2 * 3, 0.0f); - Ort::MemoryInfo info("Cpu", OrtDeviceAllocator, 0, OrtMemTypeDefault); - std::vector ort_inputs; - std::vector input_names_c; - for (size_t i = 0; i < input_names.size(); ++i) { - auto input_tensor = Ort::Value::CreateTensor(info, input_value.data(), input_value.size(), - input_dim.data(), input_dim.size()); - ort_inputs.push_back(std::move(input_tensor)); - input_names_c.push_back(input_names[i].c_str()); - } - std::vector output_names_c; - for (size_t i = 0; i < output_names.size(); ++i) { - output_names_c.push_back(output_names[i].c_str()); - } - - auto ort_outputs1 = session1.Run(Ort::RunOptions{}, input_names_c.data(), ort_inputs.data(), ort_inputs.size(), - output_names_c.data(), 1); for (auto model_path : onnx_model_paths) { std::remove(model_path.c_str()); @@ -1360,7 +1246,7 @@ TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions2) { for (auto ctx_model_path : ctx_model_paths) { std::remove(ctx_model_path.c_str()); } - std::remove(last_qnn_ctx_binary_file_name.c_str()); + std::remove(qnn_ctx_binary_file_name1.c_str()); } // For Ort sessions to generate the context binary, with session option ep.share_ep_contexts enabled @@ -1376,6 +1262,11 @@ TEST_F(QnnHTPBackendTests, QnnContextGenWeightSharingSessionAPI) { // Create QDQ models std::vector onnx_model_paths{"./weight_share1.onnx", "./weight_share2.onnx"}; + // cleanup in case some failure test doesn't remove them + for (auto model_path : onnx_model_paths) { + std::remove(model_path.c_str()); + } + std::vector ctx_model_paths; for (auto model_path : onnx_model_paths) { CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); @@ -1388,32 +1279,26 @@ TEST_F(QnnHTPBackendTests, QnnContextGenWeightSharingSessionAPI) { } ctx_model_paths.push_back(model_path); } + for (auto ctx_model_path : ctx_model_paths) { + std::remove(ctx_model_path.c_str()); + } - Ort::SessionOptions so; - so.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1"); - so.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0"); - // enable ep.share_ep_contexts so that QNNEP share the QnnBackendManager across sessions - so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); - - so.AppendExecutionProvider("QNN", provider_options); + DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); - Ort::Session session1(*ort_env, ToPathString(onnx_model_paths[0]).c_str(), so); std::string qnn_ctx_binary_file_name1; GetContextBinaryFileName(ctx_model_paths[0], qnn_ctx_binary_file_name1, DefaultLoggingManager().DefaultLogger()); EXPECT_TRUE(!qnn_ctx_binary_file_name1.empty()); - // Tell the EP stop share the QnnBackendManager from this session then on - so.AddConfigEntry(kOrtSessionOptionStopShareEpContexts, "1"); - Ort::Session session2(*ort_env, ToPathString(onnx_model_paths[1]).c_str(), so); std::string qnn_ctx_binary_file_name2; GetContextBinaryFileName(ctx_model_paths[1], qnn_ctx_binary_file_name2, DefaultLoggingManager().DefaultLogger()); EXPECT_TRUE(!qnn_ctx_binary_file_name2.empty()); + // 2 *_ctx.onn point to same .bin file + EXPECT_TRUE(qnn_ctx_binary_file_name1 == qnn_ctx_binary_file_name2); auto file_size_1 = std::filesystem::file_size(qnn_ctx_binary_file_name1); - auto file_size_2 = std::filesystem::file_size(qnn_ctx_binary_file_name2); - EXPECT_TRUE(file_size_2 > file_size_1); + EXPECT_TRUE(file_size_1 > 0); // clean up for (auto model_path : onnx_model_paths) { @@ -1423,7 +1308,6 @@ TEST_F(QnnHTPBackendTests, QnnContextGenWeightSharingSessionAPI) { ASSERT_EQ(std::remove(ctx_model_path.c_str()), 0); } ASSERT_EQ(std::remove(qnn_ctx_binary_file_name1.c_str()), 0); - ASSERT_EQ(std::remove(qnn_ctx_binary_file_name2.c_str()), 0); } #endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__) From 11216a4e91ce034e47db3fcdf7fd07a6f9432b42 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 13 Mar 2025 23:45:03 +0800 Subject: [PATCH 087/266] Correct generated cmake syntax (#24016) ### Description Previously will got CMake Error at build/Android/intermediates/armeabi-v7a/vcpkg/buildtrees/0.vcpkg_dep_info.cmake:15: Parse error. Expected a newline, got identifier with text "set". --- tools/python/util/vcpkg_helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/python/util/vcpkg_helpers.py b/tools/python/util/vcpkg_helpers.py index 875a6186e55c2..ccb3181c86486 100644 --- a/tools/python/util/vcpkg_helpers.py +++ b/tools/python/util/vcpkg_helpers.py @@ -139,11 +139,11 @@ def generate_triplet_for_android( # Valid options are dynamic and static. Libraries can ignore this setting if they do not support the preferred linkage type. In our case, we prefer to use static libs. f.write("set(VCPKG_LIBRARY_LINKAGE static)\n") if not enable_rtti: - f.write("set(CMAKE_ANDROID_RTTI OFF)") + f.write("set(CMAKE_ANDROID_RTTI OFF)\n") if not enable_exception: - f.write("set(CMAKE_ANDROID_EXCEPTIONS OFF)") + f.write("set(CMAKE_ANDROID_EXCEPTIONS OFF)\n") if use_cpp_shared: - f.write("set(ANDROID_STL c++_shared)") + f.write("set(ANDROID_STL c++_shared)\n") ldflags = [] From 1362e7cadccffa00e18ea9201b418de37a539f12 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:00:15 -0700 Subject: [PATCH 088/266] [webgpu] allow to specify UseIndicesTypeAlias for Indices (#24019) ### Description Allow to specify `UseIndicesTypeAlias` for `AddIndices` in `ShaderHelper`. --- .../contrib_ops/webgpu/bert/rotary_embedding.cc | 2 +- onnxruntime/core/providers/webgpu/shader_helper.cc | 11 +++++++++-- onnxruntime/core/providers/webgpu/shader_helper.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc index 20e1583e0da8f..b33084d60cec3 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc @@ -27,7 +27,7 @@ Status RotaryEmbeddingProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& sin_cache = shader.AddInput("sin_cache", ShaderUsage::UseUniform); const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform); // TODO: remove output_indices. - const auto& output_indices = shader.AddIndices("output_indices", false); + const auto& output_indices = shader.AddIndices("output_indices", ShaderUsage::None); const auto interleaved_str = interleaved_ ? "true" : "false"; shader.MainFunctionBody() << " let half_rotary_emb_dim = uniforms.cos_cache_shape[1];\n" " let bsnh = global_idx / uniforms.global_stride % uniforms.global_shape;\n" diff --git a/onnxruntime/core/providers/webgpu/shader_helper.cc b/onnxruntime/core/providers/webgpu/shader_helper.cc index 19cab9b178b1f..db14cb88d1963 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.cc +++ b/onnxruntime/core/providers/webgpu/shader_helper.cc @@ -104,12 +104,19 @@ const ShaderVariableHelper& ShaderHelper::AddOutput(const std::string& name, Sha return AddVariableImpl(false, name, usage, dims); } -const ShaderIndicesHelper& ShaderHelper::AddIndices(const std::string& name, bool use_uniform) { +const ShaderIndicesHelper& ShaderHelper::AddIndices(const std::string& name, ShaderUsage usage) { const size_t indices_index = indices_vars_.size(); + ORT_ENFORCE(indices_index < program_.Indices().size(), + "Too many indices in the program (", program_.Indices().size(), ")"); + + // usage of indices should not use flag other than UseUniform and UseIndicesTypeAlias + ORT_ENFORCE(!(usage & ~(ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias)), + "Invalid usage for indices variable ", name); + return *indices_vars_.emplace_back( std::make_unique(name, ProgramVariableDataType::InvalidType, - use_uniform ? ShaderUsage::UseUniform : ShaderUsage::None, + usage, program_.Indices()[indices_index])); } diff --git a/onnxruntime/core/providers/webgpu/shader_helper.h b/onnxruntime/core/providers/webgpu/shader_helper.h index 64b4c054f93d4..e5f316a46bedc 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.h +++ b/onnxruntime/core/providers/webgpu/shader_helper.h @@ -86,7 +86,7 @@ class ShaderHelper final { ShaderUsage usage = ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseUniform); // Add an indices variable to the shader. - const ShaderIndicesHelper& AddIndices(const std::string& name, bool use_uniform = true); + const ShaderIndicesHelper& AddIndices(const std::string& name, ShaderUsage usage = ShaderUsage::UseUniform); // Get the string stream for additional implementation code to the shader. inline OStringStream& AdditionalImplementation() { From 401f24a8cfb03181bfd609cc67f183587cbbe39b Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:41:49 -0700 Subject: [PATCH 089/266] [webgpu] allow overloads to Program::AddIndices (#24021) ### Description This change allows more overloads for the `Program::AddIndices` method, and makes use of r-value references for parameters when possible. Also fixed the implementation of the `AddInputs` and `AddOutputs` methods to use r-value references for the parameters --- .../contrib_ops/webgpu/bert/flash_attention.cc | 2 +- .../webgpu/math/binary_elementwise_ops.cc | 6 +++--- onnxruntime/core/providers/webgpu/program.cc | 14 ++------------ onnxruntime/core/providers/webgpu/program.h | 8 +++++--- onnxruntime/core/providers/webgpu/tensor/expand.cc | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 5759e7c1232de..7e4dbe2a111cd 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -97,7 +97,7 @@ Status CopyKVCache(onnxruntime::webgpu::ComputeContext& context, const WebgpuAtt } program.AddOutputs({{present_key, ProgramTensorMetadataDependency::Rank, components}, {present_value, ProgramTensorMetadataDependency::Rank, components}}) - .AddIndices(valid_present_shape); + .AddIndices(std::move(valid_present_shape)); program.SetDispatchGroupSize(onnxruntime::narrow(valid_kv_size + 63 / 64)) .SetWorkgroupSize(64) .CacheHint(has_past, parameters.qkv_format_, parameters.past_present_share_buffer_) diff --git a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc index 8a22e45f17047..13004af25726d 100644 --- a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc @@ -190,9 +190,9 @@ Status BinaryElementwise::ComputeInternal(ComputeContext& context) const { // Mode Vectorize broadcast // cache hint: "V{a_rank};{b_rank};{output_rank}" program - .AddIndices(reshaped_output_shape) - .AddIndices(reshaped_lhs_shape) - .AddIndices(reshaped_rhs_shape) + .AddIndices(std::move(reshaped_output_shape)) + .AddIndices(std::move(reshaped_lhs_shape)) + .AddIndices(std::move(reshaped_rhs_shape)) .CacheHint("V"); } else { // Mode Broadcast diff --git a/onnxruntime/core/providers/webgpu/program.cc b/onnxruntime/core/providers/webgpu/program.cc index 976b7927ac3dd..73291e1e93ff1 100644 --- a/onnxruntime/core/providers/webgpu/program.cc +++ b/onnxruntime/core/providers/webgpu/program.cc @@ -289,7 +289,7 @@ ProgramBase::ProgramBase(std::string_view name, ProgramMetadata&& metadata) } ProgramBase& ProgramBase::AddInput(ProgramInput&& input) { - inputs_.emplace_back(input); + inputs_.emplace_back(std::move(input)); return *this; } @@ -299,7 +299,7 @@ ProgramBase& ProgramBase::AddInputs(std::initializer_list inputs) } ProgramBase& ProgramBase::AddOutput(ProgramOutput&& output) { - outputs_.emplace_back(output); + outputs_.emplace_back(std::move(output)); return *this; } @@ -308,16 +308,6 @@ ProgramBase& ProgramBase::AddOutputs(std::initializer_list output return *this; } -ProgramBase& ProgramBase::AddIndices(const TensorShape& shape) { - indices_.emplace_back(shape); - return *this; -} - -ProgramBase& ProgramBase::AddIndices(TensorShape&& shape) { - indices_.emplace_back(shape); - return *this; -} - ProgramBase& ProgramBase::SetDispatchGroupSize(uint32_t x) { return SetDispatchGroupSize(x, 1, 1); } diff --git a/onnxruntime/core/providers/webgpu/program.h b/onnxruntime/core/providers/webgpu/program.h index 95fef36144025..ea7d8ae5471af 100644 --- a/onnxruntime/core/providers/webgpu/program.h +++ b/onnxruntime/core/providers/webgpu/program.h @@ -271,9 +271,11 @@ class ProgramBase { // add multiple program outputs ProgramBase& AddOutputs(std::initializer_list outputs); // add a program variable for indices - ProgramBase& AddIndices(const TensorShape& shape); - // add a program variable for indices - ProgramBase& AddIndices(TensorShape&& shape); + template + ProgramBase& AddIndices(Args&&... args) { + indices_.emplace_back(std::forward(args)...); + return *this; + } // set the size of dispatch groups. Y and Z are 1 if not specified. ProgramBase& SetDispatchGroupSize(uint32_t x); diff --git a/onnxruntime/core/providers/webgpu/tensor/expand.cc b/onnxruntime/core/providers/webgpu/tensor/expand.cc index 9bdebe2c1e0d3..3e831f9853451 100644 --- a/onnxruntime/core/providers/webgpu/tensor/expand.cc +++ b/onnxruntime/core/providers/webgpu/tensor/expand.cc @@ -53,7 +53,7 @@ Status Expand::ComputeInternal(ComputeContext& context) const { {data_size}, }); if (components_i != components_o) { - program.AddIndices(output_shape); + program.AddIndices(std::move(output_shape)); } return context.RunProgram(program); } From 219c919c48f54f76ac42f43555578cb019fb4e89 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:42:00 -0700 Subject: [PATCH 090/266] fix test for RotaryEmbedding (#24022) ### Description the `BaseTester::Run` function signature is: ```c++ void BaseTester::Run(ExpectResult expect_result, const std::string& expected_failure_string, const std::unordered_set& excluded_provider_types, const RunOptions* run_options, std::vector>* execution_providers, ExecutionMode execution_mode, const Graph::ResolveOptions& options); ``` Its behavior is: - if the parameter `execution_providers` is empty, it will try to aggregate all execution providers available in the build, and for each EP, create inference session and perform test. - if the parameter `execution_providers` is not empty, it will run a single inference session, use the passed-in `execution_providers` as session options and perform test. The old code may put multiple EPs into single inference sessions, but at runtime there will be only one EP running the test. Specifically, WebGPU EP is after CPU EP in this case, so the test never run on WebGPU EP. **To reviewers**: if you see **a lot of** changes, click the "setting" button next to the "Jump to", image and check the "Hide Whitespace" and load it again. {4D60F676-35F4-4546-B8E1-E2F42411A9E6} --- .../contrib_ops/rotary_embedding_op_test.cc | 78 ++++++++++--------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/onnxruntime/test/contrib_ops/rotary_embedding_op_test.cc b/onnxruntime/test/contrib_ops/rotary_embedding_op_test.cc index 0e964cf64fbbd..625c5ec35e20d 100644 --- a/onnxruntime/test/contrib_ops/rotary_embedding_op_test.cc +++ b/onnxruntime/test/contrib_ops/rotary_embedding_op_test.cc @@ -86,44 +86,48 @@ static void RunTest( return; } - OpTester test(op_type.c_str(), 1, onnxruntime::kMSDomain); - test.AddAttribute("interleaved", interleaved); - - if (rotary_embedding_dim > 0) { - test.AddAttribute("rotary_embedding_dim", rotary_embedding_dim); - test.AddAttribute("num_heads", num_heads); - } - - if (rotary_embedding_dim > 0) { - test.AddAttribute("is_packed_batching", is_packed_batching); + for (auto& ep : execution_providers) { + OpTester test(op_type.c_str(), 1, onnxruntime::kMSDomain); + test.AddAttribute("interleaved", interleaved); + + if (rotary_embedding_dim > 0) { + test.AddAttribute("rotary_embedding_dim", rotary_embedding_dim); + test.AddAttribute("num_heads", num_heads); + } + + if (rotary_embedding_dim > 0) { + test.AddAttribute("is_packed_batching", is_packed_batching); + } + + if (tensor_type == TensorType::kFloat) { + test.AddInput("input", input_dims, input_data); + test.AddInput("position_ids", pos_dims, position_ids); + test.AddInput("cos_cache", cache_dims, cos_cache); + test.AddInput("sin_cache", cache_dims, sin_cache); + test.AddOutput("output", input_dims, output_data); + } else if (tensor_type == TensorType::kFloat16) { + test.AddInput("input", input_dims, ToFloat16(input_data)); + test.AddInput("position_ids", pos_dims, position_ids); + test.AddInput("cos_cache", cache_dims, ToFloat16(cos_cache)); + test.AddInput("sin_cache", cache_dims, ToFloat16(sin_cache)); + test.AddOutput("output", input_dims, ToFloat16(output_data)); + } else { + test.AddInput("input", input_dims, FloatsToBFloat16s(input_data)); + test.AddInput("position_ids", pos_dims, position_ids); + test.AddInput("cos_cache", cache_dims, FloatsToBFloat16s(cos_cache)); + test.AddInput("sin_cache", cache_dims, FloatsToBFloat16s(sin_cache)); + test.AddOutput("output", input_dims, FloatsToBFloat16s(output_data)); + } + if (tensor_type == TensorType::kBFloat16) { + test.SetOutputAbsErr("output", 0.03f); + } else { + test.SetOutputAbsErr("output", 0.002f); + } + + std::vector> test_execution_providers; + test_execution_providers.push_back(std::move(ep)); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &test_execution_providers); } - - if (tensor_type == TensorType::kFloat) { - test.AddInput("input", input_dims, input_data); - test.AddInput("position_ids", pos_dims, position_ids); - test.AddInput("cos_cache", cache_dims, cos_cache); - test.AddInput("sin_cache", cache_dims, sin_cache); - test.AddOutput("output", input_dims, output_data); - } else if (tensor_type == TensorType::kFloat16) { - test.AddInput("input", input_dims, ToFloat16(input_data)); - test.AddInput("position_ids", pos_dims, position_ids); - test.AddInput("cos_cache", cache_dims, ToFloat16(cos_cache)); - test.AddInput("sin_cache", cache_dims, ToFloat16(sin_cache)); - test.AddOutput("output", input_dims, ToFloat16(output_data)); - } else { - test.AddInput("input", input_dims, FloatsToBFloat16s(input_data)); - test.AddInput("position_ids", pos_dims, position_ids); - test.AddInput("cos_cache", cache_dims, FloatsToBFloat16s(cos_cache)); - test.AddInput("sin_cache", cache_dims, FloatsToBFloat16s(sin_cache)); - test.AddOutput("output", input_dims, FloatsToBFloat16s(output_data)); - } - if (tensor_type == TensorType::kBFloat16) { - test.SetOutputAbsErr("output", 0.03f); - } else { - test.SetOutputAbsErr("output", 0.002f); - } - - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); } static void RunTests(const std::vector& input_data, From 99b78a9486480313b78d7d60181a11c7f6f4f338 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Thu, 13 Mar 2025 11:19:01 -0700 Subject: [PATCH 091/266] Fix attention bias broadcast (#24017) ### Description * Fix broadcast on attention bias dim 1. * Increase test cases in test_mha.py in pipeline to cover the testing. ### Motivation and Context This feature was added in https://github.com/microsoft/onnxruntime/pull/21710. There was bug when computing the offset when attention bias broadcast on dim 1 only in both CUDA and CPU kernel. It can be triggered when attention bias shape is like [batch_size, 1, sequence_length, total_sequence_length] and batch_size > 1 when unfused kernel is selected. Note that cudnn flash attention and cutlass fused attention also supports attention bias, so the bug in unfused kernel was not discovered previously. --- .../contrib_ops/cpu/bert/attention_cpu_base.h | 2 +- .../cuda/bert/attention_softmax.cu | 17 +- .../contrib_ops/cuda/bert/attention_softmax.h | 8 +- .../contrib_ops/rocm/bert/attention_softmax.h | 66 ++++---- .../test/python/transformers/test_mha.py | 152 +++++++++--------- 5 files changed, 127 insertions(+), 118 deletions(-) diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h b/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h index 87938f3728750..4345675b7e966 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h @@ -208,7 +208,7 @@ class AttentionCPUBase : public AttentionBase { // Here we handle the broadcast of batch_size and num_heads dimensions. ptrdiff_t attn_bias_offset = 0; if (attn_bias_dims[0] != 1) { - attn_bias_offset += SafeInt(batch_index) * num_heads_ * probs_matrix_size; + attn_bias_offset += SafeInt(batch_index) * attn_bias_dims[1] * probs_matrix_size; } if (attn_bias_dims[1] != 1) { attn_bias_offset += head_index * probs_matrix_size; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu index 52f94247a8b2b..04bb571f43fa3 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu @@ -49,14 +49,15 @@ namespace attention_softmax_cuda { // grid size is (num_heads * sequence_length, batch_size, 1) // input and output shape is (batch_size, num_heads, sequence_length, total_sequence_length) // bias shape is (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length) -#define DECLARE_SOFTMAX_VARS() \ - [[maybe_unused]] const int s = blockIdx.x % sequence_length; \ - const int b = blockIdx.y; \ - int64_t offset = static_cast(b * gridDim.x + blockIdx.x) * static_cast(total_sequence_length); \ - [[maybe_unused]] int64_t bias_offset = 0; \ - if constexpr (HAS_BIAS) { \ - const int j = (broadcast_attn_bias_dim_0 ? 0 : (b * gridDim.x)) + (broadcast_attn_bias_dim_1 ? s : blockIdx.x); \ - bias_offset = static_cast(j) * static_cast(total_sequence_length); \ +#define DECLARE_SOFTMAX_VARS() \ + [[maybe_unused]] const int s = blockIdx.x % sequence_length; \ + const int b = blockIdx.y; \ + int64_t offset = static_cast(b * gridDim.x + blockIdx.x) * static_cast(total_sequence_length); \ + [[maybe_unused]] int64_t bias_offset = 0; \ + if constexpr (HAS_BIAS) { \ + const int j = (broadcast_attn_bias_dim_0 ? 0 : (b * (broadcast_attn_bias_dim_1 ? sequence_length : gridDim.x))) + \ + (broadcast_attn_bias_dim_1 ? s : blockIdx.x); \ + bias_offset = static_cast(j) * static_cast(total_sequence_length); \ } // This kernel is for non causal, attention mask 1D or None, and total_sequence_length > 1024. diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h index f7fab268b4607..126de15362761 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h @@ -9,14 +9,14 @@ namespace attention_softmax_cuda { template Status ComputeSoftmax(cudaStream_t stream, const int all_sequence_length, const int sequence_length, - const int batch_size, const int num_heads, const T* rel_pos_bias, + const int batch_size, const int num_heads, const T* attn_bias, const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, T* input, T* output, bool causal); template Status ComputeSoftmaxWithCumSeqLength( const T* input, - const T* rel_pos_bias, + const T* attn_bias, const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, const int32_t* cum_seq_length, @@ -34,7 +34,7 @@ Status ComputeSoftmaxWithMask1D(cudaStream_t stream, const int num_heads, const int* mask_index, const int* mask_start, - const T* rel_pos_bias, + const T* attn_bias, const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, const T* input, @@ -49,7 +49,7 @@ Status ComputeSoftmaxWithRawMask(Stream* ort_stream, const int num_heads, const int* attention_mask, const bool* key_padding_mask, - const T* rel_pos_bias, + const T* attn_bias, const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, const T* input, diff --git a/onnxruntime/contrib_ops/rocm/bert/attention_softmax.h b/onnxruntime/contrib_ops/rocm/bert/attention_softmax.h index 5bcd46f9b9ea8..9f2faa228cf79 100644 --- a/onnxruntime/contrib_ops/rocm/bert/attention_softmax.h +++ b/onnxruntime/contrib_ops/rocm/bert/attention_softmax.h @@ -40,7 +40,7 @@ template __device__ inline void Softmax(const int all_sequence_length, const int valid_end, const int valid_start, - const T* add_before_softmax, + const T* attn_bias, const T* input, T* output) { using BlockReduce = hipcub::BlockReduce; @@ -59,9 +59,9 @@ __device__ inline void Softmax(const int all_sequence_length, for (int i = threadIdx.x; i < valid_end; i += TPB) { if (i >= valid_start) { const int index = offset + i; - float input_at_idx = add_before_softmax == nullptr + float input_at_idx = attn_bias == nullptr ? static_cast(input[index]) - : static_cast(input[index] + add_before_softmax[index]); + : static_cast(input[index] + attn_bias[index]); if (thread_data_max < input_at_idx) { thread_data_max = input_at_idx; } @@ -80,7 +80,7 @@ __device__ inline void Softmax(const int all_sequence_length, for (int i = threadIdx.x; i < valid_end; i += TPB) { if (i >= valid_start) { const int index = offset + i; - float val = add_before_softmax == nullptr ? input[index] : input[index] + add_before_softmax[index]; + float val = attn_bias == nullptr ? input[index] : input[index] + attn_bias[index]; thread_data_sum += expf(val - max_block); } } @@ -93,9 +93,9 @@ __device__ inline void Softmax(const int all_sequence_length, for (int i = threadIdx.x; i < all_sequence_length; i += TPB) { const int index = offset + i; - float input_at_idx = add_before_softmax == nullptr + float input_at_idx = attn_bias == nullptr ? static_cast(input[index]) - : static_cast(input[index] + add_before_softmax[index]); + : static_cast(input[index] + attn_bias[index]); const float val = (i >= valid_start && i < valid_end) ? expf(input_at_idx - max_block) * sum_reverse_block : 0.f; output[index] = T(val); } @@ -106,7 +106,7 @@ __device__ inline void SoftmaxSmall(const int all_sequence_length, const int sequence_length, const int valid_end, const int valid_start, - const T* add_before_softmax, + const T* attn_bias, const T* input, T* output, bool causal) { @@ -137,9 +137,9 @@ __device__ inline void SoftmaxSmall(const int all_sequence_length, // Infinity divided by Infinity is a NAN. Thus, softmax gets a NAN if one or more item are large enough. // a math transform as below is leveraged to get a stable softmax: // e^xi/(e^x1 + ...e^xn) = e^(xi - max) / (e^(x1 - max) + ... + e^(xn - max)) - float input_data = add_before_softmax == nullptr + float input_data = attn_bias == nullptr ? static_cast(input[index]) - : static_cast(input[index] + add_before_softmax[index]); + : static_cast(input[index] + attn_bias[index]); float thread_data_max = is_valid ? input_data : float(-ROCMRT_INF_F); const auto max = BlockReduce(tmp_storage).Reduce(thread_data_max, hipcub::Max(), end); @@ -178,7 +178,7 @@ __global__ void SoftmaxWithRawMaskSmallKernel( const int3 attention_mask_strides, const int* attention_mask, // 2D, 3D or 4D attention mask const bool* key_padding_mask, - const T* add_before_softmax, + const T* attn_bias, const T* input, T* output, const bool causal, @@ -225,8 +225,8 @@ __global__ void SoftmaxWithRawMaskSmallKernel( } } - if (add_before_softmax != nullptr) { - thread_data += float(add_before_softmax[index]); + if (attn_bias != nullptr) { + thread_data += float(attn_bias[index]); } } @@ -264,50 +264,50 @@ __global__ void SoftmaxWithRawMaskSmallKernel( template __global__ void SoftmaxKernelSmall(const int all_sequence_length, const int sequence_length, - const T* add_before_softmax, const T* input, T* output, bool causal) { + const T* attn_bias, const T* input, T* output, bool causal) { SoftmaxSmall(all_sequence_length, sequence_length, all_sequence_length, 0, - add_before_softmax, input, output, causal); + attn_bias, input, output, causal); } template -__global__ void SoftmaxKernel(const int all_sequence_length, const T* add_before_softmax, const T* input, T* output) { - Softmax(all_sequence_length, all_sequence_length, 0, add_before_softmax, input, output); +__global__ void SoftmaxKernel(const int all_sequence_length, const T* attn_bias, const T* input, T* output) { + Softmax(all_sequence_length, all_sequence_length, 0, attn_bias, input, output); } template Status ComputeSoftmax( hipStream_t stream, const int all_sequence_length, const int sequence_length, const int batch_size, const int num_heads, - const T* add_before_softmax, const T* input, T* output, bool causal) { + const T* attn_bias, const T* input, T* output, bool causal) { const dim3 grid(sequence_length * num_heads, batch_size, 1); if (all_sequence_length <= 32) { const int blockSize = 32; SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, add_before_softmax, input, output, causal); + all_sequence_length, sequence_length, attn_bias, input, output, causal); } else if (all_sequence_length <= 64) { const int blockSize = 64; SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, add_before_softmax, input, output, causal); + all_sequence_length, sequence_length, attn_bias, input, output, causal); } else if (all_sequence_length <= 128) { const int blockSize = 128; SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, add_before_softmax, input, output, causal); + all_sequence_length, sequence_length, attn_bias, input, output, causal); } else if (all_sequence_length <= 256) { const int blockSize = 256; SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, add_before_softmax, input, output, causal); + all_sequence_length, sequence_length, attn_bias, input, output, causal); } else if (all_sequence_length <= 512) { const int blockSize = 512; SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, add_before_softmax, input, output, causal); + all_sequence_length, sequence_length, attn_bias, input, output, causal); } else if (all_sequence_length <= 1024) { const int blockSize = 1024; SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, add_before_softmax, input, output, causal); + all_sequence_length, sequence_length, attn_bias, input, output, causal); } else if (!causal) { const int blockSize = 1024; SoftmaxKernel<<>>( - all_sequence_length, add_before_softmax, input, output); + all_sequence_length, attn_bias, input, output); } else { return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Attention ROCM operator does not support total sequence length > 1024."); } @@ -318,7 +318,7 @@ Status ComputeSoftmax( template __global__ void MaskedSoftmaxKernelSmall(const int all_sequence_length, const int sequence_length, const int* mask_end, const int* mask_start, - const T* add_before_softmax, const T* input, T* output, + const T* attn_bias, const T* input, T* output, bool causal) { __shared__ int start_position; __shared__ int end_position; @@ -337,12 +337,12 @@ __global__ void MaskedSoftmaxKernelSmall(const int all_sequence_length, const in __syncthreads(); SoftmaxSmall(all_sequence_length, sequence_length, end_position, start_position, - add_before_softmax, input, output, causal); + attn_bias, input, output, causal); } template __global__ void MaskedSoftmaxKernel(const int all_sequence_length, const int* mask_end, const int* mask_start, - const T* add_before_softmax, const T* input, T* output) { + const T* attn_bias, const T* input, T* output) { __shared__ int start_position; __shared__ int end_position; @@ -359,7 +359,7 @@ __global__ void MaskedSoftmaxKernel(const int all_sequence_length, const int* ma } __syncthreads(); - Softmax(all_sequence_length, end_position, start_position, add_before_softmax, input, output); + Softmax(all_sequence_length, end_position, start_position, attn_bias, input, output); } template @@ -367,13 +367,13 @@ Status ComputeSoftmaxWithMask1D( hipStream_t stream, const int all_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* mask_index, const int* mask_start, - const T* add_before_softmax, const T* input, T* output, const bool causal) { + const T* attn_bias, const T* input, T* output, const bool causal) { const dim3 grid(sequence_length * num_heads, batch_size, 1); #define DISPATCH_KERNEL_SMALL_WITH_BLOCKSIZE(block_size) \ MaskedSoftmaxKernelSmall<<>>( \ all_sequence_length, sequence_length, mask_index, mask_start, \ - add_before_softmax, input, output, causal); + attn_bias, input, output, causal); if (all_sequence_length <= 32) { DISPATCH_KERNEL_SMALL_WITH_BLOCKSIZE(32); @@ -391,7 +391,7 @@ Status ComputeSoftmaxWithMask1D( const int blockSize = 1024; MaskedSoftmaxKernel<<>>( all_sequence_length, mask_index, mask_start, - add_before_softmax, input, output); + attn_bias, input, output); } else { return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Attention ROCM operator does not support total sequence length > 1024."); } @@ -410,7 +410,7 @@ Status ComputeSoftmaxWithRawMask(Stream* ort_stream, const int3 attention_mask_strides, const int* attention_mask, const bool* key_padding_mask, - const T* add_before_softmax, + const T* attn_bias, const T* input, T* output, const bool causal, @@ -426,7 +426,7 @@ Status ComputeSoftmaxWithRawMask(Stream* ort_stream, #define DISPATCH_KERNEL_SMALL_WITH_BLOCKSIZE(block_size) \ SoftmaxWithRawMaskSmallKernel<<>>( \ all_sequence_length, sequence_length, attention_mask_strides, \ - attention_mask, key_padding_mask, add_before_softmax, input, out, \ + attention_mask, key_padding_mask, attn_bias, input, out, \ causal, rsqrt_head_size, \ use_persistent_softmax, mask_filter_value); diff --git a/onnxruntime/test/python/transformers/test_mha.py b/onnxruntime/test/python/transformers/test_mha.py index dc19e3ec95243..f6403636e79d9 100644 --- a/onnxruntime/test/python/transformers/test_mha.py +++ b/onnxruntime/test/python/transformers/test_mha.py @@ -41,15 +41,15 @@ def get_provider_support_info(provider: str, use_kv_cache: bool): device_id = torch.cuda.current_device() device = torch.device("cuda", device_id) - dtype = torch.float16 + dtypes = [torch.float16, torch.float] else: assert provider == "CPUExecutionProvider" formats = [InputFormats.Q_K_V_BSNH_BSNH_BSNH] if not use_kv_cache: formats.append(InputFormats.Q_K_V_BSNH_BNSH_BNSH) device = torch.device("cpu") - dtype = torch.float - return device, dtype, formats + dtypes = [torch.float] + return device, dtypes, formats def get_bias_support(format: InputFormats): @@ -211,10 +211,11 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): return yield + # Lengths of arrays are prime numbers since modulo (% length) is used in non comprehensive mode. batch_sizes = [1, 2, 3] - sequence_lengths = [1, 16, 127, 128, 255, 256, 383, 384, 512] - heads = [1, 3, 4, 16] - head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 224, 256] + sequence_lengths = [1, 16, 127, 128, 256, 384, 512] + heads = [1, 2, 3, 4, 16] + head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 256] mask_formats = [ AttentionMaskFormat.Mask_None, @@ -223,7 +224,7 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): ] atten_bias_options = get_atten_bias_support() - device, dtype, formats = get_provider_support_info(provider, False) + device, dtypes, formats = get_provider_support_info(provider, False) if comprehensive: sequence_lengths = [*sequence_lengths, 2048] # Large sequence length is slow and need a lot of memory for batch_size in batch_sizes: @@ -239,30 +240,31 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, ) in atten_bias_options: - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - past_sequence_length=0, - kv_sequence_length=sequence_length, - max_cache_sequence_length=None, - provider=provider, - device=device, - dtype=dtype, - use_kv_cache=False, - share_past_present_buffer=False, - input_format=format, - has_bias=has_bias, - mask_format=mask_format, - has_attn_bias=has_attn_bias, - broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, - broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, - ) - yield config + for dtype in dtypes: + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + past_sequence_length=0, + kv_sequence_length=sequence_length, + max_cache_sequence_length=None, + provider=provider, + device=device, + dtype=dtype, + use_kv_cache=False, + share_past_present_buffer=False, + input_format=format, + has_bias=has_bias, + mask_format=mask_format, + has_attn_bias=has_attn_bias, + broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, + ) + yield config else: - test_cases = max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) + test_cases = 2 * max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) for i in range(test_cases): batch_size = batch_sizes[i % len(batch_sizes)] sequence_length = sequence_lengths[i % len(sequence_lengths)] @@ -272,6 +274,7 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1 = atten_bias_options[ i % len(atten_bias_options) ] + dtype = dtypes[i % len(dtypes)] for format in formats: for causal in get_causal_support(format): for has_bias in get_bias_support(format): @@ -304,11 +307,13 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): return yield + # Lengths of arrays are prime numbers since modulo (% length) is used in non comprehensive mode. batch_sizes = [1, 2, 3] - sequence_lengths = [1, 15, 16, 255, 256, 512] - heads = [1, 3, 4, 16] - head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 224, 256] - device, dtype, formats = get_provider_support_info(provider, True) + sequence_lengths = [1, 15, 16, 255, 256, 384, 512] + heads = [1, 2, 3, 4, 16] + head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 224, 256] + + device, dtypes, formats = get_provider_support_info(provider, True) mask_formats = [ AttentionMaskFormat.Mask_None, AttentionMaskFormat.Mask_1D_Key_SeqLen, @@ -328,38 +333,39 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): for has_past_input in [True, False]: for mask_format in mask_formats: for has_bias in get_bias_support(format): - for ( - has_attn_bias, - broadcast_attn_bias_dim_0, - broadcast_attn_bias_dim_1, - ) in atten_bias_options: - sequence_length = 1 if has_past_input else past_sequence_length - past_seq_len = past_sequence_length if has_past_input else 0 - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - past_sequence_length=past_seq_len, - kv_sequence_length=sequence_length, - max_cache_sequence_length=None, - provider=provider, - device=device, - dtype=dtype, - use_kv_cache=True, - has_past_input=has_past_input, - share_past_present_buffer=False, - input_format=format, - has_bias=has_bias, - mask_format=mask_format, - has_attn_bias=has_attn_bias, - broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, - broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, - ) - yield config + for dtype in dtypes: + for ( + has_attn_bias, + broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1, + ) in atten_bias_options: + sequence_length = 1 if has_past_input else past_sequence_length + past_seq_len = past_sequence_length if has_past_input else 0 + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + past_sequence_length=past_seq_len, + kv_sequence_length=sequence_length, + max_cache_sequence_length=None, + provider=provider, + device=device, + dtype=dtype, + use_kv_cache=True, + has_past_input=has_past_input, + share_past_present_buffer=False, + input_format=format, + has_bias=has_bias, + mask_format=mask_format, + has_attn_bias=has_attn_bias, + broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, + ) + yield config else: - test_cases = max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) + test_cases = 2 * max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) for i in range(test_cases): batch_size = batch_sizes[i % len(batch_sizes)] past_sequence_length = sequence_lengths[i % len(sequence_lengths)] @@ -369,6 +375,8 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1 = atten_bias_options[ i % len(atten_bias_options) ] + dtype = dtypes[i % len(dtypes)] + for format in formats: for causal in get_causal_support(format): for has_past_input in [True, False]: @@ -401,7 +409,7 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): def lean_attention_test_cases(provider: str, comprehensive: bool): - if provider == "CUDAExecutionProvider" and get_compute_capability() < 80: + if provider != "CUDAExecutionProvider" or get_compute_capability() < 80: return yield @@ -409,7 +417,7 @@ def lean_attention_test_cases(provider: str, comprehensive: bool): sequence_lengths = [2, 15, 16, 255, 256, 512, 1024, 2048, 4096, 8192] if comprehensive else [2, 255, 512] heads = [1, 4, 16] if comprehensive else [1, 4] head_sizes = [64, 128] - device, dtype, formats = get_provider_support_info(provider, True) + device, dtypes, formats = get_provider_support_info(provider, True) mask_formats = [AttentionMaskFormat.Mask_None] sequence_lengths = [*sequence_lengths, 2048] # Large sequence length is slow and need a lot of memory @@ -433,7 +441,7 @@ def lean_attention_test_cases(provider: str, comprehensive: bool): max_cache_sequence_length=None, provider=provider, device=device, - dtype=dtype, + dtype=dtypes[0], use_kv_cache=True, has_past_input=True, share_past_present_buffer=False, @@ -453,7 +461,7 @@ def no_kv_cache_multi_thread_test_cases(provider: str, comprehensive: bool): heads = [4] head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 224, 256] if comprehensive else [32, 64] - device, dtype, formats = get_provider_support_info(provider, False) + device, dtypes, formats = get_provider_support_info(provider, False) for format in formats: for causal in get_causal_support(format): @@ -473,7 +481,7 @@ def no_kv_cache_multi_thread_test_cases(provider: str, comprehensive: bool): max_cache_sequence_length=None, provider=provider, device=device, - dtype=dtype, + dtype=dtypes[0], use_kv_cache=False, share_past_present_buffer=False, input_format=format, @@ -493,7 +501,7 @@ def kv_cache_multi_thread_test_cases(provider: str, comprehensive: bool): head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 224, 256] if comprehensive else [32, 64] sequence_length = 1 - device, dtype, formats = get_provider_support_info(provider, True) + device, dtypes, formats = get_provider_support_info(provider, True) for format in formats: for causal in get_causal_support(format): @@ -513,7 +521,7 @@ def kv_cache_multi_thread_test_cases(provider: str, comprehensive: bool): max_cache_sequence_length=None, provider=provider, device=device, - dtype=dtype, + dtype=dtypes[0], use_kv_cache=True, has_past_input=True, share_past_present_buffer=False, From 5bd31636d5b1bbd25e772b5c9b678956a1636617 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Thu, 13 Mar 2025 13:06:18 -0700 Subject: [PATCH 092/266] Remove unused parameter in csharp InferenceTest (#24031) ### Description Fix a warning from analyzers: ``` Theory method 'CanRunInferenceOnAModelDotnetTensors' on test class 'InferenceTest' does not use parameter 'enableParallelExecution'. Use the parameter, or remove the parameter and associated data. (https://xunit.net/xunit.analyzers/rules/xUnit1026 ``` ### Motivation and Context --- .../InferenceTest.netcore.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs index 816511150a137..eab4a3d412898 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs @@ -74,11 +74,9 @@ public void CanCreateAndDisposeSessionWithModelPath() #if NET8_0_OR_GREATER #pragma warning disable SYSLIB5001 // System.Numerics.Tensors is only in preview so we can continue receiving API feedback [Theory] - [InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL, true)] - [InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL, false)] - [InlineData(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, true)] - [InlineData(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, false)] - private void CanRunInferenceOnAModelDotnetTensors(GraphOptimizationLevel graphOptimizationLevel, bool enableParallelExecution) + [InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL)] + [InlineData(GraphOptimizationLevel.ORT_ENABLE_EXTENDED)] + private void CanRunInferenceOnAModelDotnetTensors(GraphOptimizationLevel graphOptimizationLevel) { var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); @@ -151,7 +149,7 @@ public void InferenceSessionDisposedDotnetTensors() using (var inputOrtValues = new DisposableListTest>(session.InputMetadata.Count)) using (var outputOrtValues = new DisposableListTest>(session.OutputMetadata.Count)) { - + foreach (var name in inputMeta.Keys) { Assert.Equal(typeof(float), inputMeta[name].ElementType); @@ -159,7 +157,7 @@ public void InferenceSessionDisposedDotnetTensors() var tensor = SystemNumericsTensors.Tensor.Create(inputData, inputMeta[name].Dimensions.Select(x => (nint) x).ToArray()); inputOrtValues.Add(new DisposableTestPair(name, OrtValue.CreateTensorValueFromSystemNumericsTensorObject(tensor))); } - + // Run inference with named inputs and outputs created with in Run() using (var results = session.Run(runOptions, inputOrtValues.Select(x => x.Key).ToList(), inputOrtValues.Select(x => x.Value).ToList(), new List(["softmaxout_1"]))) // results is an IDisposableReadOnlyCollection container { @@ -224,7 +222,7 @@ private void ThrowWrongOutputDimensionDotnetTensors() inputOrtValues.Add(new DisposableTestPair("data_0", OrtValue.CreateTensorValueFromSystemNumericsTensorObject(tensor))); outputOrtValues.Add(new DisposableTestPair("softmaxout_1", OrtValue.CreateTensorValueFromSystemNumericsTensorObject(outputTensor))); - + var ex = Assert.Throws(() => session.Run(runOptions, ["data_0"], [inputOrtValues[0].Value], ["softmaxout_1"], [outputOrtValues[0].Value])); } From 6bb6d791b552b14a8824098b0fabe470f60b9efd Mon Sep 17 00:00:00 2001 From: Chi Lo <54722500+chilo-ms@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:41:08 -0700 Subject: [PATCH 093/266] [TensorRT EP] Call cudaSetDevice at compute function for handling multithreading scenario (#24010) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPU device is set again at compute function/compute time to handle multithreading scenarios. Consider the following: Users can create multiple threads to initialize separate inference sessions on different devices (not just the default device 0) Later, additional threads may be spawned to execute inference_session.Run(), which calls this compute function. Since new threads default to using device 0, it’s necessary to explicitly set the correct device to ensure computations run on the intended GPU. Example code: ````python provider = [ [ ('TensorrtExecutionProvider', { 'device_id': 0, }), ], [ ('TensorrtExecutionProvider', { 'device_id': 1, }), ] ] class ThreadObj(): def __init__(self, model_path: str, iterations: int, idx: int): ... sess_opt = ort.SessionOptions() self.inference_session = ort.InferenceSession(model_path, sess_opt, provider[idx % 2]) def warmup(self): self.inference_session.run(None, self.input) def run(self, thread_times, threads_complete): for iter in range(self.iterations): self.inference_session.run(None, self.input) def thread_target(obj, thread_times, threads_complete): obj.run(thread_times, threads_complete) ... iterations = 500 num_threads = 13 t_obj_list = [] thread_list = [] for tidx in range(num_threads): obj = ThreadObj(model_path, iterations, tidx) t_obj_list.append(obj) obj.warmup() for t_obj in t_obj_list: thread = threading.Thread(target=thread_target, daemon=True, args=(t_obj,thread_times,threads_complete,)) thread.start() thread_list.append(thread) ... ```` Note: Based on our measurements (using cuda event) on the A100 GPU with CUDA 12, the execution time for `cudaSetDevice` is approximately 0.004 ms, which is negligible and does not impact runtime performance. --- .../tensorrt/tensorrt_execution_provider.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index 523ebbfae807a..00f53b96f931a 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -3538,6 +3538,15 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView // Create compute function compute_info.compute_func = [this](FunctionState state, const OrtApi* api, OrtKernelContext* context) { + // The GPU device is set again here to handle multithreading scenarios. + // Consider the following: + // Users can create multiple threads to initialize separate inference sessions on different devices (not just the default device 0) + // Later, additional threads may be spawned to execute inference_session.Run(), which calls this compute function. + // Since new threads default to using device 0, it’s necessary to explicitly set the correct device to ensure computations run on the intended GPU. + // Note: Based on our measurements on the A100 GPU with CUDA 12, the execution time for cudaSetDevice is approximately 0.004 ms, which is negligible + // and does not impact runtime performance. + CUDA_CALL_THROW(cudaSetDevice(device_id_)); + Ort::KernelContext ctx(context); TensorrtFuncState* trt_state = reinterpret_cast(state); @@ -4212,6 +4221,15 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromPrecompiledEngine(con // Create compute function compute_info.compute_func = [this](FunctionState state, const OrtApi* api, OrtKernelContext* context) { + // The GPU device is set again here to handle multithreading scenarios. + // Consider the following: + // Users can create multiple threads to initialize separate inference sessions on different devices (not just the default device 0) + // Later, additional threads may be spawned to execute inference_session.Run(), which calls this compute function. + // Since new threads default to using device 0, it’s necessary to explicitly set the correct device to ensure computations run on the intended GPU. + // Note: Based on our measurements on the A100 GPU with CUDA 12, the execution time for cudaSetDevice is approximately 0.004 ms, which is negligible + // and does not impact runtime performance. + CUDA_CALL_THROW(cudaSetDevice(device_id_)); + Ort::KernelContext ctx(context); TensorrtShortFuncState* trt_state = reinterpret_cast(state); From 3f71d637a83dc3540753a8bb06740f67e926dc13 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Thu, 13 Mar 2025 16:14:33 -0700 Subject: [PATCH 094/266] Increase timeout for ARM64-Xcode16-targeting-iphonesimulator (#24030) --- .github/workflows/mac.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 143f0b9eaea5b..50dd25898ad35 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -164,7 +164,7 @@ jobs: matrix: target_arch: [x86_64, arm64] - timeout-minutes: 60 + timeout-minutes: 75 steps: - uses: actions/setup-python@v5 From 1fc6d8ca2f96e65a2b19bb78e6911d9d8cbcb678 Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 14 Mar 2025 15:52:20 +0800 Subject: [PATCH 095/266] Support tvOS build (#24000) --- cmake/CMakeLists.txt | 4 +-- cmake/adjust_global_compile_flags.cmake | 4 +-- cmake/onnxruntime_providers_cpu.cmake | 2 +- cmake/onnxruntime_python.cmake | 2 +- cmake/onnxruntime_tvos.toolchain.cmake | 12 ++++++++ cmake/onnxruntime_unittests.cmake | 2 +- tools/ci_build/build.py | 24 ++++++++++++--- ...lt_full_tvos_framework_build_settings.json | 30 +++++++++++++++++++ 8 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 cmake/onnxruntime_tvos.toolchain.cmake create mode 100644 tools/ci_build/github/apple/default_full_tvos_framework_build_settings.json diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 0b32d51884c05..4a39a5b208a24 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1812,8 +1812,8 @@ if (onnxruntime_USE_WINML) endif() # if (onnxruntime_USE_WINML) if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_BUILD_APPLE_FRAMEWORK) - if (onnxruntime_BUILD_APPLE_FRAMEWORK AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS") - message(FATAL_ERROR "onnxruntime_BUILD_APPLE_FRAMEWORK can only be enabled for macOS or iOS or visionOS.") + if (onnxruntime_BUILD_APPLE_FRAMEWORK AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS") + message(FATAL_ERROR "onnxruntime_BUILD_APPLE_FRAMEWORK can only be enabled for macOS or iOS or visionOS or tvOS.") endif() list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime) endif() diff --git a/cmake/adjust_global_compile_flags.cmake b/cmake/adjust_global_compile_flags.cmake index 2aa83e9e3ee96..d6f5a4dce5429 100644 --- a/cmake/adjust_global_compile_flags.cmake +++ b/cmake/adjust_global_compile_flags.cmake @@ -178,9 +178,9 @@ if (onnxruntime_CROSS_COMPILING) endif() endif() -# Mark symbols to be invisible, for macOS/iOS/visionOS target only +# Mark symbols to be invisible, for macOS/iOS/visionOS/tvOS target only # Due to many dependencies have different symbol visibility settings, set global compile flags here. -if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS") +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS") foreach(flags CMAKE_CXX_FLAGS CMAKE_OBJC_FLAGS CMAKE_OBJCXX_FLAGS) string(APPEND ${flags} " -fvisibility=hidden -fvisibility-inlines-hidden") endforeach() diff --git a/cmake/onnxruntime_providers_cpu.cmake b/cmake/onnxruntime_providers_cpu.cmake index beff30d193b94..3a5131947b917 100644 --- a/cmake/onnxruntime_providers_cpu.cmake +++ b/cmake/onnxruntime_providers_cpu.cmake @@ -217,7 +217,7 @@ set_target_properties(onnxruntime_providers PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(onnxruntime_providers PROPERTIES FOLDER "ONNXRuntime") if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD - AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS" + AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") file(GLOB onnxruntime_providers_shared_cc_srcs CONFIGURE_DEPENDS diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index 64b53c2912be0..ca65c02a40c3b 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -725,7 +725,7 @@ if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) endif() if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD - AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS" + AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT onnxruntime_USE_ROCM AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") diff --git a/cmake/onnxruntime_tvos.toolchain.cmake b/cmake/onnxruntime_tvos.toolchain.cmake new file mode 100644 index 0000000000000..5c992a1f465c6 --- /dev/null +++ b/cmake/onnxruntime_tvos.toolchain.cmake @@ -0,0 +1,12 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +set(CMAKE_SYSTEM_NAME tvOS) +set(CMAKE_SYSTEM_PROCESSOR arm64) + +if (NOT DEFINED CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM AND NOT DEFINED CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY) + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO) +endif() + +SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES") +SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index 87aee2a174fab..b5d7139c6adfd 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -1843,7 +1843,7 @@ endif() # limit to only test on windows first, due to a runtime path issue on linux if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD - AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS" + AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT onnxruntime_USE_ROCM) diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 987407b278448..657259b17b458 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -433,6 +433,7 @@ def convert_arg_line_to_args(self, arg_line): platform_group = parser.add_mutually_exclusive_group() platform_group.add_argument("--ios", action="store_true", help="build for ios") platform_group.add_argument("--visionos", action="store_true", help="build for visionOS") + platform_group.add_argument("--tvos", action="store_true", help="build for tvOS") platform_group.add_argument( "--macos", choices=["MacOSX", "Catalyst"], @@ -452,6 +453,11 @@ def convert_arg_line_to_args(self, arg_line): default="", help="Path to visionos toolchain file, or cmake/onnxruntime_visionos.toolchain.cmake will be used", ) + parser.add_argument( + "--tvos_toolchain_file", + default="", + help="Path to tvos toolchain file, or cmake/onnxruntime_tvos.toolchain.cmake will be used", + ) parser.add_argument( "--xcode_code_signing_team_id", default="", help="The development team ID used for code signing in Xcode" ) @@ -945,7 +951,7 @@ def use_dev_mode(args): return False if args.use_armnn: return False - if (args.ios or args.visionos) and is_macOS(): + if (args.ios or args.visionos or args.tvos) and is_macOS(): return False SYSTEM_COLLECTIONURI = os.getenv("SYSTEM_COLLECTIONURI") # noqa: N806 if SYSTEM_COLLECTIONURI and SYSTEM_COLLECTIONURI != "https://dev.azure.com/onnxruntime/": @@ -1621,12 +1627,12 @@ def generate_build_tree( if args.use_snpe: cmake_args += ["-Donnxruntime_USE_SNPE=ON"] - if args.macos or args.ios or args.visionos: + if args.macos or args.ios or args.visionos or args.tvos: # Note: Xcode CMake generator doesn't have a good support for Mac Catalyst yet. if args.macos == "Catalyst" and args.cmake_generator == "Xcode": raise BuildError("Xcode CMake generator ('--cmake_generator Xcode') doesn't support Mac Catalyst build.") - if (args.ios or args.visionos or args.macos == "MacOSX") and not args.cmake_generator == "Xcode": + if (args.ios or args.visionos or args.tvos or args.macos == "MacOSX") and not args.cmake_generator == "Xcode": raise BuildError( "iOS/MacOS framework build requires use of the Xcode CMake generator ('--cmake_generator Xcode')." ) @@ -1686,6 +1692,16 @@ def generate_build_tree( ), "-Donnxruntime_ENABLE_CPUINFO=OFF", ] + if args.tvos: + cmake_args += [ + "-DCMAKE_SYSTEM_NAME=tvOS", + "-DCMAKE_TOOLCHAIN_FILE=" + + ( + args.tvos_toolchain_file + if args.tvos_toolchain_file + else "../cmake/onnxruntime_tvos.toolchain.cmake" + ), + ] if args.build_wasm: if not args.use_vcpkg: @@ -3148,7 +3164,7 @@ def main(): if is_macOS(): if ( - not (args.ios or args.visionos) + not (args.ios or args.visionos or args.tvos) and args.macos != "Catalyst" and not args.android and args.osx_arch == "arm64" diff --git a/tools/ci_build/github/apple/default_full_tvos_framework_build_settings.json b/tools/ci_build/github/apple/default_full_tvos_framework_build_settings.json new file mode 100644 index 0000000000000..00f00f86f627c --- /dev/null +++ b/tools/ci_build/github/apple/default_full_tvos_framework_build_settings.json @@ -0,0 +1,30 @@ +{ + "build_osx_archs": { + "appletvos": [ + "arm64" + ], + "appletvsimulator": [ + "arm64", + "x86_64" + ] + }, + "build_params": { + "base": [ + "--parallel", + "--build_apple_framework", + "--use_coreml", + "--skip_tests", + "--cmake_extra_defines=onnxruntime_BUILD_UNIT_TESTS=OFF" + ], + "appletvos": [ + "--tvos", + "--use_xcode", + "--apple_deploy_target=15.1" + ], + "appletvsimulator": [ + "--tvos", + "--use_xcode", + "--apple_deploy_target=15.1" + ] + } +} From cb3f631fed03376ebd0a5ffdf9038078769a05bf Mon Sep 17 00:00:00 2001 From: Yifan Li <109183385+yf711@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:17:27 -0700 Subject: [PATCH 096/266] [TensorRT EP] Stop enforcing oss parser during Windows debug build (#24036) ### Description Reverting as this issue disappeared after adapting newer TRT api. This has been validated by building ORT 1.20.1/1.21.0 debug build and testing on FRCNN/resnet50 models. ### Motivation and Context --- cmake/onnxruntime_providers_tensorrt.cmake | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cmake/onnxruntime_providers_tensorrt.cmake b/cmake/onnxruntime_providers_tensorrt.cmake index 7fa5ba5f7f8d4..1f7700fa7bc36 100644 --- a/cmake/onnxruntime_providers_tensorrt.cmake +++ b/cmake/onnxruntime_providers_tensorrt.cmake @@ -28,18 +28,10 @@ endif() set(CXX_VERSION_DEFINED TRUE) - # There is an issue when running "Debug build" TRT EP with "Release build" TRT builtin parser on Windows. - # We enforce following workaround for now until the real fix. - if (WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug") - set(onnxruntime_USE_TENSORRT_BUILTIN_PARSER OFF) - MESSAGE(STATUS "[Note] There is an issue when running \"Debug build\" TRT EP with \"Release build\" TRT built-in parser on Windows. This build will use tensorrt oss parser instead.") - endif() - find_path(TENSORRT_INCLUDE_DIR NvInfer.h HINTS ${TENSORRT_ROOT} PATH_SUFFIXES include) - file(READ ${TENSORRT_INCLUDE_DIR}/NvInferVersion.h NVINFER_VER_CONTENT) string(REGEX MATCH "define NV_TENSORRT_MAJOR * +([0-9]+)" NV_TENSORRT_MAJOR "${NVINFER_VER_CONTENT}") string(REGEX REPLACE "define NV_TENSORRT_MAJOR * +([0-9]+)" "\\1" NV_TENSORRT_MAJOR "${NV_TENSORRT_MAJOR}") From 9a296a0a7a20d1c534a03e314d4beba9bd811503 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:25:47 -0700 Subject: [PATCH 097/266] Set CMAKE_POLICY_DEFAULT_CMP0069 to NEW to ensure that IPO flags are added for dependencies. (#24034) Set CMAKE_POLICY_DEFAULT_CMP0069 to NEW to ensure that interprocedural optimization (IPO) flags are added for dependencies. If the OLD behavior is used, the IPO flags are only added for the Intel compiler on Linux. --- cmake/adjust_global_compile_flags.cmake | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cmake/adjust_global_compile_flags.cmake b/cmake/adjust_global_compile_flags.cmake index d6f5a4dce5429..45ad3cd140a8a 100644 --- a/cmake/adjust_global_compile_flags.cmake +++ b/cmake/adjust_global_compile_flags.cmake @@ -99,10 +99,21 @@ if (onnxruntime_ENABLE_LTO) include(CheckIPOSupported) check_ipo_supported(RESULT ipo_enabled OUTPUT ipo_output) if (NOT ipo_enabled) - message(WARNING "IPO is not supported by this compiler") + message(WARNING "Interprocedural optimization (IPO) is not supported by this compiler. ${ipo_output}") set(onnxruntime_ENABLE_LTO OFF) else() set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) + + # See https://cmake.org/cmake/help/latest/policy/CMP0069.html. + # + # "The OLD behavior for this policy is to add IPO flags only for Intel compiler on Linux. + # The NEW behavior for this policy is to add IPO flags for the current compiler or produce an error if CMake does + # not know the flags." + # + # CMake versions 3.8 and lower use the OLD behavior. This project requires CMake version > 3.8. + # However, some dependencies may specify a lower required CMake version and default to the OLD behavior. + # Ensure that CMake also uses the NEW behavior for such dependencies. + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) endif() endif() @@ -342,4 +353,4 @@ endif() if (onnxruntime_USE_EXTENSIONS) include_directories(${REPO_ROOT}/include/onnxruntime/core/session) -endif() \ No newline at end of file +endif() From 9f214561c38a4a1a2039bc7058fc1cdfd6e3c148 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Fri, 14 Mar 2025 13:28:52 -0400 Subject: [PATCH 098/266] Make Cuda packaging pipeline 1ES compliant (#23806) ### Description Make [Cuda packaging pipeline](https://dev.azure.com/aiinfra/Lotus/_build?definitionId=1287&_a=summary) 1ES compliant ### Motivation and Context ### Check List - [x] pool `onnxruntime-Win-CPU-2022` not found --- .../c-api-noopenmp-packaging-pipelines.yml | 2 - .../cuda-packaging-pipeline.yml | 242 +++++------ .../nodejs/templates/test_linux.yml | 6 +- .../nodejs/templates/test_win.yml | 5 +- .../nuget/templates/test_linux.yml | 42 +- .../stages/c-api-linux-cpu-stage.yml | 11 + .../stages/download-java-tools-stage.yml | 5 +- .../stages/java-cuda-packaging-stage.yml | 8 +- .../stages/nuget-combine-cuda-stage.yml | 20 +- .../stages/nuget-cuda-packaging-stage.yml | 386 +++++++++--------- .../nuget-linux-cuda-packaging-stage.yml | 18 +- .../stages/nuget-win-cuda-packaging-stage.yml | 183 ++++----- .../stages/set_packaging_variables_stage.yml | 2 + ...ifacts-package-and-publish-steps-posix.yml | 44 +- ...acts-package-and-publish-steps-windows.yml | 4 +- .../azure-pipelines/templates/c-api-cpu.yml | 9 - .../templates/c-api-linux-cpu.yml | 120 +++--- .../templates/final-jar-testing.yml | 18 +- ...ifacts-package-and-publish-steps-posix.yml | 27 +- .../azure-pipelines/templates/win-ci.yml | 35 +- 20 files changed, 597 insertions(+), 590 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/stages/c-api-linux-cpu-stage.yml diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index 543b2cfd19894..4a5ba81943b40 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -95,7 +95,6 @@ stages: - template: templates/c-api-cpu.yml parameters: RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} IsReleaseBuild: ${{ parameters.IsReleaseBuild }} ${{ if eq(parameters.NugetPackageSuffix, 'NONE') }}: @@ -117,7 +116,6 @@ stages: - template: stages/nuget-combine-cuda-stage.yml parameters: - DoCompliance: ${{ parameters.DoCompliance }} CudaVersion: 11.8 RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} diff --git a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml index b24310ac0c3e0..6eb1e858a812b 100644 --- a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml @@ -1,125 +1,133 @@ parameters: - - name: RunOnnxRuntimeTests - displayName: Run Tests? - type: boolean - default: true - - - name: UseIncreasedTimeoutForTests - displayName: Increase timeout for tests? Set it to false if you are doing an Onnx Runtime release. - type: boolean - default: false - - - name: DoCompliance - displayName: Run Compliance Tasks? - type: boolean - default: true - - - name: DoEsrp - displayName: Run code sign tasks? Must be true if you are doing an ONNX Runtime release - type: boolean - default: true - - - name: IsReleaseBuild - displayName: Is a release build? Set it to true if you are doing an ONNX Runtime release. - type: boolean - default: false - - - name: PreReleaseVersionSuffixString - displayName: Suffix added to pre-release package version. Only used if IsReleaseBuild is true. Denotes the type of pre-release package. - type: string - values: - - alpha - - beta - - rc - - none - default: none - - - name: PreReleaseVersionSuffixNumber - displayName: Number added to pre-release package version. Only used if IsReleaseBuild is true. Denotes the sequence of a pre-release package. - type: number - default: 0 - - # these 2 parameters are used for debugging. - - name: SpecificArtifact - displayName: Use Specific Artifact (Debugging only) - type: boolean - default: false - - - name: BuildId - displayName: Pipeline BuildId, you could find it in the URL - type: string - default: '0' - - - name: CudaVersion - displayName: CUDA version - type: string - default: '12.2' - values: - - 11.8 - - 12.2 +- name: RunOnnxRuntimeTests + displayName: Run Tests? + type: boolean + default: true + +- name: UseIncreasedTimeoutForTests + displayName: Increase timeout for tests? Set it to false if you are doing an Onnx Runtime release. + type: boolean + default: false + +- name: DoEsrp + displayName: Run code sign tasks? Must be true if you are doing an ONNX Runtime release + type: boolean + default: true + +- name: IsReleaseBuild + displayName: Is a release build? Set it to true if you are doing an ONNX Runtime release. + type: boolean + default: false + +- name: PreReleaseVersionSuffixString + displayName: Suffix added to pre-release package version. Only used if IsReleaseBuild is true. Denotes the type of pre-release package. + type: string + values: + - alpha + - beta + - rc + - none + default: none + +- name: PreReleaseVersionSuffixNumber + displayName: Number added to pre-release package version. Only used if IsReleaseBuild is true. Denotes the sequence of a pre-release package. + type: number + default: 0 + +# these 2 parameters are used for debugging. +- name: SpecificArtifact + displayName: Use Specific Artifact (Debugging only) + type: boolean + default: false + +- name: BuildId + displayName: Pipeline BuildId, you could find it in the URL + type: string + default: '0' + +- name: CudaVersion + displayName: CUDA version + type: string + default: '12.2' + values: + - 11.8 + - 12.2 variables: - - template: templates/common-variables.yml - - name: ReleaseVersionSuffix - value: '' - - name: win_trt_home - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda11 }} - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda12 }} - - name: win_cuda_home - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: $(Agent.TempDirectory)\v11.8 - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: $(Agent.TempDirectory)\v12.2 +- template: templates/common-variables.yml +- name: ReleaseVersionSuffix + value: '' +- name: win_trt_home + ${{ if eq(parameters.CudaVersion, '11.8') }}: + value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda11 }} + ${{ if eq(parameters.CudaVersion, '12.2') }}: + value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda12 }} +- name: win_cuda_home + ${{ if eq(parameters.CudaVersion, '11.8') }}: + value: $(Agent.TempDirectory)\v11.8 + ${{ if eq(parameters.CudaVersion, '12.2') }}: + value: $(Agent.TempDirectory)\v12.2 + resources: repositories: - - repository: onnxruntime-inference-examples # The name used to reference this repository in the checkout step - type: github - endpoint: ort-examples - name: microsoft/onnxruntime-inference-examples - - -stages: - # Set ReleaseVersionSuffix - - template: stages/set_packaging_variables_stage.yml - parameters: - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - PreReleaseVersionSuffixString: ${{ parameters.PreReleaseVersionSuffixString }} - PreReleaseVersionSuffixNumber: ${{ parameters.PreReleaseVersionSuffixNumber }} - - # this is needed for certain artifacts to be published - - stage: Linux_C_API_Packaging_CPU - dependsOn: [ ] - jobs: - - template: templates/c-api-linux-cpu.yml + - repository: onnxruntime-inference-examples # The name used to reference this repository in the checkout step + type: github + endpoint: ort-examples + name: microsoft/onnxruntime-inference-examples + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + sdl: + binskim: + enabled: true + analyzeTargetGlob: $(Build.ArtifactStagingDirectory)/**.dll + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + sourceRepositoriesToScan: + exclude: + - repository: onnxruntime-inference-examples + spotBugs: + enabled: false + justificationForDisabling: "Getting ##[error1. SpotBugs Error gdn.unknownFormatResult - File: spotbugs.xml, which indicates that SpotBugs found one or more errors, which are not handled by the Guardian right now." + stages: + # Set ReleaseVersionSuffix + - template: stages/set_packaging_variables_stage.yml parameters: - OnnxruntimeArch: 'x64' - OnnxruntimeNodejsBindingArch: 'x64' - PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' - PackageJava: false - PackageNodeJS: false - - # Nuget Packaging - - template: stages/nuget-combine-cuda-stage.yml - parameters: - DoCompliance: ${{ parameters.DoCompliance }} - CudaVersion: ${{ parameters.CudaVersion }} - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} - win_trt_home: ${{ variables.win_trt_home }} - win_cuda_home: ${{ variables.win_cuda_home }} - DoEsrp: ${{ parameters.DoEsrp }} - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - buildJava: true - buildNodejs: false - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + PreReleaseVersionSuffixString: ${{ parameters.PreReleaseVersionSuffixString }} + PreReleaseVersionSuffixNumber: ${{ parameters.PreReleaseVersionSuffixNumber }} - - template: stages/download-java-tools-stage.yml + # this is needed for certain artifacts to be published + - template: stages/c-api-linux-cpu-stage.yml - - template: stages/java-cuda-packaging-stage.yml - parameters: - CudaVersion: ${{ parameters.CudaVersion }} - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} + # Nuget Packaging + - template: stages/nuget-combine-cuda-stage.yml + parameters: + CudaVersion: ${{ parameters.CudaVersion }} + RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} + UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} + win_trt_home: ${{ variables.win_trt_home }} + win_cuda_home: ${{ variables.win_cuda_home }} + DoEsrp: ${{ parameters.DoEsrp }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + buildJava: true + buildNodejs: false + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + - template: stages/download-java-tools-stage.yml + + - template: stages/java-cuda-packaging-stage.yml + parameters: + CudaVersion: ${{ parameters.CudaVersion }} + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} diff --git a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml index 1d3e92056ebe2..c4102f5ba2b49 100644 --- a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml +++ b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml @@ -10,8 +10,10 @@ stages: - job: Nodejs_Test_${{ parameters.StageSuffix }} workspace: clean: all - timeoutInMinutes: 120 - pool: ${{ parameters.AgentPool }} + timeoutInMinutes: 120 + pool: + name: ${{ parameters.AgentPool }} + os: 'linux' variables: - name: OnnxRuntimeBuildDirectory diff --git a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_win.yml b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_win.yml index 667c4f2e70a63..5214a772f1a8f 100644 --- a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_win.yml +++ b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_win.yml @@ -10,8 +10,9 @@ stages: - job: Nodejs_Test_${{ parameters.StageSuffix }} workspace: clean: all - timeoutInMinutes: 120 - pool: ${{ parameters.AgentPool }} + timeoutInMinutes: 120 + pool: + name: ${{ parameters.AgentPool }} variables: - name: OnnxRuntimeBuildDirectory value: '$(Build.BinariesDirectory)' diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml index 8c6efe2c55e3a..26a6c685ffa66 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml @@ -1,7 +1,7 @@ parameters: AgentPool: 'onnxruntime-Ubuntu2204-AMD-CPU' ArtifactSuffix: '' - NugetPackageName : '' + NugetPackageName: '' StageSuffix: 'CPU' # More Suffix is used to differentiate testing for GPU and GPU-Windows/GPU-Linux packages MoreSuffix: '' @@ -20,7 +20,9 @@ stages: workspace: clean: all timeoutInMinutes: 120 - pool: ${{ parameters.AgentPool }} + pool: + name: ${{ parameters.AgentPool }} + os: 'linux' variables: - template: ../../templates/common-variables.yml @@ -91,24 +93,24 @@ stages: " displayName: 'Run Package Test' - ${{ else }}: - - task: CmdLine@2 - displayName: 'Create symlink for test models' - inputs: - script: | - ln -sf /data/models $(Build.BinariesDirectory) - - task: Bash@3 - displayName: 'Run Package Test' - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.sh' - arguments: '$(Build.BinariesDirectory)/nuget-artifact $(NuGetPackageVersionNumber)' - workingDirectory: $(Build.BinariesDirectory) - env: - OnnxRuntimeBuildDirectory: $(Build.BinariesDirectory) - DisableContribOps: $(DisableContribOps) - DisableMlOps: $(DisableMlOps) - IsReleaseBuild: $(IsReleaseBuild) - PACKAGENAME: ${{ parameters.NugetPackageName }} + - task: CmdLine@2 + displayName: 'Create symlink for test models' + inputs: + script: | + ln -sf /data/models $(Build.BinariesDirectory) + - task: Bash@3 + displayName: 'Run Package Test' + inputs: + targetType: filePath + filePath: '$(Build.SourcesDirectory)/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.sh' + arguments: '$(Build.BinariesDirectory)/nuget-artifact $(NuGetPackageVersionNumber)' + workingDirectory: $(Build.BinariesDirectory) + env: + OnnxRuntimeBuildDirectory: $(Build.BinariesDirectory) + DisableContribOps: $(DisableContribOps) + DisableMlOps: $(DisableMlOps) + IsReleaseBuild: $(IsReleaseBuild) + PACKAGENAME: ${{ parameters.NugetPackageName }} - template: ../../templates/component-governance-component-detection-steps.yml parameters: diff --git a/tools/ci_build/github/azure-pipelines/stages/c-api-linux-cpu-stage.yml b/tools/ci_build/github/azure-pipelines/stages/c-api-linux-cpu-stage.yml new file mode 100644 index 0000000000000..ee46d5dac2ff8 --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/stages/c-api-linux-cpu-stage.yml @@ -0,0 +1,11 @@ +stages: +- stage: Linux_C_API_Packaging_CPU + dependsOn: [] + jobs: + - template: ../templates/c-api-linux-cpu.yml + parameters: + OnnxruntimeArch: 'x64' + OnnxruntimeNodejsBindingArch: 'x64' + PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' + PackageJava: false + PackageNodeJS: false \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml b/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml index 49d73c699e7b7..7e5237b32bce2 100644 --- a/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml @@ -5,6 +5,7 @@ stages: - job: Download_Java_Tools pool: name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: linux steps: - checkout: none - task: CmdLine@2 @@ -17,11 +18,13 @@ stages: wget --tries=3 https://oss.sonatype.org/service/local/repositories/releases/content/com/google/protobuf/protobuf-java/3.21.7/protobuf-java-3.21.7.jar -P ./ popd workingDirectory: '$(Agent.TempDirectory)' - - task: PublishPipelineArtifact@1 + + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline Java Tools Artifact' inputs: targetPath: '$(Agent.TempDirectory)/java-tools' artifact: 'onnxruntime-java-tools' + - template: ../templates/component-governance-component-detection-steps.yml parameters : condition : 'succeeded' \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml index 82ac898906b9e..6c3407c09d463 100644 --- a/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml @@ -73,10 +73,10 @@ stages: SourceFolder: '$(Build.BinariesDirectory)\java-artifact\onnxruntime-java-win-x64' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact' inputs: - targetPath: '$(Build.ArtifactStagingDirectory)' + path: '$(Build.ArtifactStagingDirectory)' artifact: 'onnxruntime-java-gpu' - template: ../templates/component-governance-component-detection-steps.yml @@ -136,7 +136,9 @@ stages: Jar_Packaging_GPU workspace: clean: all - pool: 'Onnxruntime-Linux-GPU' + pool: + name: 'Onnxruntime-Linux-GPU-A10' + os: linux variables: - name: runCodesignValidationInjection value: false diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml index 9c7fbc24ab1b6..893bf3f1ec394 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml @@ -1,7 +1,4 @@ parameters: -- name: DoCompliance - type: boolean - - name: DoEsrp type: boolean @@ -53,7 +50,6 @@ stages: - template: nuget-cuda-packaging-stage.yml parameters: - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} IsReleaseBuild: ${{ parameters.IsReleaseBuild }} SpecificArtifact: ${{ parameters.SpecificArtifact }} @@ -61,8 +57,8 @@ stages: - template: ../nuget/templates/test_win.yml parameters: - AgentPool : 'onnxruntime-Win2022-GPU-A10' - NugetPackageName : 'Microsoft.ML.OnnxRuntime.Gpu' + AgentPool: 'onnxruntime-Win2022-GPU-A10' + NugetPackageName: 'Microsoft.ML.OnnxRuntime.Gpu' ArtifactSuffix: 'GPU' StageSuffix: 'GPU' Skipx86Tests: 'true' @@ -72,8 +68,8 @@ stages: - template: ../nuget/templates/test_win.yml parameters: - AgentPool : 'onnxruntime-Win2022-GPU-A10' - NugetPackageName : 'Microsoft.ML.OnnxRuntime.Gpu.Windows' + AgentPool: 'onnxruntime-Win2022-GPU-A10' + NugetPackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Windows' ArtifactSuffix: 'GPU' StageSuffix: 'GPU' MoreSuffix: '_Windows' @@ -84,21 +80,21 @@ stages: - template: ../nuget/templates/test_linux.yml parameters: - AgentPool : Onnxruntime-Linux-GPU-A10 + AgentPool: Onnxruntime-Linux-GPU-A10 ArtifactSuffix: 'GPU' StageSuffix: 'GPU' - NugetPackageName : 'Microsoft.ML.OnnxRuntime.Gpu' + NugetPackageName: 'Microsoft.ML.OnnxRuntime.Gpu' CudaVersion: ${{ parameters.CudaVersion }} SpecificArtifact: ${{ parameters.specificArtifact }} BuildId: ${{ parameters.BuildId }} - template: ../nuget/templates/test_linux.yml parameters: - AgentPool : Onnxruntime-Linux-GPU-A10 + AgentPool: Onnxruntime-Linux-GPU-A10 ArtifactSuffix: 'GPU' StageSuffix: 'GPU' MoreSuffix: '_Linux' - NugetPackageName : 'Microsoft.ML.OnnxRuntime.Gpu.Linux' + NugetPackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Linux' CudaVersion: ${{ parameters.CudaVersion }} SpecificArtifact: ${{ parameters.specificArtifact }} BuildId: ${{ parameters.BuildId }} diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml index 5ae60aac8f9b4..5c5b464fe24e2 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml @@ -1,7 +1,4 @@ parameters: -- name: DoCompliance - type: boolean - - name: DoEsrp type: boolean @@ -21,197 +18,198 @@ stages: # Win/Linux CUDA Combined packaging - stage: NuGet_Packaging_GPU dependsOn: - - Setup - - Windows_Packaging_CUDA - - Windows_Packaging_TensorRT - - Linux_C_API_Packaging_GPU -# This is need for Download Linux CustomOp TestData - - Linux_C_API_Packaging_CPU + - Setup + - Windows_Packaging_CUDA + - Windows_Packaging_TensorRT + - Linux_C_API_Packaging_GPU + # This is need for Download Linux CustomOp TestData + - Linux_C_API_Packaging_CPU condition: succeeded() jobs: - - job: NuGet_Packaging_GPU - workspace: - clean: all - pool: 'Onnxruntime-Win-CPU-2022' - variables: - breakCodesignValidationInjection: ${{ parameters.DoEsrp }} - ReleaseVersionSuffix: $[stageDependencies.Setup.Set_Variables.outputs['Set_Release_Version_Suffix.ReleaseVersionSuffix']] - BuildDate: $[format('{0:yyyyMMdd}', pipeline.startTime)] - BuildTime: $[format('{0:HHmm}', pipeline.startTime)] - - steps: - - checkout: self - submodules: true - - template: ../templates/flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline Artifact - NuGet' - ArtifactName: 'onnxruntime-win-x64-cuda' - TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - - template: ../templates/flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline Artifact - NuGet' - ArtifactName: 'onnxruntime-win-x64-tensorrt' - TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - - template: ../templates/flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline Artifact - NuGet' - ArtifactName: 'onnxruntime-linux-x64-cuda' - TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - - template: ../templates/flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline Artifact - NuGet' - ArtifactName: 'onnxruntime-linux-x64-tensorrt' - TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - # Reconstruct the build dir - - task: PowerShell@2 - displayName: 'PS: Extract nuget files gpu' - inputs: - targetType: filePath - filePath: $(Build.SourcesDirectory)\tools\ci_build\github\windows\extract_nuget_files_gpu.ps1 - - - script: | - dir - workingDirectory: '$(Build.BinariesDirectory)/nuget-artifact' - displayName: 'List artifacts' - - - script: | - mklink /D /J models C:\local\models - workingDirectory: '$(Build.BinariesDirectory)' - displayName: 'Create models link' - - - task: NuGetToolInstaller@0 - displayName: Use Nuget 6.10.x - inputs: - versionSpec: 6.10.x - - - task: MSBuild@1 - displayName: 'Restore NuGet Packages and create project.assets.json' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: RelWithDebInfo - msbuildArguments: '-t:restore -p:OrtPackageId="Microsoft.ML.OnnxRuntime.Gpu"' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - task: MSBuild@1 - displayName: 'Build C# bindings' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - configuration: RelWithDebInfo - platform: 'Any CPU' - msbuildArguments: > - -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" - -p:OrtPackageId="Microsoft.ML.OnnxRuntime.Gpu" - -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} - -p:ReleaseVersionSuffix=$(ReleaseVersionSuffix) - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - template: ../templates/win-esrp-dll.yml - parameters: - FolderPath: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo' - DisplayName: 'ESRP - Sign C# dlls' - DoEsrp: ${{ parameters.DoEsrp }} - - - task: UsePythonVersion@0 - displayName: 'Use Python' - inputs: - versionSpec: 3.12 - - - task: MSBuild@1 - displayName: 'Build Nuget Packages' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj' - configuration: RelWithDebInfo - platform: 'Any CPU' - msbuildArguments: '-t:CreatePackage -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} + - job: NuGet_Packaging_GPU + workspace: + clean: all + pool: + name: 'onnxruntime-Win-CPU-2022' + variables: + breakCodesignValidationInjection: ${{ parameters.DoEsrp }} + ReleaseVersionSuffix: $[stageDependencies.Setup.Set_Variables.outputs['Set_Release_Version_Suffix.ReleaseVersionSuffix']] + BuildDate: $[format('{0:yyyyMMdd}', pipeline.startTime)] + BuildTime: $[format('{0:HHmm}', pipeline.startTime)] + + steps: + - checkout: self + submodules: true + - template: ../templates/flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline Artifact - NuGet' + ArtifactName: 'onnxruntime-win-x64-cuda' + TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + - template: ../templates/flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline Artifact - NuGet' + ArtifactName: 'onnxruntime-win-x64-tensorrt' + TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + - template: ../templates/flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline Artifact - NuGet' + ArtifactName: 'onnxruntime-linux-x64-cuda' + TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + - template: ../templates/flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline Artifact - NuGet' + ArtifactName: 'onnxruntime-linux-x64-tensorrt' + TargetPath: '$(Build.BinariesDirectory)/nuget-artifact' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + # Reconstruct the build dir + - task: PowerShell@2 + displayName: 'PS: Extract nuget files gpu' + inputs: + targetType: filePath + filePath: $(Build.SourcesDirectory)\tools\ci_build\github\windows\extract_nuget_files_gpu.ps1 + + - script: | + dir + workingDirectory: '$(Build.BinariesDirectory)/nuget-artifact' + displayName: 'List artifacts' + + - script: | + mklink /D /J models C:\local\models + workingDirectory: '$(Build.BinariesDirectory)' + displayName: 'Create models link' + + - task: NuGetToolInstaller@0 + displayName: Use Nuget 6.10.x + inputs: + versionSpec: 6.10.x + + - task: MSBuild@1 + displayName: 'Restore NuGet Packages and create project.assets.json' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' + platform: 'Any CPU' + configuration: RelWithDebInfo + msbuildArguments: '-t:restore -p:OrtPackageId="Microsoft.ML.OnnxRuntime.Gpu"' + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - task: MSBuild@1 + displayName: 'Build C# bindings' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' + configuration: RelWithDebInfo + platform: 'Any CPU' + msbuildArguments: > + -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" + -p:OrtPackageId="Microsoft.ML.OnnxRuntime.Gpu" + -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} + -p:ReleaseVersionSuffix=$(ReleaseVersionSuffix) + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - template: ../templates/win-esrp-dll.yml + parameters: + FolderPath: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo' + DisplayName: 'ESRP - Sign C# dlls' + DoEsrp: ${{ parameters.DoEsrp }} + + - task: UsePythonVersion@0 + displayName: 'Use Python' + inputs: + versionSpec: 3.12 + + - task: MSBuild@1 + displayName: 'Build Nuget Packages' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj' + configuration: RelWithDebInfo + platform: 'Any CPU' + msbuildArguments: '-t:CreatePackage -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu -p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} -p:ReleaseVersionSuffix=$(ReleaseVersionSuffix) -p:CurrentDate=$(BuildDate) -p:CurrentTime=$(BuildTime)' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - task: BatchScript@1 - displayName: 'Add TensorRT header file to the native nuGet package' - inputs: - filename: $(Build.SourcesDirectory)\tools\ci_build\github\windows\bundle_nuget_with_native_headers.bat - workingFolder: $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo - - - task: CopyFiles@2 - displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - Contents: '*.snupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: CopyFiles@2 - displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - Contents: '*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: CopyFiles@2 - displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo' - Contents: '*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - template: ../templates/esrp_nuget.yml - parameters: - DisplayName: 'ESRP - sign NuGet package' - FolderPath: '$(Build.ArtifactStagingDirectory)' - DoEsrp: ${{ parameters.DoEsrp }} - - - template: ../templates/validate-package.yml - parameters: - PackageType: 'nuget' - PackagePath: '$(Build.ArtifactStagingDirectory)' - PlatformsSupported: 'win-x64,linux-x64' - # 1* stands for version number. we use it to filter Gpu.Windows and Gpu.Linux packages - PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.1*nupkg' - VerifyNugetSigning: false - - - template: ../templates/validate-package.yml - parameters: - PackageType: 'nuget' - PackagePath: '$(Build.ArtifactStagingDirectory)' - PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Windows.*nupkg' - PlatformsSupported: 'win-x64' - VerifyNugetSigning: false - - - template: ../templates/validate-package.yml - parameters: - PackageType: 'nuget' - PackagePath: '$(Build.ArtifactStagingDirectory)' - PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Linux.*nupkg' - PlatformsSupported: 'linux-x64' - VerifyNugetSigning: false - - - task: MSBuild@1 - displayName: 'Clean C#' - inputs: - solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' - platform: 'Any CPU' - configuration: RelWithDebInfo - msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu' - workingDirectory: '$(Build.SourcesDirectory)\csharp' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline NuGet Artifact' - inputs: - artifactName: 'drop-signed-nuget-GPU' - targetPath: '$(Build.ArtifactStagingDirectory)' + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - task: BatchScript@1 + displayName: 'Add TensorRT header file to the native nuGet package' + inputs: + filename: $(Build.SourcesDirectory)\tools\ci_build\github\windows\bundle_nuget_with_native_headers.bat + workingFolder: $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo + + - task: CopyFiles@2 + displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' + Contents: '*.snupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - task: CopyFiles@2 + displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' + Contents: '*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - task: CopyFiles@2 + displayName: 'Copy nuget packages to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo' + Contents: '*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - template: ../templates/esrp_nuget.yml + parameters: + DisplayName: 'ESRP - sign NuGet package' + FolderPath: '$(Build.ArtifactStagingDirectory)' + DoEsrp: ${{ parameters.DoEsrp }} + + - template: ../templates/validate-package.yml + parameters: + PackageType: 'nuget' + PackagePath: '$(Build.ArtifactStagingDirectory)' + PlatformsSupported: 'win-x64,linux-x64' + # 1* stands for version number. we use it to filter Gpu.Windows and Gpu.Linux packages + PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.1*nupkg' + VerifyNugetSigning: false + + - template: ../templates/validate-package.yml + parameters: + PackageType: 'nuget' + PackagePath: '$(Build.ArtifactStagingDirectory)' + PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Windows.*nupkg' + PlatformsSupported: 'win-x64' + VerifyNugetSigning: false + + - template: ../templates/validate-package.yml + parameters: + PackageType: 'nuget' + PackagePath: '$(Build.ArtifactStagingDirectory)' + PackageName: 'Microsoft.ML.OnnxRuntime.Gpu.Linux.*nupkg' + PlatformsSupported: 'linux-x64' + VerifyNugetSigning: false + + - task: MSBuild@1 + displayName: 'Clean C#' + inputs: + solution: '$(Build.SourcesDirectory)\csharp\OnnxRuntime.DesktopOnly.CSharp.sln' + platform: 'Any CPU' + configuration: RelWithDebInfo + msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu' + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - template: ../templates/component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' + + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline NuGet Artifact' + inputs: + artifactName: 'drop-signed-nuget-GPU' + targetPath: '$(Build.ArtifactStagingDirectory)' diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml index 6e9e3c80a298c..06576ac05569e 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml @@ -15,7 +15,9 @@ stages: workspace: clean: all timeoutInMinutes: 150 - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + pool: + name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: linux variables: - name: CUDA_VERSION_MAJOR ${{ if eq(parameters.CudaVersion, '11.8') }}: @@ -48,6 +50,7 @@ stages: version: '$(OnnxRuntimeVersion)' libraryName: 'libonnxruntime.so' nativeLibraryName: 'libonnxruntime4j_jni.so' + is1ES: true - template: ../templates/c-api-artifacts-package-and-publish-steps-posix.yml parameters: @@ -66,7 +69,9 @@ stages: workspace: clean: all timeoutInMinutes: 180 - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + pool: + name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: linux variables: - template: ../templates/common-variables.yml - name: CUDA_VERSION_MAJOR @@ -109,6 +114,7 @@ stages: version: '$(OnnxRuntimeVersion)' libraryName: 'libonnxruntime.so' nativeLibraryName: 'libonnxruntime4j_jni.so' + is1ES: true - ${{ if eq(parameters.buildNodejs, 'true') }}: - template: ../templates/nodejs-artifacts-package-and-publish-steps-posix.yml @@ -138,7 +144,9 @@ stages: condition: succeeded() workspace: clean: all - pool: 'Onnxruntime-Linux-GPU' + pool: + name: 'Onnxruntime-Linux-GPU-A10' + os: linux variables: - template: ../templates/common-variables.yml - name: CUDA_VERSION_MAJOR @@ -218,9 +226,9 @@ stages: /src_dir/onnxruntime-inference-examples/c_cxx/squeezenet/run_capi_application.sh -o /src_dir/onnxruntime -p /artifact_src/onnxruntime-linux-x64-gpu-$(OnnxRuntimeVersion).tgz -w /src_dir/onnxruntime-inference-examples/c_cxx/squeezenet workingDirectory: '$(Build.ArtifactStagingDirectory)' - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: - targetPath: '$(Build.ArtifactStagingDirectory)/onnxruntime-linux-x64-gpu-$(OnnxRuntimeVersion).tgz' + targetPath: '$(Build.ArtifactStagingDirectory)' artifactName: 'onnxruntime-linux-x64-gpu' - template: ../templates/component-governance-component-detection-steps.yml parameters: diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml index bb6b52e16f165..53e4218ae6fd5 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml @@ -7,10 +7,6 @@ parameters: type: boolean default: false -- name: DoCompliance - type: boolean - default: true - - name: DoEsrp type: boolean default: true @@ -34,7 +30,7 @@ parameters: displayName: Specific Artifact's BuildId type: string default: '0' - + - name: buildJava type: boolean @@ -43,7 +39,6 @@ stages: - template: ../templates/win-ci.yml parameters: ort_build_pool_name: 'onnxruntime-Win2022-GPU-A10' - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} stage_name_suffix: CUDA buildArch: x64 @@ -61,7 +56,6 @@ stages: - template: ../templates/win-ci.yml parameters: ort_build_pool_name: 'onnxruntime-Win2022-GPU-A10' - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} stage_name_suffix: TensorRT buildArch: x64 @@ -79,93 +73,94 @@ stages: # Windows CUDA Combined Testing and Publishing - stage: Windows_Packaging_combined_GPU dependsOn: - - Windows_Packaging_CUDA - - Windows_Packaging_TensorRT + - Windows_Packaging_CUDA + - Windows_Packaging_TensorRT condition: succeeded() jobs: - - job: Windows_Packaging_combined_GPU - workspace: - clean: all - pool: 'onnxruntime-Win2022-GPU-A10' - variables: - CUDA_MODULE_LOADINGL: 'LAZY' - GRADLE_OPTS: '-Dorg.gradle.daemon=false' - steps: - - checkout: self # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/onnxruntime - - checkout: onnxruntime-inference-examples # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/onnxruntime-inference-examples - submodules: false - - - script: dir $(Build.SourcesDirectory) - - template: ../templates/jobs/download_win_gpu_library.yml - parameters: - DownloadCUDA: true - DownloadTRT: true - CudaVersion: ${{ parameters.CudaVersion }} - - - template: ../templates/set-version-number-variables-step.yml - parameters: - versionFileDirectory: '$(Build.SourcesDirectory)\onnxruntime' - workingDirectory: '$(Build.SourcesDirectory)\onnxruntime' - - task: DownloadPipelineArtifact@2 - displayName: 'Download Pipeline Artifact - onnxruntime-win-x64-cuda' - inputs: - artifactName: 'onnxruntime-win-x64-cuda' - targetPath: '$(Build.BinariesDirectory)/zip-artifacts' - - - task: DownloadPipelineArtifact@2 - displayName: 'Download Pipeline Artifact - onnxruntime-win-x64-tensorrt' - inputs: - artifactName: 'onnxruntime-win-x64-tensorrt' - targetPath: '$(Build.BinariesDirectory)/zip-artifacts' - - - task: PowerShell@2 - displayName: 'PowerShell Script' - inputs: - targetType: filePath - filePath: $(Build.SourcesDirectory)\onnxruntime\tools\ci_build\github\windows\extract_zip_files_gpu.ps1 - - - script: | - dir - workingDirectory: '$(Build.BinariesDirectory)/zip-artifacts' - displayName: 'List artifacts' - - - task: BatchScript@1 - displayName: 'Bundle CUDA/TRT EP binaries' - inputs: - filename: $(Build.SourcesDirectory)\onnxruntime\tools\ci_build\github\windows\bundle_dlls_gpu.bat - workingFolder: $(Build.BinariesDirectory)\zip-artifacts - - - task: CopyFiles@2 - displayName: 'Copy zip file to: $(Build.ArtifactStagingDirectory)' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\zip-artifacts' - Contents: 'onnxruntime-win-x64-gpu-*.zip' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - template: ../templates/validate-package.yml - parameters: - PackageType: 'zip' - PackagePath: '$(Build.ArtifactStagingDirectory)' - PackageName: 'onnxruntime-win-x64-gpu-$(OnnxRuntimeVersion).zip' - ScriptPath: '$(Build.SourcesDirectory)\onnxruntime\tools\nuget\validate_package.py' - PlatformsSupported: 'win-x64' - VerifyNugetSigning: false - workingDirectory: '$(Build.ArtifactStagingDirectory)' - - - task: BatchScript@1 - displayName: 'Test C API application for GPU package' - inputs: - filename: $(Build.SourcesDirectory)\onnxruntime-inference-examples\c_cxx\squeezenet\run_capi_application.bat - arguments: $(Build.SourcesDirectory)\onnxruntime $(Build.ArtifactStagingDirectory)\onnxruntime-win-x64-gpu-$(OnnxRuntimeVersion).zip $(Build.SourcesDirectory)\onnxruntime-inference-examples\c_cxx\squeezenet - workingFolder: '$(Build.ArtifactStagingDirectory)' - - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline Combined GPU Package Artifact' - inputs: - artifactName: 'onnxruntime-win-x64-gpu' - targetPath: '$(Build.ArtifactStagingDirectory)/onnxruntime-win-x64-gpu-$(OnnxRuntimeVersion).zip' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - job: Windows_Packaging_combined_GPU + workspace: + clean: all + pool: + name: 'onnxruntime-Win2022-GPU-A10' + variables: + CUDA_MODULE_LOADINGL: 'LAZY' + GRADLE_OPTS: '-Dorg.gradle.daemon=false' + steps: + - checkout: self # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/onnxruntime + - checkout: onnxruntime-inference-examples # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/onnxruntime-inference-examples + submodules: false + + - script: dir $(Build.SourcesDirectory) + - template: ../templates/jobs/download_win_gpu_library.yml + parameters: + DownloadCUDA: true + DownloadTRT: true + CudaVersion: ${{ parameters.CudaVersion }} + + - template: ../templates/set-version-number-variables-step.yml + parameters: + versionFileDirectory: '$(Build.SourcesDirectory)\onnxruntime' + workingDirectory: '$(Build.SourcesDirectory)\onnxruntime' + - task: DownloadPipelineArtifact@2 + displayName: 'Download Pipeline Artifact - onnxruntime-win-x64-cuda' + inputs: + artifactName: 'onnxruntime-win-x64-cuda' + targetPath: '$(Build.BinariesDirectory)/zip-artifacts' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download Pipeline Artifact - onnxruntime-win-x64-tensorrt' + inputs: + artifactName: 'onnxruntime-win-x64-tensorrt' + targetPath: '$(Build.BinariesDirectory)/zip-artifacts' + + - task: PowerShell@2 + displayName: 'PowerShell Script' + inputs: + targetType: filePath + filePath: $(Build.SourcesDirectory)\onnxruntime\tools\ci_build\github\windows\extract_zip_files_gpu.ps1 + + - script: | + dir + workingDirectory: '$(Build.BinariesDirectory)/zip-artifacts' + displayName: 'List artifacts' + + - task: BatchScript@1 + displayName: 'Bundle CUDA/TRT EP binaries' + inputs: + filename: $(Build.SourcesDirectory)\onnxruntime\tools\ci_build\github\windows\bundle_dlls_gpu.bat + workingFolder: $(Build.BinariesDirectory)\zip-artifacts + + - task: CopyFiles@2 + displayName: 'Copy zip file to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\zip-artifacts' + Contents: 'onnxruntime-win-x64-gpu-*.zip' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - template: ../templates/validate-package.yml + parameters: + PackageType: 'zip' + PackagePath: '$(Build.ArtifactStagingDirectory)' + PackageName: 'onnxruntime-win-x64-gpu-$(OnnxRuntimeVersion).zip' + ScriptPath: '$(Build.SourcesDirectory)\onnxruntime\tools\nuget\validate_package.py' + PlatformsSupported: 'win-x64' + VerifyNugetSigning: false + workingDirectory: '$(Build.ArtifactStagingDirectory)' + + - task: BatchScript@1 + displayName: 'Test C API application for GPU package' + inputs: + filename: $(Build.SourcesDirectory)\onnxruntime-inference-examples\c_cxx\squeezenet\run_capi_application.bat + arguments: $(Build.SourcesDirectory)\onnxruntime $(Build.ArtifactStagingDirectory)\onnxruntime-win-x64-gpu-$(OnnxRuntimeVersion).zip $(Build.SourcesDirectory)\onnxruntime-inference-examples\c_cxx\squeezenet + workingFolder: '$(Build.ArtifactStagingDirectory)' + + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline Combined GPU Package Artifact' + inputs: + artifactName: 'onnxruntime-win-x64-gpu' + targetPath: '$(Build.ArtifactStagingDirectory)' + + - template: ../templates/component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml b/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml index 2e4a673d72e00..8013396018ffa 100644 --- a/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml @@ -8,6 +8,7 @@ stages: - job: Set_Variables pool: name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: 'linux' steps: - checkout: none - bash: | @@ -48,6 +49,7 @@ stages: - job: D1 pool: name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: 'linux' variables: MyVar: $[stageDependencies.Setup.Set_Variables.outputs['Set_Release_Version_Suffix.ReleaseVersionSuffix']] BuildDate: $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Date.BuildDate']] diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-posix.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-posix.yml index 602510424c1a7..c8c20b6a15728 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-posix.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-posix.yml @@ -1,11 +1,11 @@ # sets up common build tools for the windows build machines before build parameters: -- name: buildConfig +- name: buildConfig type: string default: 'Release' -- name: artifactName +- name: artifactName type: string default: 'onnxruntime-linux-x64' @@ -13,28 +13,28 @@ parameters: type: string default: 'onnxruntime-linux-x64' -- name: libraryName +- name: libraryName type: string default: 'libonnxruntime.so' - + steps: - - task: ShellScript@2 - displayName: 'Copy build artifacts for zipping' - inputs: - scriptPath: 'tools/ci_build/github/linux/copy_strip_binary.sh' - args: '-r $(Build.BinariesDirectory) -a ${{parameters.artifactName}} -l ${{parameters.libraryName}} -c ${{parameters.buildConfig}} -s $(Build.SourcesDirectory) -t $(Build.SourceVersion)' - workingDirectory: '$(Build.BinariesDirectory)/${{parameters.buildConfig}}' +- task: ShellScript@2 + displayName: 'Copy build artifacts for zipping' + inputs: + scriptPath: 'tools/ci_build/github/linux/copy_strip_binary.sh' + args: '-r $(Build.BinariesDirectory) -a ${{parameters.artifactName}} -l ${{parameters.libraryName}} -c ${{parameters.buildConfig}} -s $(Build.SourcesDirectory) -t $(Build.SourceVersion)' + workingDirectory: '$(Build.BinariesDirectory)/${{parameters.buildConfig}}' - - task: ArchiveFiles@2 - inputs: - rootFolderOrFile: '$(Build.BinariesDirectory)/${{parameters.artifactName}}' - includeRootFolder: true - archiveType: 'tar' # Options: zip, 7z, tar, wim - tarCompression: 'gz' - archiveFile: '$(Build.ArtifactStagingDirectory)/${{parameters.artifactName}}.tgz' - replaceExistingArchive: true +- task: ArchiveFiles@2 + inputs: + rootFolderOrFile: '$(Build.BinariesDirectory)/${{parameters.artifactName}}' + includeRootFolder: true + archiveType: 'tar' # Options: zip, 7z, tar, wim + tarCompression: 'gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/${{parameters.artifactName}}.tgz' + replaceExistingArchive: true - - task: PublishPipelineArtifact@1 - inputs: - targetPath: '$(Build.ArtifactStagingDirectory)' - artifactName: '${{parameters.artifactNameNoVersionString}}' +- task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)' + artifactName: '${{parameters.artifactNameNoVersionString}}' diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml index e1a514ea54123..046c737a2b151 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-artifacts-package-and-publish-steps-windows.yml @@ -111,7 +111,7 @@ steps: archiveFile: '$(Build.ArtifactStagingDirectory)\${{parameters.artifactName}}.zip' replaceExistingArchive: true - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: - targetPath: '$(Build.ArtifactStagingDirectory)\${{parameters.artifactName}}.zip' + targetPath: '$(Build.ArtifactStagingDirectory)' artifactName: '${{parameters.artifactNameNoVersionString}}' diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index a6fe5ac27749b..abd781c2ea42a 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -3,12 +3,6 @@ parameters: displayName: Run Tests? type: boolean default: true - -- name: DoCompliance - displayName: Run Compliance Tasks? - type: boolean - default: true - - name: DoEsrp displayName: Run code sign tasks? Must be true if you are doing an Onnx Runtime release. type: boolean @@ -163,7 +157,6 @@ stages: - template: win-ci.yml parameters: - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} stage_name_suffix: CPU_x86_${{ parameters.BuildVariant }} buildArch: x86 @@ -176,7 +169,6 @@ stages: - template: win-ci.yml parameters: - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} stage_name_suffix: CPU_arm64_${{ parameters.BuildVariant }} buildArch: x64 @@ -189,7 +181,6 @@ stages: - template: win-ci.yml parameters: - DoCompliance: ${{ parameters.DoCompliance }} DoEsrp: ${{ parameters.DoEsrp }} stage_name_suffix: CPU_x64_${{ parameters.BuildVariant }} buildArch: x64 diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml index 330369ed0cc7a..e25ba88daa98a 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml @@ -35,68 +35,72 @@ jobs: workspace: clean: all - timeoutInMinutes: 210 - pool: ${{parameters.PoolName}} + timeoutInMinutes: 210 + pool: + name: ${{parameters.PoolName}} + os: linux + ${{ if eq(parameters.OnnxruntimeArch, 'aarch64') }}: + hostArchitecture: Arm64 steps: - - checkout: self - clean: true - submodules: none - - template: set-version-number-variables-step.yml - - ${{ if eq(parameters.OnnxruntimeArch, 'x64') }}: - - template: get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging - - - ${{ if eq(parameters.OnnxruntimeArch, 'aarch64') }}: - - template: get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging + - checkout: self + clean: true + submodules: none + - template: set-version-number-variables-step.yml + - ${{ if eq(parameters.OnnxruntimeArch, 'x64') }}: + - template: get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu + DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" + Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging - - task: CmdLine@2 - inputs: - script: | - set -e -x - mkdir -p $HOME/.onnx - docker run -e SYSTEM_COLLECTIONURI --rm --volume /data/onnx:/data/onnx:ro --volume $(Build.SourcesDirectory):/onnxruntime_src --volume $(Build.BinariesDirectory):/build \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx -e NIGHTLY_BUILD onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging /bin/bash -c "python3 \ - /onnxruntime_src/tools/ci_build/build.py --enable_lto --build_java --build_nodejs --build_dir /build --config Release \ - --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --use_vcpkg --use_vcpkg_ms_internal_asset_cache --build_shared_lib ${{ parameters.AdditionalBuildFlags }} && cd /build/Release && make install DESTDIR=/build/installed" - mkdir $(Build.ArtifactStagingDirectory)/testdata - cp $(Build.BinariesDirectory)/Release/libcustom_op_library.so* $(Build.ArtifactStagingDirectory)/testdata - ls -al $(Build.ArtifactStagingDirectory) - displayName: 'Create Artifacts' + - ${{ if eq(parameters.OnnxruntimeArch, 'aarch64') }}: + - template: get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu + DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" + Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging - - ${{ if eq(parameters.PackageJava, 'true') }}: - - template: java-api-artifacts-package-and-publish-steps-posix.yml - parameters: - arch: 'linux-${{parameters.OnnxruntimeArch}}' - buildConfig: 'Release' - artifactName: 'onnxruntime-java-linux-${{parameters.OnnxruntimeArch}}' - version: '$(OnnxRuntimeVersion)' - libraryName: 'libonnxruntime.so' - nativeLibraryName: 'libonnxruntime4j_jni.so' + - task: CmdLine@2 + inputs: + script: | + set -e -x + mkdir -p $HOME/.onnx + docker run -e SYSTEM_COLLECTIONURI --rm --volume /data/onnx:/data/onnx:ro --volume $(Build.SourcesDirectory):/onnxruntime_src --volume $(Build.BinariesDirectory):/build \ + --volume $HOME/.onnx:/home/onnxruntimedev/.onnx -e NIGHTLY_BUILD onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging /bin/bash -c "python3 \ + /onnxruntime_src/tools/ci_build/build.py --enable_lto --build_java --build_nodejs --build_dir /build --config Release \ + --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --use_vcpkg --use_vcpkg_ms_internal_asset_cache --build_shared_lib ${{ parameters.AdditionalBuildFlags }} && cd /build/Release && make install DESTDIR=/build/installed" + mkdir $(Build.ArtifactStagingDirectory)/testdata + cp $(Build.BinariesDirectory)/Release/libcustom_op_library.so* $(Build.ArtifactStagingDirectory)/testdata + ls -al $(Build.ArtifactStagingDirectory) + displayName: 'Create Artifacts' - - template: c-api-artifacts-package-and-publish-steps-posix.yml + - ${{ if eq(parameters.PackageJava, 'true') }}: + - template: java-api-artifacts-package-and-publish-steps-posix.yml parameters: - buildConfig: 'Release' - artifactName: '${{parameters.ArtifactNamePrefix}}-linux-${{parameters.OnnxruntimeArch}}-$(OnnxRuntimeVersion)' - artifactNameNoVersionString: '${{parameters.ArtifactNamePrefix}}-linux-${{parameters.OnnxruntimeArch}}' - libraryName: 'libonnxruntime.so.$(OnnxRuntimeVersion)' + arch: 'linux-${{parameters.OnnxruntimeArch}}' + buildConfig: 'Release' + artifactName: 'onnxruntime-java-linux-${{parameters.OnnxruntimeArch}}' + version: '$(OnnxRuntimeVersion)' + libraryName: 'libonnxruntime.so' + nativeLibraryName: 'libonnxruntime4j_jni.so' - - ${{ if eq(parameters.PackageNodejs, 'true') }}: - - template: nodejs-artifacts-package-and-publish-steps-posix.yml - parameters: - arch: '${{parameters.OnnxruntimeNodejsBindingArch}}' - os: 'linux' - artifactName: 'drop-onnxruntime-nodejs-linux-${{parameters.OnnxruntimeArch}}' + - template: c-api-artifacts-package-and-publish-steps-posix.yml + parameters: + buildConfig: 'Release' + artifactName: '${{parameters.ArtifactNamePrefix}}-linux-${{parameters.OnnxruntimeArch}}-$(OnnxRuntimeVersion)' + artifactNameNoVersionString: '${{parameters.ArtifactNamePrefix}}-linux-${{parameters.OnnxruntimeArch}}' + libraryName: 'libonnxruntime.so.$(OnnxRuntimeVersion)' - - ${{ if not(eq(parameters.OnnxruntimeNodejsBindingArch, 'arm64')) }}: - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - ${{ if eq(parameters.PackageNodejs, 'true') }}: + - template: nodejs-artifacts-package-and-publish-steps-posix.yml + parameters: + arch: '${{parameters.OnnxruntimeNodejsBindingArch}}' + os: 'linux' + artifactName: 'drop-onnxruntime-nodejs-linux-${{parameters.OnnxruntimeArch}}' + + - ${{ if not(eq(parameters.OnnxruntimeNodejsBindingArch, 'arm64')) }}: + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml b/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml index 8ccba213af04a..d893cac8ef358 100644 --- a/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml +++ b/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml @@ -26,9 +26,17 @@ stages: clean: all ${{ if eq(parameters.OS, 'MacOS') }}: pool: - vmImage: ${{ parameters.PoolName }} - ${{ else }}: - pool: ${{ parameters.PoolName }} + name: 'Azure Pipelines' + image: macOS-13 + os: macOS + ${{ if eq(parameters.OS, 'Linux') }}: + pool: + name: ${{ parameters.PoolName }} + os: linux + ${{ if eq(parameters.OS, 'Windows') }}: + pool: + name: ${{ parameters.PoolName }} + os: windows variables: - name: runCodesignValidationInjection value: false @@ -88,6 +96,6 @@ stages: - template: use-xcode-version.yml - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/java-api-artifacts-package-and-publish-steps-posix.yml b/tools/ci_build/github/azure-pipelines/templates/java-api-artifacts-package-and-publish-steps-posix.yml index 6b469c1a2a551..1c4b0ae5f4137 100644 --- a/tools/ci_build/github/azure-pipelines/templates/java-api-artifacts-package-and-publish-steps-posix.yml +++ b/tools/ci_build/github/azure-pipelines/templates/java-api-artifacts-package-and-publish-steps-posix.yml @@ -7,15 +7,22 @@ parameters: libraryName: 'libonnxruntime.so' nativeLibraryName: 'libonnxruntime4j_jni.so' version: '' + is1ES: false steps: - - task: ShellScript@2 - displayName: 'Copy build artifacts for zipping' - inputs: - scriptPath: 'tools/ci_build/github/linux/java_copy_strip_binary.sh' - args: '-r $(Build.BinariesDirectory) -c ${{parameters.buildConfig}} -a ${{parameters.artifactName}} -l ${{parameters.libraryName}} -n ${{parameters.nativeLibraryName}} -v ${{parameters.version}} -h ${{parameters.arch}}' - workingDirectory: '$(Build.BinariesDirectory)/${{parameters.buildConfig}}' +- task: ShellScript@2 + displayName: 'Copy build artifacts for zipping' + inputs: + scriptPath: 'tools/ci_build/github/linux/java_copy_strip_binary.sh' + args: '-r $(Build.BinariesDirectory) -c ${{parameters.buildConfig}} -a ${{parameters.artifactName}} -l ${{parameters.libraryName}} -n ${{parameters.nativeLibraryName}} -v ${{parameters.version}} -h ${{parameters.arch}}' + workingDirectory: '$(Build.BinariesDirectory)/${{parameters.buildConfig}}' - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: '$(Build.BinariesDirectory)/${{parameters.artifactName}}' - artifactName: 'drop-${{parameters.artifactName}}' +- ${{ if eq(parameters.is1ES, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.BinariesDirectory)/${{parameters.artifactName}}' + artifactName: 'drop-${{parameters.artifactName}}' +- ${{ if eq(parameters.is1ES, false) }}: + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: '$(Build.BinariesDirectory)/${{parameters.artifactName}}' + artifactName: 'drop-${{parameters.artifactName}}' diff --git a/tools/ci_build/github/azure-pipelines/templates/win-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-ci.yml index 69a06c3db24b8..e8a1395474634 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-ci.yml @@ -177,10 +177,10 @@ stages: ${{ else }}: buildOnly: false - - task: PublishBuildArtifacts@1 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Java temp binaries' inputs: - pathtoPublish: '$(Build.BinariesDirectory)\onnxruntime-java-win-${{ parameters.msbuildPlatform }}' + targetPath: '$(Build.BinariesDirectory)\onnxruntime-java-win-${{ parameters.msbuildPlatform }}' artifactName: 'drop-onnxruntime-java-win-${{ parameters.packageName }}${{parameters.artifact_name_suffix}}' # All GPU builds will be tested in the next stage with GPU machine - ${{ if contains(parameters.ort_build_pool_name, 'CPU') }}: @@ -213,11 +213,10 @@ stages: displayName: 'Copy java pad and folder for java test' workingDirectory: '$(Build.BinariesDirectory)' - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: targetPath: '$(Agent.TempDirectory)/RelWithDebInfo' artifactName: 'Windows_Packaging_${{ parameters.stage_name_suffix }}_build_artifacts' - publishLocation: 'pipeline' - script: | dir *.dll @@ -248,34 +247,6 @@ stages: Contents: 'custom_op_library.dll' TargetFolder: '$(Build.ArtifactStagingDirectory)/testdata' - - ${{ if eq(parameters['DoCompliance'], 'true') }}: - - task: CredScan@3 - displayName: 'Run CredScan' - inputs: - debugMode: false - continueOnError: true - - - task: BinSkim@4 - displayName: 'Run BinSkim' - inputs: - AnalyzeTargetGlob: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\**\*.dll' - continueOnError: true - - - task: PostAnalysis@2 - inputs: - GdnBreakAllTools: false - GdnBreakGdnToolBinSkim: true - GdnBreakPolicy: M365 - GdnBreakPolicyMinSev: Error - - - task: TSAUpload@2 - displayName: 'TSA upload' - condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) - inputs: - GdnPublishTsaOnboard: false - GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - continueOnError: true - - template: component-governance-component-detection-steps.yml parameters : condition : 'succeeded' From 7c05e7f561162c17de4899b5123bb1ec9e2d1988 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:42:01 -0700 Subject: [PATCH 099/266] [webgpu/wasm] allow runtime switch between WebGPUEP and JSEP (#24032) ### Description Add `--webgpu-ep=runtime` to allow build ort-web with both WebGPUEP and JSEP, while at runtime use `globalThis.WEBGPU_EP` to switch between them. This change helps to do perf comparison between WebGPU EP and JSEP much easier. --- js/web/script/build.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/web/script/build.ts b/js/web/script/build.ts index 98e61c9f87fbb..6a9432c2b5acd 100644 --- a/js/web/script/build.ts +++ b/js/web/script/build.ts @@ -47,10 +47,13 @@ const DEBUG = process.env.npm_config_debug || args.debug; // boolean|'verbose'|' /** * --webgpu-ep * --no-webgpu-ep (default) + * --webgpu-ep=runtime * * Enable or disable the use of WebGPU EP. If enabled, the WebGPU EP will be used. If disabled, the WebGPU backend will * be used with JSEP. * + * If set to "runtime", it will be determined at runtime based on the value of `globalThis.WEBGPU_EP`. + * * (temporary) This flag is used to test the WebGPU EP integration. It will be removed in the future. */ const USE_WEBGPU_EP = process.env.npm_config_webgpu_ep ?? args['webgpu-ep'] ?? false; @@ -69,7 +72,7 @@ const DEFAULT_DEFINE = { 'BUILD_DEFS.DISABLE_WASM': 'false', 'BUILD_DEFS.DISABLE_WASM_PROXY': 'false', 'BUILD_DEFS.ENABLE_BUNDLE_WASM_JS': 'false', - 'BUILD_DEFS.USE_WEBGPU_EP': JSON.stringify(!!USE_WEBGPU_EP), + 'BUILD_DEFS.USE_WEBGPU_EP': USE_WEBGPU_EP === 'runtime' ? 'globalThis.WEBGPU_EP' : JSON.stringify(!!USE_WEBGPU_EP), 'BUILD_DEFS.IS_ESM': 'false', 'BUILD_DEFS.ESM_IMPORT_META_URL': 'undefined', From c9c8b48d64c45469665a6243021cd771316772f2 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:57:44 -0700 Subject: [PATCH 100/266] Move call to MLAS_CPUIDINFO::GetCPUIDInfo() out of MlasSQNBitGemmDispatchNeon initialization. (#24018) Move call to `MLAS_CPUIDINFO::GetCPUIDInfo()` out of `MlasSQNBitGemmDispatchNeon` initialization. Reduce binary size when MatMulNBits op is not included in the build. I believe the side effect of `MLAS_CPUIDINFO::GetCPUIDInfo()` (e.g., initializing a static object) prevents the linker from discarding the code in a build where the associated MLAS functions are unused. --- onnxruntime/core/mlas/lib/mlasi.h | 5 +- onnxruntime/core/mlas/lib/platform.cpp | 17 +++---- .../core/mlas/lib/qnbitgemm_kernel_neon.cpp | 50 ++++++++++++------- .../core/mlas/lib/qnbitgemm_kernel_neon.h | 1 + 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/onnxruntime/core/mlas/lib/mlasi.h b/onnxruntime/core/mlas/lib/mlasi.h index 0681b49252495..04ff3290503d3 100644 --- a/onnxruntime/core/mlas/lib/mlasi.h +++ b/onnxruntime/core/mlas/lib/mlasi.h @@ -1043,7 +1043,10 @@ extern const MLAS_FPQ4GEMM_DISPATCH MlasFpQ4GemmDispatchAvx512; struct MLAS_QNBIT_GEMM_DISPATCH; -extern const MLAS_QNBIT_GEMM_DISPATCH MlasSQNBitGemmDispatchNeon; +const MLAS_QNBIT_GEMM_DISPATCH& +GetMlasQNBitGemmDispatchNeon( + bool InitializeWithDotSupport +); extern const MLAS_QNBIT_GEMM_DISPATCH MlasSQNBitGemmDispatchAvx2; diff --git a/onnxruntime/core/mlas/lib/platform.cpp b/onnxruntime/core/mlas/lib/platform.cpp index 582c1ab944b98..44aee4a2b28d3 100644 --- a/onnxruntime/core/mlas/lib/platform.cpp +++ b/onnxruntime/core/mlas/lib/platform.cpp @@ -543,7 +543,6 @@ Return Value: this->SymmQgemmDispatch = &MlasSymmQgemmS8DispatchNeon; this->ConvSymU8S8Dispatch = &MlasConvSymU8DispatchNeon; this->ConvSymS8S8Dispatch = &MlasConvSymS8DispatchNeon; - this->QNBitGemmDispatch = &MlasSQNBitGemmDispatchNeon; this->RopeDispatch = &MlasRopeDispatchNeon; this->HGemmDispatch = &MlasHGemmDispatchNeon; this->SoftmaxDispatch = &MlasSoftmaxDispatchNeon; @@ -552,22 +551,16 @@ Return Value: // Check if the processor supports ASIMD dot product instructions. // - bool HasDotProductInstructions; - -#if defined(_WIN32) - HasDotProductInstructions = (IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) != 0); -#else - // Use the cpuinfo value which is read from sysctl and has some additional special cases. - // https://github.com/pytorch/cpuinfo/blob/959002f82d7962a473d8bf301845f2af720e0aa4/src/arm/mach/init.c#L369-L379 + // Note: // Do NOT use ID_AA64ISAR0_EL1. It causes illegal instruction errors on Mac M1 and ARMv8-A chips // as well as failing on other ARM chips as it is an EL1 level register that requires extra // privileges to read. // // uint64_t isar0_el1; // asm("mrs %[reg], ID_AA64ISAR0_EL1\n" : [reg] "=r"(isar0_el1) : :); - // HasDotProductInstructions = ((isar0_el1 >> 44) & 0xfu) == 0x1u; - HasDotProductInstructions = MLAS_CPUIDINFO::GetCPUIDInfo().HasArmNeonDot(); -#endif + // const bool HasDotProductInstructions = ((isar0_el1 >> 44) & 0xfu) == 0x1u; + + const bool HasDotProductInstructions = MLAS_CPUIDINFO::GetCPUIDInfo().HasArmNeonDot(); if (HasDotProductInstructions) { this->GemmU8U8Dispatch = &MlasGemmU8X8DispatchUdot; @@ -578,6 +571,8 @@ Return Value: this->ConvSymS8S8Dispatch = &MlasConvSymS8DispatchDot; } + this->QNBitGemmDispatch = &GetMlasQNBitGemmDispatchNeon(HasDotProductInstructions); + #if defined(__linux__) // // Check if the processor supports ASIMD I8MM instructions. diff --git a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp index d05de64e68ec8..748ad8b9ba1a0 100644 --- a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp +++ b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp @@ -15,12 +15,13 @@ Module Name: --*/ +#include "qnbitgemm_kernel_neon.h" + #include #include #include "qnbitgemm.h" -#include "qnbitgemm_kernel_neon.h" #include "sqnbitgemm_q8_block.h" namespace sqnbitgemm_neon @@ -172,30 +173,41 @@ Q4BitGemmPerGemmWorkspaceAlignment( } // namespace sqnbitgemm_neon // -// Kernel dispatch structure definition. +// Kernel dispatch structure accessor. // -const MLAS_QNBIT_GEMM_DISPATCH MlasSQNBitGemmDispatchNeon = []() { - MLAS_QNBIT_GEMM_DISPATCH d; +const MLAS_QNBIT_GEMM_DISPATCH& +GetMlasQNBitGemmDispatchNeon( + bool InitializeWithDotSupport +) +{ + // Note: The InitializeWithX parameters are only used in the invocation of this method that initializes the static + // MLAS_QNBIT_GEMM_DISPATCH instance. + + static const MLAS_QNBIT_GEMM_DISPATCH MlasQNBitGemmDispatchNeon = [&]() { + MLAS_QNBIT_GEMM_DISPATCH d; - d.Q4BitGemmPackQuantBDataSize = sqnbitgemm_neon::Q4BitGemmPackQuantBDataSize; - d.SQ4BitGemmPackQuantBData = sqnbitgemm_neon::SQ4BitGemmPackQuantBData; + d.Q4BitGemmPackQuantBDataSize = sqnbitgemm_neon::Q4BitGemmPackQuantBDataSize; + d.SQ4BitGemmPackQuantBData = sqnbitgemm_neon::SQ4BitGemmPackQuantBData; - d.Q4BitGemmPerGemmWorkspaceSize = sqnbitgemm_neon::Q4BitGemmPerGemmWorkspaceSize; - d.Q4BitGemmPerGemmWorkspaceAlignment = sqnbitgemm_neon::Q4BitGemmPerGemmWorkspaceAlignment; + d.Q4BitGemmPerGemmWorkspaceSize = sqnbitgemm_neon::Q4BitGemmPerGemmWorkspaceSize; + d.Q4BitGemmPerGemmWorkspaceAlignment = sqnbitgemm_neon::Q4BitGemmPerGemmWorkspaceAlignment; - d.SQ4BitGemmM1Kernel_CompFp32 = sqnbitgemm_neon::SQ4BitGemmM1Kernel_CompFp32; - d.SQ4BitBlkDequantBForSgemm_CompFp32 = sqnbitgemm_neon::SQ4BitBlkDequantBForSgemm_CompFp32; - if (MLAS_CPUIDINFO::GetCPUIDInfo().HasArmNeonDot()) { - d.SQ4BitGemmKernel_CompInt8 = sqnbitgemm_neon::SQ4BitGemmKernel_CompInt8; - } - d.QuantizeARow_CompInt8 = sqnbitgemm_neon::QuantizeARow_CompInt8; + d.SQ4BitGemmM1Kernel_CompFp32 = sqnbitgemm_neon::SQ4BitGemmM1Kernel_CompFp32; + d.SQ4BitBlkDequantBForSgemm_CompFp32 = sqnbitgemm_neon::SQ4BitBlkDequantBForSgemm_CompFp32; + if (InitializeWithDotSupport) { + d.SQ4BitGemmKernel_CompInt8 = sqnbitgemm_neon::SQ4BitGemmKernel_CompInt8; + } + d.QuantizeARow_CompInt8 = sqnbitgemm_neon::QuantizeARow_CompInt8; #if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) - d.HQ4BitGemmPackQuantBData = sqnbitgemm_neon::HQ4BitGemmPackQuantBData_CompFp16; - d.HQ4BitBlkDequantBForHgemm_CompFp16 = sqnbitgemm_neon::HQ4BitBlkDequantBForHgemm_CompFp16; - d.HQ4BitGemmKernel_CompFp16 = sqnbitgemm_neon::HQ4BitGemmKernel_CompFp16; + d.HQ4BitGemmPackQuantBData = sqnbitgemm_neon::HQ4BitGemmPackQuantBData_CompFp16; + d.HQ4BitBlkDequantBForHgemm_CompFp16 = sqnbitgemm_neon::HQ4BitBlkDequantBForHgemm_CompFp16; + d.HQ4BitGemmKernel_CompFp16 = sqnbitgemm_neon::HQ4BitGemmKernel_CompFp16; #endif // MLAS_F16VEC_INTRINSICS_SUPPORTED && MLAS_TARGET_ARM64 - return d; -}(); + return d; + }(); + + return MlasQNBitGemmDispatchNeon; +} diff --git a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h index ccadd24ac1991..ce9f0fe6d939d 100644 --- a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h +++ b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h @@ -23,6 +23,7 @@ Module Name: #include #include +#include "mlas_qnbit.h" #include "mlasi.h" namespace sqnbitgemm_neon From cc5840be0a502a2e816911a9b1db8b8e9747b3b1 Mon Sep 17 00:00:00 2001 From: xhcao Date: Sat, 15 Mar 2025 02:22:28 +0800 Subject: [PATCH 101/266] [webgpu] fix the wrong dispatch size in flash_attention (#24020) ### Description ### Motivation and Context Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 7e4dbe2a111cd..58ddf60df79f0 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -98,7 +98,7 @@ Status CopyKVCache(onnxruntime::webgpu::ComputeContext& context, const WebgpuAtt program.AddOutputs({{present_key, ProgramTensorMetadataDependency::Rank, components}, {present_value, ProgramTensorMetadataDependency::Rank, components}}) .AddIndices(std::move(valid_present_shape)); - program.SetDispatchGroupSize(onnxruntime::narrow(valid_kv_size + 63 / 64)) + program.SetDispatchGroupSize(onnxruntime::narrow((valid_kv_size + 63) / 64)) .SetWorkgroupSize(64) .CacheHint(has_past, parameters.qkv_format_, parameters.past_present_share_buffer_) .AddUniformVariables({{static_cast(valid_kv_size)}, From 41c239dfed8507e116cb3b2d693372c99ef736e2 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 14 Mar 2025 11:23:04 -0700 Subject: [PATCH 102/266] avoid copy unnecessary files for nodejs pkg (#23992) ### Description remove duplicated file in nodejs package. #23956 --- tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index abd781c2ea42a..c4559d4e0b918 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -684,7 +684,7 @@ stages: inputs: SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-linux-x64-tensorrt\lib' Contents: | - libonnxruntime.so.* + libonnxruntime.so.1 libonnxruntime_providers_shared.so TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\x64' - task: CopyFiles@2 @@ -699,7 +699,7 @@ stages: displayName: 'Copy nuget binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64\' inputs: SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-linux-aarch64\lib' - Contents: 'libonnxruntime.so.*' + Contents: 'libonnxruntime.so.1' TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64' - task: CopyFiles@2 displayName: 'Copy nodejs binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64\' From 5a694bcbc8bd549f24b7cd4e88cbacb4f42b894a Mon Sep 17 00:00:00 2001 From: derdeljan-msft Date: Fri, 14 Mar 2025 19:36:42 +0100 Subject: [PATCH 103/266] Add support for custom position ids and attention bias to GQA CPU operator (#23944) ### Description - Added support for custom position ids and attention masks to the GQA CPU operator (fp32 and fp16) - Added MLAS eltwise add kernel for mask application for FP32 and FP16 - Added unit tests for the added eltwise add MLAS kernel - Modified python tests to test the new GQA inputs ### Motivation and Context Custom position ids and attention mask are required in order to implement speculative decoding in PhiSilica ### Benchmarks All the benchmarks are executed on the GQA op configuration which will be used in the PhiSilica speculative decoding secnario, and the configuration is as follows: - num_heads: 32 - kv_num_heads: 32 - do_rotary: 1 - local_window_size: -1 - head_size: 96 - sequence_length: 6 - packed_qkv: True Benchmarks were executed on Cadmus with Snapdragon(R) X 12-core X1E80100 @ 3.40 GHz In the tables below, column headers are total sequence length values used for benchmarking, and the row values are if the attention bias was used or not. Values are average inference time in ms over 100000 runs. #### Fp16 results | Total sequence length | 50 | 100 | 250 | 500 | 750 | 1000 | 1500 | 2000 | 2500 | 3000 | 3500 | 4000 | |:-----------------|:---------|:---------|:---------|:---------|:---------|:---------|:---------|:--------|:--------|:--------|:--------|:--------| | Without bias | 0.284054 | 0.257449 | 0.275806 | 0.334123 | 0.458324 | 0.614133 | 0.912791 | 1.38585 | 1.92186 | 2.39203 | 2.88808 | 3.46262 | | With bias | 0.250926 | 0.253072 | 0.279724 | 0.337774 | 0.499058 | 0.585388 | 0.914316 | 1.40701 | 1.87311 | 2.47475 | 3.3906 | 3.47474 | | Runtime increase | -11.66% | -1.7% | +1.42% | +1.09% | +8.89% | -4.68% | +0.17% | +1.53% | -2.54% | +3.46% | +17.4% | +0.35% | #### Fp32 results | Total sequence length | 50 | 100 | 250 | 500 | 750 | 1000 | 1500 | 2000 | 2500 | 3000 | 3500 | 4000 | |:-----------------|:---------|:---------|:---------|:---------|:---------|:---------|:--------|:--------|:--------|:--------|:--------|:--------| | Without bias | 0.259049 | 0.270541 | 0.304583 | 0.376708 | 0.554013 | 0.633217 | 1.20696 | 1.65985 | 1.95169 | 2.45807 | 3.05637 | 4.05169 | | With bias | 0.261631 | 0.268002 | 0.300853 | 0.370452 | 0.529865 | 0.735216 | 1.43493 | 1.4385 | 1.99028 | 2.3858 | 2.99425 | 4.80197 | | Runtime increase | +1.0% | -0.94% | -1.22% | -1.66% | -4.36% | +16.11% | +18.89% | -13.34% | +1.98% | -2.94% | -2.03% | +18.52% | --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- cmake/onnxruntime_mlas.cmake | 9 + docs/ContribOperators.md | 6 +- docs/OperatorKernels.md | 6 +- .../contrib_ops/cpu/bert/attention_helper.h | 5 + .../contrib_ops/cpu/bert/gqa_attention_base.h | 127 +++-- .../cpu/bert/group_query_attention.cc | 28 +- .../cpu/bert/group_query_attention_helper.h | 44 ++ .../core/graph/contrib_ops/bert_defs.cc | 11 + onnxruntime/core/mlas/inc/mlas.h | 10 + onnxruntime/core/mlas/lib/eltwise.cpp | 71 +++ onnxruntime/core/mlas/lib/eltwise.h | 37 ++ .../core/mlas/lib/eltwise_kernel_neon.cpp | 32 ++ .../core/mlas/lib/eltwise_kernel_neon.h | 28 ++ .../mlas/lib/eltwise_kernel_neon_fp16.cpp | 118 +++++ onnxruntime/core/mlas/lib/mlasi.h | 5 + onnxruntime/core/mlas/lib/platform.cpp | 1 + .../test/mlas/unittest/test_eltwise.cpp | 106 ++++ .../test/python/transformers/test_gqa_cpu.py | 466 +++++++++++++----- 18 files changed, 944 insertions(+), 166 deletions(-) create mode 100644 onnxruntime/core/mlas/lib/eltwise.cpp create mode 100644 onnxruntime/core/mlas/lib/eltwise.h create mode 100644 onnxruntime/core/mlas/lib/eltwise_kernel_neon.cpp create mode 100644 onnxruntime/core/mlas/lib/eltwise_kernel_neon.h create mode 100644 onnxruntime/core/mlas/lib/eltwise_kernel_neon_fp16.cpp create mode 100644 onnxruntime/test/mlas/unittest/test_eltwise.cpp diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index 15864a0198161..87387d4f281ed 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -27,6 +27,8 @@ onnxruntime_add_static_library(onnxruntime_mlas ${MLAS_SRC_DIR}/activate.cpp ${MLAS_SRC_DIR}/logistic.cpp ${MLAS_SRC_DIR}/tanh.cpp + ${MLAS_SRC_DIR}/eltwise.h + ${MLAS_SRC_DIR}/eltwise.cpp ${MLAS_SRC_DIR}/erf.cpp ${MLAS_SRC_DIR}/compute.cpp ${MLAS_SRC_DIR}/quantize.cpp @@ -101,6 +103,9 @@ function(setup_mlas_source_for_windows) ${MLAS_SRC_DIR}/softmax_kernel_neon.h ${MLAS_SRC_DIR}/softmax_kernel_neon.cpp ${MLAS_SRC_DIR}/softmax_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon.h + ${MLAS_SRC_DIR}/eltwise_kernel_neon.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon_fp16.cpp ) set(mlas_platform_preprocess_srcs @@ -387,6 +392,8 @@ else() ${MLAS_SRC_DIR}/hgemm_kernel_neon.cpp ${MLAS_SRC_DIR}/softmax_kernel_neon.h ${MLAS_SRC_DIR}/softmax_kernel_neon.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon.h + ${MLAS_SRC_DIR}/eltwise_kernel_neon.cpp ) set_source_files_properties(${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+dotprod") @@ -409,6 +416,7 @@ else() ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon_fp16.cpp ${MLAS_SRC_DIR}/halfgemm_kernel_neon_fp16.cpp ${MLAS_SRC_DIR}/softmax_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon_fp16.cpp ) set_source_files_properties(${MLAS_SRC_DIR}/aarch64/HalfGemmKernelNeon.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/aarch64/QgemmS8S8KernelSmmla.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+i8mm ") @@ -423,6 +431,7 @@ else() set_source_files_properties(${MLAS_SRC_DIR}/rotary_embedding_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/halfgemm_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/softmax_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") + set_source_files_properties(${MLAS_SRC_DIR}/eltwise_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") endif() if(ONNXRUNTIME_MLAS_MULTI_ARCH) diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index 274531faaf717..f85ed1e5f146c 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -2551,7 +2551,7 @@ This version of the operator has been available since version 1 of the 'com.micr
Softcap value for attention weights. Default value is 0.
-#### Inputs (7 - 9) +#### Inputs (7 - 11)
query : T
@@ -2572,6 +2572,10 @@ This version of the operator has been available since version 1 of the 'com.micr
2D tensor with shape (max_sequence_length, head_size / 2).
sin_cache (optional) : T
2D tensor with shape (max_sequence_length, head_size / 2).
+
position_ids (optional) : tensor(int64)
+
2D tensor with shape (batch_size, sequence_length). When processing the first prompt the kernel uses only the first element
+
attention_bias (optional) : T
+
additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
#### Outputs diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 84b9c7c9fc174..1dd145463367b 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -520,7 +520,7 @@ Do not modify directly.* |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |GreedySearch|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*out* sequences:**I**|1+|**T** = tensor(float)| |GridSample|*in* X:**T1**
*in* Grid:**T1**
*out* Y:**T2**|1+|**T1** = tensor(float)
**T2** = tensor(float)| -|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |Inverse|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |MatMulBnb4|*in* A:**T1**
*in* B:**T2**
*in* absmax:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(uint8)| |MatMulFpQ4|*in* A:**T1**
*in* B:**T2**
*in* B_shape:**T3**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(uint8)
**T3** = tensor(int64)| @@ -922,7 +922,7 @@ Do not modify directly.* |GreedySearch|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*out* sequences:**I**|1+|**T** = tensor(float), tensor(float16)| |GridSample|*in* X:**T1**
*in* Grid:**T1**
*out* Y:**T2**|1+|**T1** = tensor(float)
**T2** = tensor(float)| |GroupNorm|*in* X:**T**
*in* gamma:**M**
*in* beta:**M**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| -|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(bfloat16), tensor(float16)| +|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(bfloat16), tensor(float16)| |Inverse|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |Irfft|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |LongformerAttention|*in* input:**T**
*in* weight:**T**
*in* bias:**T**
*in* mask:**T**
*in* global_weight:**T**
*in* global_bias:**T**
*in* global:**G**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| @@ -1399,7 +1399,7 @@ Do not modify directly.* |FusedMatMulActivation|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |GroupNorm|*in* X:**T**
*in* gamma:**M**
*in* beta:**M**
*out* Y:**T**|1+|**M** = tensor(float), tensor(float16)
**T** = tensor(float), tensor(float16)| -|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| |MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/attention_helper.h index 188fc6e43b5b5..ac32a4445f3ca 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_helper.h @@ -31,6 +31,11 @@ void ComputeAttentionSoftcapInplace(T* scores, int sequence_length, T softcap) { MlasComputeSoftcap(scores, scores, sequence_length, softcap); } +template +void ApplyAttentionBias(T* softmax_logits, const T* attention_mask, int N) { + MlasEltwiseAdd(softmax_logits, attention_mask, softmax_logits, N); +} + template void PrepareMask(const int32_t* mask_index, gsl::span mask_index_dims, diff --git a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h index 70d66e534ee8a..ff6cb8edc0231 100644 --- a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h @@ -50,6 +50,7 @@ class GQAAttentionBase { Status ApplyAttention(const T* Q, // Q data with shape BxNxSxH const T* K, // K data with shape BxN_kvxSxH const T* V, // V data with shape BxN_kvxSxH + const Tensor* attention_bias, // Attention bias to add to QxK' const Tensor* past_key, // past K input tensor (if not using past state) const Tensor* past_value, // past V input tensor (if not using past state) Tensor* output, // output tensor @@ -87,14 +88,18 @@ class GQAAttentionBase { const T* past_value_data = past_value != nullptr ? past_value->Data() : nullptr; T* present_value_data = present_value != nullptr ? present_value->MutableData() : nullptr; + const T* attention_bias_data = attention_bias != nullptr ? attention_bias->Data() : nullptr; + auto attention_bias_shape = attention_bias != nullptr ? attention_bias->Shape().GetDims() : gsl::span{}; + bool past_present_share_buffer = past_key_data == present_key_data && past_value_data == present_value_data; const T* k = packed_qkv ? Q + num_heads_ * sequence_length * head_size : K; if (gqa_mlas_supported) { - ComputeAttentionProbs(static_cast(attention_probs), Q, k, seqlens_k->Data(), batch_size, - sequence_length, seqlen_past_kv_cache, seqlen_present_kv_cache, head_size, past_key_data, - present_key_data, past_present_share_buffer, packed_qkv, is_prompt, tp, allocator); + ComputeAttentionProbs(static_cast(attention_probs), Q, k, seqlens_k->Data(), attention_bias_data, + batch_size, sequence_length, attention_bias_shape, seqlen_past_kv_cache, seqlen_present_kv_cache, + head_size, past_key_data, present_key_data, past_present_share_buffer, packed_qkv, is_prompt, + tp, allocator); // Compute the attentionScore * Value: out(B, N, S, H_v) = attention_probs(B, N, S, T) x V(B, N, T, H_v) const T* v = packed_qkv ? Q + (num_heads_ + kv_num_heads_) * sequence_length * head_size : V; @@ -104,9 +109,10 @@ class GQAAttentionBase { hidden_size, past_value_data, present_value_data, past_present_share_buffer, packed_qkv, is_prompt, tp, allocator); } else { - ComputeAttentionProbs(static_cast(attention_probs), Q, k, seqlens_k->Data(), batch_size, - sequence_length, seqlen_past_kv_cache, seqlen_present_kv_cache, head_size, past_key_data, - present_key_data, past_present_share_buffer, packed_qkv, is_prompt, tp, allocator); + ComputeAttentionProbs(static_cast(attention_probs), Q, k, seqlens_k->Data(), attention_bias_data, + batch_size, sequence_length, attention_bias_shape, seqlen_past_kv_cache, seqlen_present_kv_cache, + head_size, past_key_data, present_key_data, past_present_share_buffer, packed_qkv, is_prompt, + tp, allocator); // Compute the attentionScore * Value: out(B, N, S, H_v) = attention_probs(B, N, S, T) x V(B, N, T, H_v) const T* v = packed_qkv ? Q + (num_heads_ + kv_num_heads_) * sequence_length * head_size : V; @@ -126,22 +132,24 @@ class GQAAttentionBase { // attention_probs(B, N, S, T) = Softmax(attention_probs) // If T is float32, U is float32. If T is float16, U could be float16 or float32. template - void ComputeAttentionProbs(U* attention_probs, // output buffer with size BxNxSxT - const T* Q, // Q data. Its size is BxNxSxH - const T* K, // k data. Its size is BxNxLxH - const int32_t* seqlens_k, // total - 1 sequence lengths tensor - const size_t batch_size, // batch size of self-attention - const size_t sequence_length, // sequence length of self-attention (S) - const size_t past_buffer_sequence_length, // sequence length of past state - const size_t present_buffer_sequence_length, // sequence length of present state - const size_t head_size, // head size of self-attention - const T* past_key, // past key only - T* present_key, // present key only - const bool past_present_share_buffer, // whether present key and value share the same buffer - const bool packed_qkv, // whether Q, K, V are packed - const bool is_prompt, // whether it is prompt - ThreadPool* tp, // thread pool - AllocatorPtr allocator) const { // allocator for temporary buffer + void ComputeAttentionProbs(U* attention_probs, // output buffer with size BxNxSxT + const T* Q, // Q data. Its size is BxNxSxH + const T* K, // k data. Its size is BxNxLxH + const int32_t* seqlens_k, // total - 1 sequence lengths tensor + const T* attention_bias, // optional attention bias + const size_t batch_size, // batch size of self-attention + const size_t sequence_length, // sequence length of self-attention (S) + const gsl::span attention_bias_shape, // shape of the attention bias + const size_t past_buffer_sequence_length, // sequence length of past state + const size_t present_buffer_sequence_length, // sequence length of present state + const size_t head_size, // head size of self-attention + const T* past_key, // past key only + T* present_key, // present key only + const bool past_present_share_buffer, // whether present key and value share the same buffer + const bool packed_qkv, // whether Q, K, V are packed + const bool is_prompt, // whether it is prompt + ThreadPool* tp, // thread pool + AllocatorPtr allocator) const { // allocator for temporary buffer const ptrdiff_t packed_batch_stride = packed_qkv ? SafeInt(num_heads_ + 2 * kv_num_heads_) * sequence_length * head_size : SafeInt(0); @@ -189,6 +197,24 @@ class GQAAttentionBase { const ptrdiff_t output_offset = SafeInt(i) * sequence_length * present_buffer_sequence_length; U* output = attention_probs + output_offset; + // Compute attention bias offset based on the batch and head indexes + // Attention bias is of shape (B or 1, H or 1, S, T) so handle broadcasting + const T* attention_bias_thread = nullptr; + ptrdiff_t attention_total_seqlen = 0; + if (attention_bias != nullptr) { + ptrdiff_t attention_bias_offset = 0; + attention_total_seqlen = static_cast(attention_bias_shape[3]); + const ptrdiff_t attention_matrix_size = sequence_length * attention_total_seqlen; + if (attention_bias_shape[0] != 1) { + attention_bias_offset += SafeInt(batch_index) * attention_bias_shape[1] * attention_matrix_size; + } + if (attention_bias_shape[1] != 1) { + attention_bias_offset += SafeInt(head_index) * attention_matrix_size; + } + + attention_bias_thread = attention_bias + attention_bias_offset; + } + const T* k; if (packed_qkv) { k = K + packed_batch_stride * batch_index + kv_input_chunk_length * (head_index / kv_num_heads_factor); @@ -242,7 +268,15 @@ class GQAAttentionBase { U* output_softmax = output; for (size_t seq = 0; seq < sequence_length; seq++) { size_t seq_causal_length = past_seqlen + seq + 1; - if (local_window_size_ > 0 && seq_causal_length > static_cast(local_window_size_) + 1) { + + const bool should_apply_local_window = local_window_size_ > 0 && + seq_causal_length > static_cast(local_window_size_) + 1; + + const size_t start_offset = should_apply_local_window ? seq_causal_length - local_window_size_ - 1 : 0; + const size_t window_size = should_apply_local_window ? local_window_size_ + 1 : seq_causal_length; + + // Mask everything before local window, if local window should be applied + if (should_apply_local_window) { for (size_t total_seq_id = 0; total_seq_id < seq_causal_length - local_window_size_ - 1; total_seq_id++) { if constexpr (std::is_same::value) { output_softmax[total_seq_id] = 0.f; @@ -250,27 +284,34 @@ class GQAAttentionBase { output_softmax[total_seq_id] = MLFloat16::FromBits(static_cast(0)); } } - if (softcap_ > 0.f) { - ComputeAttentionSoftcapInplace(output_softmax + seq_causal_length - local_window_size_ - 1, - local_window_size_ + 1, static_cast(softcap_)); - } - if (use_smooth_softmax_) { - ComputeSmoothSoftmaxInplace(output_softmax + seq_causal_length - local_window_size_ - 1, 1, - local_window_size_ + 1, nullptr); + } + + if (softcap_ > 0.f) { + ComputeAttentionSoftcapInplace(output_softmax + start_offset, static_cast(window_size), + static_cast(softcap_)); + } + + // Add attention bias to QxK' if provided + // TODO (#23982): Implement bias addition during softmax computation in GQA CPU operator + if (attention_bias_thread != nullptr) { + if constexpr (std::is_same_v) { + ApplyAttentionBias(output_softmax + start_offset, attention_bias_thread + start_offset, + static_cast(window_size)); } else { - ComputeAttentionSoftmaxInplace(output_softmax + seq_causal_length - local_window_size_ - 1, 1, - local_window_size_ + 1, nullptr); + static_assert(std::is_same_v && std::is_same_v); + size_t bytes = window_size * sizeof(float); + auto attention_bias_thread_fp32 = static_cast(allocator->Alloc(bytes)); + BufferUniquePtr scratch_buffer(attention_bias_thread_fp32, BufferDeleter(allocator)); + + MlasConvertHalfToFloatBuffer(attention_bias_thread + start_offset, attention_bias_thread_fp32, window_size); + ApplyAttentionBias(output_softmax + start_offset, attention_bias_thread_fp32, static_cast(window_size)); } + } + + if (use_smooth_softmax_) { + ComputeSmoothSoftmaxInplace(output_softmax + start_offset, 1, static_cast(window_size), nullptr); } else { - if (softcap_ > 0.f) { - ComputeAttentionSoftcapInplace(output_softmax, static_cast(seq_causal_length), - static_cast(softcap_)); - } - if (use_smooth_softmax_) { - ComputeSmoothSoftmaxInplace(output_softmax, 1, static_cast(seq_causal_length), nullptr); - } else { - ComputeAttentionSoftmaxInplace(output_softmax, 1, static_cast(seq_causal_length), nullptr); - } + ComputeAttentionSoftmaxInplace(output_softmax + start_offset, 1, static_cast(window_size), nullptr); } // set causal [seq_causal_length, total_seqlen) to 0.f @@ -283,6 +324,10 @@ class GQAAttentionBase { } output_softmax += present_buffer_sequence_length; + + if (attention_bias_thread != nullptr) { + attention_bias_thread += attention_total_seqlen; + } } } }); diff --git a/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc index 8f662cd388c6d..9c7530f0126bb 100644 --- a/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc @@ -52,6 +52,8 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { const Tensor* total_seqlen_tensor = context->Input(6); const Tensor* cos_cache = context->Input(7); const Tensor* sin_cache = context->Input(8); + const Tensor* position_ids = context->Input(9); + const Tensor* attention_bias = context->Input(10); GroupQueryAttentionParameters parameters = {}; ORT_RETURN_IF_ERROR(group_query_attention_helper::CheckInputs(query, @@ -69,6 +71,10 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { scale_, softcap_)); + ORT_RETURN_IF_ERROR(group_query_attention_helper::CheckCustomAttentionInputs(position_ids, + attention_bias, + parameters)); + const int batch_size = parameters.batch_size; const int sequence_length = parameters.sequence_length; const int present_kv_seqlen = parameters.seqlen_present_kv_cache; @@ -129,9 +135,13 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { auto* tp = context->GetOperatorThreadPool(); // Generate position ids const int pos_ids_size = parameters.is_first_prompt ? 1 : batch_size * sequence_length; - std::vector pos_ids(pos_ids_size); - if (parameters.is_first_prompt) { - pos_ids[0] = static_cast(0); + std::vector default_pos_ids(pos_ids_size); + const int64_t* pos_ids_data = default_pos_ids.data(); + + if (position_ids != nullptr) { + pos_ids_data = position_ids->Data(); + } else if (parameters.is_first_prompt) { + default_pos_ids[0] = static_cast(0); } else { // Note: As of now, continuous decoding supports only batch size 1 and token generation supports only sequence length 1. for (int b = 0; b < batch_size; b++) { @@ -139,13 +149,14 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { const int past_seqlen = total_seqlen - sequence_length; for (int s = 0; s < sequence_length; s++) { if (past_seqlen + s < total_seqlen) { - pos_ids[b * sequence_length + s] = static_cast(past_seqlen) + s; + default_pos_ids[b * sequence_length + s] = static_cast(past_seqlen) + s; } else { - pos_ids[b * sequence_length + s] = static_cast(1); + default_pos_ids[b * sequence_length + s] = static_cast(1); } } } } + // Initialize separate buffers for rotary embeddings const T* q_input; const T* k_input; @@ -165,7 +176,7 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { } // Run rotary embedding for Q and K ORT_RETURN_IF_ERROR(RunRotaryEmbedding(tp, rotary_params, q_input, - pos_ids.data(), cos_cache->Data(), + pos_ids_data, cos_cache->Data(), sin_cache->Data(), q_rotary, rotary_interleaved_)); rotary_params.num_heads = kv_num_heads_; @@ -174,7 +185,7 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { rotary_params.batch_stride = kv_num_heads_ * rotary_params.head_stride; } ORT_RETURN_IF_ERROR(RunRotaryEmbedding(tp, rotary_params, k_input, - pos_ids.data(), cos_cache->Data(), + pos_ids_data, cos_cache->Data(), sin_cache->Data(), k_rotary, rotary_interleaved_)); // Pack V into rotary QKV buffer if (packed_qkv) { @@ -192,9 +203,10 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { } ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); + // Compute the attention score and apply the score to V return ApplyAttention(q_rotary, packed_qkv ? nullptr : k_rotary, packed_qkv ? nullptr : V.Get().Data(), - past_key, past_value, output, present_k, present_v, + attention_bias, past_key, past_value, output, present_k, present_v, seqlens_k, parameters, allocator, context); } } // namespace contrib diff --git a/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h index 4cc5a4228dc8c..7bffd768c8f7c 100644 --- a/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h @@ -288,6 +288,50 @@ Status CheckInputs(const T* query, return CheckInputs(query, key, value, past_key, past_value, cos_cache, sin_cache, parameters, num_heads, kv_num_heads, seqlens_k, total_seqlen, scale, softcap); } + +template +Status CheckCustomAttentionInputs(const T* position_ids, + const T* attention_bias, + const GroupQueryAttentionParameters& parameters) { + if (position_ids != nullptr) { + const auto& pos_ids_shape = position_ids->Shape(); + if (pos_ids_shape[0] != parameters.batch_size) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "position_ids dimension 0 must be equal to the batch size, got ", pos_ids_shape[0]); + } + + if (pos_ids_shape[1] < parameters.sequence_length) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "position_ids dimension 1 must be atleast sequence length, got ", pos_ids_shape[1]); + } + } + + if (attention_bias != nullptr) { + const auto& attn_bias_shape = attention_bias->Shape(); + if ((attn_bias_shape[0] != parameters.batch_size) && (attn_bias_shape[0] != 1)) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "attention_bias dimension 0 must be equal to the batch size or 1, got ", attn_bias_shape[0]); + } + + if ((attn_bias_shape[1] != parameters.num_heads) && (attn_bias_shape[1] != 1)) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "attention_bias dimension 1 must be equal to the num heads or 1, got ", attn_bias_shape[1]); + } + + if (attn_bias_shape[2] != parameters.sequence_length) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "attention_bias dimension 2 must be equal to the sequence length, got ", attn_bias_shape[2]); + } + + if (attn_bias_shape[3] != parameters.total_sequence_length) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "attention_bias dimension 3 must be equal to total_sequence_length, got ", attn_bias_shape[3]); + } + } + + return Status::OK(); +} + } // namespace group_query_attention_helper } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/core/graph/contrib_ops/bert_defs.cc b/onnxruntime/core/graph/contrib_ops/bert_defs.cc index ecc8cb091b1b6..718dd9a4397b5 100644 --- a/onnxruntime/core/graph/contrib_ops/bert_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/bert_defs.cc @@ -1128,6 +1128,17 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "2D tensor with shape (max_sequence_length, head_size / 2).", "T", OpSchema::Optional) + .Input(9, + "position_ids", + "2D tensor with shape (batch_size, sequence_length). When processing the first prompt the kernel " + "uses only the first element", + "tensor(int64)", + OpSchema::Optional) + .Input(10, + "attention_bias", + "additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)", + "T", + OpSchema::Optional) .Output(0, "output", "3D output tensor with shape (batch_size, sequence_length, hidden_size)", diff --git a/onnxruntime/core/mlas/inc/mlas.h b/onnxruntime/core/mlas/inc/mlas.h index 1401e27ca77e5..8033eab8262a0 100644 --- a/onnxruntime/core/mlas/inc/mlas.h +++ b/onnxruntime/core/mlas/inc/mlas.h @@ -1030,6 +1030,16 @@ MlasComputeSoftcap( T cap ); +template +void +MLASCALL +MlasEltwiseAdd( + const T* left, + const T* right, + T* output, + size_t N + ); + template void MLASCALL diff --git a/onnxruntime/core/mlas/lib/eltwise.cpp b/onnxruntime/core/mlas/lib/eltwise.cpp new file mode 100644 index 0000000000000..f63d71b40bfbb --- /dev/null +++ b/onnxruntime/core/mlas/lib/eltwise.cpp @@ -0,0 +1,71 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + eltwise.cpp + +Abstract: + + This module implements routines to compute element-wise operations on two vectors. + + Currently supported element-wise operations: + - Add + +--*/ + +#include "mlasi.h" +#include "eltwise.h" + +template <> +void +MLASCALL +MlasEltwiseAdd( + const float* left, + const float* right, + float* output, + size_t N +) { + while (N > 0) { + if (N >= 4) { + MLAS_FLOAT32X4 LeftVec = MlasLoadFloat32x4(left); + MLAS_FLOAT32X4 RightVec = MlasLoadFloat32x4(right); + + MLAS_FLOAT32X4 ResultVec = MlasAddFloat32x4(LeftVec, RightVec); + + MlasStoreFloat32x4(output, ResultVec); + + left += 4; + right += 4; + output += 4; + N -= 4; + } else { + *output = *left + *right; + + left += 1; + right += 1; + output += 1; + N -= 1; + } + } +} + + +template <> +void +MLASCALL +MlasEltwiseAdd( + const MLAS_FP16* left, + const MLAS_FP16* right, + MLAS_FP16* output, + size_t N +) { + const auto* dispatch = GetMlasPlatform().EltwiseDispatch; + if (dispatch == nullptr || dispatch->Add_Fp16 == nullptr) { + MLAS_THROW_EX(std::runtime_error, "Add_Fp16 is not supported."); + } + dispatch->Add_Fp16(left, right, output, N); +} diff --git a/onnxruntime/core/mlas/lib/eltwise.h b/onnxruntime/core/mlas/lib/eltwise.h new file mode 100644 index 0000000000000..a8345c499f6b7 --- /dev/null +++ b/onnxruntime/core/mlas/lib/eltwise.h @@ -0,0 +1,37 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + eltwise.h + +Abstract: + + This module includes kernel function prototypes and helper functions for + element-wise operations. + +--*/ +#pragma once + +#include "mlasi.h" + +struct MLAS_ELTWISE_DISPATCH { + /** + * @brief Compute the element-wise addition of the two given vectors + * @param left Address of the left operand + * @param right Address of the right operand + * @param output Address of the output array. Could be the same as the input array. + * @param N Number of elements in the input arrays + */ + typedef void(Add_Fp16_Fn)( + const MLAS_FP16* left, + const MLAS_FP16* right, + MLAS_FP16* output, + size_t N + ); + + Add_Fp16_Fn* Add_Fp16 = nullptr; +}; diff --git a/onnxruntime/core/mlas/lib/eltwise_kernel_neon.cpp b/onnxruntime/core/mlas/lib/eltwise_kernel_neon.cpp new file mode 100644 index 0000000000000..415c1281c808e --- /dev/null +++ b/onnxruntime/core/mlas/lib/eltwise_kernel_neon.cpp @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + eltwise_kernel_neon.cpp + +Abstract: + + This module implements the element-wise kernels for ARM NEON. + +--*/ + +#include "eltwise.h" +#include "eltwise_kernel_neon.h" + +// +// Kernel dispatch structure definition. +// +const MLAS_ELTWISE_DISPATCH MlasEltwiseDispatchNeon = []() { + MLAS_ELTWISE_DISPATCH d; + +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) + if (MlasFp16AccelerationSupported()) { + d.Add_Fp16 = eltwise_neon::Add_Kernel_Fp16; + } +#endif + return d; +}(); diff --git a/onnxruntime/core/mlas/lib/eltwise_kernel_neon.h b/onnxruntime/core/mlas/lib/eltwise_kernel_neon.h new file mode 100644 index 0000000000000..d99a3e97c21f2 --- /dev/null +++ b/onnxruntime/core/mlas/lib/eltwise_kernel_neon.h @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + eltwise_kernel_neon.h + +Abstract: + + This module includes function declarations and common helper functions for + element-wise operations on ARM cpu. + +--*/ + +#pragma once + +#include + +#include "mlasi.h" + +namespace eltwise_neon { + +void Add_Kernel_Fp16(const MLAS_FP16* left, const MLAS_FP16* right, MLAS_FP16* output, size_t N); + +} // namespace eltwise_neon diff --git a/onnxruntime/core/mlas/lib/eltwise_kernel_neon_fp16.cpp b/onnxruntime/core/mlas/lib/eltwise_kernel_neon_fp16.cpp new file mode 100644 index 0000000000000..decbdb576d5cd --- /dev/null +++ b/onnxruntime/core/mlas/lib/eltwise_kernel_neon_fp16.cpp @@ -0,0 +1,118 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + eltwise_kernel_neon_fp16.cpp + +Abstract: + + This module implements the fp16 element-wise kernels for ARM NEON. + +--*/ +#include +#include + +#include "fp16_common.h" +#include "eltwise.h" +#include "eltwise_kernel_neon.h" + +namespace eltwise_neon { + +void Add_Kernel_Fp16(const MLAS_FP16* left, const MLAS_FP16* right, MLAS_FP16* output, size_t N) { + const auto* left_fp16 = reinterpret_cast(left); + const auto* right_fp16 = reinterpret_cast(right); + auto* output_fp16 = reinterpret_cast<_mlas_fp16_*>(output); + + while (N >= 32) { + auto l0 = MlasLoadFloat16x8(left_fp16); + auto l1 = MlasLoadFloat16x8(left_fp16 + 8); + auto l2 = MlasLoadFloat16x8(left_fp16 + 16); + auto l3 = MlasLoadFloat16x8(left_fp16 + 24); + + auto r0 = MlasLoadFloat16x8(right_fp16); + auto r1 = MlasLoadFloat16x8(right_fp16 + 8); + auto r2 = MlasLoadFloat16x8(right_fp16 + 16); + auto r3 = MlasLoadFloat16x8(right_fp16 + 24); + + auto o0 = MlasAddFloat16(l0, r0); + auto o1 = MlasAddFloat16(l1, r1); + auto o2 = MlasAddFloat16(l2, r2); + auto o3 = MlasAddFloat16(l3, r3); + + MlasStoreFloat16x8(output_fp16, o0); + MlasStoreFloat16x8(output_fp16 + 8, o1); + MlasStoreFloat16x8(output_fp16 + 16, o2); + MlasStoreFloat16x8(output_fp16 + 24, o3); + + left_fp16 += 32; + right_fp16 += 32; + output_fp16 += 32; + N -= 32; + } + + if (N & 16) { + auto l0 = MlasLoadFloat16x8(left_fp16); + auto l1 = MlasLoadFloat16x8(left_fp16 + 8); + + auto r0 = MlasLoadFloat16x8(right_fp16); + auto r1 = MlasLoadFloat16x8(right_fp16 + 8); + + auto o0 = MlasAddFloat16(l0, r0); + auto o1 = MlasAddFloat16(l1, r1); + + MlasStoreFloat16x8(output_fp16, o0); + MlasStoreFloat16x8(output_fp16 + 8, o1); + + left_fp16 += 16; + right_fp16 += 16; + output_fp16 += 16; + N -= 16; + } + + if (N & 8) { + auto l0 = MlasLoadFloat16x8(left_fp16); + auto r0 = MlasLoadFloat16x8(right_fp16); + auto o0 = MlasAddFloat16(l0, r0); + MlasStoreFloat16x8(output_fp16, o0); + + left_fp16 += 8; + right_fp16 += 8; + output_fp16 += 8; + N -= 8; + } + + if (N & 4) { + auto l0 = MlasLoadFloat16x4(left_fp16); + auto r0 = MlasLoadFloat16x4(right_fp16); + auto o0 = MlasAddFloat16(l0, r0); + MlasStoreFloat16x4(output_fp16, o0); + + left_fp16 += 4; + right_fp16 += 4; + output_fp16 += 4; + N -= 4; + } + + if (N == 3) { + auto l0 = MlasLoadPartialFloat16x4(left_fp16, 3); + auto r0 = MlasLoadPartialFloat16x4(right_fp16, 3); + auto o0 = MlasAddFloat16(l0, r0); + MlasStorePartialFloat16x4(output_fp16, o0, 3); + } else if (N == 2) { + auto l0 = MlasLoadPartialFloat16x4(left_fp16, 2); + auto r0 = MlasLoadPartialFloat16x4(right_fp16, 2); + auto o0 = MlasAddFloat16(l0, r0); + MlasStorePartialFloat16x4(output_fp16, o0, 2); + } else if (N == 1) { + auto l0 = MlasLoadPartialFloat16x4(left_fp16, 1); + auto r0 = MlasLoadPartialFloat16x4(right_fp16, 1); + auto o0 = MlasAddFloat16(l0, r0); + MlasStorePartialFloat16x4(output_fp16, o0, 1); + } +} + +} // namespace eltwise_neon diff --git a/onnxruntime/core/mlas/lib/mlasi.h b/onnxruntime/core/mlas/lib/mlasi.h index 04ff3290503d3..b5599af85c200 100644 --- a/onnxruntime/core/mlas/lib/mlasi.h +++ b/onnxruntime/core/mlas/lib/mlasi.h @@ -1073,6 +1073,10 @@ extern const MLAS_HGEMM_DISPATCH MlasHGemmDispatchNeon; struct MLAS_SOFTMAX_DISPATCH; extern const MLAS_SOFTMAX_DISPATCH MlasSoftmaxDispatchNeon; +// eltwise dispatch structure +struct MLAS_ELTWISE_DISPATCH; +extern const MLAS_ELTWISE_DISPATCH MlasEltwiseDispatchNeon; + // // Quantized depthwise convolution kernels. // @@ -1236,6 +1240,7 @@ struct MLAS_PLATFORM { const MLAS_ROPE_DISPATCH* RopeDispatch{nullptr}; const MLAS_HGEMM_DISPATCH* HGemmDispatch{nullptr}; const MLAS_SOFTMAX_DISPATCH* SoftmaxDispatch{nullptr}; + const MLAS_ELTWISE_DISPATCH* EltwiseDispatch{nullptr}; }; inline diff --git a/onnxruntime/core/mlas/lib/platform.cpp b/onnxruntime/core/mlas/lib/platform.cpp index 44aee4a2b28d3..2165252ccd4cc 100644 --- a/onnxruntime/core/mlas/lib/platform.cpp +++ b/onnxruntime/core/mlas/lib/platform.cpp @@ -546,6 +546,7 @@ Return Value: this->RopeDispatch = &MlasRopeDispatchNeon; this->HGemmDispatch = &MlasHGemmDispatchNeon; this->SoftmaxDispatch = &MlasSoftmaxDispatchNeon; + this->EltwiseDispatch = &MlasEltwiseDispatchNeon; // // Check if the processor supports ASIMD dot product instructions. diff --git a/onnxruntime/test/mlas/unittest/test_eltwise.cpp b/onnxruntime/test/mlas/unittest/test_eltwise.cpp new file mode 100644 index 0000000000000..c4d4b9c0eb317 --- /dev/null +++ b/onnxruntime/test/mlas/unittest/test_eltwise.cpp @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "test_util.h" +#include "core/mlas/lib/mlasi.h" +#include "core/mlas/lib/eltwise.h" + +class MlasEltwiseAddTest : public MlasTestBase { + private: + MatrixGuardBuffer BufferInputLeft; + MatrixGuardBuffer BufferInputRight; + MatrixGuardBuffer BufferOutput; + MatrixGuardBuffer BufferOutputReference; + MatrixGuardBuffer BufferInputLeftFp16; + MatrixGuardBuffer BufferInputRightFp16; + MatrixGuardBuffer BufferOutputFp16; + + void Test(size_t N, float MinimumValue, float MaximumValue, const std::optional& ScalarValue = std::nullopt) { + float* InputLeft = BufferInputLeft.GetBuffer(N); + float* InputRight = BufferInputRight.GetBuffer(N); + float* Output = BufferOutput.GetBuffer(N); + float* OutputReference = BufferOutputReference.GetBuffer(N); + + std::default_random_engine generator(static_cast(N)); + std::uniform_real_distribution distribution(MinimumValue, MaximumValue); + + for (size_t n = 0; n < N; n++) { + InputLeft[n] = distribution(generator); + InputRight[n] = ScalarValue.value_or(distribution(generator)); + } + + for (size_t n = 0; n < N; n++) { + OutputReference[n] = InputLeft[n] + InputRight[n]; + } + + MlasEltwiseAdd(InputLeft, InputRight, Output, N); + + constexpr float AbsoluteTolerance = 1e-6f; + constexpr float RelativeTolerance = 1e-6f; + + for (size_t n = 0; n < N; n++) { + float diff = std::fabs(Output[n] - OutputReference[n]); + ASSERT_TRUE(diff <= AbsoluteTolerance || diff <= std::fabs(OutputReference[n]) * RelativeTolerance) + << " @" << n << " of " << N << ", got: " << Output[n] << ", expecting: " << OutputReference[n]; + } + } + +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) + + void TestFp16(size_t N, float MinimumValue, float MaximumValue, const std::optional& ScalarValue = std::nullopt) { + MLAS_FP16* InputLeft = BufferInputLeftFp16.GetBuffer(N); + MLAS_FP16* InputRight = BufferInputRightFp16.GetBuffer(N); + MLAS_FP16* Output = BufferOutputFp16.GetBuffer(N); + + std::default_random_engine generator(static_cast(N)); + std::uniform_real_distribution distribution(MinimumValue, MaximumValue); + + for (size_t n = 0; n < N; n++) { + InputLeft[n] = MLAS_FP16(distribution(generator)); + InputRight[n] = MLAS_FP16(ScalarValue.value_or(distribution(generator))); + } + + MlasEltwiseAdd(InputLeft, InputRight, Output, N); + + constexpr float AbsoluteTolerance = 5e-4f; + constexpr float RelativeTolerance = 1e-3f; + + for (size_t n = 0; n < N; n++) { + float inLeft = InputLeft[n].ToFloat(); + float inRight = InputRight[n].ToFloat(); + float ref = inLeft + inRight; + float out = Output[n].ToFloat(); + float diff = std::fabs(out - ref); + ASSERT_TRUE(diff <= AbsoluteTolerance || diff <= std::fabs(ref) * RelativeTolerance) + << " @ " << inLeft << ", " << inRight << ", got: " << out << ", expecting: " << ref + << ", r-diff: " << diff / std::fabs(ref); + } + } + +#endif // defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) + + public: + static const char* GetTestSuiteName() { + static const std::string suite_name("Eltwise_Add"); + return suite_name.c_str(); + } + + void ExecuteShort(void) override { + for (size_t n = 1; n < 128; n++) { + Test(n, -10.f, 10.f); + Test(n, -10.f, 10.f, -5000.f); +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) + TestFp16(n, -17.f, 11.f); + TestFp16(n, -17.f, 11.f, -5000.f); +#endif // defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) + } + } +}; + +static UNUSED_VARIABLE bool added_to_main = AddTestRegister([](bool is_short_execute) { + size_t count = 0; + if (is_short_execute) { + count += MlasDirectShortExecuteTests::RegisterShortExecute(); + } + return count; +}); diff --git a/onnxruntime/test/python/transformers/test_gqa_cpu.py b/onnxruntime/test/python/transformers/test_gqa_cpu.py index 77b4b326bf645..1239affcc04de 100644 --- a/onnxruntime/test/python/transformers/test_gqa_cpu.py +++ b/onnxruntime/test/python/transformers/test_gqa_cpu.py @@ -12,6 +12,7 @@ import math import random import unittest +from dataclasses import dataclass import numpy import torch @@ -41,42 +42,30 @@ class Formats: BNSH = 1 +@dataclass class Config: - batch_size = 0 - sequence_length = 0 - kv_sequence_length = 0 - past_sequence_length = 0 - num_heads = 0 - kv_num_heads = 0 - head_size = 0 - - def __init__(self, b, s, s2, sp, n, n2, h): - self.batch_size = b - self.sequence_length = s - self.kv_sequence_length = s2 - self.past_sequence_length = sp - self.num_heads = n - self.kv_num_heads = n2 - self.head_size = h - - + batch_size: int = 0 + sequence_length: int = 0 + kv_sequence_length: int = 0 + past_sequence_length: int = 0 + num_heads: int = 0 + kv_num_heads: int = 0 + head_size: int = 0 + has_position_ids: bool = False + has_attention_bias: bool = False + + +@dataclass class PromptConfig: - batch_size = 0 - q_sequence_length = 0 - kv_sequence_length = 0 - buffer_sequence_length = 0 - num_heads = 0 - kv_num_heads = 0 - head_size = 0 - - def __init__(self, b, sq, skv, sb, n, n2, h): - self.batch_size = b - self.q_sequence_length = sq - self.kv_sequence_length = skv - self.buffer_sequence_length = sb - self.num_heads = n - self.kv_num_heads = n2 - self.head_size = h + batch_size: int = 0 + q_sequence_length: int = 0 + kv_sequence_length: int = 0 + buffer_sequence_length: int = 0 + num_heads: int = 0 + kv_num_heads: int = 0 + head_size: int = 0 + has_position_ids: bool = False + has_attention_bias: bool = False # LLaMA Microsoft model @@ -173,6 +162,8 @@ def create_group_query_attention_graph_prompt( "total_sequence_length", "cos_cache" if rotary else "", "sin_cache" if rotary else "", + "position_ids" if config.has_position_ids else "", + "attention_bias" if config.has_attention_bias else "", ], ["output", "present_key", "present_value"], "GroupQueryAttention_0", @@ -278,6 +269,24 @@ def create_group_query_attention_graph_prompt( ), ] + if config.has_position_ids: + graph_input += [ + helper.make_tensor_value_info( + "position_ids", + TensorProto.INT64, + [config.batch_size, config.kv_sequence_length], + ), + ] + + if config.has_attention_bias: + graph_input += [ + helper.make_tensor_value_info( + "attention_bias", + ORT_TYPE, + [config.batch_size, 1, config.kv_sequence_length, config.kv_sequence_length], + ), + ] + graph_output = [ helper.make_tensor_value_info( "output", @@ -334,6 +343,7 @@ def create_group_query_attention_graph_prompt( ) model = helper.make_model(graph) + return model.SerializeToString() @@ -365,6 +375,8 @@ def create_group_query_attention_graph_past( "total_sequence_length", "cos_cache" if rotary else "", "sin_cache" if rotary else "", + "position_ids" if config.has_position_ids else "", + "attention_bias" if config.has_attention_bias else "", ], ["output", "present_key", "present_value"], "GroupQueryAttention_0", @@ -467,6 +479,22 @@ def create_group_query_attention_graph_past( ), ] + if config.has_position_ids: + graph_input += [ + helper.make_tensor_value_info( + "position_ids", TensorProto.INT64, [config.batch_size, config.sequence_length] + ), + ] + + if config.has_attention_bias: + graph_input += [ + helper.make_tensor_value_info( + "attention_bias", + ORT_TYPE, + [config.batch_size, 1, config.sequence_length, present_kv_seqlen], + ), + ] + graph_output = [ helper.make_tensor_value_info( "output", @@ -681,6 +709,8 @@ def gqa_prompt_func( cos=None, sin=None, seqlens_k=None, + position_ids=None, + attention_bias=None, window_size=-1, past_kv_format=Formats.BSNH, share_buffer=True, @@ -699,9 +729,17 @@ def gqa_prompt_func( softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) + q = torch.reshape(q, (config.batch_size, config.q_sequence_length, -1)) past_k = k.clone() if share_buffer else None past_v = v.clone() if share_buffer else None + + if config.has_position_ids: + assert position_ids is not None + + if config.has_attention_bias: + assert attention_bias is not None + if new_k is not None: new_k = torch.reshape(new_k, (config.batch_size, config.kv_sequence_length, -1)) new_v = torch.reshape(new_v, (config.batch_size, config.kv_sequence_length, -1)) @@ -713,6 +751,7 @@ def gqa_prompt_func( "seqlens_k": seqlens_k.detach().cpu().numpy().astype(numpy.int32), "total_sequence_length": torch.tensor([config.q_sequence_length], dtype=torch.int32).detach().cpu().numpy(), } + sess_options = SessionOptions() ort_session = InferenceSession(onnx_model_str, sess_options, providers=["CPUExecutionProvider"]) io_binding = ort_session.io_binding() @@ -726,6 +765,15 @@ def gqa_prompt_func( ort_inputs["sin_cache"] = sin.detach().cpu().numpy() io_binding.bind_cpu_input("cos_cache", ort_inputs["cos_cache"]) io_binding.bind_cpu_input("sin_cache", ort_inputs["sin_cache"]) + + if config.has_position_ids: + ort_inputs["position_ids"] = position_ids.detach().cpu().numpy() + io_binding.bind_cpu_input("position_ids", ort_inputs["position_ids"]) + + if config.has_attention_bias: + ort_inputs["attention_bias"] = attention_bias.detach().cpu().numpy() + io_binding.bind_cpu_input("attention_bias", ort_inputs["attention_bias"]) + io_binding.bind_cpu_input("query", ort_inputs["query"]) io_binding.bind_input( "past_key", "cpu", 0, NUMPY_TYPE, ort_inputs["past_key"].shape(), ort_inputs["past_key"].data_ptr() @@ -767,6 +815,15 @@ def gqa_prompt_func( ort_inputs["sin_cache"] = sin.detach().cpu().numpy() io_binding.bind_cpu_input("cos_cache", ort_inputs["cos_cache"]) io_binding.bind_cpu_input("sin_cache", ort_inputs["sin_cache"]) + + if config.has_position_ids: + ort_inputs["position_ids"] = position_ids.detach().cpu().numpy() + io_binding.bind_cpu_input("position_ids", ort_inputs["position_ids"]) + + if config.has_attention_bias: + ort_inputs["attention_bias"] = attention_bias.detach().cpu().numpy() + io_binding.bind_cpu_input("attention_bias", ort_inputs["attention_bias"]) + io_binding.bind_cpu_input("query", ort_inputs["query"]) io_binding.bind_cpu_input("seqlens_k", ort_inputs["seqlens_k"]) io_binding.bind_cpu_input("total_sequence_length", ort_inputs["total_sequence_length"]) @@ -790,6 +847,8 @@ def gqa_past_func( cos=None, sin=None, seqlens_k=None, + position_ids=None, + attention_bias=None, past_kv_format=Formats.BSNH, share_buffer=True, window_size=-1, @@ -812,6 +871,13 @@ def gqa_past_func( q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) past_k = k.clone() past_v = v.clone() + + if config.has_position_ids: + assert position_ids is not None + + if config.has_attention_bias: + assert attention_bias is not None + if new_k is not None: new_k = torch.reshape(new_k, (config.batch_size, config.sequence_length, -1)) new_v = torch.reshape(new_v, (config.batch_size, config.sequence_length, -1)) @@ -839,6 +905,15 @@ def gqa_past_func( ort_inputs["sin_cache"] = sin.detach().cpu().numpy() io_binding.bind_cpu_input("cos_cache", ort_inputs["cos_cache"]) io_binding.bind_cpu_input("sin_cache", ort_inputs["sin_cache"]) + + if config.has_position_ids: + ort_inputs["position_ids"] = position_ids.detach().cpu().numpy() + io_binding.bind_cpu_input("position_ids", ort_inputs["position_ids"]) + + if config.has_attention_bias: + ort_inputs["attention_bias"] = attention_bias.detach().cpu().numpy() + io_binding.bind_cpu_input("attention_bias", ort_inputs["attention_bias"]) + io_binding.bind_cpu_input("query", ort_inputs["query"]) io_binding.bind_input( "past_key", "cpu", 0, NUMPY_TYPE, ort_inputs["past_key"].shape(), ort_inputs["past_key"].data_ptr() @@ -887,6 +962,15 @@ def gqa_past_func( ort_inputs["sin_cache"] = sin.detach().cpu().numpy() io_binding.bind_cpu_input("cos_cache", ort_inputs["cos_cache"]) io_binding.bind_cpu_input("sin_cache", ort_inputs["sin_cache"]) + + if config.has_position_ids: + ort_inputs["position_ids"] = position_ids.detach().cpu().numpy() + io_binding.bind_cpu_input("position_ids", ort_inputs["position_ids"]) + + if config.has_attention_bias: + ort_inputs["attention_bias"] = attention_bias.detach().cpu().numpy() + io_binding.bind_cpu_input("attention_bias", ort_inputs["attention_bias"]) + io_binding.bind_cpu_input("query", ort_inputs["query"]) io_binding.bind_cpu_input("past_key", ort_inputs["past_key"]) io_binding.bind_cpu_input("past_value", ort_inputs["past_value"]) @@ -1056,6 +1140,41 @@ def attention_qkvpacked_ref( ) +def get_custom_attention_bias(batch_size, sequence_length, total_seq_len, seqlens_k=None, past=False): + if past: + assert seqlens_k is not None + attention_bias = torch.zeros((batch_size, 1, sequence_length, total_seq_len), dtype=TORCH_TYPE) + for b in range(batch_size): + total_seq_len = seqlens_k[b] + 1 + past_seq_len = total_seq_len - sequence_length + + # Configure bias + for i in range(sequence_length): + for j in range(past_seq_len + i + 1, total_seq_len): + attention_bias[b][0][i][j] = -5000 + else: + attention_bias = torch.rand(batch_size, 1, sequence_length, total_seq_len, dtype=TORCH_TYPE) + attention_bias = torch.triu(attention_bias, diagonal=1) + + return attention_bias + + +def get_custom_position_ids(batch_size, sequence_length, seqlens_k=None, past=False): + if past: + assert seqlens_k is not None + position_ids_data = [] + for b in range(batch_size): + total_seq_len = seqlens_k[b] + 1 + past_seq_len = total_seq_len - sequence_length + position_ids_data.append(list(range(past_seq_len, past_seq_len + sequence_length))) + + position_ids = torch.tensor(data=position_ids_data, dtype=torch.int64) + else: + position_ids = torch.zeros((batch_size, sequence_length), dtype=torch.int64) + + return position_ids + + def parity_check_gqa_prompt( config, causal=True, @@ -1087,6 +1206,7 @@ def parity_check_gqa_prompt( dtype=TORCH_TYPE, requires_grad=False, ) + v = torch.randn( config.batch_size, config.buffer_sequence_length if past_format == Formats.BSNH else config.kv_num_heads, @@ -1154,6 +1274,19 @@ def parity_check_gqa_prompt( cos, sin = None, None q_ro, k_ro = q, new_k + position_ids = ( + get_custom_position_ids(config.batch_size, config.kv_sequence_length, seqlens_k=None, past=False) + if config.has_position_ids + else None + ) + attention_bias = ( + get_custom_attention_bias( + config.batch_size, config.kv_sequence_length, config.q_sequence_length, seqlens_k=None, past=False + ) + if config.has_attention_bias + else None + ) + rearrange(torch.arange(config.kv_sequence_length, device="cpu"), "s -> 1 s") arange = rearrange(torch.arange(config.buffer_sequence_length, device="cpu"), "s -> 1 s") cache_seqlens_expanded = rearrange(cache_seqlens, "b -> b 1") @@ -1184,6 +1317,7 @@ def parity_check_gqa_prompt( v_cache_ref = v_cache_ref.transpose(1, 2) # Flash function + # Cache seqlens is reduced by 1 since it is required to be past_seq_len + seq_len - 1 if packed: packed_qkv = torch.concatenate([q, new_k, new_v], dim=2) out, present_k, present_v = gqa_prompt_func( @@ -1195,7 +1329,9 @@ def parity_check_gqa_prompt( None, cos, sin, - cache_seqlens, + cache_seqlens - 1, + position_ids, + attention_bias, left_window_size, past_format, True, @@ -1213,7 +1349,9 @@ def parity_check_gqa_prompt( new_v, cos, sin, - cache_seqlens, + cache_seqlens - 1, + position_ids, + attention_bias, left_window_size, past_format, True, @@ -1262,6 +1400,10 @@ def parity_check_gqa_prompt( config.kv_num_heads, " h:", config.head_size, + " has_position_ids:", + config.has_position_ids, + " has_attention_bias:", + config.has_attention_bias, " Mean Error:", numpy.mean(numpy.abs(out - out_ref)), correct, @@ -1347,6 +1489,19 @@ def parity_check_gqa_prompt_no_buff( q_ro, k_ro = q, k_cache_ref k_cache_ref = k_ro + position_ids = ( + get_custom_position_ids(config.batch_size, config.kv_sequence_length, seqlens_k=None, past=False) + if config.has_position_ids + else None + ) + attention_bias = ( + get_custom_attention_bias( + config.batch_size, config.kv_sequence_length, config.q_sequence_length, seqlens_k=None, past=False + ) + if config.has_attention_bias + else None + ) + brange = rearrange(torch.arange(config.kv_sequence_length, device="cpu"), "s -> 1 s") cache_seqlens_expanded = rearrange(cache_seqlens, "b -> b 1") new_mask = brange < cache_seqlens_expanded @@ -1371,6 +1526,7 @@ def parity_check_gqa_prompt_no_buff( v_cache_ref = v_cache_ref.transpose(1, 2) # Flash function + # Cache seqlens is reduced by 1 since it is required to be past_seq_len + seq_len - 1 if packed: packed_qkv = torch.concatenate([q, new_k, new_v], dim=2) out, present_k, present_v = gqa_prompt_func( @@ -1383,6 +1539,8 @@ def parity_check_gqa_prompt_no_buff( cos, sin, cache_seqlens - 1, + position_ids, + attention_bias, left_window_size, past_format, False, @@ -1401,6 +1559,8 @@ def parity_check_gqa_prompt_no_buff( cos, sin, cache_seqlens - 1, + position_ids, + attention_bias, left_window_size, past_format, False, @@ -1449,6 +1609,10 @@ def parity_check_gqa_prompt_no_buff( config.kv_num_heads, " h:", config.head_size, + " has_position_ids:", + config.has_position_ids, + " has_attention_bias:", + config.has_attention_bias, " Mean Error:", numpy.mean(numpy.abs(out - out_ref)), correct, @@ -1589,6 +1753,19 @@ def parity_check_gqa_past( cache_seqlens += config.sequence_length - 1 + position_ids = ( + get_custom_position_ids(config.batch_size, config.sequence_length, seqlens_k=cache_seqlens, past=True) + if config.has_position_ids + else None + ) + attention_bias = ( + get_custom_attention_bias( + config.batch_size, config.sequence_length, config.kv_sequence_length, seqlens_k=cache_seqlens, past=True + ) + if config.has_attention_bias + else None + ) + # ORT function if packed: packed_qkv = torch.concatenate([q, new_k, new_v], dim=2) @@ -1602,6 +1779,8 @@ def parity_check_gqa_past( cos, sin, cache_seqlens, + position_ids, + attention_bias, past_format, True, left_window_size, @@ -1620,6 +1799,8 @@ def parity_check_gqa_past( cos, sin, cache_seqlens, + position_ids, + attention_bias, past_format, True, left_window_size, @@ -1668,6 +1849,10 @@ def parity_check_gqa_past( config.kv_num_heads, " h:", config.head_size, + " has_position_ids:", + config.has_position_ids, + " has_attention_bias:", + config.has_attention_bias, " Mean Error:", numpy.mean(numpy.abs(out - out_ref)), correct, @@ -1814,6 +1999,23 @@ def parity_check_gqa_past_no_buff( cache_seqlens += config.sequence_length - 1 + position_ids = ( + get_custom_position_ids(config.batch_size, config.sequence_length, seqlens_k=cache_seqlens, past=True) + if config.has_position_ids + else None + ) + attention_bias = ( + get_custom_attention_bias( + config.batch_size, + config.sequence_length, + config.kv_sequence_length + config.sequence_length, + seqlens_k=cache_seqlens, + past=True, + ) + if config.has_attention_bias + else None + ) + # Flash function if packed: packed_qkv = torch.concatenate([q, new_k, new_v], dim=2) @@ -1827,6 +2029,8 @@ def parity_check_gqa_past_no_buff( cos, sin, cache_seqlens, + position_ids, + attention_bias, past_format, False, window_size=left_window_size, @@ -1845,6 +2049,8 @@ def parity_check_gqa_past_no_buff( cos, sin, cache_seqlens, + position_ids, + attention_bias, past_format, False, window_size=left_window_size, @@ -1889,6 +2095,10 @@ def parity_check_gqa_past_no_buff( config.kv_num_heads, " h:", config.head_size, + " has_position_ids:", + config.has_position_ids, + " has_attention_bias:", + config.has_attention_bias, " Mean Error:", numpy.mean(numpy.abs(out - out_ref)), correct, @@ -1916,6 +2126,11 @@ def test_gqa_no_past(self): (8000, 8000), ] ) + pos_ids_attn_bias = ( + [(False, False), (True, True)] + if pipeline_mode + else [(False, False), (True, True), (False, True), (True, False)] + ) num_h = [(32, 8)] if pipeline_mode else [(6, 6), (6, 3), (9, 9), (9, 3)] h_sizes = [128] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] for b in batches: @@ -1927,30 +2142,41 @@ def test_gqa_no_past(self): for packed in [False, True]: for softcap in [0.0, 50.0]: for use_smooth_softmax in [False, True]: - config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_prompt( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_prompt_no_buff( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) + for has_position_ids, has_attention_bias in pos_ids_attn_bias: + config = PromptConfig( + b, + sq, + skv, + sq + skv + 8, + n, + n2, + h, + has_position_ids, + has_attention_bias, + ) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_prompt( + config, + local=local, + past_format=past_kv_format, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_prompt_no_buff( + config, + local=local, + past_format=past_kv_format, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) def test_gqa_past(self): print("-------- TEST GQA PAST (TOKEN GEN) ---------") @@ -1972,6 +2198,11 @@ def test_gqa_past(self): # (128, 128), ] ) + pos_ids_attn_bias = ( + [(False, False), (True, True)] + if pipeline_mode + else [(False, False), (True, True), (False, True), (True, False)] + ) num_h = [(9, 3)] if pipeline_mode else [(6, 6), (6, 3), (9, 9), (9, 3)] h_sizes = [64] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] random.seed(69) @@ -1984,35 +2215,38 @@ def test_gqa_past(self): for packed in [False, True]: for softcap in [0.0, 50.0]: for use_smooth_softmax in [False, True]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_past( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_past_no_buff( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) + for has_position_ids, has_attention_bias in pos_ids_attn_bias: + sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 + config = Config( + b, s, s2, sp, n, n2, h, has_position_ids, has_attention_bias + ) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_past( + config, + local=local, + past_format=past_kv_format, + rtol=RTOL, + atol=ATOL, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_past_no_buff( + config, + local=local, + past_format=past_kv_format, + rtol=RTOL, + atol=ATOL, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) def test_gqa_interactive_one_batch(self): print("-------- TEST GQA INTERACTIVE ---------") @@ -2034,6 +2268,11 @@ def test_gqa_interactive_one_batch(self): # (128, 128), ] ) + pos_ids_attn_bias = ( + [(False, False), (True, True)] + if pipeline_mode + else [(False, False), (True, True), (False, True), (True, False)] + ) num_h = [(32, 8)] if pipeline_mode else [(6, 6), (6, 3), (9, 9), (9, 3)] h_sizes = [32] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] random.seed(69) @@ -2044,30 +2283,31 @@ def test_gqa_interactive_one_batch(self): for local in [False, True]: for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: for packed in [False, True]: - config = Config(b, s, s2, -1, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_past( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_past_no_buff( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) + for has_position_ids, has_attention_bias in pos_ids_attn_bias: + config = Config(b, s, s2, -1, n, n2, h, has_position_ids, has_attention_bias) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_past( + config, + local=local, + past_format=past_kv_format, + rtol=RTOL, + atol=ATOL, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_past_no_buff( + config, + local=local, + past_format=past_kv_format, + rtol=RTOL, + atol=ATOL, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + ) + self.assertTrue(all_close) if __name__ == "__main__": From 73d9826a37d7ca87a6689b460fd862f3bac84c57 Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Sat, 15 Mar 2025 04:33:31 +0800 Subject: [PATCH 104/266] [WebNN] Better int64 integration (#23831) This PR adds some workarounds to enable int64 support for some WebNN backends which don't support int64 data type. - Do not fallback ops that are specifically due to the int64 limitation. - Convert all int64 initializer and input values to int32 and handle potential overflow errors. - Register all int64 model inputs and outputs as int32 ml-tensor. - Handle ONNX ops that need inputs or outputs conversion between int64 and int32. e.g. ArgMax, ArgMin, Cast, etc. - Convert int64 output data back to int32. - Disallow int64 outputs as 'ml-tensor' preferredOutputLocation. Fixed #21401 --- js/web/lib/wasm/jsep/backend-webnn.ts | 24 ++- js/web/lib/wasm/jsep/webnn/tensor-manager.ts | 157 +++++++++++++++--- js/web/lib/wasm/jsep/webnn/webnn.d.ts | 9 + js/web/lib/wasm/wasm-core-impl.ts | 8 +- js/web/lib/wasm/wasm-types.ts | 8 + .../core/providers/webnn/builders/helper.cc | 16 +- .../core/providers/webnn/builders/helper.h | 13 +- .../builders/impl/argmax_min_op_builder.cc | 8 +- .../webnn/builders/impl/cast_op_builder.cc | 3 +- .../webnn/builders/impl/conv_op_builder.cc | 19 ++- .../webnn/builders/impl/dropout_op_builder.cc | 2 +- .../webnn/builders/impl/expand_op_builder.cc | 7 +- .../webnn/builders/impl/gemm_op_builder.cc | 10 +- .../builders/impl/normalization_op_builder.cc | 2 +- .../webnn/builders/impl/pool_op_builder.cc | 2 +- .../webnn/builders/impl/qdq_op_builder.cc | 2 +- .../webnn/builders/impl/resize_op_builder.cc | 4 +- .../impl/rotaryEmbedding_op_builder.cc | 16 +- .../webnn/builders/impl/shape_op_builder.cc | 12 +- .../webnn/builders/impl/slice_op_builder.cc | 4 +- .../impl/squeeze_unsqueeze_op_builder.cc | 2 +- .../builders/impl/transpose_op_builder.cc | 2 +- .../providers/webnn/builders/model_builder.cc | 31 +++- .../providers/webnn/builders/model_builder.h | 3 + onnxruntime/wasm/pre-jsep.js | 16 +- 25 files changed, 294 insertions(+), 86 deletions(-) diff --git a/js/web/lib/wasm/jsep/backend-webnn.ts b/js/web/lib/wasm/jsep/backend-webnn.ts index 55784ae13ad7a..c2a855bedca22 100644 --- a/js/web/lib/wasm/jsep/backend-webnn.ts +++ b/js/web/lib/wasm/jsep/backend-webnn.ts @@ -12,7 +12,7 @@ import { DataType } from '../wasm-common'; import { getInstance } from '../wasm-factory'; import { createView } from './tensor-view'; -import { TensorId, createTensorManager } from './webnn/tensor-manager'; +import { TensorId, createTensorManager, convertInt64ToInt32 } from './webnn/tensor-manager'; import { configureLogger, LOG_DEBUG } from './log'; /* @@ -288,6 +288,7 @@ export class WebNNBackend { builder: MLGraphBuilder, desc: MLOperandDescriptor, mountedFiles: Map | undefined, + shouldConvertInt64ToInt32 = false, ): MLOperand { // If available, "Module.MountedFiles" is a Map for all preloaded files. if (!mountedFiles) { @@ -324,7 +325,13 @@ export class WebNNBackend { bufferView = new Uint32Array(buffer); break; case 'int64': - bufferView = new BigInt64Array(buffer); + if (shouldConvertInt64ToInt32) { + // Int64 is not supported by current context, use int32 instead. + bufferView = convertInt64ToInt32(new Uint8Array(buffer), false) as Int32Array; + desc.dataType = 'int32'; + } else { + bufferView = new BigInt64Array(buffer); + } break; case 'uint64': bufferView = new BigUint64Array(buffer); @@ -341,7 +348,13 @@ export class WebNNBackend { throw new Error(`Unsupported data type: ${desc.dataType} in creating WebNN Constant from external data.`); } - LOG_DEBUG('verbose', () => `[WebNN] registerMLConstant {dataType: ${desc.dataType}, shape: ${desc.shape}}}`); + LOG_DEBUG( + 'verbose', + () => + `[WebNN] registerMLConstant {dataType: ${desc.dataType}, shape: ${desc.shape}}} ${ + shouldConvertInt64ToInt32 ? '(Note: it was int64 data type and registered to int32 as workaround)' : '' + }`, + ); return builder.constant(desc, bufferView); } @@ -358,6 +371,11 @@ export class WebNNBackend { return inputNames.includes(inputName); } + public isInt64Supported(sessionId: number): boolean { + const context = this.mlContextBySessionId.get(sessionId); + return !!context?.opSupportLimits().input.dataTypes.includes('int64'); + } + public flush(): void { // Unlike the WebGPU backend, the WebNN backend does not need to flush any pending operations. } diff --git a/js/web/lib/wasm/jsep/webnn/tensor-manager.ts b/js/web/lib/wasm/jsep/webnn/tensor-manager.ts index ebdd5069aa089..24d68576c176c 100644 --- a/js/web/lib/wasm/jsep/webnn/tensor-manager.ts +++ b/js/web/lib/wasm/jsep/webnn/tensor-manager.ts @@ -9,6 +9,53 @@ import { LOG_DEBUG } from '../log'; // https://github.com/webmachinelearning/webnn/issues/677 /// +// Convert BigInt64Array buffer data to Int32Array buffer data. +export const convertInt64ToInt32 = (data: Uint8Array, returnUint8 = true): Uint8Array | Int32Array => { + // Make sure it is a multiple of 8 bytes (BigInt64Array). + if (data.byteLength % 8 !== 0) { + throw new Error('Invalid Uint8Array length - must be a multiple of 8 (BigInt).'); + } + + // Convert Uint8Array to BigInt64Array. + const numElements = data.byteLength / 8; + const bigInt64Array = new BigInt64Array(data.buffer, data.byteOffset, numElements); + + // Convert BigInt64Array to Int32Array (same number of elements). + const int32Array = new Int32Array(numElements); + + for (let i = 0; i < numElements; i++) { + const value = bigInt64Array[i]; + + // Check for overflow. + if (value > 2147483647n || value < -2147483648n) { + throw new Error(`Overflow occurred when converting BigInt to Int32 at index ${i}: ${value}`); + } + + int32Array[i] = Number(value); + } + + // Return based on the requested format. + return returnUint8 ? new Uint8Array(int32Array.buffer) : int32Array; +}; + +// Convert Int32Array buffer data to BigInt64Array buffer data. +const convertInt32ToInt64 = (data: Uint8Array, returnUint8 = true): Uint8Array | BigInt64Array => { + // Make sure it is a multiple of 4 bytes (Int32Array). + if (data.byteLength % 4 !== 0) { + throw new Error('Invalid Uint8Array length - must be a multiple of 4 (Int32).'); + } + + // Convert Uint8Array to Int32Array. + const numElements = data.byteLength / 4; + const int32Array = new Int32Array(data.buffer, data.byteOffset, numElements); + + // Convert Int32Array to BigInt64Array (same number of elements). + const bigInt64Array = BigInt64Array.from(int32Array, BigInt); + + // Return based on the requested format. + return returnUint8 ? new Uint8Array(bigInt64Array.buffer) : bigInt64Array; +}; + export type TensorId = number; /** @@ -88,6 +135,9 @@ const calculateByteLength = (dataType: MLOperandDataType, shape: readonly number class TensorWrapper { // The id of the last session that used this tensor. public sessionId: number; + // This flag is used to indicate whether we should convert data from int64 to int32. + public shouldConvertInt64toInt32 = false; + public isInt64ToInt32Converted = false; private mlContext: MLContext; private mlTensor: MLTensor; @@ -100,12 +150,15 @@ class TensorWrapper { tensor: MLTensor; dataType: MLOperandDataType; shape: readonly number[]; + shouldConvertInt64toInt32?: boolean; }) { - this.sessionId = descriptor.sessionId; - this.mlContext = descriptor.context; - this.mlTensor = descriptor.tensor; - this.dataType = descriptor.dataType; - this.tensorShape = descriptor.shape; + const { sessionId, context, tensor, dataType, shape, shouldConvertInt64toInt32 = false } = descriptor; + this.sessionId = sessionId; + this.mlContext = context; + this.mlTensor = tensor; + this.dataType = dataType; + this.tensorShape = shape; + this.shouldConvertInt64toInt32 = shouldConvertInt64toInt32; } public get tensor(): MLTensor { @@ -133,13 +186,33 @@ class TensorWrapper { this.mlContext.writeTensor(this.mlTensor, data); } - public async read(): Promise; - public async read(dstBuffer: ArrayBufferView | ArrayBuffer): Promise; - async read(dstBuffer?: ArrayBufferView | ArrayBuffer): Promise { - if (dstBuffer) { - return this.mlContext.readTensor(this.mlTensor, dstBuffer); + public async read(shouldConvertInt32ToInt64?: boolean): Promise; + public async read( + shouldConvertInt32ToInt64?: boolean, + dstBuffer?: ArrayBufferView | ArrayBuffer, + ): Promise; + public async read( + shouldConvertInt32ToInt64?: boolean, + dstBuffer?: ArrayBufferView | ArrayBuffer, + ): Promise { + if (shouldConvertInt32ToInt64) { + // This was an int64 data as saved as int32 as workaround, we need to read it as int64. + const data = await this.mlContext.readTensor(this.mlTensor); + const int64Data = convertInt32ToInt64(new Uint8Array(data)) as Uint8Array; + + if (dstBuffer) { + const targetBuffer = + dstBuffer instanceof ArrayBuffer + ? new Uint8Array(dstBuffer) + : new Uint8Array(dstBuffer.buffer, dstBuffer.byteOffset, dstBuffer.byteLength); + targetBuffer.set(int64Data); + return undefined; + } else { + return int64Data.buffer; + } + } else { + return dstBuffer ? this.mlContext.readTensor(this.mlTensor, dstBuffer) : this.mlContext.readTensor(this.mlTensor); } - return this.mlContext.readTensor(this.mlTensor); } public canReuseTensor(context: MLContext, dataType: MLOperandDataType, shape: readonly number[]): boolean { @@ -150,6 +223,10 @@ class TensorWrapper { this.tensorShape.every((v, i) => v === shape[i]) ); } + + public setIsInt64ToInt32Converted(isConverted: boolean): void { + this.isInt64ToInt32Converted = isConverted; + } } /** @@ -183,13 +260,22 @@ class TensorIdTracker { shape: readonly number[], copyOld: boolean, ): Promise { + let newDataType = dataType; const context = this.tensorManager.getMLContext(sessionId); + // If the data type is int64 and the context does not support int64, we need to convert it to int32. + const shouldConvertInt64toInt32 = + newDataType === 'int64' && !context.opSupportLimits().input.dataTypes.includes('int64'); + if (shouldConvertInt64toInt32) { + newDataType = 'int32'; + LOG_DEBUG('verbose', () => `[WebNN] TensorIdTracker.ensureTensor: convert dataType from int64 to int32`); + } + if (this.wrapper) { - if (this.wrapper.canReuseTensor(context, dataType, shape)) { + if (this.wrapper.canReuseTensor(context, newDataType, shape)) { return this.wrapper.tensor; } else { if (copyOld) { - if (this.wrapper.byteLength !== calculateByteLength(dataType, shape)) { + if (this.wrapper.byteLength !== calculateByteLength(newDataType, shape)) { throw new Error('Unable to copy data to tensor with different size.'); } this.activeUpload = new Uint8Array(await this.wrapper.read()); @@ -200,9 +286,19 @@ class TensorIdTracker { // eslint-disable-next-line no-bitwise const usage = typeof MLTensorUsage == 'undefined' ? undefined : MLTensorUsage.READ | MLTensorUsage.WRITE; - this.wrapper = await this.tensorManager.getCachedTensor(sessionId, dataType, shape, usage, true, true); + this.wrapper = await this.tensorManager.getCachedTensor( + sessionId, + newDataType, + shape, + usage, + true, + true, + shouldConvertInt64toInt32, + ); if (copyOld && this.activeUpload) { + // We don't need to convert the old int64 data to int32, + // because it has been converted when it was uploaded. this.wrapper.write(this.activeUpload); this.activeUpload = undefined; } @@ -211,9 +307,15 @@ class TensorIdTracker { } public upload(data: Uint8Array): void { + let newData = data; if (this.wrapper) { - if (data.byteLength === this.wrapper.byteLength) { - this.wrapper.write(data); + if (this.wrapper.shouldConvertInt64toInt32) { + // Convert int64 to int32. + newData = convertInt64ToInt32(data, true) as Uint8Array; + this.wrapper.setIsInt64ToInt32Converted(true); + } + if (newData.byteLength === this.wrapper.byteLength) { + this.wrapper.write(newData); return; } else { LOG_DEBUG('verbose', () => 'Data size does not match tensor size. Releasing tensor.'); @@ -222,32 +324,38 @@ class TensorIdTracker { } if (this.activeUpload) { - this.activeUpload.set(data); + this.activeUpload.set(newData); } else { - this.activeUpload = new Uint8Array(data); + this.activeUpload = new Uint8Array(newData); } } public async download(dstBuffer?: ArrayBufferView | ArrayBuffer): Promise { if (this.activeUpload) { + // If this.activeUpload has been converted to int32, we need to convert it back to int64 data. + const dstData = this.wrapper?.isInt64ToInt32Converted + ? (convertInt32ToInt64(this.activeUpload) as Uint8Array) + : this.activeUpload; + if (dstBuffer) { if (dstBuffer instanceof ArrayBuffer) { - new Uint8Array(dstBuffer).set(this.activeUpload); + new Uint8Array(dstBuffer).set(dstData); } else { - new Uint8Array(dstBuffer.buffer, dstBuffer.byteOffset, dstBuffer.byteLength).set(this.activeUpload); + new Uint8Array(dstBuffer.buffer, dstBuffer.byteOffset, dstBuffer.byteLength).set(dstData); } return; } else { - return this.activeUpload.buffer; + return dstData.buffer; } } if (!this.wrapper) { throw new Error('Tensor has not been created.'); } + if (!dstBuffer) { - return this.wrapper.read(); + return this.wrapper.read(this.wrapper?.shouldConvertInt64toInt32); } - return this.wrapper.read(dstBuffer); + return this.wrapper.read(this.wrapper?.shouldConvertInt64toInt32, dstBuffer); } } @@ -367,6 +475,7 @@ class TensorManagerImpl implements TensorManager { usage: MLTensorUsageFlags | undefined, writable: boolean, readable: boolean, + shouldConvertInt64toInt32 = false, ): Promise { const context = this.getMLContext(sessionId); for (const [index, tensor] of this.freeTensors.entries()) { @@ -386,7 +495,7 @@ class TensorManagerImpl implements TensorManager { writable, readable, }); - return new TensorWrapper({ sessionId, context, tensor, dataType, shape }); + return new TensorWrapper({ sessionId, context, tensor, dataType, shape, shouldConvertInt64toInt32 }); } /** diff --git a/js/web/lib/wasm/jsep/webnn/webnn.d.ts b/js/web/lib/wasm/jsep/webnn/webnn.d.ts index c513b2ec2ed8b..0ebff457d5b33 100644 --- a/js/web/lib/wasm/jsep/webnn/webnn.d.ts +++ b/js/web/lib/wasm/jsep/webnn/webnn.d.ts @@ -415,4 +415,13 @@ interface MLContext { readTensor(sourceTensor: MLTensor): Promise; readTensor(sourceTensor: MLTensor, destinationData: ArrayBufferView|ArrayBuffer): Promise; dispatch(graph: MLGraph, inputs: MLNamedTensor, outputs: MLNamedTensor): void; + opSupportLimits() : MLOpSupportLimits; +} + +interface MLOpSupportLimits { + input: MLSupportLimits; +} + +interface MLSupportLimits { + dataTypes: MLOperandDataType[]; } diff --git a/js/web/lib/wasm/wasm-core-impl.ts b/js/web/lib/wasm/wasm-core-impl.ts index dbcf80adf3552..3979af7fa1ec9 100644 --- a/js/web/lib/wasm/wasm-core-impl.ts +++ b/js/web/lib/wasm/wasm-core-impl.ts @@ -863,13 +863,19 @@ export const run = async ( } } else if (preferredLocation === 'ml-tensor' && size > 0) { const ensureTensor = wasm.jsepEnsureTensor; - if (!ensureTensor) { + const isInt64Supported = wasm.jsepIsInt64Supported; + if (!ensureTensor || !isInt64Supported) { throw new Error('preferredLocation "ml-tensor" is not supported without using WebNN.'); } const tensorSize = calculateTensorSizeInBytes(dataType, size); if (tensorSize === undefined || !isMLTensorSupportedType(type)) { throw new Error(`Unsupported data type: ${type}`); } + if (type === 'int64' && !isInt64Supported(sessionId)) { + throw new Error( + `preferredLocation "ml-tensor" for int64 output is not supported by current WebNN Context.`, + ); + } // If the graph has been partitioned, the output tensor may have not been created. For this reason, we use // ensureTensor to get/create the MLTensor. In which case, we don't need to copy the data if a new tensor diff --git a/js/web/lib/wasm/wasm-types.ts b/js/web/lib/wasm/wasm-types.ts index 9b2ec71fd351d..6de54078af031 100644 --- a/js/web/lib/wasm/wasm-types.ts +++ b/js/web/lib/wasm/wasm-types.ts @@ -249,6 +249,7 @@ export declare namespace JSEP { * @param dataLength - specify the external data length. * @param builder - specify the MLGraphBuilder used for constructing the Constant. * @param desc - specify the MLOperandDescriptor of the Constant. + * @param shouldConvertInt64ToInt32 - specify whether to convert int64 to int32. * @returns the WebNN Constant operand for the specified external data. */ jsepRegisterMLConstant( @@ -257,6 +258,7 @@ export declare namespace JSEP { dataLength: number, builder: MLGraphBuilder, desc: MLOperandDescriptor, + shouldConvertInt64ToInt32: boolean, ): MLOperand; /** @@ -279,6 +281,12 @@ export declare namespace JSEP { * @returns the MLTensor ID for the temporary MLTensor. */ jsepCreateTemporaryTensor: (sessionId: number, dataType: DataType, shape: readonly number[]) => Promise; + /** + * [exported from pre-jsep.js] Check if a session's associated WebNN Context supports int64. + * @param sessionId - specify the session ID. + * @returns whether the WebNN Context supports int64. + */ + jsepIsInt64Supported: (sessionId: number) => boolean; } } diff --git a/onnxruntime/core/providers/webnn/builders/helper.cc b/onnxruntime/core/providers/webnn/builders/helper.cc index 20f3ffddd2779..47f65cd0b8e85 100644 --- a/onnxruntime/core/providers/webnn/builders/helper.cc +++ b/onnxruntime/core/providers/webnn/builders/helper.cc @@ -144,9 +144,19 @@ bool IsSupportedDataType(const int32_t onnx_data_type, const emscripten::val& we const std::string_view webnn_data_type = it->second; // Check if WebNN supports the data type. - emscripten::val is_supported = - webnn_supported_data_types.call("includes", emscripten::val(std::string(webnn_data_type))); - return is_supported.as(); + bool is_supported = webnn_supported_data_types.call("includes", + emscripten::val(std::string(webnn_data_type))) + .as(); + + if (webnn_data_type == "int64" && + !is_supported && + webnn_supported_data_types.call("includes", emscripten::val("int32")).as()) { + // Current context doesn't support int64, but int32 is supported. + // We can use int32 as a workaround. + is_supported = true; + } + + return is_supported; } // Check if the input or output data type of ONNX node is supported by the WebNN operator. diff --git a/onnxruntime/core/providers/webnn/builders/helper.h b/onnxruntime/core/providers/webnn/builders/helper.h index 5513001f97545..9a1566ccdc99a 100644 --- a/onnxruntime/core/providers/webnn/builders/helper.h +++ b/onnxruntime/core/providers/webnn/builders/helper.h @@ -82,13 +82,14 @@ inline std::string GetTensorName(const ConstPointerContainer index) ? std::string(input_defs[index]->Name()) : ""; } -inline std::vector GetVecUint32FromVecInt64(gsl::span int64_vec) { - std::vector uint32_vec; - uint32_vec.reserve(int64_vec.size()); +template +inline std::vector GetNarrowedIntfromInt64(gsl::span int64_vec) { + std::vector vec; + vec.reserve(int64_vec.size()); std::transform(int64_vec.begin(), int64_vec.end(), - std::back_inserter(uint32_vec), - [](int64_t val) -> uint32_t { return SafeInt(val); }); - return uint32_vec; + std::back_inserter(vec), + [](int64_t val) -> T { return SafeInt(val); }); + return vec; } template diff --git a/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc index d61ae1a1f6be7..6814b019f699c 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc @@ -43,8 +43,12 @@ Status ArgMaxMinOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, emscripten::val options = emscripten::val::object(); options.set("keepDimensions", keep_dims == 1); - // TODO(Honry): check whether int64 output data type is supported by WebNN opSupportLimits() API. - options.set("outputDataType", "int64"); + std::string output_data_type = "int64"; + if (!model_builder.IsInt64Supported()) { + // Int64 is not supported by current context, use int32 instead. + output_data_type = "int32"; + } + options.set("outputDataType", output_data_type); options.set("label", node.Name()); emscripten::val output = emscripten::val::object(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/cast_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/cast_op_builder.cc index 9eacc192d4c02..cd34dba52c066 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/cast_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/cast_op_builder.cc @@ -56,7 +56,8 @@ Status CastOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, operand_type = "int32"; break; case ONNX_NAMESPACE::TensorProto_DataType_INT64: - operand_type = "int64"; + // If int64 is not supported by current context, use int32 instead. + operand_type = model_builder.IsInt64Supported() ? "int64" : "int32"; break; case ONNX_NAMESPACE::TensorProto_DataType_UINT32: operand_type = "uint32"; diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc index 043324ba49431..1361b7dd5c14b 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc @@ -76,7 +76,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, if (output_padding.size() == 1 && is_conv1d) { output_padding.push_back(0); } - options.set("outputPadding", emscripten::val::array(GetVecUint32FromVecInt64(output_padding))); + options.set("outputPadding", emscripten::val::array(GetNarrowedIntfromInt64(output_padding))); // If output shape is explicitly provided, compute the pads. // Otherwise compute the output shape, as well as the pads if the auto_pad attribute is SAME_UPPER/SAME_LOWER. @@ -85,7 +85,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, auto_pad_type, pads_out, output_shape, !is_nhwc)); if (output_shape[0] != -1 && output_shape[1] != -1) { - options.set("outputSizes", emscripten::val::array(GetVecUint32FromVecInt64(output_shape))); + options.set("outputSizes", emscripten::val::array(GetNarrowedIntfromInt64(output_shape))); } pads = pads_out; } else { @@ -95,13 +95,13 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, const auto group = helper.Get("group", static_cast(1)); options.set("groups", group); - options.set("strides", emscripten::val::array(GetVecUint32FromVecInt64(strides))); - options.set("dilations", emscripten::val::array(GetVecUint32FromVecInt64(dilations))); + options.set("strides", emscripten::val::array(GetNarrowedIntfromInt64(strides))); + options.set("dilations", emscripten::val::array(GetNarrowedIntfromInt64(dilations))); // Permute the ONNX's pads, which is [beginning_height, beginning_width, ending_height, ending_width], // while WebNN's padding is [beginning_height, ending_height, beginning_width, ending_width]. const std::vector padding{pads[0], pads[2], pads[1], pads[3]}; - options.set("padding", emscripten::val::array(GetVecUint32FromVecInt64(padding))); + options.set("padding", emscripten::val::array(GetNarrowedIntfromInt64(padding))); // Add bias if present. if (input_defs.size() > 2) { @@ -120,7 +120,8 @@ Status AddInitializerInNewLayout(ModelBuilder& model_builder, auto data_type = tensor.data_type(); const auto& shape = tensor.dims(); - std::vector dims = GetVecUint32FromVecInt64(std::vector(std::begin(shape), std::end(shape))); + std::vector dims = + GetNarrowedIntfromInt64(std::vector(std::begin(shape), std::end(shape))); if (is_conv1d) { // Support conv1d by prepending a 1 size dimension. @@ -229,7 +230,7 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N } else { input_shape.push_back(1); } - std::vector new_shape = GetVecUint32FromVecInt64(input_shape); + std::vector new_shape = GetNarrowedIntfromInt64(input_shape); input = model_builder.GetBuilder().call("reshape", input, emscripten::val::array(new_shape)); weight_shape.resize(4, 1); // Ensure 4D by appending 1's if needed. @@ -276,7 +277,7 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N // Reshape weight to 4D for conv1d. if (!is_nhwc || !is_constant_weight) { // The weight_shape has been appended 1's, reshape weight operand. - std::vector new_shape = GetVecUint32FromVecInt64(weight_shape); + std::vector new_shape = GetNarrowedIntfromInt64(weight_shape); emscripten::val reshape_options = emscripten::val::object(); reshape_options.set("label", node.Name() + "_reshape_filter"); filter = model_builder.GetBuilder().call("reshape", @@ -329,7 +330,7 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N const auto& output_defs = node.OutputDefs(); std::vector output_shape; ORT_RETURN_IF_NOT(GetShape(*output_defs[0], output_shape, logger), "Cannot get output shape"); - std::vector new_shape = GetVecUint32FromVecInt64(output_shape); + std::vector new_shape = GetNarrowedIntfromInt64(output_shape); emscripten::val reshape_options = emscripten::val::object(); reshape_options.set("label", node.Name() + "_reshape_output"); output = model_builder.GetBuilder().call("reshape", diff --git a/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc index 9bb930c63b009..974e48bc57de9 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc @@ -58,7 +58,7 @@ Status DropoutOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, if (output_defs.size() > 1) { std::vector mask_shape; ORT_RETURN_IF_NOT(GetShape(*output_defs[1], mask_shape, logger), "Cannot get mask output's shape"); - std::vector dims = GetVecUint32FromVecInt64(mask_shape); + std::vector dims = GetNarrowedIntfromInt64(mask_shape); emscripten::val one_constant = model_builder.CreateOrGetConstant( ONNX_NAMESPACE::TensorProto_DataType_BOOL, 1, dims); diff --git a/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc index f5e1f59602c5d..8402f05d8e234 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc @@ -56,11 +56,8 @@ Status ExpandOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, emscripten::val options = emscripten::val::object(); options.set("label", node.Name()); - emscripten::val output = - model_builder.GetBuilder().call("expand", - input, - emscripten::val::array(GetVecUint32FromVecInt64(output_shape)), - options); + emscripten::val output_shape_arr = emscripten::val::array(GetNarrowedIntfromInt64(output_shape)); + emscripten::val output = model_builder.GetBuilder().call("expand", input, output_shape_arr, options); model_builder.AddOperand(node.OutputDefs()[0]->Name(), std::move(output)); return Status::OK(); } diff --git a/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc index 49c03e5af23b4..c5cc8e86bb308 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc @@ -55,22 +55,20 @@ Status GemmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N if (a_shape.size() == 1) { extended_a_shape = true; a_shape.insert(a_shape.begin(), 1); + emscripten::val a_shape_arr = emscripten::val::array(GetNarrowedIntfromInt64(a_shape)); emscripten::val reshape_a_options = emscripten::val::object(); reshape_a_options.set("label", node.Name() + "_reshape_a"); - a = model_builder.GetBuilder().call("reshape", a, - emscripten::val::array(GetVecUint32FromVecInt64(a_shape)), - reshape_a_options); + a = model_builder.GetBuilder().call("reshape", a, a_shape_arr, reshape_a_options); } // If the second argument is 1-D, it is promoted to a matrix by appending a 1 to its dimensions. bool extended_b_shape = false; if (b_shape.size() == 1) { extended_b_shape = true; b_shape.push_back(1); + emscripten::val b_shape_arr = emscripten::val::array(GetNarrowedIntfromInt64(b_shape)); emscripten::val reshape_b_options = emscripten::val::object(); reshape_b_options.set("label", node.Name() + "_reshape_b"); - b = model_builder.GetBuilder().call("reshape", b, - emscripten::val::array(GetVecUint32FromVecInt64(b_shape)), - reshape_b_options); + b = model_builder.GetBuilder().call("reshape", b, b_shape_arr, reshape_b_options); } output = model_builder.GetBuilder().call("matmul", a, b, options); diff --git a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc index 356f1a9042555..a090c21fe3356 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc @@ -208,7 +208,7 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder output = model_builder.GetBuilder().call("instanceNormalization", input, options); // Reshape back to the original output shape for 3D input. if (input_shape.size() != 4) { - std::vector output_shape = GetVecUint32FromVecInt64(input_shape); + std::vector output_shape = GetNarrowedIntfromInt64(input_shape); emscripten::val reshape_output_options = emscripten::val::object(); reshape_output_options.set("label", node.Name() + "reshape_output"); output = model_builder.GetBuilder().call("reshape", diff --git a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc index 0af62dacedbd5..b338d27986279 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc @@ -95,7 +95,7 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, auto_pad_type, pads_out, model_builder.GetPreferredLayout() == DataLayout::NCHW)); - pads = GetVecUint32FromVecInt64(pads_out); + pads = GetNarrowedIntfromInt64(pads_out); } // Permute the ONNX's pads, which is [beginning_height, beginning_width, ending_height, ending_width], // while WebNN's padding is [beginning_height, ending_height, beginning_width, ending_width]. diff --git a/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc index fddfb28184ada..1bb6523c6f86a 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc @@ -100,7 +100,7 @@ Status QDQOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, if (!has_zero_point) { if (zero_point_shape.empty()) { // zero_point has the same shape as the scale tensor. - zero_point_shape = GetVecUint32FromVecInt64(scale_shape); + zero_point_shape = GetNarrowedIntfromInt64(scale_shape); } // Create a zero constant with the same shape as the scale tensor. // The zero value has been pre-processed in the CreateOrGetConstant function, diff --git a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc index 00f8cff25ccf5..58515d2df54ec 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc @@ -225,7 +225,7 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, if (using_sizes) { ORT_RETURN_IF_NOT(GetResizeSizesAndAxes(initializers, node, sizes, axes, is_nhwc, input_shape, logger), "Error getting Resize sizes"); - webnn_sizes = GetVecUint32FromVecInt64(sizes); + webnn_sizes = GetNarrowedIntfromInt64(sizes); options.set("sizes", emscripten::val::array(webnn_sizes)); } else { ORT_RETURN_IF_NOT(GetResizeScalesAndAxes(initializers, node, scales, axes, is_nhwc, logger), @@ -233,7 +233,7 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, options.set("scales", emscripten::val::array(scales)); } - std::vector webnn_axes = GetVecUint32FromVecInt64(axes); + std::vector webnn_axes = GetNarrowedIntfromInt64(axes); options.set("axes", emscripten::val::array(webnn_axes)); emscripten::val input = model_builder.GetOperand(input_defs[0]->Name()); diff --git a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc index 966deb14196dd..1688dfc97a0c4 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc @@ -159,14 +159,22 @@ Status RotaryEmbeddingOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_build if (position_ids_is_offset) { // We generate a sequence from 0 to sequence_length and add the offset to it. const std::vector position_ids_range_shape = {1, sequence_length}; - emscripten::val position_ids_range_buffer = emscripten::val::global("BigInt64Array").new_(sequence_length); + std::string typed_array_name = "BigInt64Array"; + int position_ids_data_type = ONNX_NAMESPACE::TensorProto_DataType_INT64; + const bool is_int64_supported = model_builder.IsInt64Supported(); + if (!is_int64_supported) { + // Int64 is not supported by current context, use int32 instead. + typed_array_name = "Int32Array"; + position_ids_data_type = ONNX_NAMESPACE::TensorProto_DataType_INT32; + } + emscripten::val position_ids_range_buffer = emscripten::val::global(typed_array_name.c_str()).new_(sequence_length); for (uint32_t i = 0; i < sequence_length; i++) { - position_ids_range_buffer.set(i, emscripten::val::global("BigInt")(i)); + position_ids_range_buffer.set(i, is_int64_supported ? emscripten::val::global("BigInt")(i) : emscripten::val(i)); } emscripten::val position_ids_range_desc = emscripten::val::object(); position_ids_range_desc.set("shape", emscripten::val::array(position_ids_range_shape)); position_ids_range_desc.set("dimensions", emscripten::val::array(position_ids_range_shape)); - position_ids_range_desc.set("dataType", emscripten::val("int64")); + ORT_RETURN_IF_NOT(SetWebnnDataType(position_ids_range_desc, position_ids_data_type), "Unsupported data type"); emscripten::val position_ids_range = wnn_builder.call( "constant", position_ids_range_desc, position_ids_range_buffer); // Add the offset to the sequence. @@ -267,7 +275,7 @@ Status RotaryEmbeddingOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_build } // Reshape the output to the original shape. The output shape is the same as the input shape. - const std::vector output_shape = GetVecUint32FromVecInt64(input_shape); + const std::vector output_shape = GetNarrowedIntfromInt64(input_shape); emscripten::val reshape_output_options = emscripten::val::object(); reshape_output_options.set("label", node_name + "_reshape_output"); output = wnn_builder.call( diff --git a/onnxruntime/core/providers/webnn/builders/impl/shape_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/shape_op_builder.cc index 360c6588898f1..2bea1af896eee 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/shape_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/shape_op_builder.cc @@ -29,12 +29,20 @@ Status ShapeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const auto rank = static_cast(input_shape.size()); emscripten::val desc = emscripten::val::object(); - ORT_RETURN_IF_NOT(SetWebnnDataType(desc, ONNX_NAMESPACE::TensorProto_DataType_INT64), "Unsupported data type"); emscripten::val dims = emscripten::val::array(); dims.call("push", rank); desc.set("dimensions", dims); desc.set("shape", dims); - emscripten::val shape_buffer = emscripten::val::global("BigInt64Array").new_(emscripten::val::array(input_shape)); + int data_type = ONNX_NAMESPACE::TensorProto_DataType_INT64; + std::string typed_array_name = "BigInt64Array"; + if (!model_builder.IsInt64Supported()) { + // Int64 is not supported by current context, use int32 instead. + data_type = ONNX_NAMESPACE::TensorProto_DataType_INT32; + typed_array_name = "Int32Array"; + } + ORT_RETURN_IF_NOT(SetWebnnDataType(desc, data_type), "Unsupported data type"); + emscripten::val shape_buffer = + emscripten::val::global(typed_array_name.c_str()).new_(emscripten::val::array(input_shape)); emscripten::val shape_constant = model_builder.GetBuilder().call("constant", desc, shape_buffer); NodeAttrHelper helper(node); diff --git a/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc index 8baa450204aff..4adc5920de7fa 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc @@ -116,8 +116,8 @@ Status SliceOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const emscripten::val output = reverse_output; if (is_slice_required) { - std::vector starts = GetVecUint32FromVecInt64(compute_metadata.starts_); - std::vector steps = GetVecUint32FromVecInt64(compute_metadata.steps_); + std::vector starts = GetNarrowedIntfromInt64(compute_metadata.starts_); + std::vector steps = GetNarrowedIntfromInt64(compute_metadata.steps_); std::vector sizes(rank); std::transform(compute_metadata.ends_.cbegin(), compute_metadata.ends_.cend(), compute_metadata.starts_.cbegin(), sizes.begin(), [](int64_t i, int64_t j) { return SafeInt(i - j); }); diff --git a/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc index 5eff96873b8c4..a3be9d7e2ceee 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc @@ -86,7 +86,7 @@ Status SqueezeUnsqueezeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_buil emscripten::val output = emscripten::val::undefined(); // Use WebNN's reshape to implement Squeeze/Unsqueeze. - std::vector new_shape = GetVecUint32FromVecInt64(input_shape); + std::vector new_shape = GetNarrowedIntfromInt64(input_shape); // Sort axes_data in ascending order. std::sort(axes_data.begin(), axes_data.end()); if (op_type == "Squeeze") { diff --git a/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc index 3a5e39f7f7a56..ac440e0119bac 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc @@ -41,7 +41,7 @@ Status TransposeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, emscripten::val input = model_builder.GetOperand(input_defs[0]->Name()); emscripten::val options = emscripten::val::object(); options.set("label", node.Name()); - std::vector permutation = GetVecUint32FromVecInt64(perm); + std::vector permutation = GetNarrowedIntfromInt64(perm); options.set("permutation", emscripten::val::array(permutation)); emscripten::val output = model_builder.GetBuilder().call("transpose", input, options); model_builder.AddOperand(node.OutputDefs()[0]->Name(), std::move(output)); diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index cf4ce216ed5b3..661b2ad7056c2 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -34,6 +34,9 @@ ModelBuilder::ModelBuilder(const GraphViewer& graph_viewer, const logging::Logge if (!wnn_builder_.as()) { ORT_THROW("Failed to create WebNN builder."); } + if (wnn_limits["input"]["dataTypes"].call("includes", emscripten::val("int64")).as()) { + is_int64_supported_ = true; + } } Status ModelBuilder::Initialize() { @@ -125,6 +128,10 @@ Status ModelBuilder::RegisterInitializers() { emscripten::val view = emscripten::val::undefined(); std::byte* tensor_ptr = nullptr; + // A flag to indicate if we should convert int64 to int32. + const bool should_convert_int64_to_int32 = !is_int64_supported_ && + data_type == ONNX_NAMESPACE::TensorProto_DataType_INT64; + if (utils::HasExternalData(tensor)) { // Create WebNN Constant from external data. std::basic_string external_file_path; @@ -138,7 +145,8 @@ Status ModelBuilder::RegisterInitializers() { static_cast(data_offset), static_cast(tensor_byte_size), wnn_builder_, - desc); + desc, + should_convert_int64_to_int32); } else { if (tensor.has_raw_data()) { tensor_ptr = reinterpret_cast(const_cast(tensor.raw_data().c_str())); @@ -195,6 +203,21 @@ Status ModelBuilder::RegisterInitializers() { break; } + // If int64 is not supported, convert int64 to int32. + std::vector int32_data; + if (should_convert_int64_to_int32) { + try { + int32_data = GetNarrowedIntfromInt64( + gsl::span(reinterpret_cast(tensor_ptr), num_elements)); + LOGS(logger_, VERBOSE) << "Initializer '" << name << "' is converted from int64 to int32."; + } catch (const std::exception& e) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, e.what()); + } + view = emscripten::val{emscripten::typed_memory_view(num_elements, int32_data.data())}; + + desc.set("dataType", emscripten::val("int32")); + } + // Wasm memory grow will cause all array buffers reallocation, which will be treated as detached // buffers in JS side. Simply create a copy to fix it. view = view.call("slice"); @@ -204,7 +227,7 @@ Status ModelBuilder::RegisterInitializers() { // TODO: support other type. return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "The initializer of graph has unsupported type, name: ", - tensor.name(), " type: ", data_type); + name, " type: ", data_type); } wnn_operands_.insert(std::make_pair(name, operand)); } @@ -260,6 +283,10 @@ Status ModelBuilder::RegisterModelInputOutput(const NodeArg& node_arg, bool is_i } if (is_input) { + if (data_type == ONNX_NAMESPACE::TensorProto_DataType_INT64 && !is_int64_supported_) { + // Int64 is not supported by current context, use int32 instead. + desc.set("dataType", emscripten::val("int32")); + } wnn_operands_.insert(std::make_pair(name, wnn_builder_.call("input", name, desc))); emscripten::val::module_property("jsepRegisterGraphInput")(name); input_names_.push_back(name); diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.h b/onnxruntime/core/providers/webnn/builders/model_builder.h index 1e5f859506d6b..f45e38935651f 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.h +++ b/onnxruntime/core/providers/webnn/builders/model_builder.h @@ -34,6 +34,8 @@ class ModelBuilder { const GraphViewer& GetGraphViewer() const { return graph_viewer_; } InitializedTensorSet GetInitializerTensors(); + bool IsInt64Supported() const { return is_int64_supported_; } + const emscripten::val& GetBuilder() const { return wnn_builder_; } const emscripten::val& GetContext() const { return wnn_context_; } const emscripten::val& GetOperand(const std::string& name) const { return wnn_operands_.at(name); } @@ -74,6 +76,7 @@ class ModelBuilder { emscripten::val wnn_context_ = emscripten::val::undefined(); emscripten::val wnn_builder_ = emscripten::val::undefined(); + bool is_int64_supported_ = false; DataLayout preferred_layout_; WebnnDeviceType wnn_device_type_; emscripten::val wnn_limits_ = emscripten::val::undefined(); diff --git a/onnxruntime/wasm/pre-jsep.js b/onnxruntime/wasm/pre-jsep.js index 5b2f044d4c27b..a11c6d741d110 100644 --- a/onnxruntime/wasm/pre-jsep.js +++ b/onnxruntime/wasm/pre-jsep.js @@ -136,7 +136,8 @@ Module["jsepInit"] = (name, params) => { dataOffset, dataLength, builder, - desc + desc, + shouldConvertInt64ToInt32, ) => { return backend["registerMLConstant"]( externalFilePath, @@ -144,14 +145,13 @@ Module["jsepInit"] = (name, params) => { dataLength, builder, desc, - Module.MountedFiles + Module.MountedFiles, + shouldConvertInt64ToInt32, ); }; - Module["jsepRegisterGraphInput"] = - backend["registerGraphInput"].bind(backend); - Module["jsepIsGraphInput"] = backend["isGraphInput"].bind(backend); - - Module["jsepCreateTemporaryTensor"] = - backend["createTemporaryTensor"].bind(backend); + Module['jsepRegisterGraphInput'] = backend['registerGraphInput'].bind(backend); + Module['jsepIsGraphInput'] = backend['isGraphInput'].bind(backend); + Module['jsepCreateTemporaryTensor'] = backend['createTemporaryTensor'].bind(backend); + Module['jsepIsInt64Supported'] = backend['isInt64Supported'].bind(backend); } }; From b8966665d56e1c2295c160d2af875e3e88dd5437 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Fri, 14 Mar 2025 15:44:29 -0700 Subject: [PATCH 105/266] Convert Windows GPU pipelines and Windows OpenVino pipeline to Github Actions (#24029) ### Description Convert Windows GPU pipelines and Windows OpenVino pipeline to Github Actions --- .../install-onnxruntime-wheel/action.yml | 18 ++ .github/workflows/ios.yml | 9 +- .github/workflows/windows_cuda.yml | 135 +++++++++ .github/workflows/windows_dml.yml | 118 ++++++++ .github/workflows/windows_openvino.yml | 172 ++++++++++++ .github/workflows/windows_tensorrt.yml | 101 +++++++ .github/workflows/windows_webgpu.yml | 262 ++++++++++++++++++ tools/ci_build/build.py | 11 +- .../win-gpu-cuda-ci-pipeline.yml | 65 ----- .../win-gpu-dml-ci-pipeline.yml | 53 ---- .../win-gpu-tensorrt-ci-pipeline.yml | 98 ------- .../win-gpu-webgpu-ci-pipeline.yml | 135 --------- .../win-openvino-ci-pipeline.yml | 116 -------- tools/python/run_CIs_for_external_pr.py | 8 - tools/python/util/vcpkg_helpers.py | 5 +- 15 files changed, 825 insertions(+), 481 deletions(-) create mode 100644 .github/actions/install-onnxruntime-wheel/action.yml create mode 100644 .github/workflows/windows_cuda.yml create mode 100644 .github/workflows/windows_dml.yml create mode 100644 .github/workflows/windows_openvino.yml create mode 100644 .github/workflows/windows_tensorrt.yml create mode 100644 .github/workflows/windows_webgpu.yml delete mode 100644 tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/win-gpu-webgpu-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml diff --git a/.github/actions/install-onnxruntime-wheel/action.yml b/.github/actions/install-onnxruntime-wheel/action.yml new file mode 100644 index 0000000000000..07f9a00a1dbcf --- /dev/null +++ b/.github/actions/install-onnxruntime-wheel/action.yml @@ -0,0 +1,18 @@ +name: 'Install ONNX Runtime Wheel' +description: 'Uninstalls existing ONNX Runtime packages and installs a wheel from a specified directory.' +inputs: + whl-directory: + description: 'The directory containing the ONNX Runtime wheel files.' + required: true +runs: + using: 'composite' + steps: + - name: Uninstall onnxruntime packages + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + + - name: Install onnxruntime wheel from specified directory + shell: pwsh + run: | + Get-ChildItem -Path ${{ inputs.whl-directory }}/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} \ No newline at end of file diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 063b5488499e1..d2738f7d09d79 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -2,9 +2,14 @@ name: iOS_CI_on_Mac on: push: - branches: [ main, 'rel-*'] + branches: + - main + - rel-* pull_request: - branches: [ main ] + branches: + - main + - rel-* + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/windows_cuda.yml b/.github/workflows/windows_cuda.yml new file mode 100644 index 0000000000000..d26ee0a2b766e --- /dev/null +++ b/.github/workflows/windows_cuda.yml @@ -0,0 +1,135 @@ +name: ONNX Runtime CUDA Builds + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_RelWithDebInfo: + name: Windows GPU CUDA CI Pipeline # Job name set here + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all tags and branches + submodules: 'none' + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.2 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.2" . + dir + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.2\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.2\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.2\extras\CUPTI\lib64" + + - uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-dotnet@v4 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: nuget restore ${{ github.workspace }}\packages.config -ConfigFile ${{ github.workspace }}\NuGet.config -PackagesDirectory ${{ runner.temp }}\build\RelWithDebInfo + shell: cmd + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build and Test + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir build --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --build_java --build_nodejs --use_cuda --cuda_home="$env:RUNNER_TEMP\v12.2" --enable_cuda_profiling --enable_transformers_tool_test --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON --cmake_extra_defines onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ runner.temp }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + shell: pwsh + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\csharp + shell: cmd + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist + + timeout-minutes: 300 + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.Gpu + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 \ No newline at end of file diff --git a/.github/workflows/windows_dml.yml b/.github/workflows/windows_dml.yml new file mode 100644 index 0000000000000..c7a4c796555d6 --- /dev/null +++ b/.github/workflows/windows_dml.yml @@ -0,0 +1,118 @@ +name: ONNX Runtime DirectML Builds + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_x64_RelWithDebInfo: + name: Windows GPU DML CI Pipeline + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.DirectML + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all tags and branches + submodules: 'none' + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-dotnet@v4 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: nuget restore ${{ github.workspace }}\packages.config -ConfigFile ${{ github.workspace }}\NuGet.config -PackagesDirectory ${{ github.workspace }}\RelWithDebInfo + shell: cmd + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build and Test + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir build --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --use_dml --enable_wcos --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + shell: pwsh + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\csharp + shell: cmd + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist + + \ No newline at end of file diff --git a/.github/workflows/windows_openvino.yml b/.github/workflows/windows_openvino.yml new file mode 100644 index 0000000000000..45ffa40273df8 --- /dev/null +++ b/.github/workflows/windows_openvino.yml @@ -0,0 +1,172 @@ +name: Windows OpenVINO CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + BUILD_OPENVINO_EP: + name: Windows OpenVINO CI Pipeline + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + timeout-minutes: 240 + env: + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '1' + BuildConfig: RelWithDebInfo + buildArch: x64 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 #Keep x64, because the original pipeline is for x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Download OpenVINO Toolkit v2025.0.0 + env: + OpenVINOVersion: 2025.0.0 + shell: pwsh + run: | + $Url = "https://storage.openvinotoolkit.org/repositories/openvino/packages/2025.0/windows/openvino_toolkit_windows_2025.0.0.17942.1f68be9f594_x86_64.zip" + $OutputPath = "$env:RUNNER_TEMP\openvino.zip" + $ExtractPath = "$env:RUNNER_TEMP\openvino-v$env:OpenVINOVersion" + $TempExtractPath = "$env:RUNNER_TEMP\openvino_temp" + + # Ensure directories exist + if (Test-Path $ExtractPath) { + Remove-Item -Recurse -Force $ExtractPath + } + New-Item -ItemType Directory -Path $ExtractPath | Out-Null + New-Item -ItemType Directory -Path $TempExtractPath | Out-Null + + # Download OpenVINO ZIP + Write-Output "Downloading OpenVINO" + Invoke-WebRequest -Uri $Url -OutFile $OutputPath + + # Extract to temporary directory first + Write-Output "Extracting OpenVINO to a temporary directory" + Expand-Archive -Path $OutputPath -DestinationPath $TempExtractPath -Force + + # Locate the nested subdirectory + $InnerFolder = Get-ChildItem -Path $TempExtractPath -Directory | Select-Object -First 1 + + if ($InnerFolder) { + Write-Output "Moving extracted files to final destination" + Move-Item -Path "$($InnerFolder.FullName)\*" -Destination $ExtractPath -Force + } else { + Write-Error "Extraction failed: No expected subdirectory found in $TempExtractPath." + Write-Error "The archive may not have extracted correctly, or its structure is different than expected." + exit 1 + } + + # Clean up temporary files + Remove-Item -Recurse -Force $TempExtractPath + Remove-Item -Force $OutputPath + + # Confirm success + Write-Output "OpenVINO extracted to $ExtractPath" + + - name: Set OpenVINORootDir + shell: pwsh + # Use $GITHUB_ENV to set the variable for subsequent steps + run: | + $openVinoRootDir = Join-Path $env:RUNNER_TEMP "openvino-v2025.0.0" + echo "OpenVINORootDir=$openVinoRootDir" >> $env:GITHUB_ENV + + - name: Print OpenVINORootDir after downloading OpenVINO + shell: cmd + run: 'echo %OpenVINORootDir%' + + - name: Print contents of OpenVINO Toolkit + shell: cmd + run: 'dir %OpenVINORootDir%' + + - name: Set up OpenVINO environment + shell: pwsh + run: | + Write-Output "Setting up OpenVINO environment variables" + . "$env:OpenVINORootDir\setupvars.ps1" + + Write-Output "Exporting selected environment variables to pipeline" + + $vars = @( + "INTEL_OPENVINO_DIR", + "OpenVINO_DIR", + "OpenVINOGenAI_DIR", + "OPENVINO_LIB_PATHS", + "TBB_DIR", + "PATH", + "PYTHONPATH" + ) + + foreach ($var in $vars) { + if (Test-Path "Env:$var") { + $value = [System.Environment]::GetEnvironmentVariable($var, "Process") + Write-Output "Setting $var=$value" + echo "$var=$value" >> $env:GITHUB_ENV # Append to GITHUB_ENV + } else { + Write-Output "Warning: $var is not set." + } + } + + Write-Output "Selected environment variables exported successfully" + + + + - name: Generate onnxruntime.sln + shell: pwsh + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config ${{ env.BuildConfig }} --build_dir build --cmake_generator "Visual Studio 17 2022" --build_shared_lib --use_openvino CPU --use_binskim_compliant_compile_flags --update --parallel + + - name: Build + shell: pwsh + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config ${{ env.BuildConfig }} --build_dir build --cmake_generator "Visual Studio 17 2022" --build_shared_lib --use_openvino CPU --use_binskim_compliant_compile_flags --build --parallel + + + - name: Run unit tests + shell: pwsh + working-directory: ${{ runner.temp }} + run: | + python "${{ github.workspace }}\tools\ci_build\build.py" ` + --config "${{ env.BuildConfig }}" ` + --build_dir build ` + --cmake_generator "Visual Studio 17 2022" ` + --build_shared_lib ` + --use_openvino CPU ` + --use_binskim_compliant_compile_flags ` + --test --enable_onnx_tests \ No newline at end of file diff --git a/.github/workflows/windows_tensorrt.yml b/.github/workflows/windows_tensorrt.yml new file mode 100644 index 0000000000000..1f52b79b67d67 --- /dev/null +++ b/.github/workflows/windows_tensorrt.yml @@ -0,0 +1,101 @@ +name: Windows GPU TensorRT CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + Windows_GPU_TensorRT_CI_Pipeline: + name: Windows GPU TensorRT CI Pipeline + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all tags and branches + submodules: 'none' + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r ${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt + shell: cmd + + - name: Download Primary CUDA SDK v12.2 + run: 'azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.2" ${{ runner.temp }}' + shell: pwsh + env: + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + + - name: Download TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8 + run: 'azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8" ${{ runner.temp }}' + shell: pwsh + env: + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.2\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.2\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.2\extras\CUPTI\lib64" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8\lib" + + - name: Generate sln + working-directory: ${{ runner.temp }} + run: | + python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --parallel --use_binskim_compliant_compile_flags --build_dir build --skip_submodule_sync --build_shared_lib --update --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8" --cuda_home="${{ runner.temp }}\v12.2" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + shell: cmd + + - name: Build + working-directory: ${{ runner.temp }} + run: | + python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --parallel --use_binskim_compliant_compile_flags --build_dir build --skip_submodule_sync --build_shared_lib --build --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8" --cuda_home="${{ runner.temp }}\v12.2" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + shell: cmd + + - name: Add build dir to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\build\RelWithDebInfo\RelWithDebInfo" + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist + + - name: Run tests + working-directory: ${{ runner.temp }} + run: | + mklink /D /J ${{ github.workspace }}\RelWithDebInfo\models ${{ github.workspace }}\models + python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --parallel --use_binskim_compliant_compile_flags --build_dir build --skip_submodule_sync --build_shared_lib --test --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8" --cuda_home="${{ runner.temp }}\v12.2" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + shell: cmd + timeout-minutes: 180 \ No newline at end of file diff --git a/.github/workflows/windows_webgpu.yml b/.github/workflows/windows_webgpu.yml new file mode 100644 index 0000000000000..7b8415c223e0f --- /dev/null +++ b/.github/workflows/windows_webgpu.yml @@ -0,0 +1,262 @@ +name: ONNX Runtime WebGPU Builds + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + webgpu_build_x64_RelWithDebInfo: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] + timeout-minutes: 300 + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + NVIDIA_TF32_OVERRIDE: '0' + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: | + nuget restore packages.config -ConfigFile NuGet.config -PackagesDirectory ${{ github.workspace }}\RelWithDebInfo + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build and Test + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_nodejs --use_webgpu --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY=ON + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + shell: cmd + working-directory: ${{ github.workspace }}\csharp + continue-on-error: true + + + webgpu_external_dawn_build_x64_RelWithDebInfo: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] + timeout-minutes: 300 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Generate onnxruntime.sln + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --update --parallel --cmake_generator "Visual Studio 17 2022" --use_webgpu --use_external_dawn --skip_tests --target onnxruntime_webgpu_external_dawn_test + + - name: Build + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --build --parallel --cmake_generator "Visual Studio 17 2022" --use_webgpu --use_external_dawn --skip_tests --target onnxruntime_webgpu_external_dawn_test + + - name: Run tests (onnxruntime_webgpu_external_dawn_test) + run: onnxruntime_webgpu_external_dawn_test.exe + shell: cmd + working-directory: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + + - name: Run tests (onnxruntime_webgpu_external_dawn_test) - no_proc_table + run: onnxruntime_webgpu_external_dawn_test.exe --no_proc_table + shell: cmd + working-directory: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + + webgpu_minimal_build_edge_build_x64_RelWithDebInfo: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] + timeout-minutes: 300 + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: | + nuget restore packages.config -ConfigFile NuGet.config -PackagesDirectory ${{ github.workspace }}\RelWithDebInfo + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Build + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --build_shared_lib --disable_exceptions --disable_rtti --enable_msvc_static_runtime --enable_reduced_operator_type_support --skip_tests --use_binskim_compliant_compile_flags --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF onnxruntime_DISABLE_SPARSE_TENSORS=ON onnxruntime_DISABLE_OPTIONAL_TYPE=ON --minimal_build extended --use_webgpu + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + shell: cmd + working-directory: ${{ github.workspace }}\csharp \ No newline at end of file diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 657259b17b458..d5903c9d1d211 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -1066,6 +1066,8 @@ def generate_vcpkg_install_options(build_dir, args): if args.disable_exceptions: folder_name_parts.append("noexception") if len(folder_name_parts) == 0: + # It's hard to tell whether we must use a custom triplet or not. The official triplets work fine for most common situations. However, if a Windows build has set msvc toolset version via args.msvc_toolset then we need to, because we need to ensure all the source code are compiled by the same MSVC toolset version otherwise we will hit link errors like "error LNK2019: unresolved external symbol __std_mismatch_4 referenced in function ..." + # So, to be safe we always use a custom triplet. folder_name = "default" else: folder_name = "_".join(folder_name_parts) @@ -1259,7 +1261,6 @@ def generate_build_tree( ) if args.use_vcpkg: - # TODO: set VCPKG_PLATFORM_TOOLSET_VERSION # Setup CMake flags for vcpkg # Find VCPKG's toolchain cmake file @@ -1339,7 +1340,7 @@ def generate_build_tree( elif args.android: generate_android_triplets(build_dir, args.android_cpp_shared, args.android_api) elif is_windows(): - generate_windows_triplets(build_dir) + generate_windows_triplets(build_dir, args.msvc_toolset) elif is_macOS(): osx_target = args.apple_deploy_target if args.apple_deploy_target is None: @@ -1380,7 +1381,7 @@ def generate_build_tree( target_arch = platform.machine() if args.arm64: target_arch = "ARM64" - elif args.arm64: + elif args.arm64ec: target_arch = "ARM64EC" cpu_arch = platform.architecture()[0] if target_arch == "AMD64": @@ -2646,6 +2647,7 @@ def build_nuget_package( use_dnnl, use_winml, use_qnn, + use_dml, enable_training_apis, msbuild_extra_options, ): @@ -2688,6 +2690,8 @@ def build_nuget_package( package_name = "/p:OrtPackageId=Microsoft.ML.OnnxRuntime.DNNL" elif use_cuda: package_name = "/p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu" + elif use_dml: + package_name = "/p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML" elif use_rocm: package_name = "/p:OrtPackageId=Microsoft.ML.OnnxRuntime.ROCm" elif use_qnn: @@ -3301,6 +3305,7 @@ def main(): args.use_dnnl, args.use_winml, args.use_qnn, + args.use_dml, args.enable_training_apis, normalize_arg_list(args.msbuild_extra_options), ) diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml deleted file mode 100644 index cbebcad2af986..0000000000000 --- a/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml +++ /dev/null @@ -1,65 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -parameters: -- name: CudaVersion - displayName: CUDA version - type: string - default: '12.2' - values: - - 11.8 - - 12.2 -- name: RunOnnxRuntimeTests - displayName: Run Tests? - type: boolean - default: true - -stages: -- stage: cuda - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - EnvSetupScript: setup_env_cuda.bat - buildArch: x64 - additionalBuildFlags: >- - --build_wheel --build_java --build_nodejs --use_cuda --cuda_home="$(Agent.TempDirectory)\v${{ parameters.CudaVersion }}" - --enable_cuda_profiling --enable_transformers_tool_test - --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 - --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON - --cmake_extra_defines onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_RelWithDebInfo - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - ORT_EP_NAME: CUDA - WITH_CACHE: true - MachinePool: onnxruntime-Win2022-GPU-A10 \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml deleted file mode 100644 index 82ca32e65261c..0000000000000 --- a/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml +++ /dev/null @@ -1,53 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -parameters: -- name: RunOnnxRuntimeTests - displayName: Run Tests? - type: boolean - default: true - -stages: -- stage: dml - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - EnvSetupScript: setup_env.bat - buildArch: x64 - additionalBuildFlags: --build_wheel --use_dml --enable_wcos --use_winml --use_vcpkg --use_vcpkg_ms_internal_asset_cache - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_RelWithDebInfo - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - ORT_EP_NAME: DML - WITH_CACHE: false - MachinePool: onnxruntime-Win2022-GPU-dml-A10 \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml deleted file mode 100644 index 5c6d9dd6ed955..0000000000000 --- a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml +++ /dev/null @@ -1,98 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### -parameters: -- name: CudaVersion - displayName: CUDA version - type: string - default: '12.2' - values: - - 11.8 - - 12.2 - -variables: - - template: templates/common-variables.yml - - name: win_trt_folder - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: ${{ variables.win_trt_folder_cuda11 }} - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: ${{ variables.win_trt_folder_cuda12 }} - -jobs: -- job: 'build' - pool: 'onnxruntime-Win2022-GPU-A10' - variables: - MsbuildArguments: '-detailedsummary -maxcpucount -consoleloggerparameters:PerformanceSummary' - EnvSetupScript: setup_env_trt.bat - skipComponentGovernanceDetection: true - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - timeoutInMinutes: 180 - workspace: - clean: all - steps: - - template: templates/jobs/win-ci-prebuild-steps.yml - parameters: - EnvSetupScript: $(EnvSetupScript) - DownloadCUDA: true - DownloadTRT: true - BuildArch: 'x64' - BuildConfig: RelWithDebInfo - MachinePool: 'onnxruntime-Win2022-GPU-A10' - WithCache: true - Today: $(Today) - - - template: templates/jobs/win-ci-build-steps.yml - parameters: - WithCache: True - Today: $(TODAY) - AdditionalKey: "gpu-tensorrt | RelWithDebInfo" - BuildPyArguments: '--config RelWithDebInfo --parallel --use_binskim_compliant_compile_flags --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --update --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\${{ variables.win_trt_folder }}" --cuda_home="$(Agent.TempDirectory)\v${{ parameters.CudaVersion }}" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86' - MsbuildArguments: $(MsbuildArguments) - BuildArch: 'x64' - Platform: 'x64' - BuildConfig: RelWithDebInfo - - - task: PythonScript@0 - displayName: 'Build wheel' - inputs: - scriptPath: '$(Build.SourcesDirectory)\setup.py' - arguments: 'bdist_wheel' - workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - - - script: | - mklink /D /J $(Build.BinariesDirectory)\RelWithDebInfo\models $(Build.BinariesDirectory)\models - DIR dist\ /S /B > wheel_filename_file - set /p WHEEL_FILENAME=- - --build_nodejs - --use_webgpu - --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY=ON - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_RelWithDebInfo - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - ORT_EP_NAME: WebGPU - EnablePython: false - WITH_CACHE: true - MachinePool: onnxruntime-Win2022-VS2022-webgpu-A10 - -- stage: webgpu_external_dawn - dependsOn: [] - jobs: - - job: build_x64_RelWithDebInfo - variables: - DEPS_CACHE_DIR: $(Agent.TempDirectory)/deps_ccache - ORT_CACHE_DIR: $(Agent.TempDirectory)/ort_ccache - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - workspace: - clean: all - pool: onnxruntime-Win2022-VS2022-webgpu-A10 - timeoutInMinutes: 300 - steps: - - checkout: self - clean: true - submodules: none - - - template: templates/jobs/win-ci-prebuild-steps.yml - parameters: - EnvSetupScript: setup_env.bat - DownloadCUDA: false - DownloadTRT: false - BuildArch: x64 - BuildConfig: RelWithDebInfo - MachinePool: onnxruntime-Win2022-VS2022-webgpu-A10 - WithCache: true - Today: $(Today) - - - template: templates/jobs/win-ci-build-steps.yml - parameters: - WithCache: true - Today: $(TODAY) - CacheDir: $(ORT_CACHE_DIR) - AdditionalKey: " $(System.StageName) | RelWithDebInfo " - BuildPyArguments: '--config RelWithDebInfo --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --update --parallel --cmake_generator "Visual Studio 17 2022" --use_webgpu --use_external_dawn --skip_tests --target onnxruntime_webgpu_external_dawn_test' - MsbuildArguments: '-maxcpucount' - BuildArch: x64 - Platform: x64 - BuildConfig: RelWithDebInfo - - - script: | - onnxruntime_webgpu_external_dawn_test.exe - displayName: Run tests (onnxruntime_webgpu_external_dawn_test) - workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - - script: | - onnxruntime_webgpu_external_dawn_test.exe --no_proc_table - displayName: Run tests (onnxruntime_webgpu_external_dawn_test) - workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - -- stage: webgpu_minimal_build_edge - dependsOn: [] - jobs: - - template: templates/jobs/win-ci-vs-2022-job.yml - parameters: - BuildConfig: 'RelWithDebInfo' - EnvSetupScript: setup_env.bat - buildArch: x64 - additionalBuildFlags: >- - --build_shared_lib - --disable_exceptions - --disable_rtti - --enable_msvc_static_runtime - --enable_reduced_operator_type_support - --skip_tests - --use_binskim_compliant_compile_flags - --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF onnxruntime_DISABLE_SPARSE_TENSORS=ON onnxruntime_DISABLE_OPTIONAL_TYPE=ON - --minimal_build extended - --use_webgpu - msbuildPlatform: x64 - isX86: false - job_name_suffix: x64_RelWithDebInfo - RunOnnxRuntimeTests: false - ORT_EP_NAME: WebGPU - EnablePython: false - WITH_CACHE: true - MachinePool: onnxruntime-Win2022-VS2022-webgpu-A10 diff --git a/tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml deleted file mode 100644 index f95ac526886fa..0000000000000 --- a/tools/ci_build/github/azure-pipelines/win-openvino-ci-pipeline.yml +++ /dev/null @@ -1,116 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -jobs: -- job: 'BUILD_OPENVINO_EP' - pool: 'onnxruntime-Win-CPU-2022' - variables: - MsbuildArguments: '-detailedsummary -maxcpucount -consoleloggerparameters:PerformanceSummary' - OnnxRuntimeBuildDirectory: '$(Build.BinariesDirectory)' - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - buildArch: x64 - setVcvars: true - BuildConfig: 'RelWithDebInfo' - ALLOW_RELEASED_ONNX_OPSET_ONLY: '1' - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - timeoutInMinutes: 240 - workspace: - clean: all - steps: - - - task: UsePythonVersion@0 - inputs: - versionSpec: '3.12' - addToPath: true - architecture: $(buildArch) - - - template: templates/jobs/download_win_openvino.yml - - - powershell: | - Write-Output "Setting up OpenVINO environment variables" - . "$(OpenVINORootDir)\setupvars.ps1" - - Write-Output "Exporting selected environment variables to pipeline" - - $vars = @( - "INTEL_OPENVINO_DIR", - "OpenVINO_DIR", - "OpenVINOGenAI_DIR", - "OPENVINO_LIB_PATHS", - "TBB_DIR", - "PATH", - "PYTHONPATH" - ) - - foreach ($var in $vars) { - if (Test-Path "Env:$var") { - $value = [System.Environment]::GetEnvironmentVariable($var, "Process") - Write-Output "Setting $var" - Write-Output "##vso[task.setvariable variable=$var;]$value" - } else { - Write-Output "Warning: $var is not set." - } - } - - Write-Output "Selected environment variables exported successfully" - displayName: 'Set up OpenVINO environment' - - - template: templates/jobs/win-ci-build-steps.yml - parameters: - WithCache: True - Today: $(TODAY) - AdditionalKey: "win-openvino | $(BuildConfig)" - BuildPyArguments: >- - --config $(BuildConfig) - --build_dir $(Build.BinariesDirectory) - --cmake_generator "Visual Studio 17 2022" - --build_shared_lib - --use_openvino CPU - --use_binskim_compliant_compile_flags - --update --parallel - MsbuildArguments: $(MsbuildArguments) - BuildArch: $(buildArch) - Platform: 'x64' - BuildConfig: $(BuildConfig) - - - powershell: | - Write-Output "Getting CPU information" - Get-WmiObject Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors, Architecture | Format-Table -AutoSize - - Write-Output "Starting unit tests" - python "$(Build.SourcesDirectory)\tools\ci_build\build.py" ` - --config "$(BuildConfig)" ` - --build_dir "$(Build.BinariesDirectory)" ` - --cmake_generator "Visual Studio 17 2022" ` - --build_shared_lib ` - --use_openvino CPU ` - --use_binskim_compliant_compile_flags ` - --test --enable_onnx_tests - displayName: 'Run unit tests' diff --git a/tools/python/run_CIs_for_external_pr.py b/tools/python/run_CIs_for_external_pr.py index aca5f1df7d18b..20e0134dd370a 100644 --- a/tools/python/run_CIs_for_external_pr.py +++ b/tools/python/run_CIs_for_external_pr.py @@ -19,12 +19,7 @@ def get_pipeline_names(): # windows "Windows ARM64 QNN CI Pipeline", "Windows x64 QNN CI Pipeline", - "Windows CPU CI Pipeline", - "Windows GPU CUDA CI Pipeline", - "Windows GPU DML CI Pipeline", "Windows GPU Doc Gen CI Pipeline", - "Windows GPU TensorRT CI Pipeline", - "Windows OpenVINO CI Pipeline", "ONNX Runtime Web CI Pipeline", "Win_TRT_Minimal_CUDA_Test_CI", # linux @@ -34,8 +29,6 @@ def get_pipeline_names(): "Linux GPU TensorRT CI Pipeline", "Linux OpenVINO CI Pipeline", "Linux QNN CI Pipeline", - # mac - "MacOS CI Pipeline", # checks "onnxruntime-binary-size-checks-ci-pipeline", # big models @@ -46,7 +39,6 @@ def get_pipeline_names(): "Android CI Pipeline", "iOS CI Pipeline", "ONNX Runtime React Native CI Pipeline", - "CoreML CI Pipeline", "Linux DNNL CI Pipeline", "Linux MIGraphX CI Pipeline", "Linux ROCm CI Pipeline", diff --git a/tools/python/util/vcpkg_helpers.py b/tools/python/util/vcpkg_helpers.py index ccb3181c86486..df457cdbf2b95 100644 --- a/tools/python/util/vcpkg_helpers.py +++ b/tools/python/util/vcpkg_helpers.py @@ -429,12 +429,13 @@ def generate_vcpkg_triplets_for_emscripten(build_dir: str, emscripten_root: str) add_port_configs(f, True, True) -def generate_windows_triplets(build_dir: str) -> None: +def generate_windows_triplets(build_dir: str, toolset_version: str) -> None: """ Generate triplet files for Windows platforms. Args: build_dir (str): The directory to save the generated triplet files. + toolset_version (str, optional): The version of the platform toolset. """ # Below are all the CPU ARCHs we support on Windows. # ARM64 is for ARM64 processes that contains traditional ARM64 code. @@ -473,6 +474,8 @@ def generate_windows_triplets(build_dir: str) -> None: f.write(f"set(VCPKG_TARGET_ARCHITECTURE {target_abi})\n") f.write(f"set(VCPKG_CRT_LINKAGE {crt_linkage})\n") f.write("set(VCPKG_LIBRARY_LINKAGE static)\n") + if toolset_version: + f.write(f"set(VCPKG_PLATFORM_TOOLSET_VERSION {toolset_version})\n") cflags = ["/MP", "/DWIN32", "/D_WINDOWS"] if enable_binskim: cflags += [ From f22ee08f94bef72369987e7c7bde2e773b8b593c Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Fri, 14 Mar 2025 16:07:42 -0700 Subject: [PATCH 106/266] [ARM CPU] Fix fp16 const initialization on no-fp16 platform (#23978) ### Description Fix fp16 const initialization on no-fp16 platform [such as Raspberry PI](https://github.com/microsoft/onnxruntime/issues/23957) ### Motivation and Context Resolve #23957 --- .../mlas/lib/softmax_kernel_neon_fp16.cpp | 151 +++++++++--------- 1 file changed, 73 insertions(+), 78 deletions(-) diff --git a/onnxruntime/core/mlas/lib/softmax_kernel_neon_fp16.cpp b/onnxruntime/core/mlas/lib/softmax_kernel_neon_fp16.cpp index b4e88111b3c58..dfd65d9d55fbb 100644 --- a/onnxruntime/core/mlas/lib/softmax_kernel_neon_fp16.cpp +++ b/onnxruntime/core/mlas/lib/softmax_kernel_neon_fp16.cpp @@ -20,7 +20,6 @@ Module Name: #include "softmax.h" #include "softmax_kernel_neon.h" -// TODO(fajin): intra-loop parallelism namespace softmax_neon { template @@ -44,7 +43,7 @@ struct MlasExpConstants { T MaximumExponent; }; -const MlasExpConstants<_mlas_fp16_> ExpConstantsFp16 = { +constexpr MlasExpConstants<_mlas_fp16_> ExpConstantsFp16 = { 0xcc55, // -25 * ln2 0x498c, // 16 * ln2 0xc95f, // -15.5 * ln2 @@ -64,59 +63,57 @@ const MlasExpConstants<_mlas_fp16_> ExpConstantsFp16 = { 0x3C00, // 15 }; -const MlasExpConstants ExpConstantsFp16x8 = { - MlasBroadcastFloat16x8(ExpConstantsFp16.LowerRange), - MlasBroadcastFloat16x8(ExpConstantsFp16.UpperRange), - MlasBroadcastFloat16x8(ExpConstantsFp16.LowerRangeSumExp), - MlasBroadcastFloat16x8(ExpConstantsFp16.UpperRangeSumExp), - MlasBroadcastFloat16x8(ExpConstantsFp16.RoundingBias), - MlasBroadcastFloat16x8(ExpConstantsFp16.Log2Reciprocal), - MlasBroadcastFloat16x8(ExpConstantsFp16.Log2High), - MlasBroadcastFloat16x8(ExpConstantsFp16.Log2Mid), - MlasBroadcastFloat16x8(ExpConstantsFp16.Log2Low), - MlasBroadcastFloat16x8(ExpConstantsFp16.poly_0), - MlasBroadcastFloat16x8(ExpConstantsFp16.poly_1), - MlasBroadcastFloat16x8(ExpConstantsFp16.poly_2), - MlasBroadcastFloat16x8(ExpConstantsFp16.poly_3), - MlasBroadcastFloat16x8(ExpConstantsFp16.poly_4), - MlasBroadcastFloat16x8(ExpConstantsFp16.poly_56), - MlasBroadcastFloat16x8(ExpConstantsFp16.MinimumExponent), - MlasBroadcastFloat16x8(ExpConstantsFp16.MaximumExponent), -}; - -const MlasExpConstants ExpConstantsFp16x4 = { - MlasBroadcastFloat16x4(ExpConstantsFp16.LowerRange), - MlasBroadcastFloat16x4(ExpConstantsFp16.UpperRange), - MlasBroadcastFloat16x4(ExpConstantsFp16.LowerRangeSumExp), - MlasBroadcastFloat16x4(ExpConstantsFp16.UpperRangeSumExp), - MlasBroadcastFloat16x4(ExpConstantsFp16.RoundingBias), - MlasBroadcastFloat16x4(ExpConstantsFp16.Log2Reciprocal), - MlasBroadcastFloat16x4(ExpConstantsFp16.Log2High), - MlasBroadcastFloat16x4(ExpConstantsFp16.Log2Mid), - MlasBroadcastFloat16x4(ExpConstantsFp16.Log2Low), - MlasBroadcastFloat16x4(ExpConstantsFp16.poly_0), - MlasBroadcastFloat16x4(ExpConstantsFp16.poly_1), - MlasBroadcastFloat16x4(ExpConstantsFp16.poly_2), - MlasBroadcastFloat16x4(ExpConstantsFp16.poly_3), - MlasBroadcastFloat16x4(ExpConstantsFp16.poly_4), - MlasBroadcastFloat16x4(ExpConstantsFp16.poly_56), - MlasBroadcastFloat16x4(ExpConstantsFp16.MinimumExponent), - MlasBroadcastFloat16x4(ExpConstantsFp16.MaximumExponent), -}; - template MLAS_FORCEINLINE -MlasExpConstants Get_Exp_Constants(); +const MlasExpConstants& Get_Exp_Constants(); template <> MLAS_FORCEINLINE -MlasExpConstants Get_Exp_Constants() { +const MlasExpConstants& Get_Exp_Constants() { + const static MlasExpConstants ExpConstantsFp16x8 = { + MlasBroadcastFloat16x8(ExpConstantsFp16.LowerRange), + MlasBroadcastFloat16x8(ExpConstantsFp16.UpperRange), + MlasBroadcastFloat16x8(ExpConstantsFp16.LowerRangeSumExp), + MlasBroadcastFloat16x8(ExpConstantsFp16.UpperRangeSumExp), + MlasBroadcastFloat16x8(ExpConstantsFp16.RoundingBias), + MlasBroadcastFloat16x8(ExpConstantsFp16.Log2Reciprocal), + MlasBroadcastFloat16x8(ExpConstantsFp16.Log2High), + MlasBroadcastFloat16x8(ExpConstantsFp16.Log2Mid), + MlasBroadcastFloat16x8(ExpConstantsFp16.Log2Low), + MlasBroadcastFloat16x8(ExpConstantsFp16.poly_0), + MlasBroadcastFloat16x8(ExpConstantsFp16.poly_1), + MlasBroadcastFloat16x8(ExpConstantsFp16.poly_2), + MlasBroadcastFloat16x8(ExpConstantsFp16.poly_3), + MlasBroadcastFloat16x8(ExpConstantsFp16.poly_4), + MlasBroadcastFloat16x8(ExpConstantsFp16.poly_56), + MlasBroadcastFloat16x8(ExpConstantsFp16.MinimumExponent), + MlasBroadcastFloat16x8(ExpConstantsFp16.MaximumExponent), + }; return ExpConstantsFp16x8; } template <> MLAS_FORCEINLINE -MlasExpConstants Get_Exp_Constants() { +const MlasExpConstants& Get_Exp_Constants() { + const static MlasExpConstants ExpConstantsFp16x4 = { + MlasBroadcastFloat16x4(ExpConstantsFp16.LowerRange), + MlasBroadcastFloat16x4(ExpConstantsFp16.UpperRange), + MlasBroadcastFloat16x4(ExpConstantsFp16.LowerRangeSumExp), + MlasBroadcastFloat16x4(ExpConstantsFp16.UpperRangeSumExp), + MlasBroadcastFloat16x4(ExpConstantsFp16.RoundingBias), + MlasBroadcastFloat16x4(ExpConstantsFp16.Log2Reciprocal), + MlasBroadcastFloat16x4(ExpConstantsFp16.Log2High), + MlasBroadcastFloat16x4(ExpConstantsFp16.Log2Mid), + MlasBroadcastFloat16x4(ExpConstantsFp16.Log2Low), + MlasBroadcastFloat16x4(ExpConstantsFp16.poly_0), + MlasBroadcastFloat16x4(ExpConstantsFp16.poly_1), + MlasBroadcastFloat16x4(ExpConstantsFp16.poly_2), + MlasBroadcastFloat16x4(ExpConstantsFp16.poly_3), + MlasBroadcastFloat16x4(ExpConstantsFp16.poly_4), + MlasBroadcastFloat16x4(ExpConstantsFp16.poly_56), + MlasBroadcastFloat16x4(ExpConstantsFp16.MinimumExponent), + MlasBroadcastFloat16x4(ExpConstantsFp16.MaximumExponent), + }; return ExpConstantsFp16x4; } @@ -124,7 +121,7 @@ MlasExpConstants Get_Exp_Constants() { template MLAS_FORCEINLINE T Exp_Vector_Fp16(T x) { - const auto constants = Get_Exp_Constants(); + const auto& constants = Get_Exp_Constants(); auto clamped_x = MlasClampFloat16(x, constants.LowerRange, constants.UpperRange); // integral @@ -242,7 +239,7 @@ void Exp_Kernel_Fp16(const MLAS_FP16* Input, MLAS_FP16* Output, size_t N) { template MLAS_FORCEINLINE T SumExp_Vector_Fp16(T x, T negative_maximum) { - const auto constants = Get_Exp_Constants(); + const auto& constants = Get_Exp_Constants(); auto clamped_x = MlasMaximumFloat16(MlasAddFloat16(x, negative_maximum), constants.LowerRangeSumExp); // integral @@ -419,7 +416,7 @@ struct MlasTanhConstants { T beta_0; }; -const MlasTanhConstants<_mlas_fp16_> TanhConstantsFp16 = { +constexpr MlasTanhConstants<_mlas_fp16_> TanhConstantsFp16 = { 0xc308, // -3.51562 0x4308, // 3.51562 0x0001, @@ -432,45 +429,43 @@ const MlasTanhConstants<_mlas_fp16_> TanhConstantsFp16 = { 0x1d03, }; -const MlasTanhConstants TanhConstantsFp16x8 = { - MlasBroadcastFloat16x8(TanhConstantsFp16.LowerRange), - MlasBroadcastFloat16x8(TanhConstantsFp16.UpperRange), - MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_7), - MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_5), - MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_3), - MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_1), - MlasBroadcastFloat16x8(TanhConstantsFp16.beta_6), - MlasBroadcastFloat16x8(TanhConstantsFp16.beta_4), - MlasBroadcastFloat16x8(TanhConstantsFp16.beta_2), - MlasBroadcastFloat16x8(TanhConstantsFp16.beta_0), -}; - -const MlasTanhConstants TanhConstantsFp16x4 = { - MlasBroadcastFloat16x4(TanhConstantsFp16.LowerRange), - MlasBroadcastFloat16x4(TanhConstantsFp16.UpperRange), - MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_7), - MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_5), - MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_3), - MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_1), - MlasBroadcastFloat16x4(TanhConstantsFp16.beta_6), - MlasBroadcastFloat16x4(TanhConstantsFp16.beta_4), - MlasBroadcastFloat16x4(TanhConstantsFp16.beta_2), - MlasBroadcastFloat16x4(TanhConstantsFp16.beta_0), -}; - template MLAS_FORCEINLINE -MlasTanhConstants Get_Tanh_Constants(); +const MlasTanhConstants& Get_Tanh_Constants(); template <> MLAS_FORCEINLINE -MlasTanhConstants Get_Tanh_Constants() { +const MlasTanhConstants& Get_Tanh_Constants() { + const static MlasTanhConstants TanhConstantsFp16x8 = { + MlasBroadcastFloat16x8(TanhConstantsFp16.LowerRange), + MlasBroadcastFloat16x8(TanhConstantsFp16.UpperRange), + MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_7), + MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_5), + MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_3), + MlasBroadcastFloat16x8(TanhConstantsFp16.alpha_1), + MlasBroadcastFloat16x8(TanhConstantsFp16.beta_6), + MlasBroadcastFloat16x8(TanhConstantsFp16.beta_4), + MlasBroadcastFloat16x8(TanhConstantsFp16.beta_2), + MlasBroadcastFloat16x8(TanhConstantsFp16.beta_0), + }; return TanhConstantsFp16x8; } template <> MLAS_FORCEINLINE -MlasTanhConstants Get_Tanh_Constants() { +const MlasTanhConstants& Get_Tanh_Constants() { + const static MlasTanhConstants TanhConstantsFp16x4 = { + MlasBroadcastFloat16x4(TanhConstantsFp16.LowerRange), + MlasBroadcastFloat16x4(TanhConstantsFp16.UpperRange), + MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_7), + MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_5), + MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_3), + MlasBroadcastFloat16x4(TanhConstantsFp16.alpha_1), + MlasBroadcastFloat16x4(TanhConstantsFp16.beta_6), + MlasBroadcastFloat16x4(TanhConstantsFp16.beta_4), + MlasBroadcastFloat16x4(TanhConstantsFp16.beta_2), + MlasBroadcastFloat16x4(TanhConstantsFp16.beta_0), + }; return TanhConstantsFp16x4; } @@ -478,7 +473,7 @@ MlasTanhConstants Get_Tanh_Constants() { template MLAS_FORCEINLINE T Tanh_Vector_Fp16(T x) { - const auto constants = Get_Tanh_Constants(); + const auto& constants = Get_Tanh_Constants(); x = MlasClampFloat16(x, constants.LowerRange, constants.UpperRange); T x_2 = MlasMultiplyFloat16(x, x); From ae501eeb4d72e2f81d92ad8f7ede4d666bd3902b Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Fri, 14 Mar 2025 16:14:26 -0700 Subject: [PATCH 107/266] [Native WebGPU EP] Add packedQKV and do_rotary attribute support to GroupQueryAttention operator (#23386) ### Description Add Packed QKV inputs and do_rotary attribute to GQA. ### Motivation and Context Packed QKV inputs and do_rotary attribute are required for certain models. --- .../webgpu/bert/group_query_attention.cc | 147 +++++++++++++++++- .../webgpu/bert/group_query_attention.h | 23 +++ 2 files changed, 165 insertions(+), 5 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc index 72ccbbb9b23e2..f002db108035f 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.cc @@ -5,6 +5,7 @@ #include "contrib_ops/webgpu/bert/attention_common.h" #include "contrib_ops/webgpu/bert/group_query_attention.h" #include "contrib_ops/webgpu/webgpu_contrib_kernels.h" +#include "contrib_ops/webgpu/bert/rotary_embedding.h" #include "contrib_ops/webgpu/bert/flash_attention.h" #include "core/providers/webgpu/webgpu_supported_types.h" @@ -30,6 +31,117 @@ ONNX_OPERATOR_KERNEL_EX( .InputMemoryType(OrtMemTypeCPUInput, 6), GroupQueryAttention); +Status SplitPackedQKVProgram::GenerateShaderCode(ShaderHelper& sh) const { + const auto& packed_qkv = sh.AddInput("packed_qkv", ShaderUsage::UseOffsetToIndices | ShaderUsage::UseUniform); + const auto& query = sh.AddOutput("query", ShaderUsage::UseSetByIndices | ShaderUsage::UseUniform); + const auto& key = sh.AddOutput("key", ShaderUsage::UseSetByIndices | ShaderUsage::UseUniform); + const auto& value = sh.AddOutput("val", ShaderUsage::UseSetByIndices | ShaderUsage::UseUniform); + sh.MainFunctionBody() << " let packed_qkv_indices = " << packed_qkv.OffsetToIndices("global_idx") << ";\n" + << " let input_data = " << packed_qkv.GetByOffset("global_idx") << ";\n" + << " let index = " << packed_qkv.IndicesGet("packed_qkv_indices", "2") << ";\n" + << " if (index < uniforms.hidden_size) {\n" + << " " << query.SetByIndices("packed_qkv_indices", "input_data") << ";\n" + << " } else if (index < (uniforms.hidden_size + uniforms.kv_hidden_size)) {\n" + << " var key_indices = packed_qkv_indices;\n" + << " " << key.IndicesSet("key_indices", "2", "u32(index - uniforms.hidden_size)") << ";\n" + << " " << key.SetByIndices("key_indices", "input_data") << ";\n" + << " } else {\n" + << " var val_indices = packed_qkv_indices;\n" + << " " << value.IndicesSet("val_indices", "2", "u32(index - uniforms.hidden_size - uniforms.kv_hidden_size)") << ";\n" + << " " << value.SetByIndices("val_indices", "input_data") << ";\n" + << " }"; + return Status::OK(); +} + +Status SplitPackedQKV(onnxruntime::webgpu::ComputeContext& context, const WebgpuAttentionParameters& params, const Tensor* packedQKV, Tensor* query, Tensor* key, Tensor* val) { + SplitPackedQKVProgram program; + auto input_size = packedQKV->Shape().Size(); + program + .AddInput({packedQKV, ProgramTensorMetadataDependency::Rank}) + .AddOutputs({{query, ProgramTensorMetadataDependency::Rank}, {key, ProgramTensorMetadataDependency::Rank}, {val, ProgramTensorMetadataDependency::Rank}}) + .AddUniformVariables({ + {static_cast(params.hidden_size_)}, + {static_cast(params.kv_hidden_size_)}, + }) + .SetDispatchGroupSize((input_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE); + return context.RunProgram(program); +} + +Status GeneratePositionIDsProgram::GenerateShaderCode(ShaderHelper& sh) const { + const auto& output = sh.AddOutput("output", ShaderUsage::UseUniform); + const auto& seqlens = sh.AddInput("seqlens", ShaderUsage::UseUniform); + sh.MainFunctionBody() << " var pos_id: i32 = 0;\n" + << " let batch_idx = global_idx / uniforms.sequence_length;\n" + << " let sequence_idx = i32(global_idx % uniforms.sequence_length);\n" + << " let seqlen = " << seqlens.GetByOffset("batch_idx") << ";\n"; + if (is_first_prompt_) { + sh.MainFunctionBody() << " let total_seqlen = seqlen + 1;\n" + << " if (sequence_idx < total_seqlen) {\n" + << " pos_id = sequence_idx;\n" + << " } else {\n" + << " pos_id = 1;\n" + << " }\n" + << " " << output.SetByOffset("global_idx", "pos_id") << "\n"; + } else if (is_subsequent_prompt_) { + sh.MainFunctionBody() << " let total_seqlen = seqlen + 1;\n" + << " let past_seqlen = total_seqlen - i32(uniforms.sequence_length);\n" + << " if (past_seqlen + sequence_idx < total_seqlen) {\n" + << " pos_id = past_seqlen + sequence_idx;\n" + << " } else {\n" + << " pos_id = 1;\n" + << " }\n" + << " " << output.SetByOffset("global_idx", "pos_id") << "\n"; + } else { + sh.MainFunctionBody() << " if (global_idx < uniforms.batch_size) {\n" + << " " << output.SetByOffset("global_idx", "seqlen") << "\n" + << " }\n"; + } + return Status::OK(); +} + +Status GeneratePositionIDs(onnxruntime::webgpu::ComputeContext& context, const WebgpuAttentionParameters& params, const Tensor* seqlens, Tensor* output_tensor) { + GeneratePositionIDsProgram program(params.is_first_prompt_, params.is_subsequent_prompt_); + auto output_size = params.batch_size_ * params.sequence_length_; + program.CacheHint(params.is_first_prompt_, params.is_subsequent_prompt_) + .AddInput({seqlens, ProgramTensorMetadataDependency::Rank}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + .AddUniformVariables({{static_cast(params.batch_size_)}, {static_cast(params.sequence_length_)}}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE); + return context.RunProgram(program); +} + +Status RunRotaryEmbedding(onnxruntime::webgpu::ComputeContext& context, const WebgpuAttentionParameters& params, const Tensor* input, const Tensor* pos_ids, const Tensor* cos_cache, const Tensor* sin_cache, Tensor* output, bool is_query_input) { + const auto half_rotary_embedding_dim = gsl::narrow_cast(cos_cache->Shape()[1]); + const auto head_size = params.head_size_; + const auto hidden_size = is_query_input ? params.hidden_size_ : params.kv_hidden_size_; + const TensorShape global_shape({params.batch_size_, params.sequence_length_, hidden_size / head_size, static_cast(head_size - half_rotary_embedding_dim)}); + const auto rank = global_shape.NumDimensions(); + std::vector global_dims(rank); + std::vector global_strides(rank); + for (size_t j = 0; j < rank; ++j) { + global_dims[j] = gsl::narrow_cast(global_shape[j]); + global_strides[j] = gsl::narrow_cast(global_shape.SizeFromDimension(j + 1)); + } + const auto input_output_strides = std::vector({gsl::narrow_cast(input->Shape().SizeFromDimension(1)), gsl::narrow_cast(hidden_size), gsl::narrow_cast(head_size), 1}); + const auto output_size = gsl::narrow_cast(global_shape.Size()); + + RotaryEmbeddingProgram program(params.rotary_interleaved_); + program + .CacheHint(params.rotary_interleaved_) + .AddInputs({{input, ProgramTensorMetadataDependency::Rank}, + {pos_ids, ProgramTensorMetadataDependency::Rank}, + {cos_cache, ProgramTensorMetadataDependency::Rank}, + {sin_cache, ProgramTensorMetadataDependency::Rank}}) + .AddOutput(output) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({{params.scale_}, + {gsl::make_span(global_dims)}, + {gsl::make_span(global_strides)}, + {gsl::make_span(input_output_strides)}}) + .AddIndices(TensorShape{1, 1}); + return context.RunProgram(program); +} + Status GroupQueryAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) const { const Tensor* query = context.Input(0); const Tensor* key = context.Input(1); @@ -41,7 +153,7 @@ Status GroupQueryAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& const Tensor* cos_cache = context.Input(7); const Tensor* sin_cache = context.Input(8); - GroupQueryAttentionParameters params; + GroupQueryAttentionParameters params = {}; ORT_RETURN_IF_ERROR(group_query_attention_helper::CheckInputs(query, key, value, @@ -57,9 +169,6 @@ Status GroupQueryAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& scale_, softcap_)); WebgpuAttentionParameters parameters(params); - if (parameters.is_packed_qkv_) { - ORT_NOT_IMPLEMENTED("Packed QKV of shape (B, L, N, 3, H) not implemented for webgpu-ep."); - } TensorShapeVector output_shape(3); output_shape[0] = static_cast(parameters.batch_size_); output_shape[1] = static_cast(parameters.sequence_length_); @@ -75,11 +184,39 @@ Status GroupQueryAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& Tensor* present_value = context.Output(2, present_kv_shape); parameters.past_present_share_buffer_ = present_key != nullptr && present_value != nullptr && past_key != nullptr && past_value != nullptr && past_key->DataRaw() == present_key->DataRaw() && past_value->DataRaw() == present_value->DataRaw(); - if (CanApplyFlashAttention(nullptr /* bias */, present_key, present_value, parameters, context)) { + if (!do_rotary_ && CanApplyFlashAttention(nullptr /* bias */, present_key, present_value, parameters, context)) { return ApplyFlashAttention(query, key, value, nullptr /* attention_bias */, output, past_key, present_key, past_value, present_value, parameters, context); } + Tensor qSplit; + Tensor kSplit; + Tensor vSplit; + if (parameters.is_packed_qkv_) { + qSplit = context.CreateGPUTensor(query->DataType(), TensorShape({parameters.batch_size_, parameters.sequence_length_, parameters.hidden_size_})); + kSplit = context.CreateGPUTensor(query->DataType(), TensorShape({parameters.batch_size_, parameters.sequence_length_, parameters.kv_hidden_size_})); + vSplit = context.CreateGPUTensor(query->DataType(), TensorShape({parameters.batch_size_, parameters.sequence_length_, parameters.kv_hidden_size_})); + ORT_RETURN_IF_ERROR(SplitPackedQKV(context, parameters, query, &qSplit, &kSplit, &vSplit)); + parameters.is_packed_qkv_ = false; + query = &qSplit; + key = &kSplit; + value = &vSplit; + } + + Tensor qRotary; + Tensor kRotary; + if (do_rotary_) { + qRotary = context.CreateGPUTensor(query->DataType(), query->Shape()); + kRotary = context.CreateGPUTensor(key->DataType(), key->Shape()); + auto pos_ids_shape = TensorShape({parameters.batch_size_, parameters.sequence_length_}); + Tensor pos_ids = context.CreateGPUTensor(DataTypeImpl::GetType(), pos_ids_shape); + ORT_RETURN_IF_ERROR(GeneratePositionIDs(context, parameters, seqlen_k, &pos_ids)); + ORT_RETURN_IF_ERROR(RunRotaryEmbedding(context, parameters, query, &pos_ids, cos_cache, sin_cache, &qRotary, /* is_query_input = */ true)); + ORT_RETURN_IF_ERROR(RunRotaryEmbedding(context, parameters, key, &pos_ids, cos_cache, sin_cache, &kRotary, /* is_query_input = */ false)); + query = &qRotary; + key = &kRotary; + } + TensorShapeVector q_new_dims({parameters.batch_size_, parameters.num_heads_, parameters.sequence_length_, parameters.head_size_}); TensorShape q_new_shape(q_new_dims); diff --git a/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.h b/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.h index 04969dc778927..1fb1e1ffc91fd 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/group_query_attention.h @@ -14,6 +14,29 @@ namespace webgpu { using namespace onnxruntime::webgpu; +class GeneratePositionIDsProgram final : public Program { + public: + GeneratePositionIDsProgram(bool is_first_prompt, bool is_subsequent_prompt) : Program{"GeneratePositionIDs"}, is_first_prompt_(is_first_prompt), is_subsequent_prompt_(is_subsequent_prompt) {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"batch_size", ProgramUniformVariableDataType::Uint32}, {"sequence_length", ProgramUniformVariableDataType::Uint32}); + + private: + bool is_first_prompt_; + bool is_subsequent_prompt_; +}; + +class SplitPackedQKVProgram final : public Program { + public: + SplitPackedQKVProgram() : Program{"SplitPackedQKV"} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"hidden_size", ProgramUniformVariableDataType::Uint32}, + {"kv_hidden_size", ProgramUniformVariableDataType::Uint32}); +}; + class GroupQueryAttention final : public WebGpuKernel { public: GroupQueryAttention(const OpKernelInfo& info) : WebGpuKernel(info) { From 7942fa7ad20394574ccb3687d02b05c8853d2d9a Mon Sep 17 00:00:00 2001 From: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com> Date: Sat, 15 Mar 2025 02:46:44 -0700 Subject: [PATCH 108/266] Whisper Redesigned Solution (#23549) ### Description This PR re-designs how Whisper is created and supported in ONNX Runtime. The new solution leverages [previous optimization work](https://github.com/microsoft/onnxruntime/pull/15473), and it is designed to be used in conjunction with [this work](https://github.com/microsoft/onnxruntime-genai/pull/1229) in ONNX Runtime GenAI. Some of the added changes include: - Re-designed export that creates new ONNX models without needing a `WhisperBeamSearch` op - Creates one encoder model that also pre-computes the cross-attention KV caches (since they only need to be calculated once) - Creates one decoder model that can be used during pre-fill and token generation - Creates one jump-times model that can be used for word-level timestamps - Removes need for a `WhisperBeamSearch` op to chain the encoder and decoder subgraphs - Removes need to duplicate decoder's weights in memory - Previous solution with the `WhisperBeamSearch` op created an encoder-decoder-init model and decoder-with-past model. The decoder was duplicated twice, one in each. - Removes need for separate logic to export the PyTorch model coming from OpenAI vs. the PyTorch model coming from Hugging Face - Re-factors common parameters and logic used in CPU and CUDA attention kernels - Adds `DUMP_STRING` to enable easy logging of intermediate information when running in debug mode to debug a problem. This info is not printed in release mode so it will not impact performance. - Integrates `DecoderMaskedMultiHeadAttention` into `MultiHeadAttention` - Enables past-present buffer sharing in the `MultiHeadAttention` op for improved performance - Adds `cache_indirection` and `past_sequence_length` as new optional inputs to `MultiHeadAttention` - Adds `output_qk` as new optional output to `MultiHeadAttention` - Enables calculating `output_qk` tensor with FP16 or FP32 precision, regardless of the model's precision - CI tests that run end-to-end across various flag combinations that are used by many customers internally and externally The existing solutions are still available if desired. ### Known Issues - The FP32 CPU model with the `WhisperBeamSearch` op and output QK is currently disabled. This is because ONNX Runtime doesn't currently support output QK kernels on CPU, only on CUDA. - The `DecoderMaskedMultiHeadAttention` CPU kernel has a parity mismatch with the `DecoderMaskedMultiHeadAttention` CUDA kernel. - Using `DecoderMaskedMultiHeadAttention` for the FP32 CPU model is not enabled. Currently, it uses `MultiHeadAttention` to avoid the parity mismatch issue. ### Motivation and Context Using the beam search op has made it more difficult to debug and fix errors that are encountered. This new approach is more flexible and more customizable for users (e.g. by running with ONNX Runtime GenAI). It also helps [this issue](https://github.com/microsoft/onnxruntime/issues/18216). --------- Co-authored-by: mindest --- docs/ContribOperators.md | 26 +- docs/OperatorKernels.md | 10 +- onnxruntime/contrib_ops/cpu/bert/attention.cc | 2 +- .../contrib_ops/cpu/bert/attention_base.h | 1 + .../contrib_ops/cpu/bert/attention_common.h | 144 +-- .../contrib_ops/cpu/bert/attention_cpu_base.h | 263 ++++- .../cpu/bert/attention_parameters.h | 122 +++ .../decoder_masked_multihead_attention.cc | 266 +----- .../bert/decoder_masked_multihead_attention.h | 51 - .../contrib_ops/cpu/bert/gqa_attention_base.h | 3 +- .../cpu/bert/group_query_attention_helper.h | 1 + .../cpu/bert/multihead_attention.cc | 129 ++- .../cpu/bert/multihead_attention.h | 1 + .../cpu/bert/multihead_attention_helper.h | 49 +- .../contrib_ops/cpu/bert/rotary_helper.h | 1 - .../cpu/quantization/attention_quant.cc | 2 +- .../contrib_ops/cpu/skip_layer_norm_helper.h | 1 - .../cpu/sparse/sparse_attention_base.h | 39 +- .../cpu/sparse/sparse_attention_helper.h | 1 + .../contrib_ops/cpu/transformers/sequences.h | 1 + .../contrib_ops/cpu/utils/debug_macros.h | 14 +- .../contrib_ops/cuda/bert/attention_data.h | 185 ++++ .../contrib_ops/cuda/bert/attention_impl.cu | 421 +++++++- .../contrib_ops/cuda/bert/attention_impl.h | 137 +-- .../cuda/bert/attention_kernel_options.cc | 8 + .../cuda/bert/attention_kernel_options.h | 6 +- .../cuda/bert/attention_kv_cache.cu | 497 +++++++--- .../cuda/bert/attention_kv_cache.h | 92 ++ .../cuda/bert/attention_prepare_qkv.cu | 85 +- .../contrib_ops/cuda/bert/attention_qk.cu | 55 ++ .../contrib_ops/cuda/bert/attention_qk.h | 23 + .../cuda/bert/decoder_attention_impl.h | 1 + .../decoder_masked_multihead_attention.cc | 111 ++- .../bert/decoder_masked_self_attention.cc | 25 +- .../decoder_masked_multihead_attention_128.cu | 22 +- .../decoder_masked_multihead_attention_32.cu | 22 +- .../decoder_masked_multihead_attention_64.cu | 22 +- ...decoder_masked_multihead_attention_impl.cu | 68 +- .../decoder_masked_multihead_attention_impl.h | 14 +- ...er_masked_multihead_attention_impl_utils.h | 3 +- .../cuda/bert/group_query_attention.cc | 11 - .../cuda/bert/group_query_attention_impl.cu | 325 +------ .../cuda/bert/group_query_attention_impl.h | 51 +- .../cuda/bert/multihead_attention.cc | 168 +++- .../cuda/bert/multihead_attention.h | 3 +- .../contrib_ops/cuda/bert/packed_attention.h | 1 + .../cuda/bert/packed_attention_impl.h | 18 +- .../bert/packed_multihead_attention_impl.h | 25 +- .../contrib_ops/cuda/cuda_contrib_kernels.cc | 24 +- .../cuda/sparse/sparse_attention_impl.cu | 1 + .../cuda/sparse/sparse_attention_impl.h | 1 + .../transformers/generation_device_helper.cc | 1 + .../contrib_ops/rocm/bert/attention_impl.h | 1 + .../bert/batched_gemm_permute_pipelines.cuh | 1 + .../rocm/bert/multihead_attention.cu | 30 +- .../webgpu/bert/attention_common.h | 4 +- .../webgpu/bert/multihead_attention.cc | 25 +- .../core/graph/contrib_ops/bert_defs.cc | 42 +- .../tools/pytorch_export_contrib_ops.py | 24 +- .../python/tools/symbolic_shape_infer.py | 67 +- .../tools/transformers/convert_generation.py | 324 ++++++- .../tools/transformers/fusion_attention.py | 12 +- .../transformers/fusion_bart_attention.py | 39 +- .../transformers/models/whisper/README.md | 119 ++- .../models/whisper/convert_to_onnx.py | 102 +- .../models/whisper/requirements.txt | 4 +- .../models/whisper/whisper_chain.py | 8 +- .../models/whisper/whisper_decoder.py | 708 +++++++------- .../models/whisper/whisper_encoder.py | 201 ++-- .../whisper/whisper_encoder_decoder_init.py | 536 ++++++----- .../models/whisper/whisper_helper.py | 322 +++---- .../models/whisper/whisper_inputs.py | 380 ++++++++ .../models/whisper/whisper_jump_times.py | 477 ++++++++++ .../models/whisper/whisper_openai_helper.py | 84 -- .../{models/t5 => }/past_helper.py | 0 .../contrib_ops/attention_op_test_helper.cc | 69 ++ .../contrib_ops/attention_op_test_helper.h | 12 + ...oder_masked_multihead_attention_op_test.cc | 73 +- .../multihead_attention_op_test.cc | 266 ++++-- .../attention_kernel_options_test.cc | 37 +- .../decoder_attention_with_sln_fused.onnx | Bin 69102 -> 68540 bytes .../decoder_with_past_self_mha_fused.onnx | Bin 69238 -> 69261 bytes ...r_with_past_self_mha_split_bias_fused.onnx | Bin 69301 -> 69284 bytes .../python/transformers/test_generation.py | 2 +- .../python/transformers/test_parity_t5_mha.py | 43 +- .../transformers/whisper_model_generator.py | 87 +- .../attention/attention_test_data.txt | 898 ++++++++++++++++++ .../test/testdata/dmmha_cross_attn.onnx | Bin 0 -> 667 bytes .../testdata/dmmha_inside_mha_cross_attn.onnx | Bin 0 -> 585 bytes .../test/testdata/dmmha_inside_mha_data.py | 195 ++++ .../test/testdata/dmmha_inside_mha_graph.py | 235 +++++ .../testdata/dmmha_inside_mha_self_attn.onnx | Bin 0 -> 805 bytes .../test/testdata/dmmha_self_attn.onnx | Bin 0 -> 869 bytes .../azure-pipelines/bigmodels-ci-pipeline.yml | 43 + .../Dockerfile.package_ubuntu_2204_gpu_ffmpeg | 3 + 95 files changed, 6352 insertions(+), 2674 deletions(-) create mode 100644 onnxruntime/contrib_ops/cpu/bert/attention_parameters.h create mode 100644 onnxruntime/contrib_ops/cuda/bert/attention_data.h create mode 100644 onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.h create mode 100644 onnxruntime/contrib_ops/cuda/bert/attention_qk.cu create mode 100644 onnxruntime/contrib_ops/cuda/bert/attention_qk.h create mode 100644 onnxruntime/python/tools/transformers/models/whisper/whisper_inputs.py create mode 100644 onnxruntime/python/tools/transformers/models/whisper/whisper_jump_times.py delete mode 100644 onnxruntime/python/tools/transformers/models/whisper/whisper_openai_helper.py rename onnxruntime/python/tools/transformers/{models/t5 => }/past_helper.py (100%) create mode 100644 onnxruntime/test/testdata/dmmha_cross_attn.onnx create mode 100644 onnxruntime/test/testdata/dmmha_inside_mha_cross_attn.onnx create mode 100644 onnxruntime/test/testdata/dmmha_inside_mha_data.py create mode 100644 onnxruntime/test/testdata/dmmha_inside_mha_graph.py create mode 100644 onnxruntime/test/testdata/dmmha_inside_mha_self_attn.onnx create mode 100644 onnxruntime/test/testdata/dmmha_self_attn.onnx diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index f85ed1e5f146c..b64641230f249 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -1191,17 +1191,17 @@ This version of the operator has been available since version 1 of the 'com.micr
present state for key with shape (batch_size, num_heads, total_sequence_length, head_size). If past_present_share_buffer is set, its shape is (batch_size, num_heads, max_sequence_length, head_size), while effective_seq_length = (past_sequence_length + kv_sequence_length).
present_value (optional) : T
present state for value with shape (batch_size, num_heads, total_sequence_length, head_size). If past_present_share_buffer is set, its shape is (batch_size, num_heads, max_sequence_length, head_size), while effective_seq_length = (past_sequence_length + kv_sequence_length).
-
qk (optional) : V
+
qk (optional) : QK
normalized Q * K, of shape (batch_size, num_heads, 1, total_sequence_length).
#### Type Constraints
-
V : tensor(float)
-
Constrain qk output types to float32 tensors.
T : tensor(float), tensor(float16)
Constrain input and output types to float tensors.
+
QK : tensor(float), tensor(float16)
+
Constrain QK output to float32 or float16 tensors, independent of input type or output type.
M : tensor(int32)
Constrain mask index to integer types
@@ -3203,7 +3203,7 @@ This version of the operator has been available since version 1 of the 'com.micr
Whether every token can only attend to previous tokens. Default value is 0.
-#### Inputs (1 - 8) +#### Inputs (1 - 10)
query : T
@@ -3219,20 +3219,26 @@ This version of the operator has been available since version 1 of the 'com.micr
attention_bias (optional) : T
bias added to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
past_key (optional) : T
-
past state for self attention key with shape (batch_size, num_heads, past_sequence_length, head_size)
+
past state for key with shape (batch_size, num_heads, past_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
past_value (optional) : T
-
past state for self attention value with shape (batch_size, num_heads, past_sequence_length, head_size)
+
past state for value with shape (batch_size, num_heads, past_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
+
past_sequence_length (optional) : M
+
The past_sequence_length buffer sharing is used with
+
cache_indirection (optional) : M
+
A buffer of shape [batch_size, beam_width, max_sequence_length] where an [i, j, k] entry specifieswhich beam the 'k' th token came from for the 'j' th beam for batch 'i' in the current iteration
-#### Outputs (1 - 3) +#### Outputs (1 - 4)
output : T
3D output tensor with shape (batch_size, sequence_length, v_hidden_size)
present_key (optional) : T
-
present state for cross attention key with shape (batch_size, num_heads, kv_sequence_length, head_size)or present state for self attention key with shape (batch_size, num_heads, total_sequence_length, head_size)
+
present state for key with shape (batch_size, num_heads, total_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
present_value (optional) : T
-
present state for cross attention value with shape (batch_size, num_heads, kv_sequence_length, head_size)or present state for self attention value with shape (batch_size, num_heads, total_sequence_length, head_size)
+
present state for value with shape (batch_size, num_heads, total_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
+
qk (optional) : QK
+
normalized Q * K, of shape (batch_size, num_heads, sequence_length, total_sequence_length).
#### Type Constraints @@ -3240,6 +3246,8 @@ This version of the operator has been available since version 1 of the 'com.micr
T : tensor(float), tensor(float16)
Constrain input and output to float tensors.
+
QK : tensor(float), tensor(float16)
+
Constrain QK output to float32 or float16 tensors, independent of input type or output type.
M : tensor(int32)
Constrain mask to integer types
diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 1dd145463367b..91c68a1f5afb6 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -504,7 +504,7 @@ Do not modify directly.* |CDist|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(double), tensor(float)| |ConvTransposeWithDynamicPads|*in* X:**T**
*in* W:**T**
*in* Pads:**tensor(int64)**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |CropAndResize|*in* X:**T1**
*in* rois:**T1**
*in* batch_indices:**T2**
*in* crop_size:**T2**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(int32)| -|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**V**|1+|**T** = tensor(float)| +|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**T** = tensor(float)| |DequantizeLinear|*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|1+|**T1** = tensor(int16), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)
**T2** = tensor(float)| |DynamicQuantizeLSTM|*in* X:**T**
*in* W:**T2**
*in* R:**T2**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*in* initial_c:**T**
*in* P:**T**
*in* W_scale:**T**
*in* W_zero_point:**T2**
*in* R_scale:**T**
*in* R_zero_point:**T2**
*out* Y:**T**
*out* Y_h:**T**
*out* Y_c:**T**|1+|**T** = tensor(float)
**T1** = tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |DynamicQuantizeMatMul|*in* A:**T1**
*in* B:**T2**
*in* b_scale:**T1**
*in* b_zero_point:**T2**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| @@ -528,7 +528,7 @@ Do not modify directly.* |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)
**T3** = tensor(float), tensor(float16), tensor(uint8)
**T4** = tensor(int32)| |MaxpoolWithMask|*in* X:**T**
*in* M:**tensor(int32)**
*out* Y:**T**|1+|**T** = tensor(float)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**T** = tensor(float)| |MurmurHash3|*in* X:**T1**
*out* Y:**T2**|1+|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(string), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(uint32)| |NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcMaxPool|*in* x:**T**
*out* y:**T**|1+|**T** = tensor(int8), tensor(uint8)| @@ -906,7 +906,7 @@ Do not modify directly.* |ComplexMulConj|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float), tensor(float16)| |ConvTransposeWithDynamicPads|*in* X:**T**
*in* W:**T**
*in* Pads:**tensor(int64)**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |DecoderAttention|*in* query:**T**
*in* key:**T**
*in* q_weight:**T**
*in* kv_weight:**T**
*in* bias:**T**
*in* key_padding_mask:**B**
*in* key_cache:**T**
*in* value_cache:**T**
*in* static_kv:**B**
*in* use_past:**B**
*in* has_layer_state:**B**
*in* has_key_padding_mask:**B**
*out* output:**T**
*out* new_key_cache:**T**
*out* new_value_cache:**T**|1+|**T** = tensor(float), tensor(float16)| -|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**V**|1+|**T** = tensor(float), tensor(float16)| +|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**QK** = tensor(float), tensor(float16)
**T** = tensor(float), tensor(float16)| |DecoderMaskedSelfAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| |DequantizeLinear|*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(float16)| |DequantizeWithOrder|*in* input:**Q**
*in* scale_input:**S**
*out* output:**F**|1+|**F** = tensor(float), tensor(float16)
**Q** = tensor(int8)
**S** = tensor(float)| @@ -929,7 +929,7 @@ Do not modify directly.* |MatMulBnb4|*in* A:**T1**
*in* B:**T2**
*in* absmax:**T1**
*out* Y:**T1**|1+|**T1** = tensor(bfloat16), tensor(float), tensor(float16)
**T2** = tensor(uint8)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| |MoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float), tensor(float16)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**QK** = tensor(float), tensor(float16)
**T** = tensor(float), tensor(float16)| |NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |PackedAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* attention_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| @@ -1402,7 +1402,7 @@ Do not modify directly.* |GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |NhwcConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)
**T4** = tensor(int32)| |QLinearAdd|*in* A:**T**
*in* A_scale:**tensor(float)**
*in* A_zero_point:**T**
*in* B:**T**
*in* B_scale:**tensor(float)**
*in* B_zero_point:**T**
*in* C_scale:**tensor(float)**
*in* C_zero_point:**T**
*out* C:**T**|1+|**T** = tensor(int8), tensor(uint8)| diff --git a/onnxruntime/contrib_ops/cpu/bert/attention.cc b/onnxruntime/contrib_ops/cpu/bert/attention.cc index ad14fb8258656..de23444e95778 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/attention.cc @@ -335,7 +335,7 @@ Status Attention::Compute(OpKernelContext* context) const { // Compute the attention score and apply the score to V return ApplyAttention(Q, K, V, mask_index, past, nullptr /* past_key */, nullptr /* past_value */, - output, nullptr /* present_key */, nullptr /* present_value */, + output, nullptr /* present_key */, nullptr /* present_value */, nullptr /* output_qk */, batch_size, sequence_length, sequence_length, parameters.head_size, parameters.v_head_size, parameters.v_hidden_size, attention_bias, context); diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_base.h b/onnxruntime/contrib_ops/cpu/bert/attention_base.h index 05756cd54d842..93d35d39390f5 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_base.h @@ -7,6 +7,7 @@ #include "core/common/common.h" #include "core/framework/op_kernel.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_common.h b/onnxruntime/contrib_ops/cpu/bert/attention_common.h index 97d6cc1ce7d66..243f611da49e1 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_common.h @@ -49,148 +49,10 @@ enum AttentionKernelType { AttentionKernel_FlashAttention, AttentionKernel_CudnnFlashAttention, AttentionKernel_LeanAttention, + AttentionKernel_DecoderAttention, AttentionKernel_Default }; -// Parameters deduced from node attributes and inputs/outputs. -struct AttentionParameters { - int batch_size; - int sequence_length; - int kv_sequence_length; // input sequence length of K or V - int past_sequence_length; // sequence length in past state of K or V - int total_sequence_length; // total sequence length of K or V - int max_sequence_length; // max sequence length from 4D mask - int input_hidden_size; // first dimension of weights for input projection - int hidden_size; // hidden size of Q or K - int head_size; // hidden size per head of Q or K - int v_hidden_size; // hidden size of V - int v_head_size; // hidden size per head of V - int num_heads; - int rotary_embedding; - bool is_unidirectional; - bool past_present_share_buffer; - bool do_rotary; - bool broadcast_attn_bias_dim_0; - bool broadcast_attn_bias_dim_1; - float mask_filter_value; - float scale; - bool use_tf32; - AttentionMaskType mask_type; - AttentionQkvFormat qkv_format; -}; - -struct DecoderMaskedMultiHeadAttentionParams : AttentionParameters { - int beam_width = 1; - - // Only NeoX style rotary embedding is supported - int rotary_embedding_dim = 0; - int t_step = 0; - - // Whether to use multihead attention(excludes matmul and bias) - bool is_mha = false; - bool is_cross_attention = false; - bool is_packed_qkv = false; - - // Useful to better use global memory bandwidth on certain CUDA architectures. - // Turned off by default for now until we fully understand performance implications - // for all types of workloads. - // Can be turned on by appropriate environment variable (see attention_common.h). - bool kv_data_in_flight = false; - - void* q = nullptr; - void* q_bias = nullptr; - - void* k = nullptr; - void* k_bias = nullptr; - - void* v = nullptr; - void* v_bias = nullptr; - - void* attention_bias = nullptr; - - void* k_cache = nullptr; - void* v_cache = nullptr; - - void* out = nullptr; - void* out_qk = nullptr; - - const int32_t* cache_indir = nullptr; - const int32_t* mask = nullptr; // [B, total_sequence_length] -}; - -// Parameters deduced from node attributes and inputs/outputs. -struct PackedAttentionParameters { - int batch_size; - int sequence_length; - int input_hidden_size; // hidden size of input - int hidden_size; // hidden size of Q or K - int head_size; // hidden size per head of Q or K - int v_hidden_size; // hidden size of V - int v_head_size; // hidden size per head of V - int num_heads; - float scale; - int token_count; - bool broadcast_attn_bias_dim_0; - bool broadcast_attn_bias_dim_1; - bool use_tf32; -}; - -// Parameters deduced from node attributes and inputs/outputs. -struct GroupQueryAttentionParameters { - int batch_size; - int sequence_length; // sequence length of input query, key, value - int seqlen_past_kv_cache; // sequence length of past kv tensor - int seqlen_present_kv_cache; // sequence length of present kv tensor - int total_sequence_length; // maximum total sequence length (past_sequence_length + sequence_length) among keys - int hidden_size; - int num_heads; - int head_size; - int kv_hidden_size; - int kv_num_heads; - int num_splits; // number of splits for splitkv - int rotary_dim; // rotary embedding dimension - bool is_unidirectional; // causal - int local_window_size; - bool kv_share_buffer; - bool is_packed_qkv; - bool is_subsequent_prompt; // indicates whether we have past context and seqlen > 1 - bool is_first_prompt; // indicates whether this is first decoding step - bool do_rotary; - bool rotary_interleaved; - bool use_smooth_softmax; - float scale; - float softcap; - AttentionQkvFormat qkv_format; - AttentionQkvFormat past_kv_format; - int zeros_count; - int* zero_ptr; -}; - -// Parameters for sparse attention. -struct SparseAttentionParameters { - int batch_size; // batch size - int sequence_length; // sequence length of input query, key, value - int hidden_size; // hidden size of query - int num_heads; // number of heads of query - int head_size; // hidden size per head of query, key or value - int kv_hidden_size; // hidden size of key or value - int kv_num_heads; // number of heads of key or value - bool do_rotary; // whether to use rotary embedding - bool rotary_interleaved; // whether to use interleaved rotary embedding - int rotary_dim; // rotary embedding dimension - int sparse_block_size; // block size for sparse attention - int num_sparse_layout; // number of sparse layout - int stride_col_indices; // shape of block_col_indices is [num_sparse_layout, stride_col_indices] - int stride_row_indices; // shape of block_row_indices is [num_sparse_layout, stride_row_indices] - float scale; // scaling factor applied prior to softmax - bool is_packed_qkv; // whether qkv is packed - int total_sequence_length; // maximum total sequence length (past_sequence_length + sequence_length) among keys - int max_sequence_length; // max sequence length for sparse layout - int max_rotary_sequence_length; // max sequence length for rotary cos/sin cache - int max_cache_sequence_length; // max sequence length for kv cache buffer - bool past_present_share_buffer; // whether past_key and present_key share buffer, so is past_value and present_value -}; - constexpr bool LAYOUT_BSNH = false; constexpr bool LAYOUT_BNSH = true; @@ -215,6 +77,7 @@ enum class AttentionBackend : int { // Experimental kernels LEAN_ATTENTION = 256, + DECODER_ATTENTION = 512, // FasterTransformer's decoder masked multihead attention }; // Environment variable to enable debug information of attention kernel to be printed. Default is 0 (disabled). @@ -245,6 +108,9 @@ constexpr const char* kDisableFlashAttention = "ORT_DISABLE_FLASH_ATTENTION"; // Environment variable to enable or disable lean attention. Default is 0 (disabled). constexpr const char* kEnableLeanAttention = "ORT_ENABLE_LEAN_ATTENTION"; +// Environment variable to enable or disable FasterTransformer's decoder masked multi-head attention. Default is 0 (enabled). +constexpr const char* kDisableDecoderAttention = "ORT_DISABLE_DECODER_ATTENTION"; + // Minimum sequence length to perfer memory efficient attention when data type is float32 constexpr const char* kMinSeqLenForEfficientAttentionFp32 = "ORT_MIN_SEQ_LEN_EFFICIENT_ATTENTION_FP32"; diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h b/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h index 4345675b7e966..4abe986ffa685 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h @@ -29,6 +29,7 @@ class AttentionCPUBase : public AttentionBase { Tensor* output, // output tensor Tensor* present_key, // present K output tensor (if separating present KV) Tensor* present_value, // present V output tensor (if separating present KV) + Tensor* output_qk, // Q*K output tensor (if returning Q*K value) int batch_size, // batch size (B) int sequence_length, // sequence length of Q (S) int kv_sequence_length, // sequence length of K or V (L) @@ -37,7 +38,6 @@ class AttentionCPUBase : public AttentionBase { int v_hidden_size, // hidden size of V (D_v) const Tensor* attn_bias, // additive bias applied on scaled QK. OpKernelContext* context, - Tensor* output_qk = nullptr, // output buffer for QK (if needed) int past_sequence_length = 0, // sequence length of past state bool past_present_share_buffer = false) const { AllocatorPtr allocator; @@ -109,7 +109,7 @@ class AttentionCPUBase : public AttentionBase { static_cast(mask_data), batch_size, sequence_length, kv_sequence_length, past_sequence_length, qk_head_size == 0 ? v_head_size : qk_head_size, past_data, past_key_data, present_data, - present_key_data, tp, scale, attn_bias_data, attn_bias_dims, output_qk_data, + present_key_data, output_qk_data, tp, scale, attn_bias_data, attn_bias_dims, past_present_share_buffer, max_sequence_length); // Compute the attentionScore * Value: out_tmp(B, N, S, H_v) = attention_probs(B, N, S, T) x V(B, N, T, H_v) @@ -125,6 +125,65 @@ class AttentionCPUBase : public AttentionBase { return Status::OK(); } + // For DecoderMaskedMultiHeadAttention + template + Status ApplyAttentionWithBeams(const T* Q, + const T* K, + const T* V, + const Tensor* mask_index, + const Tensor* past_key, + const Tensor* past_value, + Tensor* output, + Tensor* present_key, + Tensor* present_value, + int batch_size, + int past_sequence_length, + int max_sequence_length, + int head_size, + int v_head_size, + const Tensor* attn_bias, + bool broadcast_attn_bias_dim_0, + bool broadcast_attn_bias_dim_1, + const Tensor* cache_indir, + OpKernelContext* context, + int beam_width, + Tensor* output_qk) const { + AllocatorPtr allocator; + ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); + + auto* tp = context->GetOperatorThreadPool(); + + int total_sequence_length = past_sequence_length + 1; // This is +1 because this is used during token generation via DecoderMaskedMultiHeadAttention + size_t bytes = SafeInt(batch_size) * num_heads_ * total_sequence_length * sizeof(T); + auto attention_probs = allocator->Alloc(bytes); + BufferUniquePtr scratch_buffer(attention_probs, BufferDeleter(allocator)); + + const T* past_key_data = past_key != nullptr ? past_key->Data() : nullptr; + T* present_key_data = present_key != nullptr ? present_key->MutableData() : nullptr; + const T* past_value_data = past_value != nullptr ? past_value->Data() : nullptr; + T* present_value_data = present_value != nullptr ? present_value->MutableData() : nullptr; + T* output_qk_data = (output_qk != nullptr) ? output_qk->MutableData() : nullptr; + + const int32_t* mask_index_data = mask_index != nullptr ? mask_index->Data() : nullptr; + const T* attn_bias_data = attn_bias != nullptr ? attn_bias->Data() : nullptr; + + ComputeAttentionProbsWithBeams(static_cast(attention_probs), Q, K, mask_index_data, batch_size, + past_sequence_length, max_sequence_length, head_size, past_key_data, + present_key_data, tp, attn_bias_data, broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1, cache_indir->Data(), beam_width, output_qk_data); + + // Compute the attentionScore * Value: out_tmp(B, N, 1, H_v) = attention_probs(B, N, 1, T) x V(B, N, T, H_v) + auto out_tmp_data = allocator->Alloc(SafeInt(batch_size) * num_heads_ * v_head_size * sizeof(T)); + BufferUniquePtr out_tmp_buffer(out_tmp_data, BufferDeleter(std::move(allocator))); + + ComputeVxAttentionScoreWithBeams(output->MutableData(), static_cast(out_tmp_data), + static_cast(attention_probs), V, batch_size, + past_sequence_length, max_sequence_length, v_head_size, past_value_data, + present_value_data, cache_indir->Data(), beam_width, tp); + + return Status::OK(); + } + private: // Helper function to compute the attention probs. It does 2 things: // attention_probs(B, N, S, T) = 1/sqrt(H) x Q(B, N, S, H) x K'(B, N, T, H -> B, N, H, T) + @@ -144,11 +203,11 @@ class AttentionCPUBase : public AttentionBase { const T* past_key, // past key only (if not using past state) T* present, // present state T* present_key, // present key only (if not using present state) + T* output_qk, // Q*K output ThreadPool* tp, // thread pool float scale, // scale factor const T* attn_bias_data, // attention bias gsl::span attn_bias_dims, // attention bias shape - T* output_qk_data = nullptr, // scaled output QK buffer bool past_present_share_buffer = false, int max_sequence_length = 0) const { const int total_sequence_length = past_sequence_length + kv_sequence_length; // T = P + L @@ -253,9 +312,9 @@ class AttentionCPUBase : public AttentionBase { }); } - if (output_qk_data != nullptr) { + if (output_qk != nullptr) { // Output the scaled Q*K^T if needed. - memcpy(output_qk_data, attention_probs, + memcpy(output_qk, attention_probs, SafeInt(batch_size) * num_heads_ * sequence_length * total_sequence_length * sizeof(T)); } @@ -360,6 +419,200 @@ class AttentionCPUBase : public AttentionBase { } }); } + + // Used for DecoderMaskedMultiHeadAttention where sequence_length = 1 + template + void ComputeAttentionProbsWithBeams(T* attention_probs, + const T* Q, + const T* K, + const int32_t* mask_index_data, + int batch_size, + int past_sequence_length, + int max_sequence_length, + int head_size, + const T* past_key_data, + T* present_key_data, + ThreadPool* tp, + const T* attn_bias_data, + bool broadcast_attn_bias_dim_0, + bool broadcast_attn_bias_dim_1, + const int32_t* cache_indir_data, + int beam_width, + T* output_qk_data) const { + float scale = scale_ == 0.0f ? 1.0f / sqrt(static_cast(head_size)) : scale_; + + TensorOpCost unit_cost; + auto total_sequence_length = past_sequence_length + 1; + const ptrdiff_t probs_matrix_size = total_sequence_length; + const ptrdiff_t probs_matrix_bytes = probs_matrix_size * sizeof(T); + + unit_cost.compute_cycles = static_cast((SafeInt(2) * head_size - 1) * total_sequence_length); + unit_cost.bytes_loaded = static_cast(SafeInt(2) * head_size * total_sequence_length * sizeof(T)); + unit_cost.bytes_stored = static_cast(SafeInt(head_size) * total_sequence_length * sizeof(T)); + + if (attn_bias_data != nullptr) { + unit_cost.bytes_loaded += static_cast(probs_matrix_bytes) * 2; + unit_cost.bytes_stored += probs_matrix_bytes; + } + + if (mask_index_data != nullptr) { + unit_cost.bytes_stored += probs_matrix_bytes; + } + + // Cost of appending current key to present key + unit_cost.compute_cycles += static_cast(head_size); + unit_cost.bytes_loaded += static_cast(head_size); + + // Parallel for loop + const int loop_len = batch_size * num_heads_; + ThreadPool::TryParallelFor(tp, loop_len, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { + for (std::ptrdiff_t i = begin; i != end; ++i) { + const std::ptrdiff_t batch_index = i / num_heads_; + const std::ptrdiff_t head_index = i % num_heads_; + const std::ptrdiff_t beam_batch_index = batch_index / beam_width; + const T* q_vec = Q + i * head_size; + const std::ptrdiff_t attn_bias_base_offset = ((broadcast_attn_bias_dim_0 ? 0 : (beam_batch_index * num_heads_)) + + (broadcast_attn_bias_dim_1 ? 0 : head_index)) * + probs_matrix_size; + + { + // Calculate the latest position of the attention_probs + // (1, H) x (T, H)^T -> (1, T) + // Decompose into T (1, H) x (1, H)^T -> (1, 1) operations + auto last_offset = past_sequence_length + i * probs_matrix_size; + T* attention_probs_ptr = reinterpret_cast(attention_probs) + last_offset; + math::Dot(head_size, q_vec, K + i * head_size, attention_probs_ptr, nullptr); + + *attention_probs_ptr *= scale; + // Apply the attention bias and mask + if (attn_bias_data != nullptr) { + *attention_probs_ptr += attn_bias_data[attn_bias_base_offset + past_sequence_length]; + } + bool is_masked = (mask_index_data != nullptr) && + (mask_index_data[(batch_index + 1) * total_sequence_length - 1] == 0); + if (is_masked) { + *attention_probs_ptr += mask_filter_value_; + } + } + + { + // Calculate the rest of the attention_probs + for (std::ptrdiff_t j = 0; j < past_sequence_length; ++j) { + const int* beam_indices = &cache_indir_data[batch_index * max_sequence_length]; + const std::ptrdiff_t beam_offset = static_cast(beam_indices[j]) * num_heads_ * + max_sequence_length * head_size; + const std::ptrdiff_t beam_batch_offset = (beam_batch_index * beam_width * num_heads_ + head_index) * + max_sequence_length * head_size; + const T* past_k_vec = past_key_data + beam_batch_offset + beam_offset + j * head_size; + T* output = reinterpret_cast(attention_probs) + j + i * probs_matrix_size; + math::Dot(head_size, q_vec, past_k_vec, output, nullptr); + + *output *= scale; + // Apply the attention bias and mask + if (attn_bias_data != nullptr) { + *output += attn_bias_data[attn_bias_base_offset + j]; + } + bool is_masked = (mask_index_data != nullptr) && + (mask_index_data[batch_index * total_sequence_length + j] == 0); + if (is_masked) { + *output += mask_filter_value_; + } + } + } + + // Append current key to present key (past_present_share_buffer_ is true) + memcpy(present_key_data + (i * max_sequence_length + past_sequence_length) * head_size, + K + i * head_size, head_size * sizeof(T)); + } + }); + + if (output_qk_data != nullptr) { + // Output the scaled Q*K^T if needed. + memcpy(output_qk_data, attention_probs, + SafeInt(batch_size) * num_heads_ * total_sequence_length * sizeof(T)); + } + + // attention_probs(B, N, 1, T) = Softmax(attention_probs) + { + const int N = batch_size * num_heads_; + const int D = total_sequence_length; + ComputeAttentionSoftmaxInplace(attention_probs, N, D, tp); + } + } + + // Used for DecoderMaskedMultiHeadAttention where sequence_length = 1 + template + void ComputeVxAttentionScoreWithBeams(T* output, + T* tmp_buffer, + const T* attention_probs, + const T* V, + int batch_size, + int past_sequence_length, + int max_sequence_length, + int v_head_size, + const T* past_value_data, + T* present_value_data, + const int32_t* cache_indir_data, + int beam_width, + ThreadPool* tp) const { + const int total_sequence_length = past_sequence_length + 1; + + TensorOpCost unit_cost; + unit_cost.compute_cycles = static_cast(SafeInt(2) * v_head_size * total_sequence_length); + unit_cost.bytes_loaded = static_cast(SafeInt(3) * v_head_size * total_sequence_length * sizeof(T)); + unit_cost.bytes_stored = static_cast(SafeInt(2) * v_head_size * total_sequence_length * sizeof(T)); + + // Cost of appending current value to present value + unit_cost.compute_cycles += static_cast(v_head_size); + unit_cost.bytes_loaded += static_cast(v_head_size); + + ThreadPool::TryParallelFor(tp, SafeInt(batch_size) * num_heads_, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { + for (std::ptrdiff_t i = begin; i != end; ++i) { + const std::ptrdiff_t batch_index = i / num_heads_; + const std::ptrdiff_t head_index = i % num_heads_; + const std::ptrdiff_t beam_batch_index = batch_index / beam_width; + + // Compute the attention score + // (1, T) x (T, H_v) -> (1, H_v) + // Decompose into T (1, 1) x (1, H_v) -> (1, H_v) operations and accumulate. + { + const T* attn_probs_ptr = attention_probs + (i + 1) * total_sequence_length - 1; + math::Scale(v_head_size, + static_cast(*attn_probs_ptr), + V + i * v_head_size, + output + i * v_head_size, + nullptr); + } + { + for (std::ptrdiff_t j = 0; j < past_sequence_length; ++j) { + const int* beam_indices = &cache_indir_data[batch_index * max_sequence_length]; + const std::ptrdiff_t beam_offset = static_cast(beam_indices[j]) * num_heads_ * + max_sequence_length * v_head_size; + const std::ptrdiff_t beam_batch_offset = (beam_batch_index * beam_width * num_heads_ + head_index) * + max_sequence_length * v_head_size; + const T* past_value_vec = past_value_data + beam_offset + beam_batch_offset; + const T* attn_probs_ptr = attention_probs + j + i * total_sequence_length; + + math::Scale(v_head_size, + static_cast(*attn_probs_ptr), + past_value_vec + j * v_head_size, + tmp_buffer + i * v_head_size, + nullptr); + math::Add(v_head_size, + output + i * v_head_size, + tmp_buffer + i * v_head_size, + output + i * v_head_size, + nullptr); + } + } + + // Append current value to present value (past_present_share_buffer_ is true) + memcpy(present_value_data + (i * max_sequence_length + past_sequence_length) * v_head_size, + V + i * v_head_size, + v_head_size * sizeof(T)); + } + }); + } }; } // namespace contrib diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h b/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h new file mode 100644 index 0000000000000..417865bb166ec --- /dev/null +++ b/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "contrib_ops/cpu/bert/attention_common.h" + +namespace onnxruntime { +namespace contrib { + +// Parameters deduced from node attributes and inputs/outputs. +struct AttentionParameters { + int batch_size; + int sequence_length; + int kv_sequence_length; // input sequence length of K or V + int past_sequence_length; // sequence length in past state of K or V + int total_sequence_length; // total sequence length of K or V + int max_sequence_length; // max sequence length from 4D mask + int input_hidden_size; // first dimension of weights for input projection + int hidden_size; // hidden size of Q or K + int head_size; // hidden size per head of Q or K + int v_hidden_size; // hidden size of V + int v_head_size; // hidden size per head of V + int num_heads; + int num_splits; + int rotary_embedding; + int beam_width; + bool is_unidirectional; + bool past_present_share_buffer; + bool do_rotary; + bool broadcast_attn_bias_dim_0; + bool broadcast_attn_bias_dim_1; + float mask_filter_value; + float scale; + bool use_tf32; + AttentionMaskType mask_type; + AttentionQkvFormat qkv_format; +}; + +// Parameters deduced from node attributes and inputs/outputs. +struct PackedAttentionParameters : AttentionParameters { + int token_count; +}; + +struct DecoderMaskedMultiHeadAttentionParameters : AttentionParameters { + int beam_width = 1; + + // Only NeoX style rotary embedding is supported + int rotary_embedding_dim = 0; + int t_step = 0; + + // Weather to use multihead attention(excludes matmul and bias) + bool is_mha = false; + bool is_cross_attention = false; + bool is_packed_qkv = false; + + // Useful to better use global memory bandwidth on certain CUDA architectures. + // Turned off by default for now until we fully understand performance implications + // for all types of workloads. + // Can be turned on by appropriate environment variable (see attention_common.h). + bool kv_data_in_flight = false; + + void* q = nullptr; + void* q_bias = nullptr; + + void* k = nullptr; + void* k_bias = nullptr; + + void* v = nullptr; + void* v_bias = nullptr; + + void* attention_bias = nullptr; + + void* k_cache = nullptr; + void* v_cache = nullptr; + + void* out = nullptr; + void* out_qk = nullptr; + + const int32_t* cache_indir = nullptr; + const int32_t* mask = nullptr; // [B, total_sequence_length] +}; + +// Parameters deduced from node attributes and inputs/outputs. +struct GroupQueryAttentionParameters : AttentionParameters { + int seqlen_past_kv_cache; // sequence length of past kv tensor + int seqlen_present_kv_cache; // sequence length of present kv tensor + int kv_hidden_size; + int kv_num_heads; + int num_splits; // number of splits for splitkv + int rotary_dim; // rotary embedding dimension + int local_window_size; + bool kv_share_buffer; + bool is_packed_qkv; + bool is_subsequent_prompt; // indicates whether we have past context and seqlen > 1 + bool is_first_prompt; // indicates whether this is first decoding step + bool rotary_interleaved; + bool use_smooth_softmax; + float softcap; + AttentionQkvFormat past_kv_format; + int zeros_count; + int* zero_ptr; +}; + +// Parameters for sparse attention. +struct SparseAttentionParameters : AttentionParameters { + int kv_hidden_size; // hidden size of key or value + int kv_num_heads; // number of heads of key or value + bool do_rotary; // whether to use rotary embedding + bool rotary_interleaved; // whether to use interleaved rotary embedding + int rotary_dim; // rotary embedding dimension + int sparse_block_size; // block size for sparse attention + int num_sparse_layout; // number of sparse layout + int stride_col_indices; // shape of block_col_indices is [num_sparse_layout, stride_col_indices] + int stride_row_indices; // shape of block_row_indices is [num_sparse_layout, stride_row_indices] + bool is_packed_qkv; // whether qkv is packed + int max_rotary_sequence_length; // max sequence length for rotary cos/sin cache + int max_cache_sequence_length; // max sequence length for kv cache buffer +}; + +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.cc b/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.cc index e6f65f92e14f4..0d2de59c05394 100644 --- a/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.cc @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "attention_cpu_base.h" -#include "attention_utils.h" -#include "core/platform/env_var_utils.h" +#include "contrib_ops/cpu/bert/attention_cpu_base.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cpu/bert/attention_utils.h" #include "contrib_ops/cpu/bert/multihead_attention_helper.h" #include "contrib_ops/cpu/bert/decoder_masked_multihead_attention.h" +#include "core/platform/env_var_utils.h" using namespace ::onnxruntime::common; using namespace ONNX_NAMESPACE; @@ -65,7 +66,7 @@ Status DecoderMaskedMultiHeadAttention::Compute(OpKernelContext* context) con const Tensor* cache_indir = context->Input(kCacheIndirectionInputIndex); const Tensor* bias = context->Input(kBiasIndex); - DecoderMaskedMultiHeadAttentionParams parameters; + DecoderMaskedMultiHeadAttentionParameters parameters; bool is_unidirectional = false; ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckInputs(query, @@ -76,6 +77,7 @@ Status DecoderMaskedMultiHeadAttention::Compute(OpKernelContext* context) con attention_bias, past_key, past_value, + cache_indir, past_seq_len, ¶meters, num_heads_, @@ -188,9 +190,9 @@ Status DecoderMaskedMultiHeadAttention::Compute(OpKernelContext* context) con return ApplyAttention(Q.GetMutable()->MutableData(), key->Data(), value->Data(), - mask_index, nullptr /* past */, past_key, past_value, output, present_key, present_value, + mask_index, nullptr /* past */, past_key, past_value, output, present_key, present_value, output_qk, batch_size, 1 /* sequence_length */, parameters.kv_sequence_length, - head_size, v_head_size, v_hidden_size, attention_bias, context, output_qk); + head_size, v_head_size, v_hidden_size, attention_bias, context); } OrtValue K, V; @@ -204,9 +206,9 @@ Status DecoderMaskedMultiHeadAttention::Compute(OpKernelContext* context) con return ApplyAttention(Q.GetMutable()->MutableData(), K.GetMutable()->MutableData(), V.GetMutable()->MutableData(), - mask_index, nullptr /* past */, past_key, past_value, output, present_key, present_value, + mask_index, nullptr /* past */, past_key, past_value, output, present_key, present_value, output_qk, batch_size, 1 /* sequence_length */, parameters.kv_sequence_length, - head_size, v_head_size, v_hidden_size, attention_bias, context, output_qk, + head_size, v_head_size, v_hidden_size, attention_bias, context, parameters.past_sequence_length, true /* past_present_share_buffer */); } @@ -221,253 +223,5 @@ Status DecoderMaskedMultiHeadAttention::Compute(OpKernelContext* context) con beam_width_value, output_qk); } -template -Status DecoderMaskedMultiHeadAttention::ApplyAttentionWithBeams( - const T* Q, - const T* K, - const T* V, - const Tensor* mask_index, - const Tensor* past_key, - const Tensor* past_value, - Tensor* output, - Tensor* present_key, - Tensor* present_value, - int batch_size, - int past_sequence_length, - int max_sequence_length, - int head_size, - int v_head_size, - const Tensor* attn_bias, - bool broadcast_attn_bias_dim_0, - bool broadcast_attn_bias_dim_1, - const Tensor* cache_indir, - OpKernelContext* context, - int beam_width, - Tensor* output_qk) const { - AllocatorPtr allocator; - ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); - - auto* tp = context->GetOperatorThreadPool(); - - int total_sequence_length = past_sequence_length + 1; - size_t bytes = SafeInt(batch_size) * num_heads_ * total_sequence_length * sizeof(T); - auto attention_probs = allocator->Alloc(bytes); - BufferUniquePtr scratch_buffer(attention_probs, BufferDeleter(allocator)); - - T* output_qk_data = (output_qk != nullptr) ? output_qk->MutableData() : nullptr; - - const int32_t* mask_index_data = mask_index != nullptr ? mask_index->Data() : nullptr; - const T* attn_bias_data = attn_bias != nullptr ? attn_bias->Data() : nullptr; - - ComputeAttentionProbsWithBeams(static_cast(attention_probs), Q, K, mask_index_data, batch_size, - past_sequence_length, max_sequence_length, head_size, past_key->Data(), - present_key->MutableData(), tp, attn_bias_data, broadcast_attn_bias_dim_0, - broadcast_attn_bias_dim_1, cache_indir->Data(), beam_width, output_qk_data); - - // Compute the attentionScore * Value: out_tmp(B, N, 1, H_v) = attention_probs(B, N, 1, T) x V(B, N, T, H_v) - auto out_tmp_data = allocator->Alloc(SafeInt(batch_size) * num_heads_ * v_head_size * sizeof(T)); - BufferUniquePtr out_tmp_buffer(out_tmp_data, BufferDeleter(std::move(allocator))); - - ComputeVxAttentionScoreWithBeams(output->MutableData(), static_cast(out_tmp_data), - static_cast(attention_probs), V, batch_size, - past_sequence_length, max_sequence_length, v_head_size, past_value->Data(), - present_value->MutableData(), cache_indir->Data(), beam_width, tp); - - return Status::OK(); -} - -template -void DecoderMaskedMultiHeadAttention::ComputeAttentionProbsWithBeams( - T* attention_probs, - const T* Q, - const T* K, - const int32_t* mask_index_data, - int batch_size, - int past_sequence_length, - int max_sequence_length, - int head_size, - const T* past_key_data, - T* present_key_data, - ThreadPool* tp, - const T* attn_bias_data, - bool broadcast_attn_bias_dim_0, - bool broadcast_attn_bias_dim_1, - const int32_t* cache_indir_data, - int beam_width, - T* output_qk_data) const { - float scale = scale_ == 0.0f ? 1.0f / sqrt(static_cast(head_size)) : scale_; - - TensorOpCost unit_cost; - auto total_sequence_length = past_sequence_length + 1; - const ptrdiff_t probs_matrix_size = total_sequence_length; - const ptrdiff_t probs_matrix_bytes = probs_matrix_size * sizeof(T); - - unit_cost.compute_cycles = static_cast((SafeInt(2) * head_size - 1) * total_sequence_length); - unit_cost.bytes_loaded = static_cast(SafeInt(2) * head_size * total_sequence_length * sizeof(T)); - unit_cost.bytes_stored = static_cast(SafeInt(head_size) * total_sequence_length * sizeof(T)); - - if (attn_bias_data != nullptr) { - unit_cost.bytes_loaded += static_cast(probs_matrix_bytes) * 2; - unit_cost.bytes_stored += probs_matrix_bytes; - } - - if (mask_index_data != nullptr) { - unit_cost.bytes_stored += probs_matrix_bytes; - } - - // Cost of appending current key to present key - unit_cost.compute_cycles += static_cast(head_size); - unit_cost.bytes_loaded += static_cast(head_size); - - // Parallel for loop - const int loop_len = batch_size * num_heads_; - ThreadPool::TryParallelFor(tp, loop_len, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { - for (std::ptrdiff_t i = begin; i != end; ++i) { - const std::ptrdiff_t batch_index = i / num_heads_; - const std::ptrdiff_t head_index = i % num_heads_; - const std::ptrdiff_t beam_batch_index = batch_index / beam_width; - const T* q_vec = Q + i * head_size; - const std::ptrdiff_t attn_bias_base_offset = ((broadcast_attn_bias_dim_0 ? 0 : (beam_batch_index * num_heads_)) + - (broadcast_attn_bias_dim_1 ? 0 : head_index)) * - probs_matrix_size; - - { - // Calculate the latest position of the attention_probs - // (1, H) x (T, H)^T -> (1, T) - // Decompose into T (1, H) x (1, H)^T -> (1, 1) operations - auto last_offset = past_sequence_length + i * probs_matrix_size; - T* attention_probs_ptr = reinterpret_cast(attention_probs) + last_offset; - math::Dot(head_size, q_vec, K + i * head_size, attention_probs_ptr, nullptr); - - *attention_probs_ptr *= scale; - // Apply the attention bias and mask - if (attn_bias_data != nullptr) { - *attention_probs_ptr += attn_bias_data[attn_bias_base_offset + past_sequence_length]; - } - bool is_masked = (mask_index_data != nullptr) && - (mask_index_data[(batch_index + 1) * total_sequence_length - 1] == 0); - if (is_masked) { - *attention_probs_ptr += mask_filter_value_; - } - } - - { - // Calculate the rest of the attention_probs - for (std::ptrdiff_t j = 0; j < past_sequence_length; ++j) { - const int* beam_indices = &cache_indir_data[batch_index * max_sequence_length]; - const std::ptrdiff_t beam_offset = static_cast(beam_indices[j]) * num_heads_ * - max_sequence_length * head_size; - const std::ptrdiff_t beam_batch_offset = (beam_batch_index * beam_width * num_heads_ + head_index) * - max_sequence_length * head_size; - const T* past_k_vec = past_key_data + beam_batch_offset + beam_offset + j * head_size; - T* output = reinterpret_cast(attention_probs) + j + i * probs_matrix_size; - math::Dot(head_size, q_vec, past_k_vec, output, nullptr); - - *output *= scale; - // Apply the attention bias and mask - if (attn_bias_data != nullptr) { - *output += attn_bias_data[attn_bias_base_offset + j]; - } - bool is_masked = (mask_index_data != nullptr) && - (mask_index_data[batch_index * total_sequence_length + j] == 0); - if (is_masked) { - *output += mask_filter_value_; - } - } - } - // Append current key to present key (past_present_share_buffer_ is true) - memcpy(present_key_data + (i * max_sequence_length + past_sequence_length) * head_size, - K + i * head_size, head_size * sizeof(T)); - } - }); - - if (output_qk_data != nullptr) { - // Output the scaled Q*K^T if needed. - memcpy(output_qk_data, attention_probs, - SafeInt(batch_size) * num_heads_ * total_sequence_length * sizeof(T)); - } - - // attention_probs(B, N, 1, T) = Softmax(attention_probs) - { - const int N = batch_size * num_heads_; - const int D = total_sequence_length; - ComputeAttentionSoftmaxInplace(attention_probs, N, D, tp); - } -} - -template -void DecoderMaskedMultiHeadAttention::ComputeVxAttentionScoreWithBeams( - T* output, - T* tmp_buffer, - const T* attention_probs, - const T* V, - int batch_size, - int past_sequence_length, - int max_sequence_length, - int v_head_size, - const T* past_value_data, - T* present_value_data, - const int32_t* cache_indir_data, - int beam_width, - ThreadPool* tp) const { - const int total_sequence_length = past_sequence_length + 1; - - TensorOpCost unit_cost; - unit_cost.compute_cycles = static_cast(SafeInt(2) * v_head_size * total_sequence_length); - unit_cost.bytes_loaded = static_cast(SafeInt(3) * v_head_size * total_sequence_length * sizeof(T)); - unit_cost.bytes_stored = static_cast(SafeInt(2) * v_head_size * total_sequence_length * sizeof(T)); - - // Cost of appending current value to present value - unit_cost.compute_cycles += static_cast(v_head_size); - unit_cost.bytes_loaded += static_cast(v_head_size); - - ThreadPool::TryParallelFor( - tp, SafeInt(batch_size) * num_heads_, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { - for (std::ptrdiff_t i = begin; i != end; ++i) { - const std::ptrdiff_t batch_index = i / num_heads_; - const std::ptrdiff_t head_index = i % num_heads_; - const std::ptrdiff_t beam_batch_index = batch_index / beam_width; - - // Compute the attention score - // (1, T) x (T, H_v) -> (1, H_v) - // Decompose into T (1, 1) x (1, H_v) -> (1, H_v) operations and accumulate. - { - const T* attn_probs_ptr = attention_probs + (i + 1) * total_sequence_length - 1; - math::Scale(v_head_size, - static_cast(*attn_probs_ptr), - V + i * v_head_size, - output + i * v_head_size, - nullptr); - } - { - for (std::ptrdiff_t j = 0; j < past_sequence_length; ++j) { - const int* beam_indices = &cache_indir_data[batch_index * max_sequence_length]; - const std::ptrdiff_t beam_offset = static_cast(beam_indices[j]) * num_heads_ * - max_sequence_length * v_head_size; - const std::ptrdiff_t beam_batch_offset = (beam_batch_index * beam_width * num_heads_ + head_index) * - max_sequence_length * v_head_size; - const T* past_value_vec = past_value_data + beam_offset + beam_batch_offset; - const T* attn_probs_ptr = attention_probs + j + i * total_sequence_length; - - math::Scale(v_head_size, - static_cast(*attn_probs_ptr), - past_value_vec + j * v_head_size, - tmp_buffer + i * v_head_size, - nullptr); - math::Add(v_head_size, - output + i * v_head_size, - tmp_buffer + i * v_head_size, - output + i * v_head_size, - nullptr); - } - } - // Append current value to present value (past_present_share_buffer_ is true) - memcpy(present_value_data + (i * max_sequence_length + past_sequence_length) * v_head_size, - V + i * v_head_size, - v_head_size * sizeof(T)); - } - }); -} - } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.h b/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.h index d5167e8989669..1a4bc72e2f73a 100644 --- a/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.h +++ b/onnxruntime/contrib_ops/cpu/bert/decoder_masked_multihead_attention.h @@ -13,57 +13,6 @@ template class DecoderMaskedMultiHeadAttention final : public OpKernel, public AttentionCPUBase { public: DecoderMaskedMultiHeadAttention(const OpKernelInfo& info); - Status ApplyAttentionWithBeams(const T* Q, - const T* K, - const T* V, - const Tensor* mask_index, - const Tensor* past_key, - const Tensor* past_value, - Tensor* output, - Tensor* present_key, - Tensor* present_value, - int batch_size, - int past_sequence_length, - int max_sequence_length, - int head_size, - int v_head_size, - const Tensor* attn_bias, - bool broadcast_attn_bias_dim_0, - bool broadcast_attn_bias_dim_1, - const Tensor* cache_indir, - OpKernelContext* context, - int beam_width, - Tensor* output_qk = nullptr) const; - void ComputeAttentionProbsWithBeams(T* attention_probs, - const T* Q, - const T* K, - const int32_t* mask_index_data, - int batch_size, - int past_sequence_length, - int max_sequence_length, - int head_size, - const T* past_key, - T* present_key, - ThreadPool* tp, - const T* attn_bias_data, - bool broadcast_attn_bias_dim_0, - bool broadcast_attn_bias_dim_1, - const int32_t* cache_indir_data, - int beam_width, - T* output_qk_data = nullptr) const; - void ComputeVxAttentionScoreWithBeams(T* output, - T* tmp_buffer, - const T* attention_probs, - const T* V, - int batch_size, - int past_sequence_length, - int max_sequence_length, - int v_head_size, - const T* past_value, - T* present_value, - const int32_t* cache_indir_data, - int beam_width, - ThreadPool* tp) const; Status Compute(OpKernelContext* context) const override; protected: diff --git a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h index ff6cb8edc0231..c8c66c880852f 100644 --- a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h @@ -4,10 +4,11 @@ #pragma once #include "contrib_ops/cpu/bert/attention_base.h" +#include "contrib_ops/cpu/bert/attention_common.h" #include "contrib_ops/cpu/bert/attention_helper.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" #include "core/common/common.h" -#include "contrib_ops/cpu/bert/attention_common.h" #include "core/common/safeint.h" #include "core/framework/op_kernel.h" diff --git a/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h index 7bffd768c8f7c..fa0d33e891f46 100644 --- a/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h @@ -6,6 +6,7 @@ #include "core/common/common.h" #include "core/providers/common.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc index ca818f09c4b1e..996f913ef6565 100644 --- a/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc @@ -1,10 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "attention_cpu_base.h" -#include "multihead_attention.h" -#include "multihead_attention_helper.h" -#include "attention_utils.h" +#include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_cpu_base.h" +#include "contrib_ops/cpu/bert/multihead_attention.h" +#include "contrib_ops/cpu/bert/multihead_attention_helper.h" +#include "contrib_ops/cpu/bert/attention_utils.h" #include "core/common/common.h" #include "core/framework/tensorprotoutils.h" @@ -48,6 +49,8 @@ MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) : OpKernel(i l2_cache_size_ = env.GetL2CacheSize(); disable_flash_ = ParseEnvironmentVariableWithDefault(attention::kDisableFlashAttention, false); + + disable_decoder_attention_ = ParseEnvironmentVariableWithDefault(attention::kDisableDecoderAttention, false); } template @@ -60,6 +63,8 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { const Tensor* attn_bias = context->Input(5); const Tensor* past_key = context->Input(6); const Tensor* past_value = context->Input(7); + const Tensor* past_sequence_length = context->Input(8); + const Tensor* cache_indirection = context->Input(9); if (query->Shape().GetDims().size() == 5) { ORT_NOT_IMPLEMENTED("Packed QKV of shape (B, L, N, 3, H) not implemented for CPU"); @@ -68,8 +73,12 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { ORT_NOT_IMPLEMENTED("Packed KV not implemented for CPU"); } + bool past_present_share_buffer = past_key != nullptr && past_sequence_length != nullptr; + if (past_key != nullptr && past_sequence_length != nullptr && cache_indirection != nullptr) { + ORT_ENFORCE(past_present_share_buffer); + } + AttentionParameters parameters = {}; - bool past_present_share_buffer = false; ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckInputs(query, key, value, @@ -78,7 +87,8 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { attn_bias, past_key, past_value, - nullptr, + cache_indirection, + past_sequence_length, ¶meters, num_heads_, mask_filter_value_, @@ -86,11 +96,24 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { is_unidirectional_, past_present_share_buffer, kMultiHeadAttention)); + DUMP_CPU_STRING_INIT(); + DUMP_CPU_STRING("Batch size = ", parameters.batch_size); + DUMP_CPU_STRING("Sequence length = ", parameters.sequence_length); + DUMP_CPU_STRING("Past sequence length = ", parameters.past_sequence_length); + DUMP_CPU_STRING("KV sequence length = ", parameters.kv_sequence_length); + DUMP_CPU_STRING("Total sequence length = ", parameters.total_sequence_length); + DUMP_CPU_STRING("Max sequence length = ", parameters.max_sequence_length); + DUMP_CPU_STRING("Hidden size = ", parameters.hidden_size); + DUMP_CPU_STRING("Head size = ", parameters.head_size); + DUMP_CPU_STRING("Num heads = ", parameters.num_heads); + DUMP_CPU_STRING("Buffer sharing = ", (parameters.past_present_share_buffer == true)); + DUMP_CPU_STRING("QKV format = ", parameters.qkv_format); + DUMP_CPU_STRING("Beam width = ", parameters.beam_width); const int batch_size = parameters.batch_size; const int q_sequence_length = parameters.sequence_length; const int kv_sequence_length = parameters.kv_sequence_length; - const int total_kv_sequence_length = parameters.total_sequence_length; + const int total_sequence_length = parameters.total_sequence_length; int qk_head_size = parameters.head_size; int v_head_size = parameters.v_head_size; int qk_hidden_size = parameters.hidden_size; @@ -106,17 +129,38 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { const int k_bias_offset = qk_hidden_size; const int v_bias_offset = 2 * qk_hidden_size; - // If optional outputs aren't needed, present_k and present_v will be null - std::vector present_k_shape({static_cast(batch_size), + // If optional outputs aren't needed, present_key, present_value, and output_qk will be null + std::vector present_key_shape({static_cast(batch_size), + static_cast(num_heads_), + static_cast(parameters.max_sequence_length), + static_cast(qk_head_size)}); + std::vector present_value_shape({static_cast(batch_size), + static_cast(num_heads_), + static_cast(parameters.max_sequence_length), + static_cast(v_head_size)}); + std::vector output_qk_shape({static_cast(batch_size), static_cast(num_heads_), - static_cast(total_kv_sequence_length), - static_cast(qk_head_size)}); - std::vector present_v_shape({static_cast(batch_size), - static_cast(num_heads_), - static_cast(total_kv_sequence_length), - static_cast(v_head_size)}); - Tensor* present_k = context->Output(1, present_k_shape); - Tensor* present_v = context->Output(2, present_v_shape); + static_cast(q_sequence_length), + static_cast(total_sequence_length)}); + Tensor* present_key = context->Output(1, present_key_shape); + Tensor* present_value = context->Output(2, present_value_shape); + Tensor* output_qk = context->Output(3, output_qk_shape); + + bool use_decoder_masked_multihead_attention = false; + if (cache_indirection != nullptr) { + bool use_dmmha_self_attention = parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH && + parameters.past_present_share_buffer && + parameters.past_sequence_length > 0; + bool use_dmmha_cross_attention = parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH && + past_key == nullptr && past_value == nullptr && nullptr != past_sequence_length && + parameters.past_sequence_length != *((*past_sequence_length).template Data()); + use_decoder_masked_multihead_attention = !disable_decoder_attention_ && + (use_dmmha_self_attention || use_dmmha_cross_attention) && + parameters.sequence_length == 1 && + parameters.head_size == parameters.v_head_size && + (parameters.mask_type == AttentionMaskType::MASK_2D_KEY_PADDING || parameters.mask_type == AttentionMaskType::MASK_NONE) && + nullptr != past_sequence_length && nullptr != cache_indirection; + } AllocatorPtr allocator; ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); @@ -125,15 +169,22 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { ORT_RETURN_IF_ERROR(MaybeTransposeToBNSHAndAddBias( context, allocator, batch_size, num_heads_, q_sequence_length, qk_head_size, query, bias, q_bias_offset, Q)); - if (parameters.qkv_format == Q_K_V_BSNH_BNSH_BNSH) { + if (parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH) { // For cross attention with k and v in BNSH format, we assume that bias for key and value are zeros. // So we don't need to add bias for key and value here. assert(past_key == nullptr); assert(past_value == nullptr); + + if (use_decoder_masked_multihead_attention) { + parameters.total_sequence_length = parameters.kv_sequence_length; + parameters.max_sequence_length = parameters.kv_sequence_length; + } + return ApplyAttention(Q.GetMutable()->MutableData(), key->Data(), value->Data(), - key_padding_mask, nullptr /* past */, past_key, past_value, output, present_k, present_v, + key_padding_mask, nullptr /* past */, past_key, past_value, + output, present_key, present_value, output_qk, batch_size, q_sequence_length, kv_sequence_length, qk_head_size, v_head_size, v_hidden_size, attn_bias, context); } @@ -152,8 +203,11 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { attn_bias == nullptr && past_key == nullptr && past_value == nullptr && - present_k == nullptr && - present_v == nullptr && + past_sequence_length == nullptr && + cache_indirection == nullptr && + present_key == nullptr && + present_value == nullptr && + output_qk == nullptr && l2_cache_size_ > 0) { MlasFlashAttentionThreadedArgs args; args.batch_size = batch_size; @@ -209,11 +263,42 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { return Status::OK(); } + if (use_decoder_masked_multihead_attention) { + // No production use-case will incur this copy cost as the implementation of + // DecoderMaskedMultiHeadAttention is written in such a way that the past and present buffers + // must be shared to have parity in the outputs. + // This is just to circumvent the OpTester's limitation of not being able to bind a specific + // buffer to inputs/outputs. + auto* past_key_data = (past_key == nullptr) ? nullptr : past_key->Data(); + auto* past_value_data = (past_value == nullptr) ? nullptr : past_value->Data(); + auto* present_key_data = (present_key == nullptr) ? nullptr : present_key->MutableData(); + auto* present_value_data = (present_value == nullptr) ? nullptr : present_value->MutableData(); + + if (present_key_data != past_key_data) { + DUMP_CPU_STRING("Copying past_key to present_key for OpTester"); + memcpy(present_key_data, past_key_data, past_key->SizeInBytes()); + } + if (present_value_data != past_value_data) { + DUMP_CPU_STRING("Copying past_value to present_value for OpTester"); + memcpy(present_value_data, past_value_data, past_value->SizeInBytes()); + } + + return ApplyAttentionWithBeams(Q.GetMutable()->MutableData(), + K.GetMutable()->MutableData(), + V.GetMutable()->MutableData(), + key_padding_mask, past_key, past_value, output, present_key, present_value, + batch_size, *((*past_sequence_length).template Data()), parameters.max_sequence_length, + qk_head_size, v_head_size, attn_bias, parameters.broadcast_attn_bias_dim_0, + parameters.broadcast_attn_bias_dim_1, cache_indirection, context, + parameters.beam_width, output_qk); + } + // Compute the attention score and apply the score to V return ApplyAttention(Q.GetMutable()->MutableData(), K.GetMutable()->MutableData(), V.GetMutable()->MutableData(), - key_padding_mask, nullptr /* past */, past_key, past_value, output, present_k, present_v, + key_padding_mask, nullptr /* past */, past_key, past_value, + output, present_key, present_value, output_qk, batch_size, q_sequence_length, kv_sequence_length, qk_head_size, v_head_size, v_hidden_size, attn_bias, context); } diff --git a/onnxruntime/contrib_ops/cpu/bert/multihead_attention.h b/onnxruntime/contrib_ops/cpu/bert/multihead_attention.h index 8a9bef1b2bf0d..a420b6a526882 100644 --- a/onnxruntime/contrib_ops/cpu/bert/multihead_attention.h +++ b/onnxruntime/contrib_ops/cpu/bert/multihead_attention.h @@ -20,6 +20,7 @@ class MultiHeadAttention final : public OpKernel, public AttentionCPUBase { float mask_filter_value_; bool is_unidirectional_; bool disable_flash_; + bool disable_decoder_attention_; int l2_cache_size_; }; diff --git a/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h index 0cfe90963c334..8af6faadd6e92 100644 --- a/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h @@ -6,6 +6,8 @@ #include "core/common/common.h" #include "core/providers/common.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cpu/utils/dump_tensor.h" namespace onnxruntime { namespace contrib { @@ -153,7 +155,7 @@ Status CheckPast(const T* past_key, const T* past_value, const T* past_seq_len, } if (past_key_dims[2] != past_value_dims[2]) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'past_key' and 'past_value' shall have same dim 2 (past_sequence_length). ", + "Input 'past_key' and 'past_value' shall have same dim 2 (past_sequence_length or max_sequence_length). ", past_key_dims[2], " vs ", past_value_dims[2]); } if (past_key_dims[3] != head_size) { @@ -233,6 +235,35 @@ AttentionMaskType GetMaskType(const T* key_padding_mask, int batch_size, int seq return mask_type; } +inline Status CheckCacheIndirection( + const gsl::span& cache_indir_dims, int batch_beam_size, int& num_beams, int max_sequence_length) { + if (cache_indir_dims.size() != 3) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "Input 'cache_indirection' is expected to have 3 dimensions, got ", + cache_indir_dims.size()); + } + num_beams = static_cast(cache_indir_dims[1]); + if (cache_indir_dims[1] == 0) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "Input 'cache_indirection' dimension 1 should be num_beams, got ", + cache_indir_dims[1]); + } + if (cache_indir_dims[0] != static_cast(batch_beam_size / num_beams)) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "Input 'cache_indirection' dimension 0 should be batch_size, got ", + cache_indir_dims[0]); + } + if (max_sequence_length > 0 && cache_indir_dims[2] != static_cast(max_sequence_length)) { + // First condition is to avoid this check for cross attention layers where + // past key/past value are passed directly into key/value (which means + // that max_sequence_length = 0) + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "Input 'cache_indirection' dimension 2 should be same as (or less than) max_sequence_length, got ", + cache_indir_dims[2]); + } + return Status::OK(); +} + template Status CheckInputs(const T* query, const T* key, @@ -242,6 +273,7 @@ Status CheckInputs(const T* query, const T* attention_bias, const T* past_key, const T* past_value, + const T* cache_indirection, const T* past_seq_len, void* parameters, int num_heads, @@ -263,6 +295,7 @@ Status CheckInputs(const T* query, // L: kv_sequence_length // T: total_sequence_length = P + L // M: max_sequence_length of kv cache when past and present share buffer + // W: beam_width // --------------------------------------------------------------- // MultiHeadAttention inputs: // --------------------------------------------------------------- @@ -308,7 +341,8 @@ Status CheckInputs(const T* query, // Other inputs: // bias (Q/K/V) : None or (3 * D) // key_padding_mask (K/V) : None or (B, T) - // attention_bias : (1, N, S, T), or (B, N, S, T) where only 1 x N x S x T data is used in CUDA. + // attention_bias : (B, N, S, T), (1, N, S, T), (B, 1, S, T) or (1, 1, S, T) + // cache_indirection : (B, W, M) // // The following inputs are not used in cross attention (so they are None for cross attention): // past_key : (B, N, P, H), or (B, N, M, H) when past_present_share_buffer is True. @@ -408,6 +442,13 @@ Status CheckInputs(const T* query, assert(qkv_format != UNKNOWN); + gsl::span cache_indir_dims; + int num_beams = 0; + if (cache_indirection != nullptr) { + cache_indir_dims = cache_indirection->Shape().GetDims(); + ORT_RETURN_IF_ERROR(CheckCacheIndirection(cache_indir_dims, batch_size, num_beams, max_sequence_length)); + } + if (parameters != nullptr) { AttentionParameters* output_parameters = reinterpret_cast(parameters); output_parameters->batch_size = batch_size; @@ -430,6 +471,7 @@ Status CheckInputs(const T* query, output_parameters->broadcast_attn_bias_dim_0 = attention_bias_dims.size() > 0 && attention_bias_dims[0] == 1; output_parameters->broadcast_attn_bias_dim_1 = attention_bias_dims.size() > 1 && attention_bias_dims[1] == 1; output_parameters->qkv_format = qkv_format; + output_parameters->beam_width = num_beams; } return Status::OK(); @@ -444,6 +486,7 @@ Status CheckInputs(const T* query, const T* attention_bias, const T* past_key, const T* past_value, + const T* cache_indirection, const T* past_seq_len, void* parameters, int num_heads, @@ -457,7 +500,7 @@ Status CheckInputs(const T* query, return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "num_heads should be no larger than ", max_threads_per_block); } - return CheckInputs(query, key, value, bias, key_padding_mask, attention_bias, past_key, past_value, + return CheckInputs(query, key, value, bias, key_padding_mask, attention_bias, past_key, past_value, cache_indirection, past_seq_len, parameters, num_heads, mask_filter_value, scale, is_unidirectional, past_present_share_buffer, operator_type); } diff --git a/onnxruntime/contrib_ops/cpu/bert/rotary_helper.h b/onnxruntime/contrib_ops/cpu/bert/rotary_helper.h index 714d962dfb34e..43415d6053fbb 100644 --- a/onnxruntime/contrib_ops/cpu/bert/rotary_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/rotary_helper.h @@ -5,7 +5,6 @@ #include "core/common/common.h" #include "core/providers/common.h" -#include "contrib_ops/cpu/bert/attention_common.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc b/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc index 2c897f183164f..d369939a861d2 100644 --- a/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc +++ b/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc @@ -289,7 +289,7 @@ Status QAttention::Compute(OpKernelContext* context) const { // Compute the attention score and apply the score to V return ApplyAttention(Q, K, V, mask_index, past_tensor, nullptr /* past_key */, nullptr /* past_value*/, - output, nullptr /* present_key */, nullptr /* present_value */, + output, nullptr /* present_key */, nullptr /* present_value */, nullptr /* output_qk */, batch_size, sequence_length, sequence_length, head_size, head_size, hidden_size, nullptr /* rel_pos_bias */, context); } diff --git a/onnxruntime/contrib_ops/cpu/skip_layer_norm_helper.h b/onnxruntime/contrib_ops/cpu/skip_layer_norm_helper.h index 4c901f5650dbd..b70bd317b95b2 100644 --- a/onnxruntime/contrib_ops/cpu/skip_layer_norm_helper.h +++ b/onnxruntime/contrib_ops/cpu/skip_layer_norm_helper.h @@ -5,7 +5,6 @@ #include "core/common/common.h" #include "core/providers/common.h" -#include "contrib_ops/cpu/bert/attention_common.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h index 37172074e5d86..2c719b3724106 100644 --- a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h @@ -4,12 +4,13 @@ #pragma once #include "contrib_ops/cpu/bert/attention_helper.h" +#include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cpu/utils/dump_tensor.h" #include "core/common/common.h" -#include "contrib_ops/cpu/bert/attention_common.h" #include "core/common/safeint.h" #include "core/framework/op_kernel.h" -#include "contrib_ops/cpu/utils/dump_tensor.h" namespace onnxruntime { namespace contrib { @@ -159,11 +160,11 @@ class SparseAttentionBase { int nonzero_elements = block_row_indices[(layout_index + 1) * parameters.stride_row_indices - 1]; int dense_nonzero = (parameters.stride_row_indices * (parameters.stride_row_indices - 1)) / 2; layout_has_sparse[layout_index] = nonzero_elements < dense_nonzero; - DUMP_STRING("layout_has_sparse[", layout_index, "]=", layout_has_sparse[layout_index]); + DUMP_CPU_STRING("layout_has_sparse[", layout_index, "]=", layout_has_sparse[layout_index]); } ThreadPool::TryParallelFor(tp, loop_len, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { - DUMP_STRING("batch_size=", batch_size, ",num_heads=", num_heads_, ",loop_len=", loop_len, ",begin=", begin, ",end=", end); + DUMP_CPU_STRING("batch_size=", batch_size, ",num_heads=", num_heads_, ",loop_len=", loop_len, ",begin=", begin, ",end=", end); for (std::ptrdiff_t i = begin; i != end; ++i) { const int batch_index = static_cast(i) / num_heads_; const int head_index = static_cast(i) % num_heads_; @@ -199,8 +200,8 @@ class SparseAttentionBase { q = Q + q_input_chunk_length * i; } - DUMP_STRING("i=", i, ",batch_index=", batch_index, ",head_index=", head_index, - ",past_seq_len=", past_seq_len, ",total_seq_len=", total_seq_len, ",packed_qkv=", packed_qkv); + DUMP_CPU_STRING("i=", i, ",batch_index=", batch_index, ",head_index=", head_index, + ",past_seq_len=", past_seq_len, ",total_seq_len=", total_seq_len, ",packed_qkv=", packed_qkv); DUMP_CPU_TENSOR("Q", q, sequence_length, head_size); DUMP_CPU_TENSOR("K", k, total_seq_len, head_size); @@ -216,7 +217,7 @@ class SparseAttentionBase { int layout_id = head_index % parameters.num_sparse_layout; bool is_sparse_layout = layout_has_sparse[layout_id]; - DUMP_STRING("layout_id=", layout_id, ",is_sparse_layout=", is_sparse_layout); + DUMP_CPU_STRING("layout_id=", layout_id, ",is_sparse_layout=", is_sparse_layout); if (!is_sparse_layout) { // dense for (int q_id = 0; q_id < sequence_length; q_id++) { @@ -246,19 +247,19 @@ class SparseAttentionBase { int nonzero_blocks = end_in_col_indices - start_in_col_indices; has_sparse = (nonzero_blocks != row_in_sparse_layout + 1); - DUMP_STRING("q_id=", q_id, - ",q_abs_position=", q_abs_position, - ",sparse_block_size=", parameters.sparse_block_size, - ",row_in_sparse_layout=", row_in_sparse_layout, - ",start_in_col_indices=", start_in_col_indices, - ",end_in_col_indices=", end_in_col_indices, - ",nonzero_blocks=", nonzero_blocks, - ",has_sparse=", has_sparse); + DUMP_CPU_STRING("q_id=", q_id, + ",q_abs_position=", q_abs_position, + ",sparse_block_size=", parameters.sparse_block_size, + ",row_in_sparse_layout=", row_in_sparse_layout, + ",start_in_col_indices=", start_in_col_indices, + ",end_in_col_indices=", end_in_col_indices, + ",nonzero_blocks=", nonzero_blocks, + ",has_sparse=", has_sparse); // Expand attention mask for current row of q_id if (has_sparse) { int block_aligned_length = q_abs_position / parameters.sparse_block_size * parameters.sparse_block_size + parameters.sparse_block_size; - DUMP_STRING("block_aligned_length=", block_aligned_length); + DUMP_CPU_STRING("block_aligned_length=", block_aligned_length); std::fill_n(mask.begin(), block_aligned_length, 0); for (int j = start_in_col_indices; j < end_in_col_indices; j++) { @@ -344,7 +345,7 @@ class SparseAttentionBase { ThreadPool::TryParallelFor( tp, SafeInt(batch_size) * num_heads_, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { - DUMP_STRING("batch_size=", batch_size, ",num_heads=", num_heads_, ",begin=", begin, ",end=", end); + DUMP_CPU_STRING("batch_size=", batch_size, ",num_heads=", num_heads_, ",begin=", begin, ",end=", end); for (std::ptrdiff_t i = begin; i != end; ++i) { const int batch_index = static_cast(i / num_heads_); @@ -353,8 +354,8 @@ class SparseAttentionBase { const size_t past_chunk_length = static_cast(past_seq_len) * head_size; const int total_seq_len = total_key_lengths[batch_index]; - DUMP_STRING("i=", i, ",batch_index=", batch_index, ",head_index=", head_index, - ",past_seq_len=", past_seq_len, ",total_seq_len=", total_seq_len, ",packed_qkv=", packed_qkv); + DUMP_CPU_STRING("i=", i, ",batch_index=", batch_index, ",head_index=", head_index, + ",past_seq_len=", past_seq_len, ",total_seq_len=", total_seq_len, ",packed_qkv=", packed_qkv); const T* v; if (packed_qkv) { diff --git a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_helper.h b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_helper.h index ca69370b4ce17..dfb60f635bc33 100644 --- a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_helper.h @@ -6,6 +6,7 @@ #include "core/common/common.h" #include "core/providers/common.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cpu/transformers/sequences.h b/onnxruntime/contrib_ops/cpu/transformers/sequences.h index 7dd1f28d270c7..e2f6b29a77a2c 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/sequences.h +++ b/onnxruntime/contrib_ops/cpu/transformers/sequences.h @@ -5,6 +5,7 @@ #include #include "contrib_ops/cpu/transformers/generation_shared.h" +#include "contrib_ops/cpu/utils/console_dumper.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cpu/utils/debug_macros.h b/onnxruntime/contrib_ops/cpu/utils/debug_macros.h index d5cbaa0a3e6b7..47d0fc5e4008c 100644 --- a/onnxruntime/contrib_ops/cpu/utils/debug_macros.h +++ b/onnxruntime/contrib_ops/cpu/utils/debug_macros.h @@ -15,11 +15,13 @@ #if DUMP_CPU_TENSOR_LEVEL > 0 #define DUMP_CPU_TENSOR_INIT() onnxruntime::contrib::CpuTensorConsoleDumper cpu_dumper #define DUMP_CPU_TENSOR(...) cpu_dumper.Print(__VA_ARGS__) -#define DUMP_STRING(...) cpu_dumper.Print(::onnxruntime::MakeString(__VA_ARGS__)) +#define DUMP_CPU_STRING_INIT() DUMP_CPU_TENSOR_INIT() +#define DUMP_CPU_STRING(...) cpu_dumper.Print(::onnxruntime::MakeString(__VA_ARGS__)) #else -#define DUMP_CPU_TENSOR_INIT() +#define DUMP_CPU_TENSOR_INIT(...) #define DUMP_CPU_TENSOR(...) -#define DUMP_STRING(...) +#define DUMP_CPU_STRING_INIT(...) +#define DUMP_CPU_STRING(...) #endif #if DUMP_CPU_TENSOR_LEVEL > 1 @@ -32,9 +34,13 @@ #if DUMP_TENSOR_LEVEL > 0 #define DUMP_TENSOR_INIT() onnxruntime::contrib::cuda::CudaTensorConsoleDumper dumper #define DUMP_TENSOR(...) dumper.Print(__VA_ARGS__) +#define DUMP_STRING_INIT() DUMP_TENSOR_INIT() +#define DUMP_STRING(...) dumper.Print(::onnxruntime::MakeString(__VA_ARGS__)) #else -#define DUMP_TENSOR_INIT() +#define DUMP_TENSOR_INIT(...) #define DUMP_TENSOR(...) +#define DUMP_STRING_INIT(...) +#define DUMP_STRING(...) #endif #if DUMP_TENSOR_LEVEL > 1 diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_data.h b/onnxruntime/contrib_ops/cuda/bert/attention_data.h new file mode 100644 index 0000000000000..c7b06d50858b4 --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/attention_data.h @@ -0,0 +1,185 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +template +struct AttentionData { + T* gemm_buffer = nullptr; + const T* bias = nullptr; + int* seqlens_k_total = nullptr; + + const T* query = nullptr; + const T* key = nullptr; + const T* value = nullptr; + const int* mask_index = nullptr; + gsl::span mask_index_dims; + const T* past = nullptr; + const T* past_key = nullptr; + const T* past_value = nullptr; + const int32_t* cache_indirection = nullptr; + const T* attention_bias = nullptr; + + bool has_qkv_workspace = false; + T* workspace = nullptr; + + T* output = nullptr; + T* present = nullptr; + T* present_key = nullptr; + T* present_value = nullptr; + void* output_qk = nullptr; + + void* fused_runner = nullptr; + const void* fused_cross_attention_kernel = nullptr; + + bool use_flash_attention = false; + bool use_memory_efficient_attention = false; + bool use_decoder_masked_multihead_attention = false; + + const int32_t* cumulated_sequence_length_q_cache = nullptr; + const int32_t* cumulated_sequence_length_kv_cache = nullptr; + + // Intermediate data + T* q = nullptr; + T* k = nullptr; + T* v = nullptr; + T* scratch = nullptr; + AttentionQkvFormat qkv_format = AttentionQkvFormat::UNKNOWN; + + // Flash buffers + T* softmax_lse = nullptr; + T* softmax_lse_accum = nullptr; + T* out_accum = nullptr; + + // Flash Atttention and Lean Attention + int num_splits; + + // Lean Attention + bool use_lean_attention = false; +#if USE_LEAN_ATTENTION + int grid_dim_z = 0; + int max_tiles_per_tb = 0; + int high_load_tbs = 0; + int tiles_per_head = 0; + int* lean_sync_flag = nullptr; +#endif + + // For Debugging + size_t workspace_bytes = 0; + bool allow_debug_info = false; + + // For MultiHeadAttention only. + AttentionKernelType kernel_type = AttentionKernelType::AttentionKernel_Default; + AllocatorPtr allocator = nullptr; + bool IsUnfused() const { + return kernel_type == AttentionKernelType::AttentionKernel_Unfused; + } + + // For DecoderMaskedMultiHeadAttention + T* q_bias = nullptr; + T* k_bias = nullptr; + T* v_bias = nullptr; + + void PrintDebugInfo() const { + std::cout << "flash=" << use_flash_attention + << ", lean=" << use_lean_attention + << ", efficient=" << use_memory_efficient_attention + << ", fused_runner=" << (fused_runner != nullptr) + << ", fused_cross=" << (fused_cross_attention_kernel != nullptr) + << ", bias=" << (bias != nullptr) + << ", attn_bias=" << (attention_bias != nullptr) + << ", mask_dims=" << mask_index_dims.size() + << ", has_qkv_workspace=" << has_qkv_workspace + << ", workspace=" << workspace_bytes + << ", past=" << (past != nullptr ? 1 : (past_key != nullptr ? 2 : 0)) + << ", present=" << (present != nullptr ? 1 : (present_key != nullptr ? 2 : 0)) + << std::endl; + } +}; + +template +struct PackedAttentionData { + T* gemm_buffer; + const T* bias; + const T* attention_bias; + const int32_t* token_offset; + const int32_t* cumulative_sequence_length; + + T* workspace; + T* output; + + void* fused_runner; + + bool use_memory_efficient_attention; +}; + +template +struct PackedMultiHeadAttentionData { + const T* query; + const T* key; + const T* value; + const T* bias; + const T* attention_bias; + + const int32_t* token_offset; + const int32_t* cumulative_sequence_length; + + AttentionQkvFormat source_qkv_format; + + bool no_qkv_workspace; + T* workspace; + T* output; + + void* fused_runner; + + bool use_flash_attention; + bool use_memory_efficient_attention; +}; + +template +struct GroupQueryAttentionData { + // Input Tensors + const T* query = nullptr; + const T* key = nullptr; + const T* value = nullptr; + const T* past_key = nullptr; + const T* past_value = nullptr; + int* seqlens_k = nullptr; + const T* cos_cache = nullptr; + const T* sin_cache = nullptr; + + // Flash buffers + T* softmax_lse = nullptr; + T* softmax_lse_accum = nullptr; + T* out_accum = nullptr; + int* seqlens_k_buff = nullptr; + + // Memory Efficient buffers + T* fmha_buffer = nullptr; + T* unpacked_qkv_buffer = nullptr; + T* rotary_buffer = nullptr; + T* k = nullptr; + T* v = nullptr; + + // Output Tensors + T* output = nullptr; + T* present_key = nullptr; + T* present_value = nullptr; + + // Kernel Flags + bool use_flash_attention = false; + bool use_memory_efficient_attention = false; +}; + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index 9e017544d7cff..0209183f46425 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -29,18 +29,23 @@ limitations under the License. #include "core/providers/cuda/cu_inc/common.cuh" #include "core/providers/cuda/cuda_common.h" #include "core/providers/cuda/shared_inc/fpgeneric.h" -#include "contrib_ops/cuda/bert/attention_softmax.h" -#include "contrib_ops/cuda/bert/transformer_common.h" -#include "contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/mha_runner.h" -#include "contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/cross_attention/fmha_cross_attention.h" +#include "core/platform/env_var_utils.h" #include "contrib_ops/cpu/bert/attention_base.h" +#include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cuda/bert/attention_impl.h" +#include "contrib_ops/cuda/bert/attention_kv_cache.h" +#include "contrib_ops/cuda/bert/attention_qk.h" +#include "contrib_ops/cuda/bert/attention_softmax.h" #include "contrib_ops/cuda/bert/bert_padding.h" -#include "contrib_ops/cuda/utils/dump_cuda_tensor.h" #include "contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h" #include "contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h" #include "contrib_ops/cuda/bert/flash_attention/flash_api.h" #include "contrib_ops/cuda/bert/lean_attention/lean_api.h" -#include "contrib_ops/cuda/bert/attention_impl.h" +#include "contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/mha_runner.h" +#include "contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/cross_attention/fmha_cross_attention.h" +#include "contrib_ops/cuda/bert/transformer_common.h" +#include "contrib_ops/cuda/utils/dump_cuda_tensor.h" using namespace onnxruntime::cuda; using namespace onnxruntime::contrib::attention_softmax_cuda; @@ -516,7 +521,7 @@ Status EfficientAttention( p.key = data.k; p.value = data.v; - p.attn_bias = (nullptr == data.attention_bias) ? nullptr : data.attention_bias; + p.attn_bias = data.attention_bias; p.broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; p.broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; @@ -533,7 +538,138 @@ Status EfficientAttention( } #endif -template +template +Status LaunchDecoderMaskedMultiHeadAttention( + const DecoderMaskedMultiHeadAttentionParameters& parameters, + cudaStream_t stream, + const int head_size) { + + DUMP_STRING_INIT(); + DUMP_STRING("DMMHA parameters..."); + DUMP_STRING("is_mha = ", (parameters.is_mha == true)); + DUMP_STRING("is_cross_attention = ", (parameters.is_cross_attention == true)); + DUMP_STRING("is_packed_qkv = ", (parameters.is_packed_qkv == true)); + DUMP_STRING("kv_data_in_flight = ", (parameters.kv_data_in_flight == true)); + + DUMP_STRING("Batch size = ", parameters.batch_size); + DUMP_STRING("Sequence length = ", parameters.sequence_length); + DUMP_STRING("Num heads = ", parameters.num_heads); + DUMP_STRING("Head size = ", parameters.head_size); + DUMP_STRING("Hidden size = ", parameters.hidden_size); + + DUMP_STRING("Past sequence length = ", parameters.past_sequence_length); + DUMP_STRING("KV sequence length = ", parameters.kv_sequence_length); + DUMP_STRING("Total sequence length = ", parameters.total_sequence_length); + DUMP_STRING("Max sequence length = ", parameters.max_sequence_length); + + DUMP_STRING("parameters.k is null = ", (parameters.k == nullptr)); + DUMP_STRING("parameters.v is null = ", (parameters.v == nullptr)); + DUMP_STRING("parameters.k_cache is null = ", (parameters.k_cache == nullptr)); + DUMP_STRING("parameters.v_cache is null = ", (parameters.v_cache == nullptr)); + + DUMP_STRING("parameters.q_bias is null = ", (parameters.q_bias == nullptr)); + DUMP_STRING("parameters.k_bias is null = ", (parameters.k_bias == nullptr)); + DUMP_STRING("parameters.v_bias is null = ", (parameters.v_bias == nullptr)); + + DUMP_STRING("parameters.attention_bias is null = ", (parameters.attention_bias == nullptr)); + DUMP_STRING("Scale = ", parameters.scale); + DUMP_STRING("Mask is null = ", (parameters.mask == nullptr)); + DUMP_STRING("Mask filter value = ", parameters.mask_filter_value); + + DUMP_STRING("Beam width = ", parameters.beam_width); + DUMP_STRING("parameters.cache_indir is null = ", (parameters.cache_indir == nullptr)); + DUMP_STRING("parameters.out_qk is null = ", (parameters.out_qk == nullptr)); + + switch (head_size) { + case 32: + mmha_launch_kernel(parameters, stream); + break; + + case 64: + mmha_launch_kernel(parameters, stream); + break; + + case 128: + mmha_launch_kernel(parameters, stream); + break; + + default: + return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, + "Unsupported head size in DecoderMaskedMultiHeadAttention. Got head size: ", + head_size); + } + + return Status::OK(); +} + +template +Status DecoderMaskedMultiHeadAttention( + cudaStream_t stream, + contrib::AttentionParameters& parameters, + AttentionData& data, + float scale) { + assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); + assert(parameters.mask_type == AttentionMaskType::MASK_NONE || + parameters.mask_type == AttentionMaskType::MASK_2D_KEY_PADDING); + assert(parameters.head_size == parameters.v_head_size); + + DecoderMaskedMultiHeadAttentionParameters p; + p.is_mha = true; + p.is_cross_attention = (data.past_key == nullptr && data.present_key == nullptr); + p.is_packed_qkv = false; + p.kv_data_in_flight = ParseEnvironmentVariableWithDefault(attention::kDecoderMaskedAttentionLoadKVDataInFlight, false); + + p.batch_size = parameters.batch_size; + p.sequence_length = parameters.sequence_length; + p.num_heads = parameters.num_heads; + p.head_size = parameters.head_size; + p.hidden_size = parameters.hidden_size; + + p.past_sequence_length = parameters.past_sequence_length; + p.kv_sequence_length = parameters.kv_sequence_length; + p.total_sequence_length = p.is_cross_attention ? parameters.kv_sequence_length : parameters.total_sequence_length; + p.max_sequence_length = p.is_cross_attention ? parameters.kv_sequence_length : parameters.max_sequence_length; + + p.q = data.q; + p.k = p.is_cross_attention ? nullptr : data.k; + p.v = p.is_cross_attention ? nullptr : data.v; + p.k_cache = p.is_cross_attention ? data.k : data.present_key; + p.v_cache = p.is_cross_attention ? data.v : data.present_value; + + p.q_bias = data.q_bias; + p.k_bias = data.k_bias; + p.v_bias = data.v_bias; + + p.attention_bias = const_cast(data.attention_bias); + p.broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; + p.broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; + + p.scale = scale; + p.mask = data.mask_index; + p.mask_filter_value = parameters.mask_filter_value; + + p.beam_width = parameters.beam_width; + p.cache_indir = data.cache_indirection; + + p.out = data.output; + p.out_qk = data.output_qk; + + // DecoderMaskedMultiHeadAttention(T, QK) is defined for: + // T = float, QK = float + // T = float, QK = half + // T = uint16_t, QK = float + // T = uint16_t, QK = half + if (std::is_same::value) { + return LaunchDecoderMaskedMultiHeadAttention(p, stream, parameters.head_size); + } + if (std::is_same::value) { + return LaunchDecoderMaskedMultiHeadAttention(p, stream, parameters.head_size); + } + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "DecoderMaskedMultiHeadAttention is only implemented for float32 and float16."); +} + +template Status UnfusedAttention( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, @@ -624,6 +760,15 @@ Status UnfusedAttention( mask_index, mask_start, data.attention_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, data.scratch, scratch2, parameters.is_unidirectional)); } else { // no mask + if (nullptr != data.output_qk) { + int64_t qk_size = (int64_t)batch_size * num_heads * sequence_length * total_sequence_length; + if (std::is_same::value) { + cudaMemcpyAsync(data.output_qk, data.scratch, qk_size * sizeof(QK), cudaMemcpyDeviceToDevice, stream); + } else { + ORT_RETURN_IF_ERROR( + (CopyQK(stream, static_cast(qk_size), data.scratch, reinterpret_cast(data.output_qk)))); + } + } ORT_RETURN_IF_ERROR( ComputeSoftmax( stream, total_sequence_length, sequence_length, batch_size, num_heads, @@ -645,10 +790,170 @@ Status UnfusedAttention( // Temp_output is BxNxSxH_v, transpose to output BxSxNxH_v Status result = LaunchTransCtx(stream, sequence_length, batch_size, v_head_size, num_heads, device_prop.maxThreadsPerBlock, false, temp_output, data.output); + DUMP_TENSOR_D("Attention Output", data.output, batch_size, sequence_length, num_heads, v_head_size); return result; } +#ifndef USE_ROCM // exclude the following from hipify since they are not used in ROCM EP + template +Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, int total_sequence_length, + cudaStream_t stream, int max_threads_per_block, + AttentionData& data) { + // Concat past key value to present (2xBxNxLxH), where L is kv_sequence_length and T is total_sequence_length. + // past_k (BxNxPxH) + k (BxNxLxH) => present_k (BxNxTxH) + // past_v (BxNxPxH) + v (BxNxLxH) => present_v (BxNxTxH) + // When there is past state, the head size for Q/K/V shall be same: H == H_v. + + if (nullptr != data.present) { // Attention op + assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH_QKV_BS3NH); + + ORT_RETURN_IF_ERROR( + LaunchConcatTensorToTensor( + stream, total_sequence_length, sequence_length, batch_size, qk_head_size, num_heads, + max_threads_per_block, 2, data.past, data.k, data.present)); + + + + // Update pointers to present_k and present_v. + data.k = data.present; + data.v = data.present + batch_size * num_heads * total_sequence_length * qk_head_size; + } else { // MultiHeadAttention op + if (nullptr != data.present_key) { + ORT_ENFORCE(data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); + if (nullptr != data.past_key) { + assert(data.past_key != data.k); + assert(data.past_value != data.v); + + ORT_RETURN_IF_ERROR( + LaunchConcatTensorToTensor(stream, total_sequence_length, sequence_length, + batch_size, qk_head_size, num_heads, + max_threads_per_block, 1, data.past_key, data.k, data.present_key)); + ORT_RETURN_IF_ERROR( + LaunchConcatTensorToTensor(stream, total_sequence_length, sequence_length, + batch_size, v_head_size, num_heads, + max_threads_per_block, 1, data.past_value, data.v, data.present_value)); + // Update pointers to present_k and present_v. + data.k = data.present_key; + data.v = data.present_value; + } else { // nullptr == data.past_key && nullptr != data.present_key + if (data.k != data.present_key) { + int64_t k_size = (int64_t)batch_size * num_heads * total_sequence_length * qk_head_size; + cudaMemcpyAsync(data.present_key, data.k, k_size * sizeof(T), cudaMemcpyDeviceToDevice, stream); + } + + if (data.v != data.present_value) { + int64_t v_size = (int64_t)batch_size * num_heads * total_sequence_length * v_head_size; + cudaMemcpyAsync(data.present_value, data.v, v_size * sizeof(T), cudaMemcpyDeviceToDevice, stream); + } + } + } + } + + return CUDA_CALL(cudaGetLastError()); +} + +// Template Instantiation +template Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, int total_sequence_length, + cudaStream_t stream, + int max_threads_per_block, + AttentionData& data); + +template Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, int total_sequence_length, + cudaStream_t stream, + int max_threads_per_block, + AttentionData& data); +#endif + +template +Status PastPresentBufferShare(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, void* fused_runner, + contrib::AttentionParameters& parameters, + AttentionData& data, + cudaStream_t stream, + int max_threads_per_block) { + ORT_ENFORCE(qk_head_size == v_head_size); + assert(data.fused_cross_attention_kernel == nullptr); + assert(nullptr == fused_runner || parameters.is_unidirectional); + assert(!data.use_memory_efficient_attention); + assert(!data.use_flash_attention); + assert(data.has_qkv_workspace); + + bool combined_key_value = nullptr != data.present; + bool separate_key_value = nullptr != data.past_key && nullptr != data.present_key && + nullptr != data.past_value && nullptr != data.present_value; + + // Return early if buffer sharing is not possible + if (!combined_key_value && !separate_key_value) { + return Status::OK(); + } + + if (combined_key_value) { // Attention op + assert(data.gemm_buffer != nullptr); + + if (data.present != data.past) { + // For easy testing. Production should better avoid this path. + int64_t kv_size = 2LL * (int64_t)batch_size * num_heads * parameters.max_sequence_length * qk_head_size; + cudaMemcpyAsync(data.present, data.past, kv_size * sizeof(T), cudaMemcpyDeviceToDevice, stream); + } + + // For fused causal, bias has been added to gemm_buffer. + const T* bias = (nullptr != fused_runner && parameters.is_unidirectional) ? nullptr : data.bias; + + // append last k v to present + ORT_RETURN_IF_ERROR(LaunchAddBiasTransAppendKvToPresent( + stream, parameters.max_sequence_length, parameters.past_sequence_length, sequence_length, + batch_size, qk_head_size, num_heads, max_threads_per_block, + bias, data.gemm_buffer, data.present)); + + data.k = data.present; + data.v = data.present + batch_size * num_heads * parameters.max_sequence_length * qk_head_size; + } else if (data.use_decoder_masked_multihead_attention) { // DecoderMaskedMultiHeadAttention op + assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); + + // DecoderMaskedMultiHeadAttention kernel manages the KV caches + // so this case is empty + } else { // MultiHeadAttention op + assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); + assert(data.seqlens_k_total); + + // Using BNSH since AddBiasTranspose has already been applied + constexpr bool is_past_kv_bnsh_format = true; + constexpr bool is_new_kv_bnsh_format = true; + ORT_RETURN_IF_ERROR(LaunchConcatKVInPlace( + batch_size, num_heads, qk_head_size, parameters.max_sequence_length, + data.seqlens_k_total, nullptr, parameters.sequence_length, data.k, data.v, data.present_key, data.present_value, + is_past_kv_bnsh_format, is_new_kv_bnsh_format, stream, max_threads_per_block)); + + data.k = data.present_key; + data.v = data.present_value; + } + + return CUDA_CALL(cudaGetLastError()); +} + +template Status PastPresentBufferShare(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, void* fused_runner, + contrib::AttentionParameters& parameters, + AttentionData& data, + cudaStream_t stream, + int max_threads_per_block); + +template Status PastPresentBufferShare(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, void* fused_runner, + contrib::AttentionParameters& parameters, + AttentionData& data, + cudaStream_t stream, + int max_threads_per_block); + +template Status QkvToContext( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, @@ -669,58 +974,36 @@ Status QkvToContext( // At most one fused kernel is enabled. assert((static_cast(data.use_flash_attention) + static_cast(data.use_memory_efficient_attention) + + static_cast(data.use_decoder_masked_multihead_attention) + static_cast(fused_runner != nullptr) + static_cast(data.fused_cross_attention_kernel != nullptr) + static_cast(data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention)) <= 1); + DUMP_STRING_INIT(); + DUMP_STRING("Preparing Q, K, V"); ORT_RETURN_IF_ERROR(PrepareQkv(parameters, data, stream, max_threads_per_block)); if (!parameters.past_present_share_buffer) { - ORT_RETURN_IF_ERROR(ConcatPastToPresent(batch_size, num_heads, qk_head_size, v_head_size, + ORT_RETURN_IF_ERROR(ConcatPastToPresent(batch_size, num_heads, qk_head_size, v_head_size, sequence_length, total_sequence_length, stream, max_threads_per_block, data)); } else { // past_present_share_buffer - assert(qk_head_size == v_head_size); - assert(data.fused_cross_attention_kernel == nullptr); - assert(nullptr == fused_runner || parameters.is_unidirectional); - assert(data.gemm_buffer != nullptr); - assert(!data.use_memory_efficient_attention); - assert(!data.use_flash_attention); - assert(data.has_qkv_workspace); - - if (nullptr != data.past_key || nullptr != data.present_key) { - // TODO: support this case. - ORT_THROW("buffer sharing for no bias case between past and present is not supported yet."); - } - - if (data.present != data.past) { - // For easy testing. Production should better avoid this path. - int64_t kv_size = 2LL * (int64_t)batch_size * num_heads * parameters.max_sequence_length * qk_head_size; - cudaMemcpyAsync(data.present, data.past, kv_size * sizeof(T), cudaMemcpyDeviceToDevice, stream); - } - - // For fused causal, bias has been added to gemm_buffer. - const T* bias = (nullptr != fused_runner && parameters.is_unidirectional) ? nullptr : data.bias; - - // append last k v to present - ORT_RETURN_IF_ERROR(LaunchAddBiasTransAppendKvToPresent( - stream, parameters.max_sequence_length, parameters.past_sequence_length, sequence_length, - batch_size, qk_head_size, num_heads, max_threads_per_block, - bias, data.gemm_buffer, data.present)); - - data.k = data.present; - data.v = data.present + batch_size * num_heads * parameters.max_sequence_length * qk_head_size; + ORT_RETURN_IF_ERROR(PastPresentBufferShare(batch_size, num_heads, qk_head_size, v_head_size, + sequence_length, fused_runner, + parameters, data, stream, max_threads_per_block)); } // Q, K and V are ready now if (data.fused_cross_attention_kernel != nullptr) { - return FusedTrtCrossAttention(stream, parameters, data); + DUMP_STRING("FusedTrtCrossAttention"); + return FusedTrtCrossAttention(stream, parameters, data); } // Run TRT fused attention. if (nullptr != fused_runner) { - return FusedTrtSelfAttention(stream, parameters, data); + DUMP_STRING("FusedTrtSelfAttention"); + return FusedTrtSelfAttention(stream, parameters, data); } // For raw attention mask, the scalar 1/sqrt(H) is moved to combine with softmax computation. @@ -728,27 +1011,37 @@ Status QkvToContext( : parameters.scale; #if USE_LEAN_ATTENTION if (data.use_lean_attention) { - return LeanAttention(device_prop, stream, parameters, data, scale); + DUMP_STRING("LeanAttention"); + return LeanAttention(device_prop, stream, parameters, data, scale); } #endif #if USE_FLASH_ATTENTION if (data.use_flash_attention) { - return FlashAttention(device_prop, stream, parameters, data, scale); + DUMP_STRING("FlashAttention"); + return FlashAttention(device_prop, stream, parameters, data, scale); } #endif if (data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { - return CudnnFlashAttention(cudnn, ort_stream, parameters, data, scale); + DUMP_STRING("CudnnFlashAttention"); + return CudnnFlashAttention(cudnn, ort_stream, parameters, data, scale); } #if USE_MEMORY_EFFICIENT_ATTENTION if (data.use_memory_efficient_attention) { - return EfficientAttention(device_prop, stream, parameters, data, scale); + DUMP_STRING("EfficientAttention"); + return EfficientAttention(device_prop, stream, parameters, data, scale); } #endif - return UnfusedAttention(device_prop, cublas, ort_stream, parameters, data, scale); + if (data.use_decoder_masked_multihead_attention) { + DUMP_STRING("DecoderMaskedMHA"); + return DecoderMaskedMultiHeadAttention(stream, parameters, data, scale); + } + + DUMP_STRING("UnfusedAttention"); + return UnfusedAttention(device_prop, cublas, ort_stream, parameters, data, scale); } // Template Instantiation @@ -772,6 +1065,42 @@ template Status QkvToContext( contrib::AttentionParameters& parameters, AttentionData& data); +template Status QkvToContext( + const cudaDeviceProp& device_prop, + cublasHandle_t& cublas, + cudnnHandle_t& cudnn, + Stream* ort_stream, + contrib::AttentionParameters& parameters, + AttentionData& data); + +template Status QkvToContext( + const cudaDeviceProp& device_prop, + cublasHandle_t& cublas, + cudnnHandle_t& cudnn, + Stream* ort_stream, + contrib::AttentionParameters& parameters, + AttentionData& data); + +template Status LaunchDecoderMaskedMultiHeadAttention( + const DecoderMaskedMultiHeadAttentionParameters& parameters, + cudaStream_t stream, + const int head_size); + +template Status LaunchDecoderMaskedMultiHeadAttention( + const DecoderMaskedMultiHeadAttentionParameters& parameters, + cudaStream_t stream, + const int head_size); + +template Status LaunchDecoderMaskedMultiHeadAttention( + const DecoderMaskedMultiHeadAttentionParameters& parameters, + cudaStream_t stream, + const int head_size); + +template Status LaunchDecoderMaskedMultiHeadAttention( + const DecoderMaskedMultiHeadAttentionParameters& parameters, + cudaStream_t stream, + const int head_size); + } // namespace cuda } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/attention_impl.h index 7d111a1ee21bf..14841b74daec8 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.h @@ -11,6 +11,9 @@ #include "core/framework/allocator.h" #include "core/providers/cuda/cuda_common.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cuda/bert/attention_data.h" +#include "contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h" namespace onnxruntime { namespace contrib { @@ -59,91 +62,6 @@ size_t GetAttentionWorkspaceSize( bool use_cudnn_flash_attention, bool no_qkv_workspace); -template -struct AttentionData { - T* gemm_buffer = nullptr; - const T* bias = nullptr; - - const T* query = nullptr; - const T* key = nullptr; - const T* value = nullptr; - const int* mask_index = nullptr; - gsl::span mask_index_dims; - const T* past = nullptr; - const T* past_key = nullptr; - const T* past_value = nullptr; - const T* attention_bias = nullptr; - - bool has_qkv_workspace = false; - T* workspace = nullptr; - - T* output = nullptr; - T* present = nullptr; - T* present_key = nullptr; - T* present_value = nullptr; - - void* fused_runner = nullptr; - const void* fused_cross_attention_kernel = nullptr; - - bool use_flash_attention = false; - bool use_memory_efficient_attention = false; - - const int32_t* cumulated_sequence_length_q_cache = nullptr; - const int32_t* cumulated_sequence_length_kv_cache = nullptr; - - // Intermediate data - T* q = nullptr; - T* k = nullptr; - T* v = nullptr; - T* scratch = nullptr; - AttentionQkvFormat qkv_format = AttentionQkvFormat::UNKNOWN; - - // Flash buffers - T* softmax_lse = nullptr; - T* softmax_lse_accum = nullptr; - T* out_accum = nullptr; - - // Flash Atttention and Lean Attention - int num_splits; - - // Lean Attention - bool use_lean_attention = false; -#if USE_LEAN_ATTENTION - int grid_dim_z = 0; - int max_tiles_per_tb = 0; - int high_load_tbs = 0; - int tiles_per_head = 0; - int* lean_sync_flag = nullptr; -#endif - - // For Debugging - size_t workspace_bytes = 0; - bool allow_debug_info = false; - - // For MultiHeadAttention only. - AttentionKernelType kernel_type = AttentionKernelType::AttentionKernel_Default; - AllocatorPtr allocator = nullptr; - bool IsUnfused() const { - return kernel_type == AttentionKernelType::AttentionKernel_Unfused; - } - - void PrintDebugInfo() const { - std::cout << "flash=" << use_flash_attention - << ", lean=" << use_lean_attention - << ", efficient=" << use_memory_efficient_attention - << ", fused_runner=" << (fused_runner != nullptr) - << ", fused_cross=" << (fused_cross_attention_kernel != nullptr) - << ", bias=" << (bias != nullptr) - << ", attn_bias=" << (attention_bias != nullptr) - << ", mask_dims=" << mask_index_dims.size() - << ", has_qkv_workspace=" << has_qkv_workspace - << ", workspace=" << workspace_bytes - << ", past=" << (past != nullptr ? 1 : (past_key != nullptr ? 2 : 0)) - << ", present=" << (present != nullptr ? 1 : (present_key != nullptr ? 2 : 0)) - << std::endl; - } -}; - // Return true if it does not need qkv workspace, false otherwise. template bool NoQkvWorkspace(contrib::AttentionParameters& parameters, AttentionData& data); @@ -154,7 +72,7 @@ Status PrepareQkv(contrib::AttentionParameters& parameters, cudaStream_t stream, int max_threads_per_block); -template +template Status QkvToContext( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, @@ -163,6 +81,12 @@ Status QkvToContext( contrib::AttentionParameters& parameters, AttentionData& data); +template +Status LaunchDecoderMaskedMultiHeadAttention( + const DecoderMaskedMultiHeadAttentionParameters& parameters, + cudaStream_t stream, + const int head_size); + // BxNxSxH => BxSxNxH or SxBxNxH (reversed_bs is true) Status LaunchTransCtx(cudaStream_t stream, const int sequence_length, const int batch_size, const int head_size, const int num_heads, @@ -189,30 +113,6 @@ Status Transpose_BSNH_to_BNSH(const int batch_size, const int sequence_length, c Status Transpose_BSNH_to_BNSH(const int batch_size, const int sequence_length, const int num_heads, const int head_size, const half* input, half* output, cudaStream_t stream, const int max_threads_per_block); -Status LaunchConcatTensorToTensor(cudaStream_t stream, - const int all_sequence_length, - const int sequence_length, - const int batch_size, - const int head_size, - const int num_heads, - const int max_threads_per_block, - const int matrix_num, - const float* tensor_in, - const float* tensor_add, - float* tensor_out); - -Status LaunchConcatTensorToTensor(cudaStream_t stream, - const int all_sequence_length, - const int sequence_length, - const int batch_size, - const int head_size, - const int num_heads, - const int max_threads_per_block, - const int matrix_num, - const half* tensor_in, - const half* tensor_add, - half* tensor_out); - template Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, int sequence_length, int total_sequence_length, @@ -221,17 +121,12 @@ Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int AttentionData& data); template -Status LaunchAddBiasTransAppendKvToPresent(cudaStream_t stream, - const int max_sequence_length, - const int past_sequence_length, - const int sequence_length, - const int batch_size, - const int head_size, - const int num_heads, - const int max_threads_per_block, - const T* biases, - const T* qkv_buffer, - T* present); +Status PastPresentBufferShare(int batch_size, int num_heads, int qk_head_size, int v_head_size, + int sequence_length, void* fused_runner, + contrib::AttentionParameters& parameters, + AttentionData& data, + cudaStream_t stream, + int max_threads_per_block); template Status LaunchStridedCopy( diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc index 8b8b764e7c785..1e0c9cb8baffd 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc @@ -23,10 +23,13 @@ void AttentionKernelOptions::Initialize(int value, bool use_build_flag, bool che use_efficient_attention_ = (value & static_cast(AttentionBackend::EFFICIENT_ATTENTION)) > 0; use_trt_fused_attention_ = (value & static_cast(AttentionBackend::TRT_FUSED_ATTENTION)) > 0; use_cudnn_flash_attention_ = (value & static_cast(AttentionBackend::CUDNN_FLASH_ATTENTION)) > 0; + use_unfused_ = (value & static_cast(AttentionBackend::MATH)) > 0; use_trt_flash_attention_ = (value & static_cast(AttentionBackend::TRT_FLASH_ATTENTION)) > 0; use_trt_cross_attention_ = (value & static_cast(AttentionBackend::TRT_CROSS_ATTENTION)) > 0; use_trt_causal_attention_ = (value & static_cast(AttentionBackend::TRT_CAUSAL_ATTENTION)) > 0; + + use_decoder_attention_ = (value & static_cast(AttentionBackend::DECODER_ATTENTION)) > 0; } else { use_flash_attention_ = !ParseEnvironmentVariableWithDefault(kDisableFlashAttention, false); #if USE_LEAN_ATTENTION @@ -40,6 +43,8 @@ void AttentionKernelOptions::Initialize(int value, bool use_build_flag, bool che use_trt_flash_attention_ = !ParseEnvironmentVariableWithDefault(kDisableTrtFlashAttention, false); use_trt_cross_attention_ = !ParseEnvironmentVariableWithDefault(kDisableFusedCrossAttention, false); use_trt_causal_attention_ = ParseEnvironmentVariableWithDefault(kEnableFusedCausalAttention, false); + + use_decoder_attention_ = !ParseEnvironmentVariableWithDefault(kDisableDecoderAttention, false); } enable_kernel_debug_info_ = ParseEnvironmentVariableWithDefault(kEnableAttentionKernelDebugInfo, false); @@ -100,6 +105,7 @@ void AttentionKernelOptions::Print() const { sstream << " TRT_FLASH_ATTENTION=" << int(use_trt_flash_attention_); sstream << " TRT_CROSS_ATTENTION=" << int(use_trt_cross_attention_); sstream << " TRT_CAUSAL_ATTENTION=" << int(use_trt_causal_attention_); + sstream << " DECODER_ATTENTION=" << int(use_decoder_attention_); sstream << " MATH=" << int(use_unfused_); if (!use_unfused_) { @@ -160,6 +166,8 @@ void AttentionKernelDebugInfo::Print(const char* operator_name, sstream << "TRT_CROSS_ATTENTION"; } else if (use_trt_causal_attention.has_value() && use_trt_causal_attention.value()) { sstream << "TRT_CAUSAL_ATTENTION"; + } else if (use_decoder_attention.has_value() && use_decoder_attention.value()) { + sstream << "DECODER_ATTENTION"; } else { sstream << "MATH"; } diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h index caed704564c3b..fd3b90387a235 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h @@ -16,6 +16,7 @@ struct AttentionKernelDebugInfo { std::optional use_trt_flash_attention = std::nullopt; std::optional use_trt_cross_attention = std::nullopt; std::optional use_trt_causal_attention = std::nullopt; + std::optional use_decoder_attention = std::nullopt; void SetTrtFusedKernel(bool causal, bool enable_trt_flash_attention, int sequence_length); void Print(const char* operator_name, const std::string& node_name, bool is_float16, bool is_bfloat16) const; }; @@ -33,6 +34,7 @@ class AttentionKernelOptions { bool UseTrtFlashAttention() const { return use_trt_flash_attention_; } bool UseTrtCrossAttention() const { return use_trt_cross_attention_; } bool UseTrtCausalAttention() const { return use_trt_causal_attention_; } + bool UseDecoderAttention() const { return use_decoder_attention_; } bool AllowDebugInfo() const { return enable_kernel_debug_info_; } @@ -53,12 +55,12 @@ class AttentionKernelOptions { bool use_unfused_{true}; bool use_trt_flash_attention_{true}; - bool use_trt_cross_attention_{true}; - // Causal attention is disabled by default in #14732. bool use_trt_causal_attention_{false}; + bool use_decoder_attention_{true}; + bool enable_kernel_debug_info_{false}; int min_seq_len_for_flash_attention_packed_qkv_{0}; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.cu b/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.cu index 9f0f49348c225..1753929d60617 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.cu @@ -2,7 +2,7 @@ // Licensed under the MIT License. #include "contrib_ops/cuda/bert/attention_impl.h" -#include "core/providers/cuda/cuda_common.h" +#include "contrib_ops/cuda/bert/attention_kv_cache.h" #include "core/providers/cuda/cu_inc/common.cuh" using namespace onnxruntime::cuda; @@ -197,128 +197,9 @@ Status LaunchConcatTensorToTensor(cudaStream_t stream, return CUDA_CALL(cudaGetLastError()); } -Status LaunchConcatPastToPresent(cudaStream_t stream, - const int all_sequence_length, - const int sequence_length, - const int batch_size, - const int head_size, - const int num_heads, - const int max_threads_per_block, - const float* past, - const float* k_v, - float* present) { - return LaunchConcatTensorToTensor( - stream, - all_sequence_length, - sequence_length, - batch_size, - head_size, - num_heads, - max_threads_per_block, - 2, - past, - k_v, - present); -} - -Status LaunchConcatPastToPresent(cudaStream_t stream, - const int all_sequence_length, - const int sequence_length, - const int batch_size, - const int head_size, - const int num_heads, - const int max_threads_per_block, - const half* past, - const half* k_v, - half* present) { - return LaunchConcatTensorToTensor( - stream, - all_sequence_length, - sequence_length, - batch_size, - head_size, - num_heads, - max_threads_per_block, - 2, - past, - k_v, - present); -} #ifndef USE_ROCM // exclude the following from hipify since they are not used in ROCM EP -template -Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, - int sequence_length, int total_sequence_length, - cudaStream_t stream, int max_threads_per_block, - AttentionData& data) { - // Concat past key value to present (2xBxNxLxH), where L is kv_sequence_length and T is total_sequence_length. - // past_k (BxNxPxH) + k (BxNxLxH) => present_k (BxNxTxH) - // past_v (BxNxPxH) + v (BxNxLxH) => present_v (BxNxTxH) - // When there is past state, the head size for Q/K/V shall be same: H == H_v. - - if (nullptr != data.present) { // Attention op - assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH || - data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH_QKV_BS3NH); - - ORT_RETURN_IF_ERROR( - LaunchConcatPastToPresent( - stream, total_sequence_length, sequence_length, batch_size, qk_head_size, num_heads, - max_threads_per_block, data.past, data.k, data.present)); - - // Update pointers to present_k and present_v. - data.k = data.present; - data.v = data.present + batch_size * num_heads * total_sequence_length * qk_head_size; - } else { // MultiHeadAttention op - if (nullptr != data.present_key) { - ORT_ENFORCE(data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH || - data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); - if (nullptr != data.past_key) { - assert(data.past_key != data.k); - assert(data.past_value != data.v); - - ORT_RETURN_IF_ERROR( - LaunchConcatTensorToTensor(stream, total_sequence_length, sequence_length, - batch_size, qk_head_size, num_heads, - max_threads_per_block, 1, data.past_key, data.k, data.present_key)); - ORT_RETURN_IF_ERROR( - LaunchConcatTensorToTensor(stream, total_sequence_length, sequence_length, - batch_size, v_head_size, num_heads, - max_threads_per_block, 1, data.past_value, data.v, data.present_value)); - // Update pointers to present_k and present_v. - data.k = data.present_key; - data.v = data.present_value; - } else { // nullptr == data.past_key && nullptr != data.present_key - if (data.k != data.present_key) { - int64_t k_size = (int64_t)batch_size * num_heads * total_sequence_length * qk_head_size; - cudaMemcpyAsync(data.present_key, data.k, k_size * sizeof(T), cudaMemcpyDeviceToDevice, stream); - } - - if (data.v != data.present_value) { - int64_t v_size = (int64_t)batch_size * num_heads * total_sequence_length * v_head_size; - cudaMemcpyAsync(data.present_value, data.v, v_size * sizeof(T), cudaMemcpyDeviceToDevice, stream); - } - } - } - } - - - return CUDA_CALL(cudaGetLastError()); -} - -// Template Instantiation -template Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, - int sequence_length, int total_sequence_length, - cudaStream_t stream, - int max_threads_per_block, - AttentionData& data); - -template Status ConcatPastToPresent(int batch_size, int num_heads, int qk_head_size, int v_head_size, - int sequence_length, int total_sequence_length, - cudaStream_t stream, - int max_threads_per_block, - AttentionData& data); - // ---------------------------------------------------------------------------------- // Below kernels are for past and present sharing buffer // ---------------------------------------------------------------------------------- @@ -454,6 +335,382 @@ template Status LaunchAddBiasTransAppendKvToPresent(cudaStream_t stream, half* present); #endif +// Kernel to append new and past kv in either BSNH or BNSH format +// Adapted from ConcatTensorToTensor kernel in attention_kv_cache.cu file +template +__global__ void ConcatNewToPastKV(const int new_seqlen, + const int past_buffer_seqlen, + const T* past_kv, + const T* new_kv, + T* present_kv, + const int* seqlens_k, + const bool past_only, + // const int* seqlens_q, + const bool is_bsnh) { // refers to past; otherwise bnsh + const int h = threadIdx.x; + const int n = threadIdx.y; + const int s = blockIdx.x; + const int b = blockIdx.y; + + const int present_buffer_seqlen = gridDim.x; + const int num_heads = blockDim.y; + const int H = blockDim.x; + + const int present_batch_stride = present_buffer_seqlen * num_heads * H; + const int row_stride = is_bsnh ? num_heads * H : H; + const int present_head_stride = is_bsnh ? H : present_buffer_seqlen * H; + + // past_kv: BPNH or BNPH + // new_kv: BLNH + // present_kv: BTNH or BNTH, where T = P + L + + // prompt, token, and interactive decoding cases + const int past_seqlen = seqlens_k == nullptr ? 0 : seqlens_k[b] + 1 - new_seqlen; + + int out_offset = b * present_batch_stride + s * row_stride + n * present_head_stride + h; + if (s < past_seqlen) { + const int past_batch_stride = past_buffer_seqlen * num_heads * H; + const int past_head_stride = is_bsnh ? H : past_buffer_seqlen * H; + const int in_offset = b * past_batch_stride + s * row_stride + n * past_head_stride + h; + present_kv[out_offset] = past_kv[in_offset]; + } else if (!past_only && s < past_seqlen + new_seqlen) { + // Note: new KV always BSNH + const int new_batch_stride = new_seqlen * num_heads * H; + const int new_row_stride = num_heads * H; + const int new_head_stride = H; + const int in_offset = b * new_batch_stride + (s - past_seqlen) * new_row_stride + n * new_head_stride + h; + present_kv[out_offset] = new_kv[in_offset]; + } +} + +// Use when (H*)*num_heads > 1024 +template +__global__ void ConcatNewToPastKVLarge(const int new_seqlen, + const int past_buffer_seqlen, + const int H, + const int num_heads, + const T* past_kv, + const T* new_kv, + T* present_kv, + const int* seqlens_k, + const bool past_only, + const bool is_bsnh) { + int i = threadIdx.x + (blockDim.x * blockIdx.x); + if (i < H * num_heads) { + const int h = i % H; + const int n = i / H; + const int s = blockIdx.y; + const int b = blockIdx.z; + const int present_buffer_seqlen = gridDim.y; + + const int present_batch_stride = present_buffer_seqlen * num_heads * H; + const int row_stride = is_bsnh ? num_heads * H : H; + const int present_head_stride = is_bsnh ? H : present_buffer_seqlen * H; + + // past_kv: BPNH or BNPH + // new_kv: BLNH + // present_kv: BTNH or BNTH, where T = P + L + + // prompt, token, and interactive decoding cases + const int past_seqlen = seqlens_k == nullptr ? 0 : seqlens_k[b] + 1 - new_seqlen; + + int out_offset = b * present_batch_stride + s * row_stride + n * present_head_stride + h; + if (s < past_seqlen) { + const int past_batch_stride = past_buffer_seqlen * num_heads * H; + const int past_head_stride = is_bsnh ? H : past_buffer_seqlen * H; + const int in_offset = b * past_batch_stride + s * row_stride + n * past_head_stride + h; + present_kv[out_offset] = past_kv[in_offset]; + } else if (!past_only && s < past_seqlen + new_seqlen) { + const int new_batch_stride = new_seqlen * num_heads * H; + const int new_row_stride = num_heads * H; + const int new_head_stride = H; + const int in_offset = b * new_batch_stride + (s - past_seqlen) * new_row_stride + n * new_head_stride + h; + present_kv[out_offset] = new_kv[in_offset]; + } + } +} + +// Concat new to kv buffer in place +template +Status LaunchConcatNewToPastKV(const int batch_size, + const int kv_num_heads, + const int head_size, + const int kv_sequence_length, + const int past_sequence_length, + const int present_sequence_length, + const bool is_bsnh, + const int* seqlens_k, + const T* past_key, + const T* past_value, + const T* new_key, + const T* new_value, + T* present_key, + T* present_value, + cudaStream_t stream, + const int max_threads_per_block, + const bool past_only) { + const int H = head_size / 4; // divide by 4 so kernel can operate on 4 float16 elements at a time. + if (H * kv_num_heads <= max_threads_per_block) { + const dim3 grid(present_sequence_length, batch_size, 1); + const dim3 block(H, kv_num_heads, 1); + ConcatNewToPastKV<<>>(kv_sequence_length, + past_sequence_length, + reinterpret_cast(past_key), + reinterpret_cast(new_key), + reinterpret_cast(present_key), + seqlens_k, + past_only, + is_bsnh); + ConcatNewToPastKV<<>>(kv_sequence_length, + past_sequence_length, + reinterpret_cast(past_value), + reinterpret_cast(new_value), + reinterpret_cast(present_value), + seqlens_k, + past_only, + is_bsnh); + } else { + int steps = (H * kv_num_heads + 255) / 256; + const dim3 grid(steps, present_sequence_length, batch_size); + const dim3 block(256, 1, 1); + ConcatNewToPastKVLarge<<>>(kv_sequence_length, + past_sequence_length, + H, + kv_num_heads, + reinterpret_cast(past_key), + reinterpret_cast(new_key), + reinterpret_cast(present_key), + seqlens_k, + past_only, + is_bsnh); + ConcatNewToPastKVLarge<<>>(kv_sequence_length, + past_sequence_length, + H, + kv_num_heads, + reinterpret_cast(past_value), + reinterpret_cast(new_value), + reinterpret_cast(present_value), + seqlens_k, + past_only, + is_bsnh); + } + return CUDA_CALL(cudaGetLastError()); +} + +template Status LaunchConcatNewToPastKV(const int batch_size, + const int kv_num_heads, + const int head_size, + const int kv_sequence_length, + const int past_sequence_length, + const int present_sequence_length, + const bool is_bsnh, + const int* seqlens_k, + const half* past_key, + const half* past_value, + const half* new_key, + const half* new_value, + half* present_key, + half* present_value, + cudaStream_t stream, + const int max_threads_per_block, + const bool past_only); + +template Status LaunchConcatNewToPastKV(const int batch_size, + const int kv_num_heads, + const int head_size, + const int kv_sequence_length, + const int past_sequence_length, + const int present_sequence_length, + const bool is_bsnh, + const int* seqlens_k, + const BFloat16* past_key, + const BFloat16* past_value, + const BFloat16* new_key, + const BFloat16* new_value, + BFloat16* present_key, + BFloat16* present_value, + cudaStream_t stream, + const int max_threads_per_block, + const bool past_only); + +// Kernel to append new kv to kv buffer in place +template +__global__ void ConcatKVInPlace(const int max_seqlen, + T* kv_buff, + const T* new_kv, + const int* seqlens_k, + const int* total_seqlens_k, + const bool is_past_kv_bnsh_format, + const bool is_new_kv_bnsh_format) { + const int h = threadIdx.x; + const int n = threadIdx.y; + const int s = blockIdx.x; + const int b = blockIdx.y; + + const int new_seqlen = gridDim.x; + const int kv_num_heads = blockDim.y; + const int H = blockDim.x; + + const int past_seq_len = (total_seqlens_k != nullptr) + ? (total_seqlens_k[b] - new_seqlen) + : (seqlens_k == nullptr ? 0 : (seqlens_k[b] + 1 - new_seqlen)); + + int out_offset = is_past_kv_bnsh_format + ? INDEX_4D(kv_num_heads, max_seqlen, H, b, n, s + past_seq_len, h) + : INDEX_4D(max_seqlen, kv_num_heads, H, b, s + past_seq_len, n, h); + + int in_offset = is_new_kv_bnsh_format + ? INDEX_4D(kv_num_heads, new_seqlen, H, b, n, s, h) + : INDEX_4D(new_seqlen, kv_num_heads, H, b, s, n, h); + + kv_buff[out_offset] = new_kv[in_offset]; +} + +template +__global__ void ConcatKVInPlaceLarge(const int max_seqlen, + const int H, + const int kv_num_heads, + T* kv_buff, + const T* new_kv, + const int* seqlens_k, + const int* total_seqlens_k, + const bool is_past_kv_bnsh_format, + const bool is_new_kv_bnsh_format) { // refers to kv buff; otherwise bnsh + int i = threadIdx.x + (blockDim.x * blockIdx.x); + if (i < H * kv_num_heads) { + const int h = i % H; + const int n = i / H; + const int s = blockIdx.y; + const int b = blockIdx.z; + const int new_seqlen = gridDim.y; + const int past_seq_len = (total_seqlens_k != nullptr) + ? (total_seqlens_k[b] - new_seqlen) + : (seqlens_k == nullptr ? 0 : (seqlens_k[b] + 1 - new_seqlen)); + + int out_offset = is_past_kv_bnsh_format + ? INDEX_4D(kv_num_heads, max_seqlen, H, b, n, s + past_seq_len, h) + : INDEX_4D(max_seqlen, kv_num_heads, H, b, s + past_seq_len, n, h); + + int in_offset = is_new_kv_bnsh_format + ? INDEX_4D(kv_num_heads, new_seqlen, H, b, n, s, h) + : INDEX_4D(new_seqlen, kv_num_heads, H, b, s, n, h); + + kv_buff[out_offset] = new_kv[in_offset]; + } +} + +// Concat new to kv buffer in place +template +Status LaunchConcatKVInPlace(int batch_size, + int kv_num_heads, + int head_size, + int max_sequence_length, + const int* seqlens_k, + const int* total_seqlens_k, + int new_seq_len, + const T* new_key, + const T* new_value, + T* present_key, + T* present_value, + const bool is_past_kv_bnsh_format, + const bool is_new_kv_bnsh_format, + cudaStream_t stream, + const int max_threads_per_block) { + // static_assert(sizeof(T) == 2); + assert(head_size % 4 == 0); + + const int H = head_size / 4; + if (H * kv_num_heads <= max_threads_per_block) { + const dim3 grid(new_seq_len, batch_size, 1); + const dim3 block(H, kv_num_heads, 1); + ConcatKVInPlace<<>>(max_sequence_length, + reinterpret_cast(present_key), + reinterpret_cast(new_key), + seqlens_k, + total_seqlens_k, + is_past_kv_bnsh_format, + is_new_kv_bnsh_format); + ConcatKVInPlace<<>>(max_sequence_length, + reinterpret_cast(present_value), + reinterpret_cast(new_value), + seqlens_k, + total_seqlens_k, + is_past_kv_bnsh_format, + is_new_kv_bnsh_format); + } else { + int steps = int(ceil(float(H * kv_num_heads) / 256.0)); + const dim3 grid(steps, new_seq_len, batch_size); + const dim3 block(256, 1, 1); + ConcatKVInPlaceLarge<<>>(max_sequence_length, + H, + kv_num_heads, + reinterpret_cast(present_key), + reinterpret_cast(new_key), + seqlens_k, + total_seqlens_k, + is_past_kv_bnsh_format, + is_new_kv_bnsh_format); + ConcatKVInPlaceLarge<<>>(max_sequence_length, + H, + kv_num_heads, + reinterpret_cast(present_value), + reinterpret_cast(new_value), + seqlens_k, + total_seqlens_k, + is_past_kv_bnsh_format, + is_new_kv_bnsh_format); + } + return CUDA_CALL(cudaGetLastError()); +} + +template Status LaunchConcatKVInPlace(int batch_size, + int kv_num_heads, + int head_size, + int max_sequence_length, + const int* seqlens_k, + const int* total_seqlens_k, + int new_seq_len, + const half* new_key, + const half* new_value, + half* present_key, + half* present_value, + bool is_past_kv_bnsh_format, + bool is_new_kv_bnsh_format, + cudaStream_t stream, + const int max_threads_per_block); + +template Status LaunchConcatKVInPlace(int batch_size, + int kv_num_heads, + int head_size, + int max_sequence_length, + const int* seqlens_k, + const int* total_seqlens_k, + int new_seq_len, + const BFloat16* new_key, + const BFloat16* new_value, + BFloat16* present_key, + BFloat16* present_value, + bool is_past_kv_bnsh_format, + bool is_new_kv_bnsh_format, + cudaStream_t stream, + const int max_threads_per_block); + +template Status LaunchConcatKVInPlace(int batch_size, + int kv_num_heads, + int head_size, + int max_sequence_length, + const int* seqlens_k, + const int* total_seqlens_k, + int new_seq_len, + const float* new_key, + const float* new_value, + float* present_key, + float* present_value, + bool is_past_kv_bnsh_format, + bool is_new_kv_bnsh_format, + cudaStream_t stream, + const int max_threads_per_block); + } // namespace cuda } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.h b/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.h new file mode 100644 index 0000000000000..94104e8b6a5d6 --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kv_cache.h @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include "core/providers/cuda/shared_inc/cuda_utils.h" +#include +#include "core/framework/allocator.h" +#include "core/providers/cuda/cuda_common.h" + +// Macro to help compute index of flatten 4D matrix, note that dim1 is not used so it is excluded. +#define INDEX_4D(dim2, dim3, dim4, i, j, k, l) ((i) * (dim2) * (dim3) * (dim4) + (j) * (dim3) * (dim4) + (k) * (dim4) + (l)) + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +Status LaunchConcatTensorToTensor(cudaStream_t stream, + const int all_sequence_length, + const int sequence_length, + const int batch_size, + const int head_size, + const int num_heads, + const int max_threads_per_block, + const int matrix_num, + const float* tensor_in, + const float* tensor_add, + float* tensor_out); + +Status LaunchConcatTensorToTensor(cudaStream_t stream, + const int all_sequence_length, + const int sequence_length, + const int batch_size, + const int head_size, + const int num_heads, + const int max_threads_per_block, + const int matrix_num, + const half* tensor_in, + const half* tensor_add, + half* tensor_out); + +template +Status LaunchAddBiasTransAppendKvToPresent(cudaStream_t stream, + const int max_sequence_length, + const int past_sequence_length, + const int sequence_length, + const int batch_size, + const int head_size, + const int num_heads, + const int max_threads_per_block, + const T* biases, + const T* qkv_buffer, + T* present); + +template +Status LaunchConcatNewToPastKV(const int batch_size, + const int kv_num_heads, + const int head_size, + const int kv_sequence_length, + const int past_sequence_length, + const int present_sequence_length, + const bool is_bsnh, + const int* seqlens_k, + const T* past_key, + const T* past_value, + const T* new_key, + const T* new_value, + T* present_key, + T* present_value, + cudaStream_t stream, + const int max_threads_per_block, + const bool past_only); + +template +Status LaunchConcatKVInPlace(int batch_size, + int kv_num_heads, + int head_size, + int max_sequence_length, // max sequence length of present_key or present_value. + const int* seqlens_k, // it is not used when total_seqlens_k is available. + const int* total_seqlens_k, // optional, nullptr means it is not available. + int new_seq_len, + const T* new_key, + const T* new_value, + T* present_key, + T* present_value, + bool is_past_kv_bnsh_format, + bool is_new_kv_bnsh_format, + cudaStream_t stream, + const int max_threads_per_block); + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu b/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu index 282ba2403b135..122e94d9558e3 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu @@ -12,10 +12,10 @@ namespace onnxruntime { namespace contrib { namespace cuda { -#if DEBUG_TENSOR_LEVEL > 1 +#if DUMP_TENSOR_LEVEL > 1 // Dump the workspace for Q, K, V after processing QKV data. template -void DumpQkv(AttentionData& data) { +void DumpQkv(contrib::AttentionParameters& parameters, AttentionData& data) { const int batch_size = parameters.batch_size; const int sequence_length = parameters.sequence_length; const int kv_sequence_length = parameters.kv_sequence_length; @@ -33,7 +33,7 @@ void DumpQkv(AttentionData& data) { DUMP_TENSOR_D("k(BSNH)", data.k, batch_size, kv_sequence_length, num_heads, qk_head_size); DUMP_TENSOR_D("v(BSNH)", data.v, batch_size, kv_sequence_length, num_heads, v_head_size); } else if (data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH) { - DUMP_TENSOR_D("q(BNSH)", data.q, batch_size, num_heads, sequence_length, qk_head_size); + DUMP_TENSOR_D("q(BSNH)", data.q, batch_size, sequence_length, num_heads, qk_head_size); DUMP_TENSOR_D("k(BNSH)", data.k, batch_size, num_heads, kv_sequence_length, qk_head_size); DUMP_TENSOR_D("v(BNSH)", data.v, batch_size, num_heads, kv_sequence_length, v_head_size); } else if (data.qkv_format == AttentionQkvFormat::QKV_BSN3H) { @@ -52,23 +52,25 @@ void DumpInputs(contrib::AttentionParameters& parameters, AttentionData& data const int v_head_size = parameters.v_head_size; DUMP_TENSOR_INIT(); - if (parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH) { - DUMP_TENSOR_D("Query(BNSH)", data.query, batch_size, num_heads, sequence_length, qk_head_size); - DUMP_TENSOR_D("Key(BNSH)", data.key, batch_size, num_heads, kv_sequence_length, qk_head_size); - DUMP_TENSOR_D("Value(BNSH)", data.value, batch_size, num_heads, kv_sequence_length, v_head_size); - } else if (data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH) { - DUMP_TENSOR_D("Query(BSNH)", data.query, batch_size, sequence_length, num_heads, qk_head_size); - DUMP_TENSOR_D("Key(BSNH)", data.key, batch_size, kv_sequence_length, num_heads, qk_head_size); - DUMP_TENSOR_D("Value(BSNH)", data.value, batch_size, kv_sequence_length, num_heads, v_head_size); - } else if (data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH) { - DUMP_TENSOR_D("Query(BNSH)", data.query, batch_size, num_heads, sequence_length, qk_head_size); - DUMP_TENSOR_D("Key(BNSH)", data.key, batch_size, num_heads, kv_sequence_length, qk_head_size); - DUMP_TENSOR_D("Value(BNSH)", data.value, batch_size, num_heads, kv_sequence_length, v_head_size); - } else if (data.qkv_format == AttentionQkvFormat::QKV_BSN3H) { - DUMP_TENSOR_D("Query(BSN3H)", data.query, batch_size, sequence_length, num_heads * 3, qk_head_size); - } else if (data.qkv_format == AttentionQkvFormat::Q_KV_BSNH_BSN2H) { - DUMP_TENSOR_D("Query(BNSH)", data.query, batch_size, num_heads, sequence_length, qk_head_size); - DUMP_TENSOR_D("Value(BSN2H)", data.value, batch_size, sequence_length, num_heads * 2, qk_head_size); + if (data.gemm_buffer == nullptr) { // MultiHeadAttention + if (parameters.qkv_format == AttentionQkvFormat::Q_K_V_BNSH) { + DUMP_TENSOR_D("Query(BNSH)", data.query, batch_size, num_heads, sequence_length, qk_head_size); + DUMP_TENSOR_D("Key(BNSH)", data.key, batch_size, num_heads, kv_sequence_length, qk_head_size); + DUMP_TENSOR_D("Value(BNSH)", data.value, batch_size, num_heads, kv_sequence_length, v_head_size); + } else if (parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH) { + DUMP_TENSOR_D("Query(BSNH)", data.query, batch_size, sequence_length, num_heads, qk_head_size); + DUMP_TENSOR_D("Key(BSNH)", data.key, batch_size, kv_sequence_length, num_heads, qk_head_size); + DUMP_TENSOR_D("Value(BSNH)", data.value, batch_size, kv_sequence_length, num_heads, v_head_size); + } else if (parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH) { + DUMP_TENSOR_D("Query(BSNH)", data.query, batch_size, sequence_length, num_heads, qk_head_size); + DUMP_TENSOR_D("Key(BNSH)", data.key, batch_size, num_heads, kv_sequence_length, qk_head_size); + DUMP_TENSOR_D("Value(BNSH)", data.value, batch_size, num_heads, kv_sequence_length, v_head_size); + } else if (parameters.qkv_format == AttentionQkvFormat::QKV_BSN3H) { + DUMP_TENSOR_D("Query(BSN3H)", data.query, batch_size, sequence_length, num_heads * 3, qk_head_size); + } else if (parameters.qkv_format == AttentionQkvFormat::Q_KV_BSNH_BSN2H) { + DUMP_TENSOR_D("Query(BSNH)", data.query, batch_size, sequence_length, num_heads, qk_head_size); + DUMP_TENSOR_D("Key(BSN2H)", data.key, batch_size, sequence_length, num_heads * 2, qk_head_size); + } } if (data.bias != nullptr) { @@ -99,7 +101,7 @@ void DumpInputs(contrib::AttentionParameters& parameters, AttentionData& data // Dump the kernel outputs template -void DumpOutputs(AttentionData& data) { +void DumpOutputs(contrib::AttentionParameters& parameters, AttentionData& data) { DUMP_TENSOR_INIT(); DUMP_TENSOR("output", data.output, parameters.batch_size, parameters.sequence_length, parameters.num_heads, parameters.v_head_size); @@ -193,9 +195,22 @@ Status PrepareQkv_MHA_Cross(contrib::AttentionParameters& parameters, data.q = const_cast(data.query); } - // Here we have assumption that there is no bias for key and value when they are in BNSH format. + // Here we assume that there is no bias for key and value when they are in BNSH format. data.k = const_cast(data.key); data.v = const_cast(data.value); + data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH; + } else if (data.use_decoder_masked_multihead_attention) { + assert(data.attention_bias == nullptr); + + data.q = const_cast(data.query); + data.k = const_cast(data.key); + data.v = const_cast(data.value); + + // Here we assume that there is no bias for key and value when they are in BNSH format. + data.q_bias = const_cast(data.bias); + data.k_bias = nullptr; + data.v_bias = nullptr; + data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH; } else { // unfused kernel assert(data.IsUnfused()); @@ -455,6 +470,16 @@ Status PrepareQkv_MHA_WithPast_Bias(contrib::AttentionParameters& parameters, data.value, data.bias + 2 * num_heads * qk_head_size, data.v, true, -1); data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH; + } else if (data.use_decoder_masked_multihead_attention) { + data.q = const_cast(data.query); + data.k = const_cast(data.key); + data.v = const_cast(data.value); + + data.q_bias = const_cast(data.bias); + data.k_bias = const_cast(data.bias + parameters.hidden_size); + data.v_bias = const_cast(data.bias + 2LL * parameters.hidden_size); + + data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH; } else { // unfused kernel assert(data.IsUnfused()); @@ -628,24 +653,31 @@ Status PrepareQkv_MultiHeadAttention(contrib::AttentionParameters& parameters, AttentionData& data, cudaStream_t stream, int max_threads_per_block) { + DUMP_STRING_INIT(); switch (parameters.qkv_format) { case AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH: + DUMP_STRING("PrepareQkv_MHA_Cross"); ORT_RETURN_IF_ERROR(PrepareQkv_MHA_Cross(parameters, data, stream, max_threads_per_block)); break; case AttentionQkvFormat::Q_KV_BSNH_BSN2H: + DUMP_STRING("PrepareQkv_MHA_PackedKV"); ORT_RETURN_IF_ERROR(PrepareQkv_MHA_PackedKV(parameters, data, stream, max_threads_per_block)); break; case AttentionQkvFormat::QKV_BSN3H: + DUMP_STRING("PrepareQkv_MHA_PackedQKV"); ORT_RETURN_IF_ERROR(PrepareQkv_MHA_PackedQKV(parameters, data, stream, max_threads_per_block)); break; case AttentionQkvFormat::Q_K_V_BSNH: if (data.past_key != nullptr || data.present_key != nullptr) { if (data.bias == nullptr) { + DUMP_STRING("PrepareQkv_MHA_WithPast_NoBias"); ORT_RETURN_IF_ERROR(PrepareQkv_MHA_WithPast_NoBias(parameters, data, stream, max_threads_per_block)); } else { + DUMP_STRING("PrepareQkv_MHA_WithPast_Bias"); ORT_RETURN_IF_ERROR(PrepareQkv_MHA_WithPast_Bias(parameters, data, stream, max_threads_per_block)); } } else { // no past state + DUMP_STRING("PrepareQkv_MHA_NoPast"); ORT_RETURN_IF_ERROR(PrepareQkv_MHA_NoPast(parameters, data, stream, max_threads_per_block)); } break; @@ -705,7 +737,9 @@ Status PrepareQkv(contrib::AttentionParameters& parameters, data.scratch = data.workspace; } -#if DEBUG_TENSOR_LEVEL > 1 +#if DUMP_TENSOR_LEVEL > 1 + DUMP_STRING_INIT(); + DUMP_STRING("Dump Inputs Before PrepareQkv..."); DumpInputs(parameters, data); #endif @@ -717,8 +751,9 @@ Status PrepareQkv(contrib::AttentionParameters& parameters, assert(data.qkv_format != AttentionQkvFormat::UNKNOWN); -#if DEBUG_TENSOR_LEVEL > 1 - DumpQkv(data); +#if DUMP_TENSOR_LEVEL > 1 + DUMP_STRING("Dump Inputs After PrepareQkv..."); + DumpQkv(parameters, data); #endif CUDA_RETURN_IF_ERROR(cudaGetLastError()); diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu b/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu new file mode 100644 index 0000000000000..78c407fd3bb3b --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/cuda/cu_inc/common.cuh" +#include "contrib_ops/cuda/bert/attention_qk.h" + +using namespace onnxruntime::cuda; + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +__global__ void ConvertAndCopyQK(const int count, const float* input, half* output) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx < count) { + output[idx] = __float2half(input[idx]); + } +} + +__global__ void ConvertAndCopyQK(const int count, const half* input, float* output) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx < count) { + output[idx] = __half2float(input[idx]); + } +} + +template +Status CopyQK(cudaStream_t stream, + const int qk_size, + const T* input, + QK* output) { + const bool half2float = std::is_same::value && std::is_same::value; + const bool float2half = std::is_same::value && std::is_same::value; + ORT_ENFORCE(half2float || float2half); + + int block_size = 256; + int num_blocks = (qk_size + block_size - 1) / block_size; + ConvertAndCopyQK<<>>(qk_size, input, output); + + return CUDA_CALL(cudaGetLastError()); +} + +template Status CopyQK(cudaStream_t stream, + const int qk_size, + const float* input, + half* output); + +template Status CopyQK(cudaStream_t stream, + const int qk_size, + const half* input, + float* output); + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_qk.h b/onnxruntime/contrib_ops/cuda/bert/attention_qk.h new file mode 100644 index 0000000000000..3dead308e7d17 --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/attention_qk.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/cuda/shared_inc/cuda_utils.h" +#include +#include "core/framework/allocator.h" +#include "core/providers/cuda/cuda_common.h" + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +template +Status CopyQK(cudaStream_t stream, + const int qk_size, + const T* input, + QK* output); + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.h index f9667a613e648..d5357a690ce47 100644 --- a/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.h @@ -4,6 +4,7 @@ #pragma once #include "contrib_ops/cuda/bert/attention_impl.h" +#include "contrib_ops/cuda/bert/attention_kv_cache.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc index 350c4718c437e..bf94cca52a9e9 100644 --- a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc @@ -4,9 +4,13 @@ #include "core/providers/cuda/cuda_common.h" #include "core/providers/cuda/shared_inc/fpgeneric.h" #include "core/platform/env_var_utils.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" #include "contrib_ops/cpu/bert/multihead_attention_helper.h" +#include "contrib_ops/cpu/utils/dump_tensor.h" +#include "contrib_ops/cuda/bert/attention_impl.h" #include "contrib_ops/cuda/bert/decoder_masked_multihead_attention.h" #include "contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h" +#include "contrib_ops/cuda/utils/dump_cuda_tensor.h" using namespace onnxruntime::cuda; using namespace ::onnxruntime::common; @@ -25,26 +29,29 @@ static constexpr int kPresentOutputIndex = 1; static constexpr int kQKOutputIndex = 3; static constexpr int kBiasIndex = 10; -#define REGISTER_KERNEL_TYPED(T1, T2) \ +#define REGISTER_KERNEL_TYPED(T, QK) \ ONNX_OPERATOR_TYPED_KERNEL_EX( \ DecoderMaskedMultiHeadAttention, \ kMSDomain, \ 1, \ - T1, \ + T##_##QK, \ kCudaExecutionProvider, \ (*KernelDefBuilder::Create()) \ .MayInplace(kPastInputIndex, kPresentOutputIndex) \ .MayInplace(kPastInputIndex + 1, kPresentOutputIndex + 1) \ - .TypeConstraint("T", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("QK", DataTypeImpl::GetTensorType()) \ .InputMemoryType(OrtMemTypeCPUInput, kPastSequenceLengthInputIndex) \ .InputMemoryType(OrtMemTypeCPUInput, kBeamWidthInputIndex), \ - DecoderMaskedMultiHeadAttention); + DecoderMaskedMultiHeadAttention); REGISTER_KERNEL_TYPED(float, float) -REGISTER_KERNEL_TYPED(MLFloat16, uint16_t) +REGISTER_KERNEL_TYPED(float, MLFloat16) +REGISTER_KERNEL_TYPED(MLFloat16, float) +REGISTER_KERNEL_TYPED(MLFloat16, MLFloat16) -template -DecoderMaskedMultiHeadAttention::DecoderMaskedMultiHeadAttention(const OpKernelInfo& info) : CudaKernel(info) { +template +DecoderMaskedMultiHeadAttention::DecoderMaskedMultiHeadAttention(const OpKernelInfo& info) : CudaKernel(info) { int64_t num_heads = 0; ORT_ENFORCE(info.GetAttr("num_heads", &num_heads).IsOK() && num_heads > 0); num_heads_ = static_cast(num_heads); @@ -54,8 +61,8 @@ DecoderMaskedMultiHeadAttention::DecoderMaskedMultiHeadAttention(const O output_qk_ = info.GetAttrOrDefault("output_qk", 0LL); } -template -Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* context) const { +template +Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* query = context->Input(0); const Tensor* key = context->Input(1); const Tensor* value = context->Input(2); @@ -69,7 +76,7 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* const Tensor* bias = context->Input(kBiasIndex); auto& device_prop = GetDeviceProp(); - DecoderMaskedMultiHeadAttentionParams parameters; + DecoderMaskedMultiHeadAttentionParameters parameters; parameters.kv_data_in_flight = ParseEnvironmentVariableWithDefault( attention::kDecoderMaskedAttentionLoadKVDataInFlight, false); @@ -83,6 +90,7 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* attention_bias, past_key, past_value, + cache_indir, past_seq_len, ¶meters, num_heads_, @@ -93,11 +101,24 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* kDecoderMaskedMultiHeadAttention, device_prop.maxThreadsPerBlock)); + DUMP_STRING_INIT(); + DUMP_STRING("Batch size = ", parameters.batch_size); + DUMP_STRING("Sequence length = ", parameters.sequence_length); + DUMP_STRING("Past sequence length = ", parameters.past_sequence_length); + DUMP_STRING("KV sequence length = ", parameters.kv_sequence_length); + DUMP_STRING("Total sequence length = ", parameters.total_sequence_length); + DUMP_STRING("Max sequence length = ", parameters.max_sequence_length); + DUMP_STRING("Hidden size = ", parameters.hidden_size); + DUMP_STRING("Head size = ", parameters.head_size); + DUMP_STRING("Num heads = ", parameters.num_heads); + DUMP_STRING("Buffer sharing = ", (parameters.past_present_share_buffer == true)); + DUMP_STRING("QKV format = ", parameters.qkv_format); + if (bias) { - const T1* bias_data = bias->Data(); - parameters.q_bias = const_cast(bias_data); - parameters.k_bias = const_cast(bias_data + parameters.hidden_size); - parameters.v_bias = const_cast(bias_data + 2LL * parameters.hidden_size); + const T* bias_data = bias->Data(); + parameters.q_bias = const_cast(bias_data); + parameters.k_bias = const_cast(bias_data + parameters.hidden_size); + parameters.v_bias = const_cast(bias_data + 2LL * parameters.hidden_size); } int batch_size = parameters.batch_size; @@ -125,10 +146,7 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* output_shape[2] = static_cast(parameters.v_hidden_size); Tensor* output = context->Output(0, output_shape); - std::vector present_dims{ - parameters.batch_size, parameters.num_heads, - past_present_share_buffer_ ? parameters.max_sequence_length : parameters.total_sequence_length, - parameters.head_size}; + std::vector present_dims{parameters.batch_size, parameters.num_heads, parameters.max_sequence_length, parameters.head_size}; TensorShape present_shape(present_dims); Tensor* present_key = context->Output(kPresentOutputIndex, present_shape); Tensor* present_value = context->Output(kPresentOutputIndex + 1, present_shape); @@ -139,11 +157,11 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* parameters.is_mha = true; // Update the q buffers - parameters.q = const_cast(query->Data()); + parameters.q = const_cast(query->Data()); // Update the attention bias for self attention if (attention_bias != nullptr) { - parameters.attention_bias = const_cast(attention_bias->Data()); + parameters.attention_bias = const_cast(attention_bias->Data()); } // Decoder cross-attention @@ -157,8 +175,8 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* parameters.total_sequence_length = parameters.kv_sequence_length; parameters.max_sequence_length = parameters.kv_sequence_length; // parameters.k and parameters.v are nullptr - parameters.k_cache = const_cast(key->Data()); - parameters.v_cache = const_cast(value->Data()); + parameters.k_cache = const_cast(key->Data()); + parameters.v_cache = const_cast(value->Data()); parameters.k_bias = nullptr; parameters.v_bias = nullptr; @@ -167,10 +185,10 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* ORT_ENFORCE(past_present_share_buffer_); ORT_ENFORCE(past_key != nullptr && past_value != nullptr); - auto* present_key_data = present_key->MutableData(); - auto* present_value_data = present_value->MutableData(); - auto* past_key_data = past_key->Data(); - auto* past_value_data = past_value->Data(); + auto* present_key_data = present_key->MutableData(); + auto* present_value_data = present_value->MutableData(); + auto* past_key_data = past_key->Data(); + auto* past_value_data = past_value->Data(); // No production use-case will incur this copy cost as the implementation of // GreedySearch/BeamSearch is written in such a way that the past and present buffers @@ -192,11 +210,11 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* parameters.is_packed_qkv = is_packed_qkv; parameters.k = is_packed_qkv - ? const_cast(query->Data() + parameters.hidden_size) - : const_cast(key->Data()); + ? const_cast(query->Data() + parameters.hidden_size) + : const_cast(key->Data()); parameters.v = is_packed_qkv - ? const_cast(query->Data() + 2 * static_cast(parameters.hidden_size)) - : const_cast(value->Data()); + ? const_cast(query->Data() + 2 * static_cast(parameters.hidden_size)) + : const_cast(value->Data()); parameters.k_cache = present_key_data; parameters.v_cache = present_value_data; } @@ -205,7 +223,7 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* int64_t qk_dims[] = {parameters.batch_size, parameters.num_heads, 1, parameters.total_sequence_length}; TensorShape qk_shape(&qk_dims[0], sizeof(qk_dims) / sizeof(qk_dims[0])); cross_qk = context->Output(kQKOutputIndex, qk_shape); - parameters.out_qk = cross_qk->MutableData(); + parameters.out_qk = cross_qk->MutableData(); } parameters.out = output->MutableDataRaw(); @@ -237,26 +255,19 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* parameters.cache_indir = cache_indir->Data(); } - switch (parameters.head_size) { - case 32: - mmha_launch_kernel(parameters, cuda_stream); - break; - - case 64: - mmha_launch_kernel(parameters, cuda_stream); - break; - - case 128: - mmha_launch_kernel(parameters, cuda_stream); - break; - - default: - return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, - "Unsupported head size in DecoderMaskedMultiHeadAttention. " - "Got head size: ", - parameters.head_size); + // DecoderMaskedMultiHeadAttention(T, QK) is defined for: + // T = float, QK = float + // T = float, QK = half + // T = uint16_t, QK = float + // T = uint16_t, QK = half + typedef typename ToCudaType::MappedType CudaQK; + if (std::is_same::value) { + return LaunchDecoderMaskedMultiHeadAttention(parameters, cuda_stream, parameters.head_size); + } + if (std::is_same::value) { + return LaunchDecoderMaskedMultiHeadAttention(parameters, cuda_stream, parameters.head_size); } - return Status::OK(); + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "DecoderMaskedMultiHeadAttention is only implemented for float32 and float16."); } } // namespace cuda diff --git a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc index e7d117686a538..a15b59d0c018a 100644 --- a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc @@ -4,6 +4,8 @@ #include "core/providers/cuda/cuda_common.h" #include "core/providers/cuda/shared_inc/fpgeneric.h" #include "core/platform/env_var_utils.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cuda/bert/attention_impl.h" #include "contrib_ops/cuda/bert/decoder_masked_self_attention.h" #include "contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h" @@ -51,7 +53,7 @@ Status DecoderMaskedSelfAttention::ComputeInternal(OpKernelContext* cont const Tensor* cache_indir = context->Input(kCacheIndirectionInputIndex); auto& device_prop = GetDeviceProp(); - DecoderMaskedMultiHeadAttentionParams parameters; + DecoderMaskedMultiHeadAttentionParameters parameters; parameters.kv_data_in_flight = ParseEnvironmentVariableWithDefault( attention::kDecoderMaskedAttentionLoadKVDataInFlight, false); @@ -197,26 +199,7 @@ Status DecoderMaskedSelfAttention::ComputeInternal(OpKernelContext* cont parameters.t_step = parameters.past_sequence_length; } - switch (parameters.head_size) { - case 32: - mmha_launch_kernel(parameters, cuda_stream); - break; - - case 64: - mmha_launch_kernel(parameters, cuda_stream); - break; - - case 128: - mmha_launch_kernel(parameters, cuda_stream); - break; - - default: - return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, - "Unsupported head size in DecoderMaskedSelfAttention. " - "Got head size: ", - parameters.head_size); - } - return Status::OK(); + return LaunchDecoderMaskedMultiHeadAttention(parameters, cuda_stream, parameters.head_size); } } // namespace cuda diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_128.cu b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_128.cu index 3582758d1daba..0f2db956e55db 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_128.cu +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_128.cu @@ -29,35 +29,37 @@ namespace cuda { using namespace decoder_masked_self_attention_details; #define MMHA_LAUNCH_KERNEL( \ - T, head_size, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK) \ + T, QK, head_size, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK) \ size_t dynamic_block_memory = CalcDynamicBlockMemory(params, THDS_PER_VALUE, THDS_PER_BLOCK); \ dim3 grid(params.num_heads, params.batch_size); \ masked_multihead_attention_kernel \ <<>>(params) -template -void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream) { +template +void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream) { constexpr int THREADS_PER_VALUE = ThreadsPerValue::value; int total_sequence_length = params.total_sequence_length; if (total_sequence_length < 32) { - MMHA_LAUNCH_KERNEL(T, head_size, 4, THREADS_PER_VALUE, 64); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 4, THREADS_PER_VALUE, 64); } else if (total_sequence_length < 2048) { - MMHA_LAUNCH_KERNEL(T, head_size, 2, THREADS_PER_VALUE, 128); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 2, THREADS_PER_VALUE, 128); } else { - MMHA_LAUNCH_KERNEL(T, head_size, 1, THREADS_PER_VALUE, 256); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 1, THREADS_PER_VALUE, 256); } } // Instantiate templates -template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); - -template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); } // namespace cuda } // namespace contrib -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_32.cu b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_32.cu index 3d295116252f6..d878291cabca0 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_32.cu +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_32.cu @@ -29,35 +29,37 @@ namespace cuda { using namespace decoder_masked_self_attention_details; #define MMHA_LAUNCH_KERNEL( \ - T, head_size, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK) \ + T, QK, head_size, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK) \ size_t dynamic_block_memory = CalcDynamicBlockMemory(params, THDS_PER_VALUE, THDS_PER_BLOCK); \ dim3 grid(params.num_heads, params.batch_size); \ masked_multihead_attention_kernel \ <<>>(params) -template -void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream) { +template +void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream) { constexpr int THREADS_PER_VALUE = ThreadsPerValue::value; int total_sequence_length = params.total_sequence_length; if (total_sequence_length < 32) { - MMHA_LAUNCH_KERNEL(T, head_size, 4, THREADS_PER_VALUE, 64); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 4, THREADS_PER_VALUE, 64); } else if (total_sequence_length < 2048) { - MMHA_LAUNCH_KERNEL(T, head_size, 2, THREADS_PER_VALUE, 128); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 2, THREADS_PER_VALUE, 128); } else { - MMHA_LAUNCH_KERNEL(T, head_size, 1, THREADS_PER_VALUE, 256); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 1, THREADS_PER_VALUE, 256); } } // Instantiate templates -template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); - -template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); } // namespace cuda } // namespace contrib -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_64.cu b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_64.cu index e5f57fac73cf2..b547ad67a61a5 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_64.cu +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_64.cu @@ -29,35 +29,37 @@ namespace cuda { using namespace decoder_masked_self_attention_details; #define MMHA_LAUNCH_KERNEL( \ - T, head_size, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK) \ + T, QK, head_size, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK) \ size_t dynamic_block_memory = CalcDynamicBlockMemory(params, THDS_PER_VALUE, THDS_PER_BLOCK); \ dim3 grid(params.num_heads, params.batch_size); \ masked_multihead_attention_kernel \ <<>>(params) -template -void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream) { +template +void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream) { constexpr int THREADS_PER_VALUE = ThreadsPerValue::value; int total_sequence_length = params.total_sequence_length; if (total_sequence_length < 32) { - MMHA_LAUNCH_KERNEL(T, head_size, 4, THREADS_PER_VALUE, 64); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 4, THREADS_PER_VALUE, 64); } else if (total_sequence_length < 2048) { - MMHA_LAUNCH_KERNEL(T, head_size, 2, THREADS_PER_VALUE, 128); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 2, THREADS_PER_VALUE, 128); } else { - MMHA_LAUNCH_KERNEL(T, head_size, 1, THREADS_PER_VALUE, 256); + MMHA_LAUNCH_KERNEL(T, QK, head_size, 1, THREADS_PER_VALUE, 256); } } // Instantiate templates -template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); - -template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); +template void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); } // namespace cuda } // namespace contrib -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu index e4c1659c0fb2c..75ea7454791b6 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu @@ -39,6 +39,8 @@ using namespace decoder_masked_self_attention_details; template < // The type of the inputs. Supported types: float and half. typename T, + // The type of the QK output. Supported types: float and half. + typename QK, // The hidden dimension per head. int head_size, // The number of threads per key. @@ -47,7 +49,7 @@ template < int THREADS_PER_VALUE, // The number of threads in a threadblock. int THREADS_PER_BLOCK> -__global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params) { +__global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params) { // This kernel contains some code that cannot be compiled on CUDA ARCH 5.3 or lower #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 530 (void)(params); @@ -537,9 +539,9 @@ __global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentio if (params.out_qk != nullptr) { // store cross qk before softmax, out_qk has shape [B(batchxbeam), #Head, 1, total_sequence_length] - float* target = (reinterpret_cast(params.out_qk)) + (static_cast(bhi) * (sum_tlength + 1)); + QK* target = (reinterpret_cast(params.out_qk)) + (static_cast(bhi) * (sum_tlength + 1)); for (int ti = tidx; ti <= sum_tlength; ti += THREADS_PER_BLOCK) { - target[ti] = (float)(qk_smem[ti]); + target[ti] = static_cast(qk_smem[ti]); } } @@ -739,46 +741,58 @@ __global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentio // Template instantiation(s) // fp32 + head size = 32 -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); - -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); // fp16 + head size = 32 -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); - -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); // fp32 + head size = 64 -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); - -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); // fp16 + head size = 64 -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); - -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); // fp32 + head size = 128 -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); - -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); // fp16 + head size = 128 -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); - -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); +template void __global__ masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); } // namespace cuda } // namespace contrib diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h index 0e1c9ce7b108e..4dbf7d932b389 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h @@ -5,6 +5,7 @@ #include "core/providers/cuda/cuda_common.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" namespace onnxruntime { namespace contrib { @@ -13,6 +14,8 @@ namespace cuda { template < // The type of the inputs. Supported types: float and half. typename T, + // The type of the QK output. Supported types: float and half. + typename QK, // The hidden dimension per head. int head_size, // The number of threads per key. @@ -21,10 +24,15 @@ template < int THREADS_PER_VALUE, // The number of threads in a threadblock. int THREADS_PER_BLOCK> -__global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParams params); +__global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentionParameters params); -template -void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cudaStream_t stream); +template +void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParameters& params, cudaStream_t stream); + +inline bool has_decoder_masked_multihead_attention(int sm, int head_size) { + // This kernel contains some code that cannot be compiled on CUDA ARCH 5.3 or lower + return (sm >= 53) && (head_size == 32 || head_size == 64 || head_size == 128); +} } // namespace cuda diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl_utils.h b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl_utils.h index 6b012432cd0f5..08e4293528d5a 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl_utils.h +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl_utils.h @@ -24,6 +24,7 @@ #pragma once +#include "contrib_ops/cpu/bert/attention_parameters.h" #include "contrib_ops/cuda/bert/utils.cuh" using namespace onnxruntime::cuda; @@ -140,7 +141,7 @@ struct ThreadsPerValue { //------------------------------------------------------------ template -inline size_t CalcDynamicBlockMemory(const DecoderMaskedMultiHeadAttentionParams& params, +inline size_t CalcDynamicBlockMemory(const DecoderMaskedMultiHeadAttentionParameters& params, int threads_per_value, int threads_per_block) { // The amount of shared memory needed to store the Q*K^T values in float. diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc index 6eff584cec5da..8b63b363d8863 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc @@ -262,17 +262,6 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { if (fmha_buffer != nullptr) { data.fmha_buffer = reinterpret_cast(fmha_buffer.get()); } - if (k_buffer != nullptr) { - data.k = reinterpret_cast(k_buffer.get()); - data.v = reinterpret_cast(v_buffer.get()); - } - if (k_buffer != nullptr) { - data.k = reinterpret_cast(k_buffer.get()); - data.v = reinterpret_cast(v_buffer.get()); - } - if (fmha_buffer != nullptr) { - data.fmha_buffer = reinterpret_cast(fmha_buffer.get()); - } if (unpacked_qkv_buffer != nullptr) { data.unpacked_qkv_buffer = reinterpret_cast(unpacked_qkv_buffer.get()); } diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu index 8bf9848245ec7..dbbee87238d0c 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu @@ -47,9 +47,6 @@ limitations under the License. using namespace onnxruntime::cuda; -// Macro to help compute index of flatten 4D matrix, note that dim1 is not used so it is excluded. -#define INDEX_4D(dim2, dim3, dim4, i, j, k, l) ((i) * (dim2) * (dim3) * (dim4) + (j) * (dim3) * (dim4) + (k) * (dim4) + (l)) - namespace onnxruntime { namespace contrib { namespace cuda { @@ -62,101 +59,6 @@ __global__ void repeat_seqlen(int32_t* seqlens_k, int32_t seqlen, int batch_size if (id < batch_size) seqlens_k[id] = seqlen; } -// Kernel to append new and past kv in either BSNH or BNSH format -// Adapted from ConcatTensorToTensor kernel in attention_kv_cache.cu file -template -__global__ void ConcatNewToPastKV(const int new_seqlen, - const int past_buffer_seqlen, - const T* past_kv, - const T* new_kv, - T* present_kv, - const int* seqlens_k, - const bool past_only, - // const int* seqlens_q, - const bool is_bsnh) { // refers to past; otherwise bnsh - const int h = threadIdx.x; - const int n = threadIdx.y; - const int s = blockIdx.x; - const int b = blockIdx.y; - - const int present_buffer_seqlen = gridDim.x; - const int num_heads = blockDim.y; - const int H = blockDim.x; - - const int present_batch_stride = present_buffer_seqlen * num_heads * H; - const int row_stride = is_bsnh ? num_heads * H : H; - const int present_head_stride = is_bsnh ? H : present_buffer_seqlen * H; - - // past_kv: BPNH or BNPH - // new_kv: BLNH - // present_kv: BTNH or BNTH, where T = P + L - - // prompt, token, and interactive decoding cases - const int past_seqlen = seqlens_k == nullptr ? 0 : seqlens_k[b] + 1 - new_seqlen; - - int out_offset = b * present_batch_stride + s * row_stride + n * present_head_stride + h; - if (s < past_seqlen) { - const int past_batch_stride = past_buffer_seqlen * num_heads * H; - const int past_head_stride = is_bsnh ? H : past_buffer_seqlen * H; - const int in_offset = b * past_batch_stride + s * row_stride + n * past_head_stride + h; - present_kv[out_offset] = past_kv[in_offset]; - } else if (!past_only && s < past_seqlen + new_seqlen) { - // Note: new KV always BSNH - const int new_batch_stride = new_seqlen * num_heads * H; - const int new_row_stride = num_heads * H; - const int new_head_stride = H; - const int in_offset = b * new_batch_stride + (s - past_seqlen) * new_row_stride + n * new_head_stride + h; - present_kv[out_offset] = new_kv[in_offset]; - } -} - -// Use when (H*)*num_heads > 1024 -template -__global__ void ConcatNewToPastKVLarge(const int new_seqlen, - const int past_buffer_seqlen, - const int H, - const int num_heads, - const T* past_kv, - const T* new_kv, - T* present_kv, - const int* seqlens_k, - const bool past_only, - const bool is_bsnh) { - int i = threadIdx.x + (blockDim.x * blockIdx.x); - if (i < H * num_heads) { - const int h = i % H; - const int n = i / H; - const int s = blockIdx.y; - const int b = blockIdx.z; - const int present_buffer_seqlen = gridDim.y; - - const int present_batch_stride = present_buffer_seqlen * num_heads * H; - const int row_stride = is_bsnh ? num_heads * H : H; - const int present_head_stride = is_bsnh ? H : present_buffer_seqlen * H; - - // past_kv: BPNH or BNPH - // new_kv: BLNH - // present_kv: BTNH or BNTH, where T = P + L - - // prompt, token, and interactive decoding cases - const int past_seqlen = seqlens_k == nullptr ? 0 : seqlens_k[b] + 1 - new_seqlen; - - int out_offset = b * present_batch_stride + s * row_stride + n * present_head_stride + h; - if (s < past_seqlen) { - const int past_batch_stride = past_buffer_seqlen * num_heads * H; - const int past_head_stride = is_bsnh ? H : past_buffer_seqlen * H; - const int in_offset = b * past_batch_stride + s * row_stride + n * past_head_stride + h; - present_kv[out_offset] = past_kv[in_offset]; - } else if (!past_only && s < past_seqlen + new_seqlen) { - const int new_batch_stride = new_seqlen * num_heads * H; - const int new_row_stride = num_heads * H; - const int new_head_stride = H; - const int in_offset = b * new_batch_stride + (s - past_seqlen) * new_row_stride + n * new_head_stride + h; - present_kv[out_offset] = new_kv[in_offset]; - } - } -} - // Concat new to past in present. Supports past BSNH or past BNSH template Status LaunchConcatNewToPastKV(contrib::GroupQueryAttentionParameters& parameters, @@ -174,185 +76,26 @@ Status LaunchConcatNewToPastKV(contrib::GroupQueryAttentionParameters& parameter const int head_size = parameters.head_size; const int* seqlens_k = parameters.is_first_prompt ? nullptr : reinterpret_cast(data.seqlens_k); AttentionQkvFormat past_kv_format = parameters.past_kv_format; - assert(past_kv_format == AttentionQkvFormat::Q_K_V_BSNH || past_kv_format == AttentionQkvFormat::Q_K_V_BNSH); - const int H = head_size / 4; // divide by 4 so kernel can operate on 4 float16 elements at a time. - if (H * kv_num_heads <= max_threads_per_block) { - const dim3 grid(present_sequence_length, batch_size, 1); - const dim3 block(H, kv_num_heads, 1); - ConcatNewToPastKV<<>>(kv_sequence_length, - past_sequence_length, - reinterpret_cast(data.past_key), - reinterpret_cast(new_key), - reinterpret_cast(data.present_key), - seqlens_k, - past_only, - past_kv_format == AttentionQkvFormat::Q_K_V_BSNH); - ConcatNewToPastKV<<>>(kv_sequence_length, - past_sequence_length, - reinterpret_cast(data.past_value), - reinterpret_cast(new_value), - reinterpret_cast(data.present_value), - seqlens_k, - past_only, - past_kv_format == AttentionQkvFormat::Q_K_V_BSNH); - } else { - int steps = (H * kv_num_heads + 255) / 256; - const dim3 grid(steps, present_sequence_length, batch_size); - const dim3 block(256, 1, 1); - ConcatNewToPastKVLarge<<>>(kv_sequence_length, - past_sequence_length, - H, - kv_num_heads, - reinterpret_cast(data.past_key), - reinterpret_cast(new_key), - reinterpret_cast(data.present_key), - seqlens_k, - past_only, - past_kv_format == AttentionQkvFormat::Q_K_V_BSNH); - ConcatNewToPastKVLarge<<>>(kv_sequence_length, - past_sequence_length, - H, - kv_num_heads, - reinterpret_cast(data.past_value), - reinterpret_cast(new_value), - reinterpret_cast(data.present_value), - seqlens_k, - past_only, - past_kv_format == AttentionQkvFormat::Q_K_V_BSNH); - } - return CUDA_CALL(cudaGetLastError()); -} - -// Kernel to append new kv to kv buffer in place -template -__global__ void ConcatKVInPlace(const int max_seqlen, - T* kv_buff, - const T* new_kv, - const int* seqlens_k, - const int* total_seqlens_k, - const bool is_past_kv_bnsh_format, - const bool is_new_kv_bnsh_format) { - const int h = threadIdx.x; - const int n = threadIdx.y; - const int s = blockIdx.x; - const int b = blockIdx.y; - - const int new_seqlen = gridDim.x; - const int kv_num_heads = blockDim.y; - const int H = blockDim.x; - - const int past_seq_len = (total_seqlens_k != nullptr) - ? (total_seqlens_k[b] - new_seqlen) - : (seqlens_k == nullptr ? 0 : (seqlens_k[b] + 1 - new_seqlen)); - - int out_offset = is_past_kv_bnsh_format - ? INDEX_4D(kv_num_heads, max_seqlen, H, b, n, s + past_seq_len, h) - : INDEX_4D(max_seqlen, kv_num_heads, H, b, s + past_seq_len, n, h); - - int in_offset = is_new_kv_bnsh_format - ? INDEX_4D(kv_num_heads, new_seqlen, H, b, n, s, h) - : INDEX_4D(new_seqlen, kv_num_heads, H, b, s, n, h); - - kv_buff[out_offset] = new_kv[in_offset]; -} - -template -__global__ void ConcatKVInPlaceLarge(const int max_seqlen, - const int H, - const int kv_num_heads, - T* kv_buff, - const T* new_kv, - const int* seqlens_k, - const int* total_seqlens_k, - const bool is_past_kv_bnsh_format, - const bool is_new_kv_bnsh_format) { // refers to kv buff; otherwise bnsh - int i = threadIdx.x + (blockDim.x * blockIdx.x); - if (i < H * kv_num_heads) { - const int h = i % H; - const int n = i / H; - const int s = blockIdx.y; - const int b = blockIdx.z; - const int new_seqlen = gridDim.y; - - const int past_seq_len = (total_seqlens_k != nullptr) - ? (total_seqlens_k[b] - new_seqlen) - : (seqlens_k == nullptr ? 0 : (seqlens_k[b] + 1 - new_seqlen)); - - int out_offset = is_past_kv_bnsh_format - ? INDEX_4D(kv_num_heads, max_seqlen, H, b, n, s + past_seq_len, h) - : INDEX_4D(max_seqlen, kv_num_heads, H, b, s + past_seq_len, n, h); - - int in_offset = is_new_kv_bnsh_format - ? INDEX_4D(kv_num_heads, new_seqlen, H, b, n, s, h) - : INDEX_4D(new_seqlen, kv_num_heads, H, b, s, n, h); - - kv_buff[out_offset] = new_kv[in_offset]; - } -} - -// Concat new to kv buffer in place -template -Status LaunchConcatKVInPlace(int batch_size, - int kv_num_heads, - int head_size, - int max_sequence_length, - const int* seqlens_k, - const int* total_seqlens_k, - int new_seq_len, - const T* new_key, - const T* new_value, - T* present_key, - T* present_value, - const bool is_past_kv_bnsh_format, - const bool is_new_kv_bnsh_format, - cudaStream_t stream, - const int max_threads_per_block) { - static_assert(sizeof(T) == 2); - assert(head_size % 4 == 0); + const bool is_bsnh = past_kv_format == AttentionQkvFormat::Q_K_V_BSNH; - const int H = head_size / 4; - if (H * kv_num_heads <= max_threads_per_block) { - const dim3 grid(new_seq_len, batch_size, 1); - const dim3 block(H, kv_num_heads, 1); - ConcatKVInPlace<<>>(max_sequence_length, - reinterpret_cast(present_key), - reinterpret_cast(new_key), - seqlens_k, - total_seqlens_k, - is_past_kv_bnsh_format, - is_new_kv_bnsh_format); - ConcatKVInPlace<<>>(max_sequence_length, - reinterpret_cast(present_value), - reinterpret_cast(new_value), - seqlens_k, - total_seqlens_k, - is_past_kv_bnsh_format, - is_new_kv_bnsh_format); - } else { - int steps = int(ceil(float(H * kv_num_heads) / 256.0)); - const dim3 grid(steps, new_seq_len, batch_size); - const dim3 block(256, 1, 1); - ConcatKVInPlaceLarge<<>>(max_sequence_length, - H, - kv_num_heads, - reinterpret_cast(present_key), - reinterpret_cast(new_key), - seqlens_k, - total_seqlens_k, - is_past_kv_bnsh_format, - is_new_kv_bnsh_format); - ConcatKVInPlaceLarge<<>>(max_sequence_length, - H, - kv_num_heads, - reinterpret_cast(present_value), - reinterpret_cast(new_value), - seqlens_k, - total_seqlens_k, - is_past_kv_bnsh_format, - is_new_kv_bnsh_format); - } - return CUDA_CALL(cudaGetLastError()); + return LaunchConcatNewToPastKV(batch_size, + kv_num_heads, + head_size, + kv_sequence_length, + past_sequence_length, + present_sequence_length, + is_bsnh, + seqlens_k, + data.past_key, + data.past_value, + reinterpret_cast(new_key), + reinterpret_cast(new_value), + data.present_key, + data.present_value, + stream, + max_threads_per_block, + past_only); } // Concat new to kv buffer in place @@ -955,38 +698,6 @@ template Status LaunchUnpackQKV( const int kv_num_heads, const int head_size, const int sequence_length, const int batch_size, cudaStream_t stream, const int max_threads_per_block); -template Status LaunchConcatKVInPlace(int batch_size, - int kv_num_heads, - int head_size, - int max_sequence_length, - const int* seqlens_k, - const int* total_seqlens_k, - int new_seq_len, - const half* new_key, - const half* new_value, - half* present_key, - half* present_value, - bool is_past_kv_bnsh_format, - bool is_new_kv_bnsh_format, - cudaStream_t stream, - const int max_threads_per_block); - -template Status LaunchConcatKVInPlace(int batch_size, - int kv_num_heads, - int head_size, - int max_sequence_length, - const int* seqlens_k, - const int* total_seqlens_k, - int new_seq_len, - const BFloat16* new_key, - const BFloat16* new_value, - BFloat16* present_key, - BFloat16* present_value, - bool is_past_kv_bnsh_format, - bool is_new_kv_bnsh_format, - cudaStream_t stream, - const int max_threads_per_block); - } // namespace cuda } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.h index 8593ecede2bab..4ae4c450902f8 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.h @@ -6,43 +6,15 @@ #include #include #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cuda/bert/attention_data.h" +#include "contrib_ops/cuda/bert/attention_kv_cache.h" #include "core/framework/allocator.h" namespace onnxruntime { namespace contrib { namespace cuda { -template -struct GroupQueryAttentionData { - // Input Tensors - const T* query = nullptr; - const T* key = nullptr; - const T* value = nullptr; - const T* past_key = nullptr; - const T* past_value = nullptr; - int* seqlens_k = nullptr; - const T* cos_cache = nullptr; - const T* sin_cache = nullptr; - // Flash buffers - T* softmax_lse = nullptr; - T* softmax_lse_accum = nullptr; - T* out_accum = nullptr; - int* seqlens_k_buff = nullptr; - // Memory Efficient buffers - T* fmha_buffer = nullptr; - T* unpacked_qkv_buffer = nullptr; - T* rotary_buffer = nullptr; - T* k = nullptr; - T* v = nullptr; - // Output Tensors - T* output = nullptr; - T* present_key = nullptr; - T* present_value = nullptr; - // Kernel Flags - bool use_flash_attention = false; - bool use_memory_efficient_attention = false; -}; - template Status QkvToContext( const cudaDeviceProp& device_prop, @@ -56,23 +28,6 @@ Status LaunchUnpackQKV(const T* packed_qkv, T* unpacked_q, T* unpacked_k, T* unp const int kv_num_heads, const int head_size, const int sequence_length, const int batch_size, cudaStream_t stream, const int max_threads_per_block); -template -Status LaunchConcatKVInPlace(int batch_size, - int kv_num_heads, - int head_size, - int max_sequence_length, // max sequence length of present_key or present_value. - const int* seqlens_k, // it is not used when total_seqlens_k is available. - const int* total_seqlens_k, // optional, nullptr means it is not available. - int new_seq_len, - const T* new_key, - const T* new_value, - T* present_key, - T* present_value, - bool is_past_kv_bnsh_format, - bool is_new_kv_bnsh_format, - cudaStream_t stream, - const int max_threads_per_block); - } // namespace cuda } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index e2587d172af94..130a0c1e4c00e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -2,12 +2,14 @@ // Licensed under the MIT License. #include "core/providers/cuda/cuda_common.h" +#include "contrib_ops/cpu/bert/multihead_attention_helper.h" +#include "contrib_ops/cpu/utils/dump_tensor.h" #include "contrib_ops/cuda/bert/attention_impl.h" #include "contrib_ops/cuda/bert/multihead_attention.h" -#include "contrib_ops/cpu/bert/multihead_attention_helper.h" #include "contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h" #include "contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h" #include "contrib_ops/cuda/bert/flash_attention/flash_api.h" +#include "contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h" #include "contrib_ops/cuda/utils/dump_cuda_tensor.h" #include "contrib_ops/cuda/bert/lean_attention/lean_api.h" @@ -19,22 +21,26 @@ namespace onnxruntime { namespace contrib { namespace cuda { -#define REGISTER_KERNEL_TYPED(T) \ - ONNX_OPERATOR_TYPED_KERNEL_EX( \ - MultiHeadAttention, \ - kMSDomain, \ - 1, \ - T, \ - kCudaExecutionProvider, \ - (*KernelDefBuilder::Create()) \ - .TypeConstraint("T", DataTypeImpl::GetTensorType()), \ - MultiHeadAttention); - -REGISTER_KERNEL_TYPED(float) -REGISTER_KERNEL_TYPED(MLFloat16) - -template -MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) +#define REGISTER_KERNEL_TYPED(T, QK) \ + ONNX_OPERATOR_TYPED_KERNEL_EX( \ + MultiHeadAttention, \ + kMSDomain, \ + 1, \ + T##_##QK, \ + kCudaExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("QK", DataTypeImpl::GetTensorType()) \ + .InputMemoryType(OrtMemTypeCPUInput, 8), \ + MultiHeadAttention); + +REGISTER_KERNEL_TYPED(float, float) +REGISTER_KERNEL_TYPED(float, MLFloat16) +REGISTER_KERNEL_TYPED(MLFloat16, float) +REGISTER_KERNEL_TYPED(MLFloat16, MLFloat16) + +template +MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) : CudaKernel(info), fused_fp16_cross_attention_kernel_(nullptr), cumulated_sequence_length_q_cache_(), @@ -65,6 +71,8 @@ MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) enable_cudnn_flash_attention_ = sizeof(T) == 2 && kernel_options_->UseCudnnFlashAttention(); + disable_decoder_attention_ = !kernel_options_->UseDecoderAttention(); + // Allocate cache buffers constexpr size_t cache_bytes = sizeof(int32_t) * (static_cast(kCumulatedSequenceLengthCacheMaxBatchSize) + 1); cumulated_sequence_length_q_cache_.buffer = GetTransientScratchBuffer(cache_bytes); @@ -73,8 +81,8 @@ MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) cumulated_sequence_length_kv_cache_.max_batch_size = kCumulatedSequenceLengthCacheMaxBatchSize; } -template -Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { +template +Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* query = context->Input(0); const Tensor* key = context->Input(1); const Tensor* value = context->Input(2); @@ -83,6 +91,13 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* attention_bias = context->Input(5); const Tensor* past_key = context->Input(6); const Tensor* past_value = context->Input(7); + const Tensor* past_sequence_length = context->Input(8); + const Tensor* cache_indirection = context->Input(9); + + bool past_present_share_buffer = past_key != nullptr && past_sequence_length != nullptr; + if (past_key != nullptr && past_sequence_length != nullptr && cache_indirection != nullptr) { + ORT_ENFORCE(past_present_share_buffer); + } auto& device_prop = GetDeviceProp(); AttentionParameters parameters; @@ -96,15 +111,29 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { attention_bias, past_key, past_value, - nullptr, // past_seq_len + cache_indirection, + past_sequence_length, ¶meters, num_heads_, mask_filter_value_, scale_, is_unidirectional_, - false, // past_present_share_buffer + past_present_share_buffer, kMultiHeadAttention, device_prop.maxThreadsPerBlock)); + DUMP_STRING_INIT(); + DUMP_STRING("Batch size = ", parameters.batch_size); + DUMP_STRING("Sequence length = ", parameters.sequence_length); + DUMP_STRING("Past sequence length = ", parameters.past_sequence_length); + DUMP_STRING("KV sequence length = ", parameters.kv_sequence_length); + DUMP_STRING("Total sequence length = ", parameters.total_sequence_length); + DUMP_STRING("Max sequence length = ", parameters.max_sequence_length); + DUMP_STRING("Hidden size = ", parameters.hidden_size); + DUMP_STRING("Head size = ", parameters.head_size); + DUMP_STRING("Num heads = ", parameters.num_heads); + DUMP_STRING("Buffer sharing = ", (parameters.past_present_share_buffer == true)); + DUMP_STRING("QKV format = ", parameters.qkv_format); + int sequence_length = parameters.sequence_length; TensorShapeVector output_shape(3); @@ -114,11 +143,16 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { Tensor* output = context->Output(0, output_shape); std::vector present_dims{ - parameters.batch_size, parameters.num_heads, parameters.total_sequence_length, parameters.head_size}; + parameters.batch_size, parameters.num_heads, parameters.max_sequence_length, parameters.head_size}; TensorShape present_shape(present_dims); Tensor* present_key = context->Output(1, present_shape); Tensor* present_value = context->Output(2, present_shape); + std::vector output_qk_dims{ + parameters.batch_size, parameters.num_heads, parameters.sequence_length, parameters.total_sequence_length}; + TensorShape output_qk_shape(output_qk_dims); + Tensor* output_qk = context->Output(3, output_qk_shape); + int num_past = static_cast(past_key != nullptr) + static_cast(past_value != nullptr); int num_present = static_cast(present_key != nullptr) + static_cast(present_value != nullptr); if (num_past == 0 && num_present == 0) { @@ -155,6 +189,51 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { int sm = device_prop.major * 10 + device_prop.minor; AttentionKernelType kernel_type = AttentionKernelType::AttentionKernel_Default; + cudaStream_t stream = Stream(context); + + bool use_decoder_masked_multihead_attention = false; + if (cache_indirection != nullptr) { + bool use_dmmha_self_attention = parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH && + parameters.past_present_share_buffer && + parameters.past_sequence_length > 0; + bool use_dmmha_cross_attention = parameters.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH && + past_key == nullptr && past_value == nullptr && nullptr != past_sequence_length && + parameters.past_sequence_length != *((*past_sequence_length).template Data()); + use_decoder_masked_multihead_attention = !disable_decoder_attention_ && + (std::is_same::value || std::is_same::value) && + (use_dmmha_self_attention || use_dmmha_cross_attention) && + parameters.sequence_length == 1 && + parameters.head_size == parameters.v_head_size && + (parameters.mask_type == AttentionMaskType::MASK_2D_KEY_PADDING || parameters.mask_type == AttentionMaskType::MASK_NONE) && + nullptr != past_sequence_length && nullptr != cache_indirection && + has_decoder_masked_multihead_attention(sm, parameters.head_size); + } + DUMP_STRING("Use DMMHA = ", (use_decoder_masked_multihead_attention == true)); + if (use_decoder_masked_multihead_attention) { + // Kernel only works for token generation with beam search + kernel_type = AttentionKernelType::AttentionKernel_DecoderAttention; + + // No production use-case will incur this copy cost as the implementation of + // DecoderMaskedMultiHeadAttention is written in such a way that the past and present buffers + // must be shared to have parity in the outputs. + // This is just to circumvent the OpTester's limitation of not being able to bind a specific + // buffer to inputs/outputs. + auto* past_key_data = (past_key == nullptr) ? nullptr : past_key->Data(); + auto* past_value_data = (past_value == nullptr) ? nullptr : past_value->Data(); + auto* present_key_data = (present_key == nullptr) ? nullptr : present_key->MutableData(); + auto* present_value_data = (present_value == nullptr) ? nullptr : present_value->MutableData(); + + if (present_key_data != past_key_data) { + DUMP_STRING("Copying past_key to present_key for OpTester"); + CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(present_key_data, past_key_data, past_key->SizeInBytes(), + cudaMemcpyDeviceToDevice, stream)); + } + if (present_value_data != past_value_data) { + DUMP_STRING("Copying past_value to present_value for OpTester"); + CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(present_value_data, past_value_data, past_value->SizeInBytes(), + cudaMemcpyDeviceToDevice, stream)); + } + } typedef typename ToCudaType::MappedType CudaT; AttentionData data; @@ -179,6 +258,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { parameters.num_heads); size_t sync_flag_bytes = 0; + DUMP_STRING("Use lean attn = ", (use_lean_attention == true)); if (use_lean_attention) { softmax_lse_bytes = onnxruntime::lean::get_softmax_lse_size(parameters.sequence_length, parameters.batch_size, @@ -216,12 +296,16 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { !disable_flash_attention_ && nullptr == attention_bias && nullptr == key_padding_mask && + nullptr == past_sequence_length && + nullptr == cache_indirection && + nullptr == output_qk && parameters.head_size == parameters.v_head_size && onnxruntime::flash::is_supported(device_prop, parameters.head_size, parameters.num_heads, parameters.num_heads); // When input is packed QKV format, TensorRT kernel might be faster than flash attention when sequence length <= 512. + DUMP_STRING("Use flash attn = ", (use_flash_attention == true)); if (use_flash_attention && parameters.qkv_format == AttentionQkvFormat::QKV_BS3NH && parameters.sequence_length < kernel_options_->MinSeqLenForFlashAttentionPackedQkv()) { use_flash_attention = false; @@ -270,6 +354,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { parameters.sequence_length, // seq_len_q parameters.total_sequence_length, // seq_len_kv is_unidirectional_); + DUMP_STRING("Use cuDNN SDPA = ", (use_cudnn_sdpa == true)); if (use_cudnn_sdpa) { kernel_type = AttentionKernelType::AttentionKernel_CudnnFlashAttention; } @@ -280,10 +365,16 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { !is_unidirectional_ && nullptr == key_padding_mask && nullptr == attention_bias && - nullptr == past_key && nullptr == present_key && + nullptr == past_key && + nullptr == past_sequence_length && + nullptr == cache_indirection && + nullptr == present_key && + nullptr == output_qk && (parameters.qkv_format == Q_K_V_BSNH || (parameters.qkv_format == Q_KV_BSNH_BSN2H && bias == nullptr)) && parameters.hidden_size == parameters.v_hidden_size && has_fused_cross_attention_kernel(sm, parameters.head_size, parameters.kv_sequence_length); + + DUMP_STRING("Use fused cross attn = ", (use_fused_cross_attention == true)); if (use_fused_cross_attention) { if (fused_fp16_cross_attention_kernel_ == nullptr) { std::call_once(fused_cross_init_once_flag_, [&]() { @@ -305,12 +396,15 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { !is_unidirectional_ && nullptr == attention_bias && (parameters.qkv_format == Q_K_V_BSNH || parameters.qkv_format == QKV_BSN3H) && - nullptr == past_key && nullptr == present_key && + nullptr == past_key && nullptr == past_sequence_length && nullptr == cache_indirection && + nullptr == present_key && nullptr == output_qk && is_mask_none_or_1d_k_len && parameters.hidden_size == parameters.v_hidden_size && parameters.sequence_length == parameters.kv_sequence_length && // self attention only for fused runner FusedMHARunnerFP16v2::IsSupported(sm, parameters.head_size, sequence_length, enable_trt_flash_attention_, is_unidirectional_); + + DUMP_STRING("Use fused runner = ", (use_fused_runner == true)); if (use_fused_runner) { // Here we assume that num_heads and head_size does not change for a MultiHeadAttention node. if (nullptr == fused_fp16_runner_.get()) { @@ -342,8 +436,10 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { // Check whether the attention bias alignment is good for memory efficient attention. (attention_bias == nullptr || parameters.sequence_length % (4 * sizeof(T)) == 0) && (nullptr == key_padding_mask || parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN_START) && + nullptr == past_sequence_length && nullptr == cache_indirection && nullptr == output_qk && has_memory_efficient_attention(sm, std::is_same::value, parameters.head_size, parameters.v_head_size); + DUMP_STRING("Use memory efficient attention = ", (use_memory_efficient_attention == true)); if (use_memory_efficient_attention) { kernel_type = AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention; } @@ -355,6 +451,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { kernel_type = AttentionKernelType::AttentionKernel_Unfused; } + typedef typename ToCudaType::MappedType CudaQK; data.bias = (nullptr == bias) ? nullptr : reinterpret_cast(bias->Data()); data.query = reinterpret_cast(query->Data()); data.key = (nullptr == key) ? nullptr : reinterpret_cast(key->Data()); @@ -366,21 +463,27 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { if (nullptr != attention_bias) { data.attention_bias = reinterpret_cast(attention_bias->Data()); } + if (nullptr != cache_indirection) { + data.cache_indirection = reinterpret_cast(cache_indirection->Data()); + } data.output = reinterpret_cast(output->MutableData()); data.present_key = (nullptr == present_key) ? nullptr : reinterpret_cast(present_key->MutableData()); data.present_value = (nullptr == present_value) ? nullptr : reinterpret_cast(present_value->MutableData()); + if (nullptr != output_qk) { + data.output_qk = reinterpret_cast(output_qk->MutableData()); + } data.fused_runner = reinterpret_cast(fused_runner); data.fused_cross_attention_kernel = fused_cross_attention_kernel; data.use_flash_attention = use_flash_attention; data.use_lean_attention = use_lean_attention; data.use_memory_efficient_attention = use_memory_efficient_attention; + data.use_decoder_masked_multihead_attention = use_decoder_masked_multihead_attention; data.kernel_type = kernel_type; data.allocator = Info().GetAllocator(OrtMemType::OrtMemTypeDefault); // Cache of cumulated sequence length that could help when sequence length does not change (for example, image model). // The cache will be initialized only once, and become readonly after that. if ((data.fused_cross_attention_kernel != nullptr || data.fused_runner != nullptr) && data.mask_index == nullptr) { - cudaStream_t stream = Stream(context); data.cumulated_sequence_length_q_cache = this->cumulated_sequence_length_q_cache_.TryGet( parameters.batch_size, parameters.sequence_length, stream); @@ -414,6 +517,18 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { data.allow_debug_info = kernel_options_->AllowDebugInfo(); + // For past-present buffer sharing. + if (parameters.past_present_share_buffer) { + std::vector seqlens_k(parameters.batch_size, parameters.total_sequence_length - 1); + size_t seqlens_k_bytes = 0; + seqlens_k_bytes = sizeof(int) * parameters.batch_size; + auto seqlens_k_buffer = GetScratchBuffer(seqlens_k_bytes, context->GetComputeStream()); + if (seqlens_k_buffer != nullptr) { + data.seqlens_k_total = reinterpret_cast(seqlens_k_buffer.get()); + CUDA_RETURN_IF_ERROR(cudaMemcpy(data.seqlens_k_total, seqlens_k.data(), seqlens_k_bytes, cudaMemcpyHostToDevice)); + } + } + if (data.allow_debug_info) { AttentionKernelDebugInfo debug_info; debug_info.use_flash_attention = use_flash_attention; @@ -434,7 +549,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { cublasHandle_t cublas = GetCublasHandle(context); cudnnHandle_t cudnn = GetCudnnHandle(context); - return QkvToContext( + DUMP_STRING("Run QkvToContext from MHA CUDA"); + return QkvToContext( device_prop, cublas, cudnn, context->GetComputeStream(), parameters, data); } diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h index b093b226c50b0..7de27c24fb601 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h @@ -17,7 +17,7 @@ namespace cuda { using namespace onnxruntime::cuda; -template +template class MultiHeadAttention final : public CudaKernel { public: MultiHeadAttention(const OpKernelInfo& info); @@ -37,6 +37,7 @@ class MultiHeadAttention final : public CudaKernel { #endif bool disable_memory_efficient_attention_; bool enable_cudnn_flash_attention_; + bool disable_decoder_attention_; // These mutable members are readonly after they are initialized so that they can be shared among multiple threads. // Initialization are done only once by the first thread using the resource, so use once_flag to guard each resource. diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention.h b/onnxruntime/contrib_ops/cuda/bert/packed_attention.h index 6fcacd4d46ada..0f7456d0cd0d8 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention.h @@ -9,6 +9,7 @@ #include "core/providers/cuda/cuda_kernel.h" #include "contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/mha_runner.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" #include "contrib_ops/cuda/bert/attention_kernel_options.h" namespace onnxruntime { diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h index 1126c8a046da9..711718016486f 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h @@ -6,6 +6,8 @@ #include #include #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cuda/bert/attention_data.h" namespace onnxruntime { namespace contrib { @@ -29,22 +31,6 @@ size_t GetAttentionWorkspaceSize( bool use_memory_efficient_attention, bool no_qkv_workspace); -template -struct PackedAttentionData { - T* gemm_buffer; - const T* bias; - const T* attention_bias; - const int32_t* token_offset; - const int32_t* cumulative_sequence_length; - - T* workspace; - T* output; - - void* fused_runner; - - bool use_memory_efficient_attention; -}; - template Status QkvToContext( const cudaDeviceProp& device_prop, diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h index 9d0ff77e5fcaa..10e95b95657f1 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h @@ -6,34 +6,13 @@ #include #include #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" +#include "contrib_ops/cuda/bert/attention_data.h" namespace onnxruntime { namespace contrib { namespace cuda { -template -struct PackedMultiHeadAttentionData { - const T* query; - const T* key; - const T* value; - const T* bias; - const T* attention_bias; - - const int32_t* token_offset; - const int32_t* cumulative_sequence_length; - - AttentionQkvFormat source_qkv_format; - - bool no_qkv_workspace; - T* workspace; - T* output; - - void* fused_runner; - - bool use_flash_attention; - bool use_memory_efficient_attention; -}; - template Status QkvToContext( const cudaDeviceProp& device_prop, diff --git a/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc b/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc index cbe4d87dbf398..b8931bf1ea0f8 100644 --- a/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc @@ -92,8 +92,10 @@ class CUDA_ONNX_OP_TYPED_CLASS_NAME(1, MLFloat16, Crop); class CUDA_MS_OP_TYPED_CLASS_NAME(1, float, MoE); class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16, MoE); class CUDA_MS_OP_CLASS_NAME(1, QMoE); -class CUDA_MS_OP_TYPED_CLASS_NAME(1, float, MultiHeadAttention); -class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16, MultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, float_float, MultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, float_MLFloat16, MultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16_float, MultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16_MLFloat16, MultiHeadAttention); class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16, GroupQueryAttention); class CUDA_MS_OP_TYPED_CLASS_NAME(1, BFloat16, GroupQueryAttention); class CUDA_MS_OP_TYPED_CLASS_NAME(1, float, DecoderAttention); @@ -169,8 +171,10 @@ class CUDA_MS_OP_CLASS_NAME(1, QOrderedAttention); class CUDA_MS_OP_CLASS_NAME(1, QOrderedLongformerAttention); class CUDA_MS_OP_TYPED_CLASS_NAME(1, float, DecoderMaskedSelfAttention); class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16, DecoderMaskedSelfAttention); -class CUDA_MS_OP_TYPED_CLASS_NAME(1, float, DecoderMaskedMultiHeadAttention); -class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16, DecoderMaskedMultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, float_float, DecoderMaskedMultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, float_MLFloat16, DecoderMaskedMultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16_float, DecoderMaskedMultiHeadAttention); +class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16_MLFloat16, DecoderMaskedMultiHeadAttention); class CUDA_MS_OP_CLASS_NAME(1, GemmFloat8); class CUDA_MS_OP_TYPED_CLASS_NAME(1, MLFloat16, SparseAttention); class CUDA_MS_OP_TYPED_CLASS_NAME(1, BFloat16, SparseAttention); @@ -298,8 +302,10 @@ Status RegisterCudaContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -381,8 +387,10 @@ Status RegisterCudaContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.cu b/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.cu index 4cb25af970599..e55163186b505 100644 --- a/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.cu @@ -7,6 +7,7 @@ #include "contrib_ops/cuda/bert/group_query_attention_impl.h" #include "contrib_ops/cpu/bert/attention_common.h" #include "contrib_ops/cuda/bert/attention_impl.h" +#include "contrib_ops/cuda/bert/attention_kv_cache.h" #include "contrib_ops/cuda/sparse/sparse_attention_v1/sparse_attention_common.h" #include "contrib_ops/cuda/sparse/sparse_attention_v1/sparse_attention_v1_api.h" #include "contrib_ops/cuda/sparse/sparse_attention_v2/sparse_attention_v2_api.h" diff --git a/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.h b/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.h index 0b07b234b7315..d4f686afe5db0 100644 --- a/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/sparse/sparse_attention_impl.h @@ -6,6 +6,7 @@ #include #include "core/providers/cuda/shared_inc/cuda_utils.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" #include "core/framework/allocator.h" #include "core/providers/cuda/tunable/cuda_tunable.h" diff --git a/onnxruntime/contrib_ops/cuda/transformers/generation_device_helper.cc b/onnxruntime/contrib_ops/cuda/transformers/generation_device_helper.cc index 23283706a11cf..f7ed758aedbb2 100644 --- a/onnxruntime/contrib_ops/cuda/transformers/generation_device_helper.cc +++ b/onnxruntime/contrib_ops/cuda/transformers/generation_device_helper.cc @@ -1360,6 +1360,7 @@ Status ExpandBuffer(Stream* ort_stream, // Input shape (batch_size, xxx). The input is required with data type T. // Output shape (batch_size * num_beams, xxx) const TensorShape& input_shape = input.Get().Shape(); + const int64_t& batch_size = input_shape[0]; int64_t sequence_length = 0; diff --git a/onnxruntime/contrib_ops/rocm/bert/attention_impl.h b/onnxruntime/contrib_ops/rocm/bert/attention_impl.h index 6c2e36b596d32..3053521ad946e 100644 --- a/onnxruntime/contrib_ops/rocm/bert/attention_impl.h +++ b/onnxruntime/contrib_ops/rocm/bert/attention_impl.h @@ -6,6 +6,7 @@ #include #include #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" #include "core/providers/rocm/shared_inc/rocm_utils.h" #include "core/providers/rocm/tunable/rocm_tunable.h" diff --git a/onnxruntime/contrib_ops/rocm/bert/batched_gemm_permute_pipelines.cuh b/onnxruntime/contrib_ops/rocm/bert/batched_gemm_permute_pipelines.cuh index f7709e8242147..66d21e12c2740 100644 --- a/onnxruntime/contrib_ops/rocm/bert/batched_gemm_permute_pipelines.cuh +++ b/onnxruntime/contrib_ops/rocm/bert/batched_gemm_permute_pipelines.cuh @@ -8,6 +8,7 @@ #include "core/providers/rocm/tunable/gemm.h" #include "core/providers/rocm/tunable/rocm_tunable.h" #include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" namespace onnxruntime { namespace contrib { diff --git a/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu b/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu index fe0d621f1d601..5d4ef53b8ba97 100644 --- a/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu +++ b/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu @@ -92,6 +92,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* past_value{}; const Tensor* past_seq_len{}; + const Tensor* cache_indirection = nullptr; + if (attn_type_ == kMultiHeadAttention) { bias = context->Input(3); key_padding_mask = context->Input(4); @@ -117,16 +119,24 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { auto& device_prop = GetDeviceProp(); RocmAttentionParameters attn; - ORT_RETURN_IF_ERROR( - multihead_attention_helper::CheckInputs( - query, key, value, bias, - key_padding_mask, attention_bias, - past_key, past_value, past_seq_len, - &attn, num_heads_, - mask_filter_value_, scale_, false, /*is_unidirectional_*/ - past_present_share_buffer_, - attn_type_, - device_prop.maxThreadsPerBlock)); + ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckInputs(query, + key, + value, + bias, + key_padding_mask, + attention_bias, + past_key, + past_value, + cache_indirection, + past_seq_len, + &attn, /* parameters */ + num_heads_, + mask_filter_value_, + scale_, + is_unidirectional_, + past_present_share_buffer_, + attn_type_, + device_prop.maxThreadsPerBlock)); if (attn_type_ == kDecoderMaskedMultiHeadAttention && attn.sequence_length != 1) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, diff --git a/onnxruntime/contrib_ops/webgpu/bert/attention_common.h b/onnxruntime/contrib_ops/webgpu/bert/attention_common.h index be80ade8b87d0..06b9c88ce8993 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/webgpu/bert/attention_common.h @@ -7,9 +7,9 @@ #include "core/providers/webgpu/program.h" #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_kernel.h" -#include "contrib_ops/webgpu/bert/attention_common.h" -#include "contrib_ops/cpu/bert/attention_common.h" +#include "contrib_ops/cpu/bert/attention_parameters.h" + namespace onnxruntime { namespace contrib { namespace webgpu { diff --git a/onnxruntime/contrib_ops/webgpu/bert/multihead_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/multihead_attention.cc index 72931a7310a75..f218b1f0a51ff 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/multihead_attention.cc @@ -42,6 +42,11 @@ Status MultiHeadAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& const Tensor* past_key = context.Input(6); const Tensor* past_value = context.Input(7); + // Not supported in WebGPU EP currently + const Tensor* cache_indirection = nullptr; + const Tensor* past_sequence_length = nullptr; + constexpr bool past_present_share_buffer = false; + if (query->Shape().GetDims().size() == 5) { ORT_NOT_IMPLEMENTED("Packed QKV of shape (B, L, N, 3, H) not implemented for webgpu"); } @@ -53,9 +58,23 @@ Status MultiHeadAttention::ComputeInternal(onnxruntime::webgpu::ComputeContext& } AttentionParameters params; - ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckInputs(query, key, value, - bias, key_padding_mask, attention_bias, past_key, past_value, nullptr, ¶ms, - num_heads_, mask_filter_value_, scale_, is_unidirectional_, false, kMultiHeadAttention, + ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckInputs(query, + key, + value, + bias, + key_padding_mask, + attention_bias, + past_key, + past_value, + cache_indirection, + past_sequence_length, + ¶ms, + num_heads_, + mask_filter_value_, + scale_, + is_unidirectional_, + past_present_share_buffer, + kMultiHeadAttention, context.DeviceLimits().maxComputeInvocationsPerWorkgroup)); WebgpuAttentionParameters parameters(params); TensorShapeVector output_shape(3); diff --git a/onnxruntime/core/graph/contrib_ops/bert_defs.cc b/onnxruntime/core/graph/contrib_ops/bert_defs.cc index 718dd9a4397b5..bdcc93692379a 100644 --- a/onnxruntime/core/graph/contrib_ops/bert_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/bert_defs.cc @@ -207,7 +207,8 @@ void MultiHeadAttentionTypeAndShapeInference(ONNX_NAMESPACE::InferenceContext& c } auto past_present_share_buffer = getAttribute(ctx, "past_present_share_buffer", 0); - if (past_present_share_buffer) { + bool mha_buffer_sharing = hasInputShape(ctx, 6) && hasInputShape(ctx, 8); // equal to MHA op's definition for past_present_share_buffer + if (past_present_share_buffer || mha_buffer_sharing) { propagateElemTypeFromInputToOutput(ctx, past_key_index, 1); propagateElemTypeFromInputToOutput(ctx, static_cast(past_key_index) + 1, 2); } else { @@ -879,7 +880,7 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "past state for key with shape (batch_size, num_heads, past_sequence_length, head_size) for self attention" "When past_present_share_buffer is set, " "its shape is (batch_size, num_heads, max_sequence_length, head_size). " - // The re-ordering happens only for CUDA EP at the moment. We probably shall support 4 or 5D shape or + // The re-ordering happens only for CUDA EP at the moment. We probably shall support 4D or 5D shape or // attribute to distinguish whether it is re-ordered or not. "The keys buffer is re-ordered in such a way that its virtual sub-tensor of shape " "(batch_size, num_heads, max_sequence_length, head_size) which may be perceived as being of shape " @@ -940,12 +941,14 @@ ONNX_MS_OPERATOR_SET_SCHEMA( .Output(3, "qk", "normalized Q * K, of shape (batch_size, num_heads, 1, total_sequence_length). ", - "V", + "QK", OpSchema::Optional) - .TypeConstraint("V", {"tensor(float)"}, "Constrain qk output types to float32 tensors.") .TypeConstraint("T", {"tensor(float)", "tensor(float16)"}, "Constrain input and output types to float tensors.") + .TypeConstraint("QK", + {"tensor(float)", "tensor(float16)"}, + "Constrain QK output to float32 or float16 tensors, independent of input type or output type.") .TypeConstraint("M", {"tensor(int32)"}, "Constrain mask index to integer types") @@ -1010,31 +1013,50 @@ ONNX_MS_OPERATOR_SET_SCHEMA( OpSchema::Optional) .Input(6, "past_key", - "past state for self attention key with shape (batch_size, num_heads, past_sequence_length, head_size)", + "past state for key with shape (batch_size, num_heads, past_sequence_length, head_size) " + "or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used", "T", OpSchema::Optional) .Input(7, "past_value", - "past state for self attention value with shape (batch_size, num_heads, past_sequence_length, head_size)", + "past state for value with shape (batch_size, num_heads, past_sequence_length, head_size) " + "or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used", "T", OpSchema::Optional) + .Input(8, + "past_sequence_length", + "The past_sequence_length buffer sharing is used with", + "M", + OpSchema::Optional) + .Input(9, + "cache_indirection", + "A buffer of shape [batch_size, beam_width, max_sequence_length] where an [i, j, k] entry specifies" + "which beam the 'k' th token came from for the 'j' th beam for batch 'i' in the current iteration", + "M", + OpSchema::Optional) .Output(0, "output", "3D output tensor with shape (batch_size, sequence_length, v_hidden_size)", "T") .Output(1, "present_key", - "present state for cross attention key with shape (batch_size, num_heads, kv_sequence_length, head_size)" - "or present state for self attention key with shape (batch_size, num_heads, total_sequence_length, head_size)", + "present state for key with shape (batch_size, num_heads, total_sequence_length, head_size) " + "or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used", "T", OpSchema::Optional) .Output(2, "present_value", - "present state for cross attention value with shape (batch_size, num_heads, kv_sequence_length, head_size)" - "or present state for self attention value with shape (batch_size, num_heads, total_sequence_length, head_size)", + "present state for value with shape (batch_size, num_heads, total_sequence_length, head_size) " + "or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used", "T", OpSchema::Optional) + .Output(3, + "qk", + "normalized Q * K, of shape (batch_size, num_heads, sequence_length, total_sequence_length). ", + "QK", + OpSchema::Optional) .TypeConstraint("T", {"tensor(float)", "tensor(float16)"}, "Constrain input and output to float tensors.") + .TypeConstraint("QK", {"tensor(float)", "tensor(float16)"}, "Constrain QK output to float32 or float16 tensors, independent of input type or output type.") .TypeConstraint("M", {"tensor(int32)"}, "Constrain mask to integer types") .TypeAndShapeInferenceFunction([](ONNX_NAMESPACE::InferenceContext& ctx) { MultiHeadAttentionTypeAndShapeInference(ctx, 6); diff --git a/onnxruntime/python/tools/pytorch_export_contrib_ops.py b/onnxruntime/python/tools/pytorch_export_contrib_ops.py index f3cd4c2c89801..bdfd2ce332217 100644 --- a/onnxruntime/python/tools/pytorch_export_contrib_ops.py +++ b/onnxruntime/python/tools/pytorch_export_contrib_ops.py @@ -22,8 +22,8 @@ _registered_ops: typing.AbstractSet[str] = set() -def _reg(symbolic_fn: typing.Callable): - name = f"::{symbolic_fn.__name__}" +def _reg(symbolic_fn: typing.Callable, namespace: str = ""): + name = f"{namespace}::{symbolic_fn.__name__}" torch.onnx.register_custom_op_symbolic(name, symbolic_fn, _OPSET_VERSION) _registered_ops.add(name) @@ -91,6 +91,26 @@ def tril(g, self, diagonal): _reg(tril) + @torch.onnx.symbolic_helper.parse_args("v") + def DynamicTimeWarping(g, self): # noqa: N802 + return g.op("com.microsoft::DynamicTimeWarping", self) + + _reg(DynamicTimeWarping, namespace="onnxruntime") + + def UnfoldTensor(g, self, dim, size, step): # noqa: N802 + dim = int(symbolic_helper._maybe_get_const(dim, "i")) + size = int(symbolic_helper._maybe_get_const(size, "i")) + step = int(symbolic_helper._maybe_get_const(step, "i")) + return g.op( + "com.microsoft::UnfoldTensor", + self, + dim_i=dim, + size_i=size, + step_i=step, + ).setType(self.type().with_sizes([None, None, None, None, size])) + + _reg(UnfoldTensor, namespace="onnxruntime") + def unregister(): """Unregister ONNX Runtime's built-in contrib ops.""" diff --git a/onnxruntime/python/tools/symbolic_shape_infer.py b/onnxruntime/python/tools/symbolic_shape_infer.py index fda604d3f729b..bd88eb1b6b353 100755 --- a/onnxruntime/python/tools/symbolic_shape_infer.py +++ b/onnxruntime/python/tools/symbolic_shape_infer.py @@ -126,6 +126,7 @@ class SymbolicShapeInference: def __init__(self, int_max, auto_merge, guess_output_rank, verbose, prefix=""): self.dispatcher_ = { "Add": self._infer_symbolic_compute_ops, + "AllReduce": self._pass_on_shape_and_type, "ArrayFeatureExtractor": self._infer_ArrayFeatureExtractor, "AveragePool": self._infer_Pool, "BatchNormalization": self._infer_BatchNormalization, @@ -147,7 +148,6 @@ def __init__(self, int_max, auto_merge, guess_output_rank, verbose, prefix=""): "GatherElements": self._infer_GatherElements, "GatherND": self._infer_GatherND, "Identity": self._pass_on_shape_and_type, - "AllReduce": self._pass_on_shape_and_type, "If": self._infer_If, "Loop": self._infer_Loop, "MatMul": self._infer_MatMul, @@ -199,6 +199,7 @@ def __init__(self, int_max, auto_merge, guess_output_rank, verbose, prefix=""): "BiasSplitGelu": self._infer_BiasSplitGelu, "DecoderMaskedMultiHeadAttention": self._infer_DecoderMaskedMultiHeadAttention, "DequantizeLinear": self._infer_DequantizeLinear, + "DynamicTimeWarping": self._infer_DynamicTimeWarping, "EmbedLayerNormalization": self._infer_EmbedLayerNormalization, "FastGelu": self._infer_FastGelu, "GatedRelativePositionBias": self._infer_GatedRelativePositionBias, @@ -229,6 +230,7 @@ def __init__(self, int_max, auto_merge, guess_output_rank, verbose, prefix=""): "SkipLayerNormalization": self._infer_SkipLayerNormalization, "SkipSimplifiedLayerNormalization": self._infer_SkipLayerNormalization, "SparseAttention": self._infer_SparseAttention, + "UnfoldTensor": self._infer_UnfoldTensor, } self.aten_op_dispatcher_ = { "embedding": self._infer_Gather, @@ -457,36 +459,37 @@ def _onnx_infer_single_node(self, node): "SplitToSequence", "ZipMap", # contrib ops "Attention", + "BiasAdd", "BiasGelu", + "BiasSplitGelu", + "DequantizeLinear", + "DynamicTimeWarping", "EmbedLayerNormalization", "FastGelu", "GatherBlockQuantized", "Gelu", "GemmFastGelu", + "GroupNorm", + "GroupNormalization", + "GroupQueryAttention", "LayerNormalization", "LongformerAttention", - "DequantizeLinear", + "MultiHeadAttention", + "NhwcConv", + "PackedAttention", + "PagedAttention", + "PythonOp", "QuantizeLinear", + "QuickGelu", "RelativePositionBias", "RemovePadding", "RestorePadding", + "RotaryEmbedding", "SimplifiedLayerNormalization", "SkipLayerNormalization", "SkipSimplifiedLayerNormalization", - "PackedAttention", - "PagedAttention", - "PythonOp", - "MultiHeadAttention", - "GroupNorm", - "GroupNormalization", - "GroupQueryAttention", "SparseAttention", "SkipGroupNorm", - "BiasSplitGelu", - "BiasAdd", - "NhwcConv", - "QuickGelu", - "RotaryEmbedding", ] if not skip_infer: @@ -2413,6 +2416,42 @@ def _infer_DecoderMaskedMultiHeadAttention(self, node): # noqa: N802 vi = self.known_vi_[node.output[2]] vi.CopyFrom(helper.make_tensor_value_info(vi.name, output_dtype, past_shape)) + def _infer_UnfoldTensor(self, node): # noqa: N802 + input_shape = self._get_shape(node, 0) + if input_shape is not None: + output_shape = input_shape.copy() + output_dtype = self.known_vi_[node.input[0]].type.tensor_type.elem_type + assert output_dtype is not None + + rank, dim, size, step = len(input_shape), None, None, None + for attr in node.attribute: + if attr.name == "dim": + dim = attr.i + dim = rank + dim if dim == -1 else dim + elif attr.name == "size": + size = attr.i + elif attr.name == "step": + step = attr.i + + output_shape.append(size) + output_shape[dim] = (input_shape[dim] - size) // step + 1 + + vi = self.known_vi_[node.output[0]] + vi.CopyFrom(helper.make_tensor_value_info(node.output[0], output_dtype, output_shape)) + + def _infer_DynamicTimeWarping(self, node): # noqa: N802 + # Input 0 has shape M x N or 1 x M x N + # Output 0 has shape (2, O) where max(M, N) <= O < M + N + input_shape = self._get_shape(node, 0) + if input_shape is not None: + shape_len = len(input_shape) + assert shape_len == 2 or shape_len == 3 + M, N = input_shape[shape_len - 2], input_shape[shape_len - 1] # noqa: N806 + output_shape = [2, f"max({M}, {N}) <= O < {M} + {N}"] + output_dtype = onnx.TensorProto.FLOAT + vi = self.known_vi_[node.output[0]] + vi.CopyFrom(helper.make_tensor_value_info(node.output[0], output_dtype, output_shape)) + def _infer_FastGelu(self, node): # noqa: N802 self._propagate_shape_and_type(node) diff --git a/onnxruntime/python/tools/transformers/convert_generation.py b/onnxruntime/python/tools/transformers/convert_generation.py index 68bf9e9e69059..045910ea20828 100644 --- a/onnxruntime/python/tools/transformers/convert_generation.py +++ b/onnxruntime/python/tools/transformers/convert_generation.py @@ -1241,37 +1241,337 @@ def find_past_seq_len_usage(subg: GraphProto): output_name_to_node[output_name] = node for node in subg.node: - # find "Shape(past_key_self..) --> Gather(*, 2)" + # find "past_key_self_0 --> [Transpose(past_key_self_0) --> Reshape(past_key_self_0)] --> Shape(past_key_self_0) --> Gather(*, 2)" + # where [Transpose(past_key_self_0) --> Reshape(past_key_self_0)] may or may not exist if node.op_type == "Gather": if not node.input[1] or not node.input[0]: continue + + # Find Gather node's index value shape_tensor_name, shape_index_name = (node.input[0], node.input[1]) ini_gather_indices = None - for tensor in subg.initializer: - if tensor.name == shape_index_name: - ini_gather_indices = tensor - break + if "Constant_" in shape_index_name: + # If shape_index_name refers to a Constant node + for const_node in subg.node: + if const_node.op_type == "Constant" and const_node.output[0] == shape_index_name: + ini_gather_indices = const_node.attribute[0].t + break + else: + # If shape_index_name refers to an initializer + for tensor in subg.initializer: + if tensor.name == shape_index_name: + ini_gather_indices = tensor + break if ini_gather_indices is None: continue gather_indices_arr = onnx.numpy_helper.to_array(ini_gather_indices) - if gather_indices_arr.size == 1 and gather_indices_arr.item() == 2 and node.input[0] in output_name_to_node: + + if ( + gather_indices_arr.size == 1 + and gather_indices_arr.item() in {1, 2} + and node.input[0] in output_name_to_node + ): shape_node = output_name_to_node[shape_tensor_name] + if not (shape_node.op_type == "Shape" and shape_node.input[0]): + continue + if ( - shape_node.op_type == "Shape" - and shape_node.input[0] - and shape_node.input[0] in graph_input_names + shape_node.input[0] in graph_input_names and ( shape_node.input[0].startswith("past_key_self_") or shape_node.input[0].startswith("past_value_self_") ) + and gather_indices_arr.item() == 2 ): + # "past_key_self_0 --> Shape(past_key_self_0) --> Gather(*, 2)" tensor_names_to_rename.add(node.output[0]) nodes_to_remove.append(node) if len(input_name_to_nodes[shape_node.output[0]]) == 1: nodes_to_remove.append(shape_node) + continue + + if shape_node.input[0] not in output_name_to_node: + continue + reshape_node = output_name_to_node[shape_node.input[0]] + if not (reshape_node.op_type == "Reshape" and reshape_node.input[0]): + continue + transpose_node = output_name_to_node[reshape_node.input[0]] + if not (transpose_node.op_type == "Transpose" and transpose_node.input[0]): + continue + + if ( + transpose_node.input[0] in graph_input_names + and ( + transpose_node.input[0].startswith("past_key_self_") + or transpose_node.input[0].startswith("past_value_self_") + ) + and gather_indices_arr.item() == 1 + ): + # "past_key_self_0 --> Transpose(past_key_self_0) --> Reshape(past_key_self_0) --> Shape(past_key_self_0) --> Gather(*, 2)" + tensor_names_to_rename.add(node.output[0]) + nodes_to_remove.extend([node, shape_node, reshape_node]) + if len(input_name_to_nodes[transpose_node.output[0]]) == 1: + nodes_to_remove.append(transpose_node) + continue + return tensor_names_to_rename, nodes_to_remove +def add_cache_indirection_to_mha(model: OnnxModel, past_seq_len_name: str): + # Add past_sequence_length and cache_indirection as inputs to all MultiHeadAttention ops and as inputs to model + cache_indirection_name = "cache_indirection" + mha_nodes = list(filter(lambda node: node.op_type == "MultiHeadAttention", model.model.graph.node)) + for node in mha_nodes: + # MHA op takes the following potential inputs: + # query, key, value, bias, key_padding_mask, add_qk, past_key, past_value + while len(node.input) < 8: + node.input.append("") + node.input.append(past_seq_len_name) + node.input.append(cache_indirection_name) + + model.model.graph.input.append( + onnx.helper.make_tensor_value_info( + cache_indirection_name, TensorProto.INT32, shape=["batch_size", "beam_width", "max_sequence_length"] + ), + ) + model.topological_sort() + return model + + +def add_output_qk_to_mha(model: OnnxModel, dtype: int = 0, skip_node_idxs: list[int] = []): # noqa: B006 + # Add output_qk as output to MultiHeadAttention ops and as outputs to model + output_qk_basename = "output_cross_qk" + output_qks = [] + mha_nodes = list(filter(lambda node: node.op_type == "MultiHeadAttention", model.model.graph.node)) + for idx, node in enumerate(mha_nodes): + # Skip MHA nodes where output_qk does not need to be added + if idx in skip_node_idxs: + continue + + # Get `num_heads` attribute from MHA + num_heads = 0 + for att in node.attribute: + if att.name == "num_heads": + num_heads = att.i + break + + # Get dtype for `output_qk` based on MHA bias if not provided + output_qk_dtype = dtype + if output_qk_dtype == 0: + for i in model.model.graph.initializer: + if i.name == node.input[3]: + output_qk_dtype = i.data_type + break + + # Get `target_sequence_length` attribute from 4D input for key if it's a constant + target_sequence_length = "target_sequence_length" + for i in model.model.graph.input: + if i.name == node.input[1]: + target_sequence_length = i.type.tensor_type.shape.dim[2].dim_value + break + + # MHA op takes the following potential outputs: + # output, present_key, present_value + while len(node.output) < 3: + node.output.append("") + + output_qk_name = f"{output_qk_basename}_{idx // 2}" + node.output.append(output_qk_name) + output_qks.append( + onnx.helper.make_tensor_value_info( + output_qk_name, + output_qk_dtype, + shape=["batch_size", num_heads, "sequence_length", target_sequence_length], + ), + ) + + model.model.graph.output.extend(output_qks) + model.topological_sort() + return model + + +def fix_past_sequence_length(model: ModelProto): + # Modify total_sequence_length = past_sequence_length + curr_sequence_length subgraph to calculate + # past_sequence_length from the new `past_sequence_length` input of size 1D and type int32 instead of + # from `past_key_self_0` since DecoderMaskedMultiHeadAttention (DMMHA) uses buffer sharing and + # `past_key_self_0.shape[2] = max_sequence_length` instead of `past_key_self_0.shape[2] = past_sequence_length` + # when buffer sharing is enabled + # + # Before: + # + # input_ids past_key_self_0 + # | | + # Shape Shape + # | | + # Gather Gather + # (idx=1) (idx=2) + # | | \ + # +--------+--------+ Unsqueeze + # | + # Add + # + # After: + # + # input_ids past_sequence_length (1D) + # | | + # Shape Squeeze + # | | + # Gather Cast + # (idx=1) (int64) + # | | \ + # +--------+--------+ Unsqueeze + # | + # Add + + node = list(filter(lambda n: n.op_type == "LayerNormalization", model.model.graph.node))[0] # noqa: RUF015 + + base_path = model.match_parent_path( + node, + ["Add", "Slice"], + [0, 1], + ) + if base_path is None: + return + + left_path = model.match_parent_path( + base_path[-1], + ["Unsqueeze", "Add", "Gather", "Shape"], + [2, 0, 0, 0], + ) + right_path = model.match_parent_path( + base_path[-1], + ["Unsqueeze", "Gather", "Shape"], + [1, 0, 0], + ) + long_right_path = model.match_parent_path( + base_path[-1], + ["Unsqueeze", "Gather", "Shape", "Reshape", "Transpose"], + [1, 0, 0, 0, 0], + ) + if left_path is None or right_path is None or left_path[-2:] != right_path[-2:]: + return + + # Remove `past_key_self_0 --> [Transpose --> Reshape] --> Shape --> Gather` connection + # where `Transpose --> Reshape` part may or may not exist. The OpenAI implementation of + # Whisper has an extra `Transpose --> Reshape` connection to remove. + constant_node = list(filter(lambda n: n.output[0] == left_path[-2].input[1], model.model.graph.node))[0] # noqa: RUF015 + model.model.graph.node.remove(left_path[-2]) + model.model.graph.node.remove(left_path[-1]) + model.model.graph.node.remove(constant_node) + if long_right_path is not None: + # Remove `Transpose --> Reshape` part + model.model.graph.node.remove(long_right_path[-2]) + model.model.graph.node.remove(long_right_path[-1]) + + # Add `past_sequence_length` as model input + past_seq_len_name = "past_sequence_length" + model.model.graph.input.append( + onnx.helper.make_tensor_value_info(past_seq_len_name, TensorProto.INT32, shape=[1]), + ) + + # Add `past_sequence_length --> Squeeze --> Cast` connection + past_seq_len_int32 = "past_seq_len_int32" + past_seq_len_int64 = "past_seq_len_int64" + + squeeze_node = onnx.helper.make_node( + "Squeeze", + inputs=[past_seq_len_name], + outputs=[past_seq_len_int32], + name=model.create_node_name("Squeeze"), + ) + squeeze_output = onnx.helper.make_tensor_value_info(past_seq_len_int32, TensorProto.INT32, shape=[]) + cast_node = onnx.helper.make_node( + "Cast", + inputs=[past_seq_len_int32], + outputs=[past_seq_len_int64], + name=model.create_node_name("Cast"), + to=TensorProto.INT64, + ) + cast_output = onnx.helper.make_tensor_value_info(past_seq_len_int64, TensorProto.INT64, shape=[]) + + model.model.graph.value_info.extend([squeeze_output, cast_output]) + + # Add `past_seq_len_int64` as an input name to existing nodes + left_path[1].input[0] = past_seq_len_int64 + right_path[0].input[0] = past_seq_len_int64 + + # Add new nodes to graph + model.model.graph.node.extend([squeeze_node, cast_node]) + model.topological_sort() + return model, past_seq_len_name + + +def replace_mha_with_dmmha(model: OnnxModel, past_seq_len_name: str): + # Add `beam_width` and `cache_indirection` as model inputs + beam_width = "beam_width" + cache_indirection = "cache_indirection" + + model.model.graph.input.extend( + [ + onnx.helper.make_tensor_value_info(beam_width, TensorProto.INT32, shape=[1]), + onnx.helper.make_tensor_value_info( + cache_indirection, TensorProto.INT32, shape=["batch_size", "beam_width", "max_sequence_length"] + ), + ] + ) + + # Replace all `MultiHeadAttention` nodes with `DecoderMaskedMultiHeadAttention` nodes + mha_nodes = list(filter(lambda node: node.op_type == "MultiHeadAttention", model.model.graph.node)) + for idx, node in enumerate(mha_nodes): + # Get `num_heads` attribute from MHA + num_heads = 0 + for att in node.attribute: + if att.name == "num_heads": + num_heads = att.i + break + + # Make Q*K outputs for cross-attention layers, which happen every alternative layer + qk_output_name = f"output_cross_qk_{idx // 2}" + qk_output = onnx.helper.make_tensor_value_info( + qk_output_name, TensorProto.FLOAT, shape=["batch_size", num_heads, 1, "encode_sequence_length / 2"] + ) + if idx % 2 == 1: + model.model.graph.output.append(qk_output) + + # Make DMMHA node + dmmha_node = onnx.helper.make_node( + "DecoderMaskedMultiHeadAttention", + inputs=[ + node.input[0], # query + node.input[1], # key + node.input[2], # value + "", # mask_index + "", # relative_position_bias + node.input[6] if len(node.input) > 4 else "", # past_key + node.input[7] if len(node.input) > 4 else "", # past_value + past_seq_len_name, # past_sequence_length + beam_width, # beam_width + cache_indirection, # cache_indirection + node.input[3], # bias + ], + outputs=[ + node.output[0], # output + node.output[1] if len(node.input) > 4 else "", # present_key + node.output[2] if len(node.input) > 4 else "", # present_value + qk_output_name if idx % 2 == 1 else "", # output_cross_qk + ], + name=node.name.replace("MultiHeadAttention", "DecoderMaskedMultiHeadAttention"), + domain="com.microsoft", + num_heads=num_heads, + output_qk=(idx % 2), + past_present_share_buffer=1, + ) + if idx % 2 == 0: + # Remove empty string for output_cross_qk, which happens every alternative layer + dmmha_node.output.remove("") + + model.model.graph.node.remove(node) + model.model.graph.node.extend([dmmha_node]) + + model.topological_sort() + return model + + def replace_mha_with_gqa( model: OnnxModel, attn_mask: str, kv_num_heads: int = 0, world_size: int = 1, window_size: int = -1 ): @@ -1510,7 +1810,7 @@ def update_decoder_subgraph_output_cross_attention(subg: GraphProto): num_layers = (len(subg.output) - output_self_present_0) // 2 input_cross_past_0 = 2 * num_layers + input_self_past_0 past_key_cross_inputs = {subg.input[layer * 2 + input_cross_past_0].name: layer for layer in range(num_layers)} - print(f" --past_key_cross_inputs={past_key_cross_inputs}") + print(f" -- past_key_cross_inputs = {past_key_cross_inputs}") input_past_key_cross_0_shape = shape_of(subg.input[input_cross_past_0]) print(f"past_key_cross_0_shape is {input_past_key_cross_0_shape}") @@ -1579,9 +1879,9 @@ def update_decoder_subgraph_share_buffer_and_use_decoder_masked_mha(subg: ModelP tensor_names_to_rename, nodes_to_remove = find_past_seq_len_usage(subg) if len(tensor_names_to_rename) > 0: for name_to_rename in tensor_names_to_rename: - print(f"Found tensor name {name_to_rename} to be renamed to {target_squeezed_past_seq_name}") + print(f"Found tensor name `{name_to_rename}` to be renamed to `{target_squeezed_past_seq_name}`") for nr in nodes_to_remove: - print(f"Found node to removed: type:{nr.op_type}, name:{nr.name}") + print(f"Found node to remove: type = {nr.op_type}, name = {nr.name}") squeeze_node = onnx.helper.make_node( "Squeeze", diff --git a/onnxruntime/python/tools/transformers/fusion_attention.py b/onnxruntime/python/tools/transformers/fusion_attention.py index 6a15db20f44ed..5e1d491daae23 100644 --- a/onnxruntime/python/tools/transformers/fusion_attention.py +++ b/onnxruntime/python/tools/transformers/fusion_attention.py @@ -541,6 +541,7 @@ def create_multihead_attention_node( output: str, key_padding_mask: str = "", add_qk: str = "", + unidirectional: bool = False, past_k: str = "", past_v: str = "", present_k: str = "", @@ -561,6 +562,7 @@ def create_multihead_attention_node( output (str): output name of MHA key_padding_mask (str): name of key padding mask add_qk (str): name of add after Q x K' + unidirectional (bool): whether to apply causal attention mask automatically or not past_k (str): name of past K value - (batch_size, num_heads, past_sequence_length, head_size) past_v (str): name of past V value - (batch_size, num_heads, past_sequence_length, head_size) present_k (str): name of present K value - (batch_size, num_heads, sequence_length, head_size) @@ -623,7 +625,6 @@ def create_multihead_attention_node( mha_inputs.append("") # Add optional inputs for MHA - if past_k and past_v: mha_inputs.extend([key_padding_mask, add_qk, past_k, past_v]) elif key_padding_mask or add_qk: @@ -641,7 +642,11 @@ def create_multihead_attention_node( name=mha_node_name, ) mha_node.domain = "com.microsoft" - mha_node.attribute.extend([helper.make_attribute("num_heads", num_heads)]) + mha_node.attribute.append(helper.make_attribute("num_heads", num_heads)) + if unidirectional: + mha_node.attribute.append(helper.make_attribute("unidirectional", int(unidirectional))) + + self.increase_counter("MultiHeadAttention") return mha_node def create_attention_node( @@ -821,6 +826,8 @@ def create_attention_node( outputs=[output], name=attention_node_name, ) + self.increase_counter("MultiHeadAttention") + else: attention_inputs = [ first_input, @@ -855,6 +862,7 @@ def create_attention_node( outputs=attention_outputs, name=attention_node_name, ) + self.increase_counter("Attention") attention_node.domain = "com.microsoft" attention_node.attribute.extend([helper.make_attribute("num_heads", num_heads)]) diff --git a/onnxruntime/python/tools/transformers/fusion_bart_attention.py b/onnxruntime/python/tools/transformers/fusion_bart_attention.py index 69445f93e683d..45bbfa94f6aa2 100644 --- a/onnxruntime/python/tools/transformers/fusion_bart_attention.py +++ b/onnxruntime/python/tools/transformers/fusion_bart_attention.py @@ -82,14 +82,11 @@ def check_runtime_shape_path_openai( matmul_qk, add_q, ): - reshape_qkv_2_path = self.model.match_parent_path( - reshape_qkv_2, ["Concat", "Slice", "Gather", "Shape"], [1, 0, 0, 0] + reshape_qkv_path = self.model.match_parent_path( + reshape_qkv_2, ["Concat", "Slice", "Shape", "Transpose"], [1, 0, 0, 0] ) - if reshape_qkv_2_path is None: + if reshape_qkv_path is None or reshape_qkv_path[-1].input[0] != matmul_qkv.output[0]: return False - else: - if reshape_qkv_2_path[-1].input[0] != matmul_qkv.output[0]: - return False matmul_qk_path_1 = self.model.match_parent_path( matmul_qk, ["Mul", "Pow", "Cast", "Div", "Gather", "Shape"], [0, 1, 0, 0, 0, 0] @@ -348,7 +345,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): ["Transpose", "Reshape", "Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, 0, 0, 1], ) - k_nodes_with_bias_openai = self.model.match_parent_path( + k_nodes_no_bias_openai = self.model.match_parent_path( matmul_qk, ["Mul", "Transpose", "Reshape", "MatMul"], [1, 0, 0, 0], @@ -381,9 +378,9 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): if k_nodes_with_bias is not None: _, reshape_k_2, transpose_k_1, reshape_k_1, add_k, matmul_k = k_nodes_with_bias k_nodes = k_nodes_with_bias - elif k_nodes_with_bias_openai is not None: - mul_k, transpose_k_1, reshape_k_1, matmul_k = k_nodes_with_bias_openai - k_nodes = k_nodes_with_bias_openai + elif k_nodes_no_bias_openai is not None: + mul_k, transpose_k_1, reshape_k_1, matmul_k = k_nodes_no_bias_openai + k_nodes = k_nodes_no_bias_openai present_k = matmul_k.output[0] # Find the child path to access the correct present_k values @@ -403,7 +400,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): # \ / # -> Concat <- # | - # |--> Reshape -> Transpose -> Present_K + # +--> Reshape -> Transpose -> Present_K concat_path = self.model.match_child_path(matmul_k, ["Concat", "Reshape", "Transpose"]) if reshape_path is not None: (_, transpose_matmul_k) = reshape_path @@ -455,7 +452,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): past_k = past_k if past_k in graph_input_names else "" present_k = present_k if present_k in graph_output_names else "" - if k_nodes in (k_nodes_with_bias_openai, k_nodes_no_bias, k_nodes_no_bias_with_past_self_attn): + if k_nodes in (k_nodes_no_bias_openai, k_nodes_no_bias, k_nodes_no_bias_with_past_self_attn): # Create empty Add node for attention graph bias_dim = self.model.get_initializer(add_v.input[0]).dims[0] empty_bias_name = "empty_bias" @@ -473,7 +470,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): if ( model_impl_openai - and not past_k + and not bool(past_k) and not self.check_runtime_shape_path_openai( reshape_qkv_2, matmul_qkv, @@ -485,7 +482,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): return elif ( not model_impl_openai - and not past_k + and not bool(past_k) and not self.check_runtime_shape_path( reshape_qkv_2, reshape_qkv_1, @@ -497,7 +494,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): ): return - three_root_inputs = past_k and past_v and matmul_k is None and "matmul_v" not in locals() + three_root_inputs = bool(past_k) and bool(past_v) and matmul_k is None and "matmul_v" not in locals() one_root_input = ( not three_root_inputs and matmul_k.input[0] == root_input @@ -520,13 +517,13 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): encoder_attention = one_root_input and qk_nodes == qk_nodes_1 decoder_attention = one_root_input and qk_nodes in (qk_nodes_2, qk_nodes_2_openai) decoder_attention_with_past = ( - (encoder_attention if not model_impl_openai else decoder_attention) and past_k and past_v + (encoder_attention if not model_impl_openai else decoder_attention) and bool(past_k) and bool(past_v) ) decoder_cross_attention = two_root_inputs and qk_nodes == qk_nodes_1 decoder_cross_attention_with_past = three_root_inputs and qk_nodes == qk_nodes_1 # For decoder_attention, the attention mask needs to be included in the attention node - mask_index = None + mask_index, mask_nodes = None, [] if decoder_attention: mask_nodes_bart = self.model.match_parent_path( add_qk, @@ -540,8 +537,10 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): ) if mask_nodes_whisper is not None: mask_index = mask_nodes_whisper[0].output[-1] + mask_nodes = mask_nodes_whisper elif mask_nodes_bart is not None: mask_index = mask_nodes_bart[0].output[-1] + mask_nodes = mask_nodes_bart if ( encoder_attention @@ -573,6 +572,7 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): num_heads=num_heads, hidden_size=hidden_size, output=attention_last_node.output[0], + unidirectional=decoder_attention_with_past, past_k=past_k if decoder_attention_with_past else "", past_v=past_v if decoder_attention_with_past else "", present_k=present_k, @@ -599,11 +599,14 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): hidden_size=hidden_size, first_input=root_input, output=attention_last_node.output[0], - add_qk_str=add_qk_str, + add_qk_str=( + None if len(mask_nodes) > 1 else add_qk_str + ), # deprecate and use is_unidirectional attr instead for Whisper past_k=past_k, past_v=past_v, present_k=present_k, present_v=present_v, + causal=decoder_attention, ) self.use_multi_head_attention = use_multi_head_attention_ground_truth if new_node is None: diff --git a/onnxruntime/python/tools/transformers/models/whisper/README.md b/onnxruntime/python/tools/transformers/models/whisper/README.md index 6e3385a1a9cc6..598eeea8d2e49 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/README.md +++ b/onnxruntime/python/tools/transformers/models/whisper/README.md @@ -19,9 +19,65 @@ In addition to the above packages, you will need to install `ffmpeg` on your mac **FFMPEG includes numerous codecs, many of which are likely not used by your product/service. Microsoft engineering teams using FFMPEG must build FFMPEG to remove all the unneeded and unused codecs. Including codecs in your product/service, even if not used, can create patent risk for Microsoft. You are responsible for building FFMPEG in a way that follows this codec guidance.** +## Exporting Whisper + +It is recommended to export Whisper for ONNX Runtime GenAI as you will get much more granular control over the generation loop and you can produce word-level timestamps. The alternative option is to export Whisper with the beam search op in the ONNX model, which does not provide these extra benefits and may have additional limitations. + +To see all available options: +``` +# From source: +$ python3 -m models.whisper.convert_to_onnx --help + +# From wheel: +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx --help +``` + +## Exporting Whisper for [ONNX Runtime GenAI](https://github.com/microsoft/onnxruntime-genai) + +To export Whisper for ONNX Runtime GenAI, you can use the `convert_to_onnx.py` script. + +``` +# From source +$ git clone https://github.com/microsoft/onnxruntime +$ cd onnxruntime/onnxruntime/python/tools/transformers/ +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --no_beam_search_op --output_cross_qk + +# From wheel +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --no_beam_search_op --output_cross_qk +``` + +Here are some additional examples for exporting Whisper for ONNX Runtime GenAI. + +Export + Optimize for FP32 CPU +``` +# From source: +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --precision fp32 --provider cpu --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk + +# From wheel: +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --precision fp32 --provider cpu --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk +``` + +Export + Optimize for FP32 CUDA +``` +# From source: +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --precision fp32 --provider cuda --use_gpu --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk + +# From wheel: +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --precision fp32 --provider cuda --use_gpu --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk +``` + +Export + Optimize for FP16 CUDA +``` +# From source: +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --precision fp16 --provider cuda --use_gpu --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk + +# From wheel: +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --precision fp16 --provider cuda --use_gpu --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk +``` + ## Exporting Whisper with Beam Search -There are several ways to export Whisper with beam search (using Whisper tiny as an example). +There are several ways to export Whisper with beam search. ### Option 1: from convert_to_onnx @@ -29,10 +85,10 @@ There are several ways to export Whisper with beam search (using Whisper tiny as # From source $ git clone https://github.com/microsoft/onnxruntime $ cd onnxruntime/onnxruntime/python/tools/transformers/ -$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format # From wheel -$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format ``` ### Option 2: end-to-end model from [Olive](https://github.com/microsoft/Olive/tree/main/examples/whisper) @@ -46,7 +102,7 @@ Run the following Python code to export: ``` from optimum.onnxruntime import ORTModelForSpeechSeq2Seq -model_name = "openai/whisper-large-v2" +model_name = "openai/whisper-large-v3-turbo" model = ORTModelForSpeechSeq2Seq.from_pretrained( model_name, export=True, @@ -58,51 +114,46 @@ model.save_pretrained(model_name.split("/")[-1] + "-onnx") Here are some additional examples for exporting Whisper with beam search. -To see all available options -``` -# From source: -$ python3 -m models.whisper.convert_to_onnx --help - -# From wheel: -$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx --help -``` - Export with Forced Decoder Input Ids ``` # From source: -$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --use_forced_decoder_ids +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --use_forced_decoder_ids # From wheel: -$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --use_forced_decoder_ids +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --use_forced_decoder_ids ``` Export + Optimize for FP32 ``` # From source: -$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --optimize_onnx --precision fp32 +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --optimize_onnx --precision fp32 # From wheel: -$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --optimize_onnx --precision fp32 +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --optimize_onnx --precision fp32 ``` -Export + Optimize for FP16 and GPU +Note: FP32 CPU is not compatible with `--output_cross_qk`. + +Export + Optimize for FP16 GPU ``` # From source: -$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --optimize_onnx --precision fp16 --use_gpu --provider cuda --disable_auto_mixed_precision +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --optimize_onnx --precision fp16 --use_gpu --provider cuda # From wheel: -$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --optimize_onnx --precision fp16 --use_gpu --provider cuda --disable_auto_mixed_precision +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --optimize_onnx --precision fp16 --use_gpu --provider cuda ``` Export + Quantize for INT8 ``` # From source: -$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --precision int8 --quantize_embedding_layer +$ python3 -m models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --precision int8 --quantize_embedding_layer # From wheel: -$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3 --output whisperlargev3 --use_external_data_format --precision int8 --quantize_embedding_layer +$ python3 -m onnxruntime.transformers.models.whisper.convert_to_onnx -m openai/whisper-large-v3-turbo --output whisper-turbo --use_external_data_format --precision int8 --quantize_embedding_layer ``` +Note: INT8 CPU is not compatible with `--output_cross_qk`. + ## Benchmark Whisper Here are some examples of how you can benchmark Whisper across various end-to-end (E2E) implementations. @@ -114,7 +165,7 @@ Here are some examples of how you can benchmark Whisper across various end-to-en python3 -m models.whisper.benchmark \ --benchmark-type hf-pt-eager \ --audio-path 1272-141231-0002.mp3 \ - --model-name openai/whisper-large-v2 \ + --model-name openai/whisper-large-v3-turbo \ --precision fp32 \ --device cpu ``` @@ -124,7 +175,7 @@ python3 -m models.whisper.benchmark \ python3 -m models.whisper.benchmark \ --benchmark-type hf-pt-compile \ --audio-path 1272-141231-0002.mp3 \ - --model-name openai/whisper-large-v2 \ + --model-name openai/whisper-large-v3-turbo \ --precision fp16 \ --device cuda ``` @@ -134,8 +185,8 @@ python3 -m models.whisper.benchmark \ python3 -m models.whisper.benchmark \ --benchmark-type hf-ort \ --audio-path 1272-141231-0002.mp3 \ - --model-name openai/whisper-large-v2 \ - --hf-ort-dir-path ./whisper-large-v2-onnx/ \ + --model-name openai/whisper-large-v3-turbo \ + --hf-ort-dir-path ./whisper-large-v3-turbo-onnx/ \ --precision fp32 \ --device cpu ``` @@ -145,8 +196,8 @@ python3 -m models.whisper.benchmark \ python3 -m models.whisper.benchmark \ --benchmark-type ort \ --audio-path 1272-141231-0002.mp3 \ - --model-name openai/whisper-large-v2 \ - --ort-model-path ./wlarge-fp32/whisper-large-v2_beamsearch.onnx \ + --model-name openai/whisper-large-v3-turbo \ + --ort-model-path ./wlarge-fp32/whisper-large-v3-turbo_beamsearch.onnx \ --precision fp32 \ --device cpu ``` @@ -156,7 +207,7 @@ python3 -m models.whisper.benchmark \ python3 -m models.whisper.benchmark \ --benchmark-type ort \ --audio-path 1272-141231-0002.mp3 \ - --model-name openai/whisper-large-v2 \ + --model-name openai/whisper-large-v3-turbo \ --ort-model-path ./wlarge-fp32/whisper-large_all.onnx \ --precision fp16 \ --device cuda @@ -167,8 +218,8 @@ python3 -m models.whisper.benchmark \ python3 -m models.whisper.benchmark \ --benchmark-type ort \ --audio-path 1272-141231-0002.mp3 \ - --model-name openai/whisper-large-v2 \ - --ort-model-path ./wlarge-fp32/whisper-large-v2_all.onnx \ + --model-name openai/whisper-large-v3-turbo \ + --ort-model-path ./wlarge-fp32/whisper-large-v3-turbo_all.onnx \ --precision fp32 \ --device cpu ``` @@ -184,9 +235,9 @@ python3 -m models.whisper.benchmark_all \ --audio-path ./whisper-test-audios/ \ --hf-pt-eager \ --hf-pt-compile \ - --hf-ort-dir-path ./whisper-large-v2-onnx/ \ - --ort-model-path ./wlarge-fp32/whisper-large-v2_all.onnx \ - --model-name openai/whisper-large-v2 \ + --hf-ort-dir-path ./whisper-large-v3-turbo-onnx/ \ + --ort-model-path ./wlarge-fp32/whisper-large-v3-turbo_all.onnx \ + --model-name openai/whisper-large-v3-turbo \ --precision fp32 \ --device cpu ``` diff --git a/onnxruntime/python/tools/transformers/models/whisper/convert_to_onnx.py b/onnxruntime/python/tools/transformers/models/whisper/convert_to_onnx.py index 3220f43ced152..2cc002928b16e 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/convert_to_onnx.py +++ b/onnxruntime/python/tools/transformers/models/whisper/convert_to_onnx.py @@ -5,13 +5,13 @@ # -------------------------------------------------------------------------- import argparse -import copy import logging import os import torch from benchmark_helper import Precision, create_onnxruntime_session, prepare_environment, setup_logger from whisper_chain import chain_model +from whisper_encoder import WhisperEncoder from whisper_helper import PRETRAINED_WHISPER_MODELS, WhisperHelper from onnxruntime import quantization @@ -106,14 +106,6 @@ def parse_arguments(argv=None): ) conversion_args.set_defaults(use_int64_inputs=False) - conversion_args.add_argument( - "--disable_auto_mixed_precision", - required=False, - action="store_true", - help="Use pure fp16 instead of mixed precision", - ) - conversion_args.set_defaults(disable_auto_mixed_precision=False) - conversion_args.add_argument( "-r", "--provider", @@ -330,26 +322,36 @@ def export_onnx_models( verbose, use_forced_decoder_ids: bool = False, merge_encoder_and_decoder_init: bool = True, + no_beam_search_op: bool = False, + output_qk: bool = False, overwrite: bool = False, - disable_auto_mixed_precision: bool = False, use_int32_inputs: bool = True, quantize_embedding_layer: bool = False, quantize_per_channel: bool = False, quantize_reduce_range: bool = False, provider: str = "cpu", ): - device = torch.device("cuda:0" if use_gpu else "cpu") + device = torch.device("cuda" if use_gpu else "cpu") - models = WhisperHelper.load_model(model_name_or_path, model_impl, cache_dir, device, merge_encoder_and_decoder_init) + models = WhisperHelper.load_model( + model_name_or_path, + model_impl, + cache_dir, + device, + torch.float16 if precision == Precision.FLOAT16 else torch.float32, + merge_encoder_and_decoder_init, + no_beam_search_op, + output_qk, + ) config = models["decoder"].config if (not use_external_data_format) and (config.num_hidden_layers > 24): - logger.info("Try use_external_data_format when model size > 2GB") + logger.warning("You MUST pass `--use_external_data_format` because model size > 2GB") + raise Exception("Please pass `--use_external_data_format` for this model.") output_paths = [] for name, model in models.items(): print(f"========> Handling {name} model......") - model.to(device) filename_suffix = "_" + name onnx_path = WhisperHelper.get_onnx_path( @@ -359,23 +361,24 @@ def export_onnx_models( new_folder=False, ) + # Export to ONNX if overwrite or not os.path.exists(onnx_path): logger.info(f"Exporting ONNX model to {onnx_path}") - # We have to clone model before exporting onnx, otherwise verify_onnx will report large difference. - device_to_export = torch.device("cpu") - cloned_model = copy.deepcopy(model).to(device_to_export) WhisperHelper.export_onnx( - cloned_model, - device_to_export, + model, onnx_path, + PROVIDERS[provider], verbose, use_external_data_format, + use_fp16_inputs=(precision == Precision.FLOAT16), use_int32_inputs=use_int32_inputs, + use_encoder_hidden_states=(name == "decoder_init"), + use_kv_cache_inputs=(name == "decoder"), ) else: - logger.info(f"Skip exporting: existed ONNX model {onnx_path}") + logger.info(f"Skip exporting: existing ONNX model {onnx_path}") - # Optimize ONNX graph. Note that we have not implemented graph optimization for Whisper yet. + # Optimize ONNX model if optimize_onnx or precision != Precision.FLOAT32: output_path = WhisperHelper.get_onnx_path( output_dir, @@ -391,15 +394,37 @@ def export_onnx_models( onnx_path, output_path, precision == Precision.FLOAT16, - config.encoder_attention_heads, - config.d_model, + model.config.encoder_attention_heads, + model.config.d_model, + model.config.num_hidden_layers, use_external_data_format, - auto_mixed_precision=not disable_auto_mixed_precision, use_gpu=use_gpu, provider=provider, + is_decoder=(name == "decoder"), + no_beam_search_op=no_beam_search_op, + output_qk=output_qk, ) + # Remove old ONNX model and old data file + if os.path.exists(onnx_path): + os.remove(onnx_path) + if os.path.exists(onnx_path + ".data"): + os.remove(onnx_path + ".data") onnx_path = output_path + if isinstance(model, WhisperEncoder): + model.verify_onnx( + onnx_path, + PROVIDERS[provider], + use_fp16_inputs=(precision == Precision.FLOAT16), + ) + else: + model.verify_onnx( + onnx_path, + PROVIDERS[provider], + use_fp16_inputs=(precision == Precision.FLOAT16), + use_int32_inputs=use_int32_inputs, + ) + if precision == Precision.INT8: quantization.quantize_dynamic( onnx_path, @@ -417,13 +442,6 @@ def export_onnx_models( else: output_path = onnx_path - ort_session = create_onnxruntime_session( - output_path, - use_gpu=use_gpu, - provider=provider, - ) - assert ort_session is not None - output_paths.append(output_path) return output_paths @@ -443,9 +461,6 @@ def main(argv=None): if args.precision == Precision.FLOAT16: assert args.use_gpu, "fp16 requires --use_gpu" - if args.optimize_onnx: - logger.warning("Applying graph optimization for Whisper...") - output_paths = export_onnx_models( args.model_name_or_path, args.model_impl, @@ -458,8 +473,9 @@ def main(argv=None): args.verbose, args.use_forced_decoder_ids, not args.separate_encoder_and_decoder_init, + args.no_beam_search_op, + args.output_cross_qk, args.overwrite, - args.disable_auto_mixed_precision, not args.use_int64_inputs, args.quantize_embedding_layer, args.quantize_per_channel, @@ -477,7 +493,7 @@ def main(argv=None): new_folder=False, ) for path in output_paths: - if "encoder_decoder" in path: + if "encoder_decoder" in path or "encoder" in path: args.encoder_path = path elif "decoder" in path: args.decoder_path = path @@ -490,12 +506,12 @@ def main(argv=None): use_gpu=args.use_gpu, provider=args.provider, ) - device = torch.device("cuda:0" if args.use_gpu else "cpu") + device = torch.device("cuda" if args.use_gpu else "cpu") # Wrap parity check in try-except to allow export to continue in case this produces an error try: with torch.no_grad(): - # Verify batched decoding with prompts for whisper openai implementation + # Verify batched decoding with prompts for OpenAI implementation if args.model_impl == "openai" and args.use_forced_decoder_ids: max_diff = WhisperHelper.verify_onnx( args.model_name_or_path, cache_dir, ort_session, device, batch_size=2, prompt_mode=True @@ -512,10 +528,12 @@ def main(argv=None): ) # Remove extra ONNX models saved in output directory - for fle in os.listdir(output_dir): - if "_beamsearch" not in fle: - os.remove(os.path.join(output_dir, fle)) - output_paths = [args.beam_model_output_dir] + for _file in os.listdir(output_dir): + if "_beamsearch" not in _file and "_jump_times" not in _file: + path = os.path.join(output_dir, _file) + os.remove(path) + if path in output_paths: + output_paths.remove(path) logger.info(f"Done! Outputs: {output_paths}") return max_diff diff --git a/onnxruntime/python/tools/transformers/models/whisper/requirements.txt b/onnxruntime/python/tools/transformers/models/whisper/requirements.txt index 408b5b6c3a728..29a08b5ccd220 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/requirements.txt +++ b/onnxruntime/python/tools/transformers/models/whisper/requirements.txt @@ -1,6 +1,6 @@ torch>=1.13.0 -transformers>=4.24.0,<= 4.42.4 -openai-whisper>=20231117 +transformers>=4.36.0,<= 4.42.4 +openai-whisper>=20231117,<=20240927 ffmpeg-python datasets soundfile diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_chain.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_chain.py index feb688948d8f5..365a69ee4ec67 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/whisper_chain.py +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_chain.py @@ -312,13 +312,15 @@ def chain_model(args): # Save WhisperBeamSearch graph and external data if os.path.isfile(args.beam_model_output_dir): logger.info(f"Overwriting {args.beam_model_output_dir} and {args.beam_model_output_dir + '.data'}") - os.remove(args.beam_model_output_dir) - os.remove(args.beam_model_output_dir + ".data") + if os.path.exists(args.beam_model_output_dir): + os.remove(args.beam_model_output_dir) + if os.path.exists(args.beam_model_output_dir + ".data"): + os.remove(args.beam_model_output_dir + ".data") onnx.save( beam_model, args.beam_model_output_dir, - save_as_external_data=True, + save_as_external_data=args.use_external_data_format, all_tensors_to_one_file=True, convert_attribute=True, location=f"{os.path.basename(args.beam_model_output_dir)}.data", diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_decoder.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_decoder.py index 400cafc4c93c3..69683942656e0 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/whisper_decoder.py +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_decoder.py @@ -7,395 +7,459 @@ import logging import os import tempfile +from itertools import chain from pathlib import Path -import numpy +import numpy as np import onnx import torch -from io_binding_helper import TypeHelper -from models.t5.past_helper import PastKeyValuesHelper +from float16 import convert_float_to_float16 +from google.protobuf.internal.containers import RepeatedCompositeFieldContainer +from onnx import ModelProto, ValueInfoProto from onnx_model import OnnxModel -from torch_onnx_export_helper import torch_onnx_export -from transformers import WhisperConfig, file_utils -from whisper_openai_helper import WhisperDecoderInitOpenai +from past_helper import PastKeyValuesHelper +from transformers import WhisperConfig +from whisper_inputs import ( + convert_inputs_for_ort, + get_model_dynamic_axes, + get_sample_decoder_inputs, + group_past_key_values, +) from onnxruntime import InferenceSession logger = logging.getLogger(__name__) -class WhisperDecoderInit(torch.nn.Module): - """A Whisper decoder to create initial past key values. - This model is only called once during starting decoding. - """ +class WhisperDecoder(torch.nn.Module): + """A Whisper decoder with optional past key values""" - def __init__( - self, - decoder: torch.nn.Module, - config: WhisperConfig, - decoder_start_token_id: int | None = None, - ): + def __init__(self, config: WhisperConfig, model: torch.nn.Module, model_impl: str, no_beam_search_op: bool = False): super().__init__() - self.decoder = decoder self.config = config - self.decoder_start_token_id = ( - decoder_start_token_id if decoder_start_token_id is not None else self.config.decoder_start_token_id - ) + self.device = model.device + self.model_impl = model_impl + self.no_beam_search_op = no_beam_search_op - def forward( + self.decoder = None if model_impl == "openai" else model.model.decoder + self.proj_out = None if model_impl == "openai" else model.proj_out + self.model = model if model_impl == "openai" else None + + self.max_source_positions = self.config.max_source_positions + self.num_heads = self.config.decoder_attention_heads + self.head_size = self.config.d_model // self.num_heads + + def hf_forward( self, decoder_input_ids: torch.Tensor, - encoder_hidden_states: torch.FloatTensor, + encoder_hidden_states: torch.Tensor | None = None, + past_key_values: list[tuple[torch.Tensor]] | None = None, ): - encoder_outputs = file_utils.ModelOutput() - encoder_outputs["last_hidden_state"] = encoder_hidden_states - encoder_outputs["hidden_states"] = None - encoder_outputs["attentions"] = None - - out = self.decoder.model( - None, - encoder_outputs=encoder_outputs, - decoder_input_ids=decoder_input_ids, - past_key_values=None, + outputs = self.decoder( + encoder_hidden_states=encoder_hidden_states, + input_ids=decoder_input_ids, + past_key_values=past_key_values, use_cache=True, - return_dict=True, ) - logits = self.decoder.proj_out(out[0]) - return logits, out.past_key_values, out.encoder_last_hidden_state - + logits = self.proj_out(outputs.last_hidden_state) + present_key_values = outputs.past_key_values -class WhisperDecoder(torch.nn.Module): - """A Whisper decoder with past key values""" + if past_key_values is None: + # Return present_self_* and present_cross_* for decoder-init + return logits, present_key_values - def __init__(self, decoder, config, model_impl: str = "hf", model: torch.nn.Module = None): - super().__init__() - self.decoder = decoder - self.config = config - self.model_impl = model_impl - if model is not None: - self.whisper_decoder_openai_init = WhisperDecoderInitOpenai(model, decoder) + # Before: (past_key_self_0, past_value_self_0, past_key_cross_0, past_value_cross_0), + # (past_key_self_1, past_value_self_1, past_key_cross_1, past_value_cross_1), + # After: (past_key_self_0, past_value_self_0, past_key_self_1, past_value_self_1), ..., + # (past_key_cross_0, past_value_cross_0, past_key_cross_1, past_value_cross_1), ... + present_self, present_cross = PastKeyValuesHelper.group_by_self_and_cross(present_key_values) - def forward(self, decoder_input_ids, *past): - encoder_outputs = file_utils.ModelOutput() - dummy_encoder_hidden_states = torch.randn((decoder_input_ids.shape[0], 3000, int(self.config.d_model))) - encoder_outputs["last_hidden_state"] = dummy_encoder_hidden_states - encoder_outputs["hidden_states"] = dummy_encoder_hidden_states - encoder_outputs["attentions"] = None + # Return present_self_* for decoder-with-past since past_cross_* and present_cross_* are identical + return logits, present_self - if self.model_impl == "openai": - dummy_encoder_hidden_states.unsqueeze(0) - dec_out, present = self.whisper_decoder_openai_init( - decoder_input_ids, dummy_encoder_hidden_states, past=past + def oai_forward( + self, + decoder_input_ids: torch.Tensor, + encoder_hidden_states: torch.Tensor | None = None, + past_key_values: list[tuple[torch.Tensor]] | None = None, + ): + past_kv_cache = {} + if past_key_values is not None: + # Convert past KV caches (BxNxSxH --> BxSxNxH --> BxSxD) for OpenAI's forward pass + self_attn_kv_caches, cross_attn_kv_caches = group_past_key_values(past_key_values) + self_attn_kv_caches = [past_kv.transpose(1, 2) for past_kv in self_attn_kv_caches] + self_attn_kv_caches = [past_kv.reshape(past_kv.shape[:2] + (-1,)) for past_kv in self_attn_kv_caches] + cross_attn_kv_caches = [past_kv.transpose(1, 2) for past_kv in cross_attn_kv_caches] + cross_attn_kv_caches = [past_kv.reshape(past_kv.shape[:2] + (-1,)) for past_kv in cross_attn_kv_caches] + + for idx, block in enumerate(self.model.decoder.blocks): + past_kv_cache[block.attn.key] = self_attn_kv_caches[2 * idx] + past_kv_cache[block.attn.value] = self_attn_kv_caches[2 * idx + 1] + past_kv_cache[block.cross_attn.key] = cross_attn_kv_caches[2 * idx] + past_kv_cache[block.cross_attn.value] = cross_attn_kv_caches[2 * idx + 1] + + # Install OpenAI's hooks on the forward pass of each nn.Linear for key and value + # since the hooks will capture the output of the key and value MatMuls, which + # represent the current keys and values. + # + # For OpenAI's forward pass, the hook function will also perform the concat + # operation (past_kv + curr_kv --> pres_kv) if needed. However, the ONNX model + # will not contain this concat operation because the present KV caches aren't + # returned by OpenAI's forward pass. + kv_cache, hooks = self.model.install_kv_cache_hooks() + + # Run forward pass + # NOTE: There is a bug with openai-whisper==20240930 with the introduction of SDPA. + # In the Whisper codebase, the following line + # + # is_causal = mask is not None and n_ctx > 1 + # + # has been added where `mask` is a torch tensor. The right-hand side evaluates to `tensor(True/False)` + # but `is_causal` only accepts the boolean value. The fix is to apply `.item()` after the right-hand + # side has been evaluated. In other words, the line should be + # + # is_causal = (mask is not None and n_ctx > 1).item() + # + # instead. + logits = self.model.decoder(x=decoder_input_ids, xa=encoder_hidden_states, kv_cache=past_kv_cache) + + # Re-do concat operation on self attention KV caches for ONNX export (if past self attention KV caches exist) + if past_key_values is not None: + for block in self.model.decoder.blocks: + kv_cache[block.attn.key] = torch.cat( + [past_kv_cache[block.attn.key], kv_cache[block.attn.key]], dim=1 + ).detach() + kv_cache[block.attn.value] = torch.cat( + [past_kv_cache[block.attn.value], kv_cache[block.attn.value]], dim=1 + ).detach() + + present_self, present_cross = [], [] + for block in self.model.decoder.blocks: + # Group self and cross values + present_self.append(kv_cache[block.attn.key]) + present_self.append(kv_cache[block.attn.value]) + if past_key_values is None: + # Return present_self_* and present_cross_* for decoder-init + present_cross.append(kv_cache[block.cross_attn.key]) + present_cross.append(kv_cache[block.cross_attn.value]) + + # Convert present KV caches (BxSxD --> BxSxNxH --> BxNxSxH) after OpenAI's forward pass + present_self = [ + present_kv.reshape(present_kv.shape[:2] + (-1, self.head_size)).transpose(1, 2) + for present_kv in present_self + ] + present_cross = [ + present_kv.reshape(present_kv.shape[:2] + (-1, self.head_size)).transpose(1, 2) + for present_kv in present_cross + ] + + # Remove OpenAI's hooks since they can persist after this function completes + for hook in hooks: + hook.remove() + + if past_key_values is None: + # Return present_self_* and present_cross_* for decoder-init + present_key_values = PastKeyValuesHelper.group_by_layer( + present_self + present_cross, len(present_self) // 2 ) - return dec_out, present - - if len(past) == 0: - past_key_values = None - else: - past_key_values = PastKeyValuesHelper.back_group_by_layer(past) + return logits, present_key_values - decoder_out = self.decoder( - None, - encoder_outputs=encoder_outputs, - decoder_input_ids=decoder_input_ids, - past_key_values=past_key_values, - use_cache=True, - return_dict=True, - ) - logits = decoder_out[0] - present_self, _ = PastKeyValuesHelper.group_by_self_and_cross(decoder_out.past_key_values) + # Return present_self_* for decoder-with-past since past_cross_* and present_cross_* are identical return logits, present_self - -class WhisperDecoderInputs: - def __init__( + def forward( self, - decoder_input_ids, - past_key_values=None, + decoder_input_ids: torch.Tensor, + encoder_hidden_states: torch.Tensor | None = None, + past_key_values: list[tuple[torch.Tensor]] | None = None, ): - self.decoder_input_ids: torch.LongTensor = decoder_input_ids - self.past_key_values: list[torch.FloatTensor] | list[torch.HalfTensor] | None = past_key_values - - @staticmethod - def create_dummy( - config: WhisperConfig, - batch_size: int, - encode_sequence_length: int, - past_decode_sequence_length: int, - device: torch.device, - float16: bool = False, - use_int32_inputs: bool = False, - model_impl: str = "hf", - ): # -> WhisperDecoderInputs: - """Create dummy inputs for WhisperDecoder. - - Args: - decoder: decoder - batch_size (int): batch size - encode_sequence_length (int): sequence length of input_ids for encoder - past_decode_sequence_length (int): past sequence length of input_ids for decoder - device (torch.device): device of output tensors - float16 (bool): whether the model uses float32 or float16 in input - use_int32_inputs(bool): whether use int32 instead of int64 for some inputs - - Returns: - WhisperDecoderInputs: dummy inputs for decoder - """ - num_attention_heads: int = config.encoder_attention_heads - num_layers: int = config.decoder_layers # + config.encoder_layers - vocab_size: int = config.vocab_size - - # Use head_size, use hidden_size / num_attention_heads here. - # For example, whisper-large, d_model=1280 and num_heads=20 - head_size: int = config.d_model // config.encoder_attention_heads - - sequence_length: int = 1 # fixed for decoding - decoder_input_ids = torch.randint( - low=0, - high=vocab_size - 1, - size=(batch_size, sequence_length), - dtype=(torch.int32 if use_int32_inputs else torch.int64), - device=device, - ) - - float_type = torch.float16 if float16 else torch.float32 + if self.model_impl == "openai": + return self.oai_forward(decoder_input_ids, encoder_hidden_states, past_key_values) + return self.hf_forward(decoder_input_ids, encoder_hidden_states, past_key_values) - if past_decode_sequence_length > 0: - self_attention_past_shape = [ - batch_size, - num_attention_heads, - past_decode_sequence_length, - head_size, + def input_names(self): + if self.first_pass: + input_names = ["input_ids", "encoder_hidden_states"] + else: + input_names = [ + "input_ids", + "encoder_hidden_states", + *list( + chain.from_iterable( + (f"past_key_self_{i}", f"past_value_self_{i}", f"past_key_cross_{i}", f"past_value_cross_{i}") + for i in range(self.config.num_hidden_layers) + ) + ), ] - cross_attention_past_shape = [ - batch_size, - num_attention_heads, - encode_sequence_length if model_impl == "hf" else past_decode_sequence_length, - head_size, + return input_names + + def output_names(self): + if self.first_pass: + output_names = [ + "logits", + *list( + chain.from_iterable( + ( + f"present_key_self_{i}", + f"present_value_self_{i}", + f"present_key_cross_{i}", + f"present_value_cross_{i}", + ) + for i in range(self.config.num_hidden_layers) + ) + ), ] - - past = [] - for _ in range(2 * num_layers): - past.append(torch.rand(self_attention_past_shape, dtype=float_type, device=device)) - - for _ in range(2 * num_layers): - past.append(torch.rand(cross_attention_past_shape, dtype=float_type, device=device)) else: - past = None - - return WhisperDecoderInputs(decoder_input_ids, past) - - def to_list(self) -> list: - input_list = [self.decoder_input_ids] - if self.past_key_values: - input_list.extend(self.past_key_values) - return input_list - - def to_fp32(self): - past = [p.to(dtype=torch.float32) for p in self.past_key_values] if self.past_key_values else None - return WhisperDecoderInputs( - self.decoder_input_ids.clone(), - past, + output_names = [ + "logits", + *list( + chain.from_iterable( + (f"present_key_self_{i}", f"present_value_self_{i}") + for i in range(self.config.num_hidden_layers) + ) + ), + ] + return output_names + + def dynamic_axes(self, input_names, output_names): + dynamic_axes = get_model_dynamic_axes(self.config, input_names, output_names) + if "input_ids" in dynamic_axes and not self.no_beam_search_op: + # Set dynamic axes for `input_ids` when using beam search op to {0: "batch_size"} only + del dynamic_axes["input_ids"][1] + return dynamic_axes + + def inputs(self, use_fp16_inputs: bool, use_int32_inputs: bool, return_dict: bool = False): + inputs = get_sample_decoder_inputs( + self.config, + self.device, + batch_size=2, + past_sequence_length=(0 if self.first_pass else 6), + sequence_length=(6 if self.first_pass else 1), + use_fp16=use_fp16_inputs, + use_int32=use_int32_inputs, + ) + if return_dict: + if self.first_pass: + del inputs["past_key_values"] + return inputs + + if self.first_pass: + return ( + inputs["decoder_input_ids"], + inputs["encoder_hidden_states"], + ) + return ( + inputs["decoder_input_ids"], + inputs["encoder_hidden_states"], + inputs["past_key_values"], ) + def fix_key_value_cache_dims(self, io: ValueInfoProto, is_cross: bool = False, is_output: bool = False): + # Shape should be (batch_size, num_heads, sequence_length, head_size) for self attention KV caches + # and (batch_size, num_heads, num_frames // 2, head_size) for cross attention KV caches + num_heads = io.type.tensor_type.shape.dim[1] + if "_dim_" in num_heads.dim_param: + num_heads.Clear() + num_heads.dim_value = self.num_heads + sequence_length = io.type.tensor_type.shape.dim[2] + if "_dim_" in sequence_length.dim_param: + sequence_length.Clear() + if is_cross: + sequence_length.dim_value = self.max_source_positions + else: + sequence_length.dim_param = "total_sequence_length" if is_output else "past_sequence_length" + head_size = io.type.tensor_type.shape.dim[3] + if "_dim_" in head_size.dim_param: + head_size.Clear() + head_size.dim_value = self.head_size + return io + + def fix_io(self, io_list: RepeatedCompositeFieldContainer, is_output: bool = False): + # Fix order of inputs/outputs and each dim_value of input/output + reordered_io = [] + self_attn_kv_caches = [] + cross_attn_kv_caches = [] + + for io in io_list: + if "past" not in io.name and "present" not in io.name: + reordered_io.append(io) + elif "self" in io.name: + # Self attention KV caches + new_io = self.fix_key_value_cache_dims(io, is_cross=False, is_output=is_output) + if self.no_beam_search_op: + reordered_io.append(new_io) + else: + self_attn_kv_caches.append(new_io) + else: + # Cross attention KV caches + new_io = self.fix_key_value_cache_dims(io, is_cross=True, is_output=is_output) + if self.no_beam_search_op: + reordered_io.append(new_io) + else: + cross_attn_kv_caches.append(new_io) + + if not self.no_beam_search_op: + reordered_io += self_attn_kv_caches + cross_attn_kv_caches + return reordered_io + + def fix_inputs_and_outputs(self, model: ModelProto): + # ONNX exporter might mark dimensions like 'Transposepresent_value_self_1_dim_2' in shape inference. + # We now change the dim_values to the correct one. + reordered_inputs = self.fix_io(model.graph.input, is_output=False) + while len(model.graph.input) > 0: + model.graph.input.pop() + model.graph.input.extend(reordered_inputs) + + reordered_outputs = self.fix_io(model.graph.output, is_output=True) + while len(model.graph.output) > 0: + model.graph.output.pop() + model.graph.output.extend(reordered_outputs) + return model + + def fix_layernorm_weights(self, model: ModelProto, use_fp16_inputs: bool): + if self.model_impl == "openai" and use_fp16_inputs: + # Cast ONNX model to float16 to ensure LayerNorm weights are converted from + # float32 to float16 since exported model already has float16 weights everywhere + # except for LayerNorm ops. This happens because OpenAI always upcasts to float32 + # when computing LayerNorm. + # + # Reference: + # https://github.com/openai/whisper/blob/90db0de1896c23cbfaf0c58bc2d30665f709f170/whisper/model.py#L41 + model = convert_float_to_float16(model) + return model -class WhisperDecoderHelper: - @staticmethod def export_onnx( - decoder: WhisperDecoder, - device: torch.device, + self, onnx_model_path: str, + provider: str, verbose: bool = True, use_external_data_format: bool = False, - use_int32_inputs: bool = False, + use_fp16_inputs: bool = False, + use_int32_inputs: bool = True, + use_encoder_hidden_states: bool = False, + use_kv_cache_inputs: bool = True, ): """Export decoder to ONNX Args: - decoder (Union[WhisperDecoder, WhisperDecoderNoPastState]): decoder object - device (torch.device): device of decoder object - onnx_model_path (str): onnx path + onnx_model_path (str): path to save ONNX model + provider (str): provider to use for verifying parity on ONNX model verbose (bool, optional): print verbose information. Defaults to True. use_external_data_format (bool, optional): use external data format or not. Defaults to False. - use_int32_inputs (bool, optional): use int32 inputs + use_fp16_inputs (bool, optional): use float16 inputs for the KV caches. Defaults to False. + use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids. Defaults to True. + use_encoder_hidden_states (bool, optional): use encoder_hidden_states as model input for decoder-init/decoder-without-past models. Defaults to False. + use_kv_cache_inputs (bool, optional): use KV caches as model inputs for decoder-with-past models. Defaults to True. """ - assert isinstance(decoder, (WhisperDecoder, WhisperDecoderInit)) - - inputs = WhisperDecoderInputs.create_dummy( - decoder.config, - batch_size=2, - encode_sequence_length=3000, - past_decode_sequence_length=6 if isinstance(decoder, WhisperDecoder) else 0, - device=device, - use_int32_inputs=use_int32_inputs, - model_impl=decoder.model_impl, - ) - input_list = inputs.to_list() - - # Fix past disappearing bug - duplicate first past entry - # input_list.insert(2, input_list[2]) + # Shape of decoder's tensors: + # Required Inputs: + # decoder_input_ids: (batch_size, sequence_length) + # Optional Inputs: + # encoder_hidden_states (comes from encoder's outputs): (batch_size, num_frames // 2, hidden_size) + # past_{key/value}_self_* (past self attention KV caches): (batch_size, num_heads, past_sequence_length, head_size) + # past_{key/value}_cross_* (past cross attention KV caches): (batch_size, num_heads, num_frames // 2, head_size) + # Outputs: + # logits: (batch_size, sequence_length, vocab_size) + # present_{key/value}_self_* (present self attention KV caches): (batch_size, num_heads, past_sequence_length + sequence_length, head_size) + # present_{key/value}_cross_* (present cross attention KV caches): (batch_size, num_heads, num_frames // 2, head_size) - past_names = PastKeyValuesHelper.get_past_names(decoder.config.decoder_layers, present=False) - present_names = PastKeyValuesHelper.get_past_names(decoder.config.decoder_layers, present=True) - present_self_names = present_names[: 2 * decoder.config.decoder_layers] + # For the first pass through the decoder (i.e. decoder-init/decoder-without-past) + self.first_pass = use_encoder_hidden_states and not use_kv_cache_inputs - input_past_names = past_names if isinstance(decoder, WhisperDecoder) else [] - output_present_names = present_self_names if isinstance(decoder, WhisperDecoder) else present_names - output_names = ["logits", *output_present_names] + # For subsequent passes through the decoder (i.e. decoder-with-past) + self.later_pass = not use_encoder_hidden_states and use_kv_cache_inputs - # Shape of input tensors (sequence_length==1): - # input_ids: (batch_size, sequence_length) - # past_self_*: (batch_size, num_heads, past_decode_sequence_length, head_size) - # past_cross_*: (batch_size, num_heads, encode_sequence_length, head_size) + assert self.first_pass or self.later_pass, ( + "Only one of `use_encoder_hidden_states` and `use_kv_cache_inputs` can be true at once." + ) - # Shape of output tensors: - # logits: (batch_size, sequence_length, vocab_size) - # past_self_*: (batch_size, num_heads, past_decode_sequence_length + sequence_length, head_size) - # past_cross_*: (batch_size, num_heads, encode_sequence_length, head_size) - - input_names = ["input_ids"] - input_names.extend(input_past_names) - - dynamic_axes = { - "input_ids": {0: "batch_size"}, - "encoder_hidden_states": {0: "batch_size", 1: "encode_sequence_length / 2"}, - "logits": {0: "batch_size", 1: "sequence_length"}, - } - - for name in input_past_names: - dynamic_axes[name] = { - 0: "batch_size", - 2: "past_decode_sequence_length" if "self" in name else "encode_sequence_length", - } - - for name in output_present_names: - if "cross" in name: - dynamic_axes[name] = {0: "batch_size", 2: "encode_sequence_length"} - else: # self attention past state - if isinstance(decoder, WhisperDecoder): - dynamic_axes[name] = { - 0: "batch_size", - 2: "past_decode_sequence_length + 1", - } - else: - dynamic_axes[name] = { - 0: "batch_size", - # 2: 'sequence_length' - } + inputs = self.inputs(use_fp16_inputs=use_fp16_inputs, use_int32_inputs=use_int32_inputs) + input_names = self.input_names() + output_names = self.output_names() + dynamic_axes = self.dynamic_axes(input_names, output_names) Path(onnx_model_path).parent.mkdir(parents=True, exist_ok=True) - with tempfile.TemporaryDirectory() as tmp_dir_name: temp_onnx_model_path = os.path.join(tmp_dir_name, "decoder.onnx") Path(temp_onnx_model_path).parent.mkdir(parents=True, exist_ok=True) - torch_onnx_export( - decoder, - args=tuple(input_list), - f=temp_onnx_model_path if use_external_data_format else onnx_model_path, + out_path = temp_onnx_model_path if use_external_data_format else onnx_model_path + + torch.onnx.export( + self, + args=inputs, + f=out_path, export_params=True, input_names=input_names, output_names=output_names, dynamic_axes=dynamic_axes, opset_version=17, do_constant_folding=True, - use_external_data_format=use_external_data_format, verbose=verbose, ) - if use_external_data_format: - model = onnx.load_model(temp_onnx_model_path, load_external_data=True) - OnnxModel.save( - model, - onnx_model_path, - save_as_external_data=True, - all_tensors_to_one_file=True, - ) - - @staticmethod - def onnxruntime_inference(ort_session, inputs: WhisperDecoderInputs): - """Run inference of ONNX model.""" - logger.debug("start onnxruntime_inference") - - ort_inputs = { - "input_ids": numpy.ascontiguousarray(inputs.decoder_input_ids.cpu().numpy()), - } - - if inputs.past_key_values: - assert len(inputs.past_key_values) % 4 == 0 - num_layers = int(len(inputs.past_key_values) / 4) - past_names = PastKeyValuesHelper.get_past_names(num_layers) - for i, past_tensor in enumerate(inputs.past_key_values): - ort_inputs[past_names[i]] = numpy.ascontiguousarray(past_tensor.cpu().numpy()) - - ort_outputs = ort_session.run(None, ort_inputs) - return ort_outputs - - @staticmethod - def verify_onnx( - model: WhisperDecoder | WhisperDecoderInit, - ort_session: InferenceSession, - device: torch.device, - use_int32_inputs: bool, - max_cases: int = 4, - ): - """Compare the result from PyTorch and OnnxRuntime to verify the ONNX model is good.""" - float16: bool = TypeHelper.get_input_type(ort_session, "past_key_self_0") == "tensor(float16)" - - test_cases = [(4, 11, 3), (1, 2, 5), (3, 1, 1), (8, 5, 2)] - test_cases_max_diff = [] - for ( - batch_size, - encode_sequence_length, - past_decode_sequence_length, - ) in test_cases[:max_cases]: - if isinstance(model, WhisperDecoderInit): - dec_seq_len = 0 - else: - dec_seq_len = past_decode_sequence_length - - inputs = WhisperDecoderInputs.create_dummy( - model.config, - batch_size, - encode_sequence_length, - dec_seq_len, - device=device, - float16=float16, - use_int32_inputs=use_int32_inputs, + model = onnx.load_model(out_path, load_external_data=use_external_data_format) + model = self.fix_inputs_and_outputs(model) + model = self.fix_layernorm_weights(model, use_fp16_inputs) + OnnxModel.save( + model, + onnx_model_path, + save_as_external_data=use_external_data_format, + all_tensors_to_one_file=True, ) - # We use fp32 PyTroch model as baseline even when ONNX model is fp16 - input_list = inputs.to_fp32().to_list() + self.verify_onnx(onnx_model_path, provider, use_fp16_inputs, use_int32_inputs) - # Run inference of PyTorch model - with torch.no_grad(): - torch_outputs = model(*input_list) - - ort_outputs = WhisperDecoderHelper.onnxruntime_inference(ort_session, inputs) - - max_diff = numpy.amax(numpy.abs(torch_outputs[0].cpu().numpy() - ort_outputs[0])) - max_diff_all = max_diff - logger.debug(f"logits max_diff={max_diff}") - - for i in range(2 * model.config.num_layers): - max_diff = numpy.amax(numpy.abs(torch_outputs[1][i].cpu().numpy() - ort_outputs[1 + i])) - logger.debug(f"self attention past state {i} max_diff={max_diff}") - max_diff_all = max(max_diff_all, max_diff) - - if isinstance(model, WhisperDecoderInit): - for i in range(2 * model.config.num_layers): - max_diff = numpy.amax( - numpy.abs(torch_outputs[2][i].cpu().numpy() - ort_outputs[1 + 2 * model.config.num_layers + i]) - ) - logger.debug(f"cross attention past state {i} max_diff={max_diff}") - max_diff_all = max(max_diff_all, max_diff) - - test_cases_max_diff.append(max_diff_all) - logger.info( - "batch_size=%s, encode_sequence_length=%s, past_decode_sequence_length=%s, max_diff=%s", - batch_size, - encode_sequence_length, - past_decode_sequence_length, - max_diff_all, - ) + def verify_onnx( + self, + onnx_model_path: str, + provider: str, + use_fp16_inputs: bool, + use_int32_inputs: bool, + ): + """Verify ONNX model outputs and PyTorch model outputs match - return max_diff_all + Args: + onnx_model_path (str): path to save ONNX model + provider (str): execution provider for ONNX model + use_fp16_inputs (bool, optional): use float16 inputs for the KV caches + use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids + """ + # Shape of decoder's tensors: + # Required Inputs: + # decoder_input_ids: (batch_size, sequence_length) + # Optional Inputs: + # encoder_hidden_states (comes from encoder's outputs): (batch_size, num_frames // 2, hidden_size) + # past_{key/value}_self_* (past self attention KV caches): (batch_size, num_heads, past_sequence_length, head_size) + # past_{key/value}_cross_* (past cross attention KV caches): (batch_size, num_heads, num_frames // 2, head_size) + # Outputs: + # logits: (batch_size, sequence_length, vocab_size) + # present_{key/value}_self_* (present self attention KV caches): (batch_size, num_heads, past_sequence_length + sequence_length, head_size) + # present_{key/value}_cross_* (present cross attention KV caches): (batch_size, num_heads, num_frames // 2, head_size) + + # Run PyTorch model + inputs = self.inputs(use_fp16_inputs=use_fp16_inputs, use_int32_inputs=use_int32_inputs, return_dict=True) + pt_outputs = [] + if self.first_pass: + out = self.forward(**inputs) + pt_outputs.append(out[0].detach().cpu().numpy()) + for present_key_value_layer in out[1]: + for present_key_value in present_key_value_layer: + pt_outputs.append(present_key_value.detach().cpu().numpy()) + else: + out = self.forward(**inputs) + pt_outputs.append(out[0].detach().cpu().numpy()) + for present_self_key_value in out[1]: + pt_outputs.append(present_self_key_value.detach().cpu().numpy()) + + # Run ONNX model + sess = InferenceSession(onnx_model_path, providers=[provider]) + ort_outputs = sess.run(None, convert_inputs_for_ort(inputs, sess)) + + # Calculate output difference + try: + for i, output_name in enumerate(self.output_names()): + diff = np.abs(pt_outputs[i] - ort_outputs[i]) + logger.warning(f"Comparing {output_name}...") + logger.warning(f"Max diff: {np.max(diff)}") + except: # noqa: E722 + pass diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder.py index 0b9db81486caa..851f641442016 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder.py +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder.py @@ -9,12 +9,14 @@ import tempfile from pathlib import Path -import numpy +import numpy as np import onnx import torch +from float16 import convert_float_to_float16 +from onnx import ModelProto from onnx_model import OnnxModel -from torch_onnx_export_helper import torch_onnx_export from transformers import WhisperConfig +from whisper_inputs import get_model_dynamic_axes, get_sample_encoder_inputs from onnxruntime import InferenceSession @@ -22,142 +24,141 @@ class WhisperEncoder(torch.nn.Module): - """Whisper encoder outputs only the last hidden state""" + """Whisper encoder component""" - def __init__(self, encoder, config: WhisperConfig, model_impl: str = "hf"): + def __init__(self, config: WhisperConfig, model: torch.nn.Module, model_impl: str): super().__init__() - self.encoder = encoder self.config = config + self.device = model.device self.model_impl = model_impl - def forward(self, input_features): - if self.model_impl == "openai": - return self.encoder(input_features) - return self.encoder.model.encoder(input_features)[0] + self.encoder = model.encoder if model_impl == "openai" else model.model.encoder + def forward(self, audio_features: torch.Tensor): + outputs = self.encoder(audio_features) + return outputs if self.model_impl == "openai" else outputs.last_hidden_state -class WhisperEncoderInputs: - def __init__(self, input_features): - self.input_ids: torch.LongTensor = input_features + def input_names(self): + input_names = ["audio_features"] + return input_names - @staticmethod - def create_dummy( - batch_size: int, - sequence_length: int, - feature_size: int, - device: torch.device, - use_int32_inputs: bool = False, - ): - """Create dummy inputs for Whisper encoder. - - Args: - batch_size (int): batch size - sequence_length (int): sequence length - feature_size (int): feature size for spectrogram input - device (torch.device): device of output tensors - - Returns: - WhisperEncoderInputs: dummy inputs for encoder - """ + def output_names(self): + output_names = ["encoder_hidden_states"] + return output_names - input_features = torch.randn( - size=(batch_size, feature_size, sequence_length), - device=device, - ) - return WhisperEncoderInputs(input_features) - - def to_list(self) -> list: - if self.input_ids is None: - return [] - return [self.input_ids] + def dynamic_axes(self, input_names, output_names): + dynamic_axes = get_model_dynamic_axes(self.config, input_names, output_names) + return dynamic_axes + def fix_layernorm_weights(self, model: ModelProto, use_fp16_inputs: bool): + if self.model_impl == "openai" and use_fp16_inputs: + # Cast ONNX model to float16 to ensure LayerNorm weights are converted from + # float32 to float16 since exported model already has float16 weights everywhere + # except for LayerNorm ops. This happens because OpenAI always upcasts to float32 + # when computing LayerNorm. + # + # Reference: + # https://github.com/openai/whisper/blob/90db0de1896c23cbfaf0c58bc2d30665f709f170/whisper/model.py#L41 + model = convert_float_to_float16(model) + return model -class WhisperEncoderHelper: - @staticmethod def export_onnx( - encoder, - device: torch.device, + self, onnx_model_path: str, + provider: str, verbose: bool = True, use_external_data_format: bool = False, - use_int32_inputs: bool = False, + use_fp16_inputs: bool = False, ): """Export encoder to ONNX Args: - encoder (WhisperEncoder): encoder object - device (torch.device): device of encoder object - onnx_model_path (str): onnx path + onnx_model_path (str): path to save ONNX model + provider (str): provider to use for verifying parity on ONNX model verbose (bool, optional): print verbose information. Defaults to True. use_external_data_format (bool, optional): use external data format or not. Defaults to False. + use_fp16_inputs (bool, optional): use float16 inputs for the audio_features. Defaults to False. """ - config = encoder.config - encoder_inputs = WhisperEncoderInputs.create_dummy( + # Shape of encoder's tensors: + # Inputs: + # audio_features: (batch_size, num_mels, num_frames) + # Outputs: + # encoder_hidden_states: (batch_size, num_frames // 2, hidden_size) + + inputs = get_sample_encoder_inputs( + self.config, + self.device, batch_size=2, - sequence_length=3000, - feature_size=config.num_mel_bins, - device=device, - use_int32_inputs=use_int32_inputs, + use_fp16=use_fp16_inputs, ) - Path(onnx_model_path).parent.mkdir(parents=True, exist_ok=True) + input_names = self.input_names() + output_names = self.output_names() + dynamic_axes = self.dynamic_axes(input_names, output_names) + Path(onnx_model_path).parent.mkdir(parents=True, exist_ok=True) with tempfile.TemporaryDirectory() as tmp_dir_name: temp_onnx_model_path = os.path.join(tmp_dir_name, "encoder.onnx") Path(temp_onnx_model_path).parent.mkdir(parents=True, exist_ok=True) - torch_onnx_export( - encoder, - args=tuple(encoder_inputs.to_list()), - f=temp_onnx_model_path if use_external_data_format else onnx_model_path, + out_path = temp_onnx_model_path if use_external_data_format else onnx_model_path + + torch.onnx.export( + self, + args=(inputs["audio_features"]), + f=out_path, export_params=True, - input_names=["input_features"], - output_names=["hidden_states"], - dynamic_axes={ - "input_ids": {0: "batch_size", 1: "feature_size", 2: "sequence_length"}, - "hidden_states": {0: "batch_size", 1: "sequence_length"}, - }, + input_names=input_names, + output_names=output_names, + dynamic_axes=dynamic_axes, opset_version=17, do_constant_folding=True, - use_external_data_format=use_external_data_format, verbose=verbose, ) - if use_external_data_format: - model = onnx.load_model(temp_onnx_model_path, load_external_data=True) - OnnxModel.save( - model, - onnx_model_path, - save_as_external_data=True, - all_tensors_to_one_file=True, - ) - - @staticmethod - def onnxruntime_inference(ort_session, inputs: WhisperEncoderInputs): - """Run inference of ONNX model.""" - ort_inputs = { - "input_ids": numpy.ascontiguousarray(inputs.input_ids.cpu().numpy()), - } - - return ort_session.run(None, ort_inputs) - - @staticmethod + model = onnx.load_model(out_path, load_external_data=use_external_data_format) + model = self.fix_layernorm_weights(model, use_fp16_inputs) + OnnxModel.save( + model, + onnx_model_path, + save_as_external_data=use_external_data_format, + all_tensors_to_one_file=True, + ) + + self.verify_onnx(onnx_model_path, provider, use_fp16_inputs) + def verify_onnx( - model: WhisperEncoder, ort_session: InferenceSession, device: torch.device, use_int32_inputs: bool = False + self, + onnx_model_path: str, + provider: str, + use_fp16_inputs: bool, ): - """Compare the result from PyTorch and OnnxRuntime to verify the ONNX model is good.""" - inputs = WhisperEncoderInputs.create_dummy( - batch_size=4, - sequence_length=11, - device=device, - use_int32_inputs=use_int32_inputs, - ) - input_list = inputs.to_list() - torch_outputs = model(*input_list) + """Verify ONNX model outputs and PyTorch model outputs match - ort_outputs = WhisperEncoderHelper.onnxruntime_inference(ort_session, inputs) + Args: + onnx_model_path (str): path to save ONNX model + provider (str): execution provider for ONNX model + use_fp16_inputs (bool, optional): use float16 inputs for the audio_features + """ + # Shape of encoder's tensors: + # Inputs: + # audio_features: (batch_size, num_mels, num_frames) + # Outputs: + # encoder_hidden_states: (batch_size, num_frames // 2, hidden_size) + inputs = get_sample_encoder_inputs( + self.config, + self.device, + batch_size=2, + use_fp16=use_fp16_inputs, + ) - max_diff = numpy.amax(numpy.abs(torch_outputs.cpu().numpy() - ort_outputs[0])) + # Run PyTorch model + pt_outputs = self.forward(inputs["audio_features"]).detach().cpu().numpy() - logger.info(f"max_diff={max_diff}") + # Run ONNX model + sess = InferenceSession(onnx_model_path, providers=[provider]) + ort_outputs = sess.run(None, {"audio_features": inputs["audio_features"].detach().cpu().numpy()})[0] - return max_diff + # Calculate output difference + diff = np.abs(pt_outputs - ort_outputs) + logger.warning("Comparing encoder_hidden_states...") + logger.warning(f"Max diff: {np.max(diff)}") diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder_decoder_init.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder_decoder_init.py index c7c7a7675c1a7..26dc3aee7018b 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder_decoder_init.py +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_encoder_decoder_init.py @@ -7,18 +7,24 @@ import logging import os import tempfile +from itertools import chain from pathlib import Path -import numpy +import numpy as np import onnx import torch -from models.t5.past_helper import PastKeyValuesHelper +from float16 import convert_float_to_float16 +from onnx import ModelProto, ValueInfoProto from onnx_model import OnnxModel -from torch_onnx_export_helper import torch_onnx_export from transformers import WhisperConfig -from whisper_decoder import WhisperDecoderInit -from whisper_encoder import WhisperEncoder, WhisperEncoderInputs -from whisper_openai_helper import WhisperDecoderInitOpenai +from whisper_decoder import WhisperDecoder +from whisper_encoder import WhisperEncoder +from whisper_inputs import ( + convert_inputs_for_ort, + get_model_dynamic_axes, + get_sample_encoder_decoder_init_inputs, + group_past_key_values, +) from onnxruntime import InferenceSession @@ -26,205 +32,275 @@ class WhisperEncoderDecoderInit(torch.nn.Module): - """A combination of WhisperEncoder and WhisperDecoderInit.""" + """Whisper encoder component + first pass through Whisper decoder component to initialize KV caches""" - def __init__( - self, - encoder: torch.nn.Module, - decoder: torch.nn.Module, - config: WhisperConfig, - decoder_start_token_id: int | None = None, - model_impl: str = "hf", - model: torch.nn.Module = None, - ): + def __init__(self, config: WhisperConfig, model: torch.nn.Module, model_impl: str, no_beam_search_op: bool = False): super().__init__() self.config = config - self.whisper_encoder = WhisperEncoder(encoder, config, model_impl=model_impl) - self.whisper_decoder_init = WhisperDecoderInit(decoder, config, decoder_start_token_id) - if model is not None: - self.whisper_decoder_openai_init = WhisperDecoderInitOpenai(model, decoder) + self.device = model.device self.model_impl = model_impl + self.no_beam_search_op = no_beam_search_op + + self.encoder = WhisperEncoder(config, model, model_impl) + self.decoder = WhisperDecoder(config, model, model_impl, no_beam_search_op) + + self.max_source_positions = self.config.max_source_positions + self.num_heads = self.config.decoder_attention_heads + self.head_size = self.config.d_model // self.num_heads + + def hf_forward_for_beam_search_op(self, audio_features: torch.Tensor, decoder_input_ids: torch.Tensor): + encoder_hidden_states = self.encoder(audio_features) + logits, present_key_values = self.decoder(decoder_input_ids, encoder_hidden_states) + return logits, encoder_hidden_states, present_key_values + + def hf_forward_for_no_beam_search_op(self, audio_features: torch.Tensor): + encoder_hidden_states = self.encoder(audio_features) + + # Get cross attention KV caches and return them for this model + # We do this because these MatMuls are only run once before their outputs are being re-used in the decoder + present_cross_attention_key_value_caches = [] + for layer in self.decoder.decoder.layers: + cross_attn_key_cache = ( + layer.encoder_attn.k_proj(encoder_hidden_states) + .view(-1, self.max_source_positions, self.num_heads, self.head_size) + .transpose(1, 2) + ) + cross_attn_value_cache = ( + layer.encoder_attn.v_proj(encoder_hidden_states) + .view(-1, self.max_source_positions, self.num_heads, self.head_size) + .transpose(1, 2) + ) + present_cross_attention_key_value_caches.append(cross_attn_key_cache) + present_cross_attention_key_value_caches.append(cross_attn_value_cache) + + return encoder_hidden_states, present_cross_attention_key_value_caches + + def oai_forward_for_beam_search_op(self, audio_features: torch.Tensor, decoder_input_ids: torch.Tensor): + encoder_hidden_states = self.encoder(audio_features) + logits, present_key_values = self.decoder(decoder_input_ids, encoder_hidden_states) + return logits, encoder_hidden_states, present_key_values + + def oai_forward_for_no_beam_search_op(self, audio_features: torch.Tensor): + encoder_hidden_states = self.encoder(audio_features) + + # Get cross attention KV caches and return them for this model + # We do this because these MatMuls are only run once before their outputs are being re-used in the decoder + present_cross_attention_key_value_caches = [] + for block in self.decoder.model.decoder.blocks: + cross_attn_key_cache = ( + block.cross_attn.key(encoder_hidden_states) + .view(-1, self.max_source_positions, self.num_heads, self.head_size) + .transpose(1, 2) + ) + cross_attn_value_cache = ( + block.cross_attn.value(encoder_hidden_states) + .view(-1, self.max_source_positions, self.num_heads, self.head_size) + .transpose(1, 2) + ) + present_cross_attention_key_value_caches.append(cross_attn_key_cache) + present_cross_attention_key_value_caches.append(cross_attn_value_cache) - def forward( - self, - encoder_input_ids: torch.Tensor, - decoder_input_ids: torch.Tensor = None, - remove_hooks: bool = False, - ): - encoder_hidden_states: torch.FloatTensor = self.whisper_encoder(encoder_input_ids) - # Decoder out: (logits, past_key_values, encoder_hidden_state) + return encoder_hidden_states, present_cross_attention_key_value_caches + + def forward(self, audio_features: torch.Tensor, decoder_input_ids: torch.Tensor | None = None): if self.model_impl == "openai": - encoder_hidden_states.unsqueeze(0) - decinit_out, present = self.whisper_decoder_openai_init( - decoder_input_ids, encoder_hidden_states, remove_hooks=remove_hooks - ) - return decinit_out, encoder_hidden_states, present + if self.no_beam_search_op: + return self.oai_forward_for_no_beam_search_op(audio_features) + return self.oai_forward_for_beam_search_op(audio_features, decoder_input_ids) + + # Hugging Face implementation + if self.no_beam_search_op: + return self.hf_forward_for_no_beam_search_op(audio_features) + return self.hf_forward_for_beam_search_op(audio_features, decoder_input_ids) + + def input_names(self): + if self.no_beam_search_op: + input_names = ["audio_features"] + else: + input_names = ["encoder_input_ids", "decoder_input_ids"] + return input_names + + def output_names(self): + if self.no_beam_search_op: + output_names = [ + "encoder_hidden_states", + *list( + chain.from_iterable( + (f"present_key_cross_{i}", f"present_value_cross_{i}") + for i in range(self.config.num_hidden_layers) + ) + ), + ] else: - decinit_out = self.whisper_decoder_init(decoder_input_ids, encoder_hidden_states) - present_self, present_cross = PastKeyValuesHelper.group_by_self_and_cross(decinit_out[1]) - present = present_self + present_cross - return decinit_out[0], encoder_hidden_states, present - - -class WhisperEncoderDecoderInitInputs: - def __init__(self, encoder_input_ids, decoder_input_ids=None): - self.encoder_input_ids: torch.LongTensor = encoder_input_ids - self.decoder_input_ids: torch.LongTensor = decoder_input_ids - - @staticmethod - def create_dummy( - config: WhisperConfig, - batch_size: int, - encode_sequence_length: int, - use_decoder_input_ids: bool, - device: torch.device, - use_int32_inputs: bool = False, - ): # -> WhisperEncoderDecoderInitInputs: - encoder_inputs: WhisperEncoderInputs = WhisperEncoderInputs.create_dummy( - batch_size, - sequence_length=3000, - feature_size=config.num_mel_bins, - device=device, + output_names = [ + "logits", + "encoder_hidden_states", + *list( + chain.from_iterable( + ( + f"present_key_self_{i}", + f"present_value_self_{i}", + f"present_key_cross_{i}", + f"present_value_cross_{i}", + ) + for i in range(self.config.num_hidden_layers) + ) + ), + ] + return output_names + + def dynamic_axes(self, input_names, output_names): + dynamic_axes = get_model_dynamic_axes(self.config, input_names, output_names) + return dynamic_axes + + def inputs(self, use_fp16_inputs: bool, use_int32_inputs: bool, return_dict: bool = False): + inputs = get_sample_encoder_decoder_init_inputs( + self.config, + self.device, + batch_size=2, + decoder_sequence_length=6, + use_fp16=use_fp16_inputs, + use_int32=use_int32_inputs, + ) + if return_dict: + if self.no_beam_search_op: + del inputs["decoder_input_ids"] + return inputs + + if self.no_beam_search_op: + return (inputs["audio_features"],) + return ( + inputs["audio_features"], + inputs["decoder_input_ids"], ) - decoder_input_ids = None - if use_decoder_input_ids: - dtype = torch.int32 if use_int32_inputs else torch.int64 - decoder_input_ids = torch.ones((batch_size, 2), dtype=dtype, device=device) * config.decoder_start_token_id - - return WhisperEncoderDecoderInitInputs(encoder_inputs.input_ids, decoder_input_ids) - - def to_list(self) -> list: - input_list = [self.encoder_input_ids] - if self.decoder_input_ids is not None: - input_list.append(self.decoder_input_ids) - return input_list + def fix_key_value_cache_dims(self, output: ValueInfoProto, is_cross: bool = False): + # Shape should be (batch_size, num_heads, sequence_length, head_size) for self attention KV caches + # and (batch_size, num_heads, num_frames // 2, head_size) for cross attention KV caches + num_heads = output.type.tensor_type.shape.dim[1] + if "_dim_" in num_heads.dim_param: + num_heads.Clear() + num_heads.dim_value = self.num_heads + sequence_length = output.type.tensor_type.shape.dim[2] + if "_dim_" in sequence_length.dim_param: + sequence_length.Clear() + if is_cross: + sequence_length.dim_value = self.max_source_positions + else: + sequence_length.dim_param = "total_sequence_length" + head_size = output.type.tensor_type.shape.dim[3] + if "_dim_" in head_size.dim_param: + head_size.Clear() + head_size.dim_value = self.head_size + return output + + def fix_outputs(self, model: ModelProto): + # ONNX exporter might mark dimensions like 'Transposepresent_value_self_1_dim_2' in shape inference. + # We now change the dim_values to the correct one. + reordered_outputs = [] + self_attn_kv_caches = [] + cross_attn_kv_caches = [] + + for output in model.graph.output: + if "present" not in output.name: + reordered_outputs.append(output) + + elif "self" in output.name: + # Self attention KV caches + new_output = self.fix_key_value_cache_dims(output, is_cross=False) + if self.no_beam_search_op: + reordered_outputs.append(new_output) + else: + self_attn_kv_caches.append(new_output) + else: + # Cross attention KV caches + new_output = self.fix_key_value_cache_dims(output, is_cross=True) + if self.no_beam_search_op: + reordered_outputs.append(new_output) + else: + cross_attn_kv_caches.append(new_output) + + if not self.no_beam_search_op: + reordered_outputs += self_attn_kv_caches + cross_attn_kv_caches + + while len(model.graph.output) > 0: + model.graph.output.pop() + model.graph.output.extend(reordered_outputs) + return model + + def fix_layernorm_weights(self, model: ModelProto, use_fp16_inputs: bool): + if self.model_impl == "openai" and use_fp16_inputs: + # Cast ONNX model to float16 to ensure LayerNorm weights are converted from + # float32 to float16 since exported model already has float16 weights everywhere + # except for LayerNorm ops. This happens because OpenAI always upcasts to float32 + # when computing LayerNorm. + # + # Reference: + # https://github.com/openai/whisper/blob/90db0de1896c23cbfaf0c58bc2d30665f709f170/whisper/model.py#L41 + model = convert_float_to_float16(model) + return model -class WhisperEncoderDecoderInitHelper: - @staticmethod def export_onnx( - model: WhisperEncoderDecoderInit, - device: torch.device, + self, onnx_model_path: str, - use_decoder_input_ids: bool = True, + provider: str, verbose: bool = True, use_external_data_format: bool = False, - use_int32_inputs: bool = False, + use_fp16_inputs: bool = False, + use_int32_inputs: bool = True, ): - """Export decoder to ONNX + """Export encoder-decoder-init to ONNX Args: - model (WhisperEncoderDecoderInit): the model to export - device (torch.device): device of decoder object - onnx_model_path (str): onnx path + onnx_model_path (str): path to save ONNX model + provider (str): provider to use for verifying parity on ONNX model verbose (bool, optional): print verbose information. Defaults to True. use_external_data_format (bool, optional): use external data format or not. Defaults to False. + use_fp16_inputs (bool, optional): use float16 inputs for the audio_features. Defaults to False. + use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids. Defaults to True. """ - assert isinstance(model, WhisperEncoderDecoderInit) - - inputs = WhisperEncoderDecoderInitInputs.create_dummy( - model.config, - batch_size=2, - encode_sequence_length=3000, - use_decoder_input_ids=True, - device=device, - use_int32_inputs=use_int32_inputs, - ) - input_list = inputs.to_list() - - out = model(inputs.encoder_input_ids, inputs.decoder_input_ids, remove_hooks=True) - present = out[2] - present_names = PastKeyValuesHelper.get_input_names(present, encoder=True) - - output_names = ["logits", "encoder_hidden_states", *present_names] - - # Shape of input tensors (sequence_length==1): - # input_ids: (batch_size, sequence_length) - # encoder_hidden_states: (batch_size, encode_sequence_length, hidden_size) - # past_self_*: (batch_size, num_heads, past_decode_sequence_length, head_size) - # past_cross_*: (batch_size, num_heads, encode_sequence_length, head_size) - - # Shape of output tensors: + # Shape of encoder's tensors: + # Inputs: + # audio_features: (batch_size, num_mels, num_frames) + # Outputs: + # encoder_hidden_states: (batch_size, num_frames // 2, hidden_size) + + # Shape of decoder's tensors: + # Inputs: + # decoder_input_ids: (batch_size, sequence_length) + # encoder_hidden_states (comes from encoder's outputs): (batch_size, num_frames // 2, hidden_size) + # Outputs: # logits: (batch_size, sequence_length, vocab_size) - # past_self_*: (batch_size, num_heads, past_decode_sequence_length + sequence_length, head_size) - # past_cross_*: (batch_size, num_heads, encode_sequence_length, head_size) - - input_names = ["encoder_input_ids"] - - # ONNX exporter might mark dimension like 'Transposepresent_value_self_1_dim_2' in shape inference. - # We use a workaround here: first use dim_param "1" for sequence_length, and later change to dim_value. - sequence_length = "1" - num_heads = str(model.config.encoder_attention_heads) - hidden_size = str(model.config.d_model) - head_size = str(model.config.d_model // model.config.encoder_attention_heads) - dynamic_axes = { - "encoder_input_ids": {0: "batch_size", 1: "feature_size"}, - "encoder_hidden_states": { - 0: "batch_size", - 1: "encode_sequence_length", - 2: hidden_size, - }, - "logits": { - 0: "batch_size", - 1: "decode_sequence_length", - }, - } - - if use_decoder_input_ids: - input_names.append("decoder_input_ids") - dynamic_axes["decoder_input_ids"] = { - 0: "batch_size", - 1: "decode_sequence_length", - } - - for name in present_names: - if "cross" in name: - dynamic_axes[name] = { - 0: "batch_size", - 1: num_heads, - 2: "encode_sequence_length", - 3: head_size, - } - - else: # self attention past state - dynamic_axes[name] = { - 0: "batch_size", - 1: num_heads, - 2: "decode_sequence_length", - 3: head_size, - } + # present_{key/value}_self_* (present self attention KV caches): (batch_size, num_heads, past_sequence_length + sequence_length, head_size) + # present_{key/value}_cross_* (present cross attention KV caches): (batch_size, num_heads, num_frames // 2, head_size) + + inputs = self.inputs(use_fp16_inputs=use_fp16_inputs, use_int32_inputs=use_int32_inputs) + input_names = self.input_names() + output_names = self.output_names() + dynamic_axes = self.dynamic_axes(input_names, output_names) + Path(onnx_model_path).parent.mkdir(parents=True, exist_ok=True) with tempfile.TemporaryDirectory() as tmp_dir_name: temp_onnx_model_path = os.path.join(tmp_dir_name, "encoder_decoder_init.onnx") Path(temp_onnx_model_path).parent.mkdir(parents=True, exist_ok=True) - torch_onnx_export( - model, - args=tuple(input_list), - f=temp_onnx_model_path, + out_path = temp_onnx_model_path if use_external_data_format else onnx_model_path + + torch.onnx.export( + self, + args=inputs, + f=out_path, export_params=True, input_names=input_names, output_names=output_names, dynamic_axes=dynamic_axes, opset_version=17, do_constant_folding=True, - use_external_data_format=use_external_data_format, verbose=verbose, ) - # Workaround as mentioned earlier: change numeric dim_param to dim_value - model = onnx.load(temp_onnx_model_path) - for tensor in model.graph.output: - for dim_proto in tensor.type.tensor_type.shape.dim: - if dim_proto.HasField("dim_param") and dim_proto.dim_param in [ - sequence_length, - num_heads, - hidden_size, - head_size, - ]: - dim_value = int(dim_proto.dim_param) - dim_proto.Clear() - dim_proto.dim_value = dim_value - + model = onnx.load_model(out_path, load_external_data=use_external_data_format) + model = self.fix_outputs(model) + model = self.fix_layernorm_weights(model, use_fp16_inputs) OnnxModel.save( model, onnx_model_path, @@ -232,74 +308,64 @@ def export_onnx( all_tensors_to_one_file=True, ) - @staticmethod - def onnxruntime_inference(ort_session, inputs: WhisperEncoderDecoderInitInputs): - """Run inference of ONNX model.""" - logger.debug("start onnxruntime_inference") - - ort_inputs = { - "encoder_input_ids": numpy.ascontiguousarray(inputs.encoder_input_ids.cpu().numpy()), - } - if inputs.decoder_input_ids is not None: - ort_inputs["decoder_input_ids"] = numpy.ascontiguousarray(inputs.decoder_input_ids.cpu().numpy()) + self.verify_onnx(onnx_model_path, provider, use_fp16_inputs, use_int32_inputs) - ort_outputs = ort_session.run(None, ort_inputs) - return ort_outputs - - @staticmethod def verify_onnx( - model: WhisperEncoderDecoderInit, - ort_session: InferenceSession, - device: torch.device, + self, + onnx_model_path: str, + provider: str, + use_fp16_inputs: bool, use_int32_inputs: bool, - max_cases: int = 4, ): - """Compare the result from PyTorch and OnnxRuntime to verify the ONNX model is good.""" - ort_inputs = ort_session.get_inputs() - use_decoder_input_ids = len(ort_inputs) == 3 - - test_cases = [(4, 11), (1, 2), (3, 1), (8, 5)] - test_cases_max_diff = [] - for batch_size, encode_sequence_length in test_cases[:max_cases]: - inputs = WhisperEncoderDecoderInitInputs.create_dummy( - model.config, - batch_size, - encode_sequence_length, - use_decoder_input_ids=use_decoder_input_ids, - device=device, - use_int32_inputs=use_int32_inputs, - ) - - ort_outputs = WhisperEncoderDecoderInitHelper.onnxruntime_inference(ort_session, inputs) + """Verify ONNX model outputs and PyTorch model outputs match - # Run inference of PyTorch model - input_list = inputs.to_list() - torch_outputs = model(*input_list) - - assert torch_outputs[0].cpu().numpy().shape == ort_outputs[0].shape - max_diff = numpy.amax(numpy.abs(torch_outputs[0].cpu().numpy() - ort_outputs[0])) - logger.debug(f"logits max_diff={max_diff}") - max_diff_all = max_diff - - assert torch_outputs[1].cpu().numpy().shape == ort_outputs[1].shape - max_diff = numpy.amax(numpy.abs(torch_outputs[1].cpu().numpy() - ort_outputs[1])) - logger.debug(f"encoder_hidden_states max_diff={max_diff}") - max_diff_all = max(max_diff_all, max_diff) - - for i in range(2 * model.config.num_layers): - max_diff = numpy.amax(numpy.abs(torch_outputs[2][i].cpu().numpy() - ort_outputs[2 + i])) - logger.debug(f"self attention past state {i} max_diff={max_diff}") - - for i in range(2 * model.config.num_layers): - max_diff = numpy.amax( - numpy.abs(torch_outputs[3][i].cpu().numpy() - ort_outputs[2 + 2 * model.config.num_layers + i]) - ) - logger.debug(f"cross attention past state {i} max_diff={max_diff}") - max_diff_all = max(max_diff_all, max_diff) - - test_cases_max_diff.append(max_diff_all) - logger.info( - f"batch_size={batch_size} encode_sequence_length={encode_sequence_length}, max_diff={max_diff_all}" + Args: + onnx_model_path (str): path to save ONNX model + provider (str): execution provider for ONNX model + use_fp16_inputs (bool, optional): use float16 inputs for the audio_features + use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids + """ + # Shape of encoder's tensors: + # Inputs: + # audio_features: (batch_size, num_mels, num_frames) + # Outputs: + # encoder_hidden_states: (batch_size, num_frames // 2, hidden_size) + + # Shape of decoder's tensors: + # Inputs: + # decoder_input_ids: (batch_size, sequence_length) + # encoder_hidden_states (comes from encoder's outputs): (batch_size, num_frames // 2, hidden_size) + # Outputs: + # logits: (batch_size, sequence_length, vocab_size) + # present_{key/value}_self_* (present self attention KV caches): (batch_size, num_heads, past_sequence_length + sequence_length, head_size) + # present_{key/value}_cross_* (present cross attention KV caches): (batch_size, num_heads, num_frames // 2, head_size) + + inputs = self.inputs(use_fp16_inputs=use_fp16_inputs, use_int32_inputs=use_int32_inputs, return_dict=True) + + # Run PyTorch model + pt_outputs = [] + if self.no_beam_search_op: + out = self.forward(**inputs) + pt_outputs.append(out[0].detach().cpu().numpy()) + for present_cross_attn_cache in out[1]: + pt_outputs.append(present_cross_attn_cache.detach().cpu().numpy()) + else: + out = self.forward(**inputs) + pt_outputs.append(out[0].detach().cpu().numpy()) + pt_outputs.append(out[1].detach().cpu().numpy()) + + (self_attn_kv_caches, cross_attn_kv_caches) = group_past_key_values(out[2]) + pt_outputs.extend([self_attn_kv_cache.detach().cpu().numpy() for self_attn_kv_cache in self_attn_kv_caches]) + pt_outputs.extend( + [cross_attn_kv_cache.detach().cpu().numpy() for cross_attn_kv_cache in cross_attn_kv_caches] ) - return max(test_cases_max_diff) + # Run ONNX model + sess = InferenceSession(onnx_model_path, providers=[provider]) + ort_outputs = sess.run(None, convert_inputs_for_ort(inputs, sess)) + + # Calculate output difference + for i, output_name in enumerate(self.output_names()): + diff = np.abs(pt_outputs[i] - ort_outputs[i]) + logger.warning(f"Comparing {output_name}...") + logger.warning(f"Max diff: {np.max(diff)}") diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_helper.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_helper.py index e1206a30871d1..3cb6c23848f13 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/whisper_helper.py +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_helper.py @@ -10,15 +10,13 @@ import numpy as np import torch -from float16 import float_to_float16_max_diff -from onnx_model import OnnxModel +from convert_generation import add_cache_indirection_to_mha, add_output_qk_to_mha, fix_past_sequence_length from optimizer import optimize_model -from packaging import version from transformers import WhisperConfig, WhisperForConditionalGeneration, WhisperProcessor -from transformers import __version__ as transformers_version -from whisper_decoder import WhisperDecoder, WhisperDecoderHelper, WhisperDecoderInit -from whisper_encoder import WhisperEncoder, WhisperEncoderHelper -from whisper_encoder_decoder_init import WhisperEncoderDecoderInit, WhisperEncoderDecoderInitHelper +from whisper_decoder import WhisperDecoder +from whisper_encoder import WhisperEncoder +from whisper_encoder_decoder_init import WhisperEncoderDecoderInit +from whisper_jump_times import WhisperJumpTimes from onnxruntime import InferenceSession @@ -36,6 +34,7 @@ "whisper-large", "whisper-large-v2", "whisper-large-v3", + "whisper-large-v3-turbo", ] @@ -54,7 +53,6 @@ def get_onnx_path( model_name_or_path (str): pretrained model name, or path to the model checkpoint suffix (str, optional): suffix like "_encoder" or "_decoder_fp16" will be appended to file name. Defaults to None. new_folder (bool, optional): create a new directory for the model. Defaults to False. - Returns: str: path of onnx model """ @@ -69,205 +67,132 @@ def get_onnx_path( directory = os.path.join(output_dir, model_name) if new_folder else output_dir return os.path.join(directory, model_name + ".onnx") - @staticmethod - def load_model_openai( - model_name_or_path: str, - cache_dir: str, - device: torch.device, - ) -> torch.nn.Module: - """Load model given a pretrained name or path, then build models for ONNX conversion. - - Args: - model_name_or_path (str): pretrained model name or path - cache_dir (str): cache directory - device (torch.device): device to run the model - merge_encoder_and_decoder_init (bool, optional): Whether merge encoder and decoder initialization into one ONNX model. Defaults to True. - Returns: - Dict[str, torch.nn.Module]: mapping from name to modules for ONNX conversion. - """ - from whisper import _ALIGNMENT_HEADS, _MODELS, _download - from whisper.model import ModelDimensions, Whisper - - in_memory = False - - model_name = model_name_or_path.split("/")[-1][8:] - checkpoint_file, alignment_heads = None, None - if model_name in _MODELS: - checkpoint_file = _download(_MODELS[model_name], cache_dir, in_memory) - alignment_heads = _ALIGNMENT_HEADS[model_name] - - with open(checkpoint_file, "rb") as fp: - checkpoint = torch.load(fp, map_location=device) - del checkpoint_file - - dims = ModelDimensions(**checkpoint["dims"]) - model = Whisper(dims) - model.load_state_dict(checkpoint["model_state_dict"]) - - if alignment_heads is not None: - model.set_alignment_heads(alignment_heads) - return model.to(device) - @staticmethod def load_model( model_name_or_path: str, model_impl: str, cache_dir: str, device: torch.device, + dtype: torch.dtype, merge_encoder_and_decoder_init: bool = True, + no_beam_search_op: bool = False, + output_qk: bool = False, ) -> dict[str, torch.nn.Module]: """Load model given a pretrained name or path, then build models for ONNX conversion. Args: model_name_or_path (str): pretrained model name or path + model_impl (str): library to load model from cache_dir (str): cache directory device (torch.device): device to run the model + dtype (torch.dtype): dtype to run the model merge_encoder_and_decoder_init (bool, optional): Whether merge encoder and decoder initialization into one ONNX model. Defaults to True. + no_beam_search_op (bool, optional): Whether to use beam search op or not. Defaults to False. + output_qk (bool, optional): Whether to output QKs to calculate batched jump times for word-level timestamps. Defaults to False. Returns: Dict[str, torch.nn.Module]: mapping from name to modules for ONNX conversion. """ - extra_kwargs = {} - if version.parse(transformers_version) >= version.parse("4.36.0"): - extra_kwargs["attn_implementation"] = "eager" - model = WhisperForConditionalGeneration.from_pretrained(model_name_or_path, cache_dir=cache_dir, **extra_kwargs) - - if model_impl == "openai": - openai_model = WhisperHelper.load_model_openai(model_name_or_path, cache_dir, device) - model_encoder, model_decoder = openai_model.encoder, openai_model.decoder - passed_model = openai_model + # Load PyTorch model + if model_impl == "hf": + # Load from Hugging Face + model = WhisperForConditionalGeneration.from_pretrained( + model_name_or_path, cache_dir=cache_dir, attn_implementation="eager" + ) else: - model_encoder, model_decoder = model, model - passed_model = None + # Load from OpenAI + import whisper - decoder = WhisperDecoder(model_decoder, model.config, model_impl=model_impl, model=passed_model) - decoder.eval().to(device) + if not os.path.exists(model_name_or_path): + name_or_path = model_name_or_path.split("/")[-1][8:] + else: + name_or_path = model_name_or_path + model = whisper.load_model(name_or_path, device, download_root=cache_dir, in_memory=True) + + # Set PyTorch model properties + model.eval().to(device=device) + if model_impl == "hf": + model.to(dtype=dtype) + config = WhisperConfig.from_pretrained(model_name_or_path, cache_dir=cache_dir) + # Load each component of PyTorch model + decoder = WhisperDecoder(config, model, model_impl, no_beam_search_op).eval() + components = {"decoder": decoder} if merge_encoder_and_decoder_init: - encoder_decoder_init = WhisperEncoderDecoderInit( - model_encoder, - model_decoder, - model.config, - decoder_start_token_id=None, - model_impl=model_impl, - model=passed_model, - ) - return {"encoder_decoder_init": encoder_decoder_init, "decoder": decoder} + encoder_decoder_init = WhisperEncoderDecoderInit(config, model, model_impl, no_beam_search_op).eval() + components.update({"encoder": encoder_decoder_init}) else: - encoder = WhisperEncoder(model.model.encoder, model.config) - encoder.eval().to(device) - decoder_init = WhisperDecoderInit(model.decoder, model.config) - decoder_init.eval().to(device) - return { - "encoder": encoder, - "decoder": decoder, - "decoder_init": decoder_init, - } + encoder = WhisperEncoder(config, model, model_impl).eval() + components.update({"encoder": encoder, "decoder_init": decoder}) + + if output_qk: + batched_jump_times = WhisperJumpTimes(config, device, cache_dir).eval() + components.update({"jump_times": batched_jump_times}) + return components @staticmethod def export_onnx( - model: WhisperEncoder | WhisperDecoder | WhisperDecoderInit | WhisperEncoderDecoderInit, - device: torch.device, + model: WhisperEncoder | WhisperEncoderDecoderInit | WhisperDecoder, onnx_model_path: str, - verbose: bool = True, - use_external_data_format: bool = False, - use_decoder_input_ids: bool = True, - use_int32_inputs: bool = False, + provider: str, + verbose: bool, + use_external_data_format: bool, + use_fp16_inputs: bool, + use_int32_inputs: bool, + use_encoder_hidden_states: bool, + use_kv_cache_inputs: bool, ): + """Export model component to ONNX + + Args: + model (class): PyTorch class to export + onnx_model_path (str): path to save ONNX model + provider (str): provider to use for verifying parity on ONNX model + verbose (bool): print verbose information. + use_external_data_format (bool): use external data format or not. + use_fp16_inputs (bool): use float16 inputs for the audio_features, encoder_hidden_states, logits, and KV caches. + use_int32_inputs (bool): use int32 inputs for the decoder_input_ids. + use_encoder_hidden_states (bool): use encoder_hidden_states as model input for decoder-init/decoder-without-past models. + use_kv_cache_inputs (bool): use KV caches as model inputs for decoder-with-past models. + """ if isinstance(model, WhisperEncoder): - WhisperEncoderHelper.export_onnx( - model, - device, + model.export_onnx( onnx_model_path, + provider, verbose, use_external_data_format, + use_fp16_inputs, ) elif isinstance(model, WhisperEncoderDecoderInit): - WhisperEncoderDecoderInitHelper.export_onnx( - model, - device, + model.export_onnx( onnx_model_path, - use_decoder_input_ids, + provider, verbose, use_external_data_format, + use_fp16_inputs, use_int32_inputs, ) - else: - WhisperDecoderHelper.export_onnx( - model, - device, + elif isinstance(model, WhisperDecoder): + model.export_onnx( onnx_model_path, + provider, verbose, use_external_data_format, + use_fp16_inputs, + use_int32_inputs, + use_encoder_hidden_states, + use_kv_cache_inputs, + ) + elif isinstance(model, WhisperJumpTimes): + model.export_onnx( + onnx_model_path, + provider, + verbose, + use_external_data_format, + use_fp16_inputs, use_int32_inputs, ) - - @staticmethod - def auto_mixed_precision( - onnx_model: OnnxModel, - op_block_list: tuple[str] = ( - "SimplifiedLayerNormalization", - "SkipSimplifiedLayerNormalization", - "Relu", - "Add", - ), - ): - """Convert model to mixed precision. - It detects whether original model has fp16 precision weights, and set parameters for float16 conversion automatically. - Args: - onnx_model (OnnxModel): optimized ONNX model - op_block_list (List[str], optional): . Defaults to ["SimplifiedLayerNormalization", "SkipSimplifiedLayerNormalization", "Relu", "Add"] - Returns: - parameters(dict): a dictionary of parameters used in float16 conversion - """ - op_full_set = {node.op_type for node in onnx_model.nodes()} - fp32_op_set = set(op_block_list) - fp16_op_set = op_full_set.difference(fp32_op_set) - logger.info(f"fp32 op: {fp32_op_set} fp16 op: {fp16_op_set}") - - # logits is the first output - logits_output_name = onnx_model.graph().output[0].name - - # We use the weight in last MatMul node to detect whether the model is stored with float16 weights from training. - is_weight_fp16_precision = False - output_name_to_node = onnx_model.output_name_to_node() - assert logits_output_name in output_name_to_node - node = output_name_to_node[logits_output_name] - last_matmul_node = None - if node.op_type == "MatMul": - last_matmul_node = node - logger.info(f"Found last MatMul node for logits: {node.name}") - initializer = None - for input in node.input: - initializer = onnx_model.get_initializer(input) - if initializer is not None: - break - - # when the max difference of value after converting float to float16 is lower than a threshold (1e-6), - # we can deduce that the weights are stored in float16 precision. - max_diff = float_to_float16_max_diff(initializer) - logger.debug(f"max diff of converting weights in last MatMul node {node.name}: {max_diff}") - is_weight_fp16_precision = max_diff < 1e-6 else: - logger.warning(f"Failed to find MatMul node for logits. Found {node.op_type} of node {node.name}") - - keep_io_types = [] - node_block_list = [] - if (not is_weight_fp16_precision) and (last_matmul_node is not None): - # When original weight is float32 precision, keep logits and last MatMul in float32 could get better precision. - keep_io_types = [logits_output_name] - node_block_list = [last_matmul_node.name] - - parameters = { - "keep_io_types": keep_io_types, - "op_block_list": list(op_block_list), - "node_block_list": node_block_list, - "force_fp16_initializers": is_weight_fp16_precision, - } - - logger.info(f"auto_mixed_precision parameters: {parameters}") - onnx_model.convert_float_to_float16(use_symbolic_shape_infer=True, **parameters) - - return parameters + raise ValueError(f"Unknown instance for model detected: {type(model)}") @staticmethod def optimize_onnx( @@ -276,10 +201,13 @@ def optimize_onnx( is_float16: bool, num_attention_heads: int, hidden_size: int, + num_layers: int, use_external_data_format: bool = False, - auto_mixed_precision: bool = True, use_gpu: bool = False, provider: str = "cpu", + is_decoder: bool = False, + no_beam_search_op: bool = False, + output_qk: bool = False, ): """Optimize ONNX model with an option to convert it to use mixed precision.""" @@ -294,17 +222,23 @@ def optimize_onnx( model_type="bart", num_heads=num_attention_heads, hidden_size=hidden_size, - opt_level=2 if not use_external_data_format else None, + opt_level=0, optimization_options=optimization_options, use_gpu=use_gpu, only_onnxruntime=False, ) - if is_float16: - if auto_mixed_precision: - WhisperHelper.auto_mixed_precision(m) - else: - m.convert_model_float32_to_float16(cast_input_output=False) + # Add `past_sequence_length`, `cache_indirection`, and `output_qk` to `MultiHeadAttention` ops + if is_decoder and no_beam_search_op: + if provider == "cuda": # FP32 CPU can be supported here once the DMMHA CPU kernel bugs are fixed + # FP16 CUDA, FP32 CUDA, and FP32 CPU use the `DecoderMaskedMultiHeadAttention` kernel + # via `MultiHeadAttention`, which requires the `past_sequence_length` and + # `cache_indirection` inputs + m, past_seq_len_name = fix_past_sequence_length(m) + m = add_cache_indirection_to_mha(m, past_seq_len_name) + + if output_qk: + m = add_output_qk_to_mha(m, skip_node_idxs=list(range(0, 2 * num_layers, 2))) m.save_model_to_file(optimized_model_path, use_external_data_format, all_tensors_to_one_file=True) @@ -362,7 +296,7 @@ def pt_transcription_for_verify_onnx( # https://huggingface.co/docs/transformers/model_doc/whisper#transformers.WhisperForConditionalGeneration.generate.prompt_ids # prompt_ids input requires a tensor of rank 1 for i in range(batch_size): - inputs["prompt_ids"] = torch.from_numpy(prompt_ids[i]) + inputs["prompt_ids"] = torch.from_numpy(prompt_ids[i]).to(device=device) inputs["input_features"] = input_features_[i].to(device) pt_output = pt_model.generate(**inputs).detach().cpu().numpy() pt_outputs.append(pt_output) @@ -411,6 +345,33 @@ def select_transcription_options( } return expected_transcription_options + @staticmethod + def get_outputs( + pt_outputs: np.ndarray, + ort_outputs: np.ndarray, + i: int, + ): + """Get PyTorch and ONNX Runtime output token ids at index i""" + pt_output, ort_output = pt_outputs[i], ort_outputs[i] + pt_shape, ort_shape = pt_output.shape, ort_output.shape + + # Hugging Face impl. + Beam Search op: PyTorch = (26,) and ORT = (30,) + # OpenAI impl. + Beam Search op: PyTorch = (1, 30) and ORT = (30,) + if pt_shape != ort_shape: + if len(pt_shape) > 1: + pt_output = pt_output[0] + pt_shape = pt_output.shape + if len(ort_shape) > 1: + ort_output = ort_output[0] + ort_shape = ort_output.shape + if pt_shape[0] != ort_shape[0]: + min_len = min(pt_shape[0], ort_shape[0]) + pt_output = pt_output[:min_len] + ort_output = ort_output[:min_len] + + assert pt_output.shape == ort_output.shape + return pt_output, ort_output + @staticmethod def verify_onnx( model_name_or_path: str, @@ -421,11 +382,8 @@ def verify_onnx( prompt_mode: bool = False, ): """Compare the result from PyTorch and ONNX Runtime to verify the ONNX model is good.""" - extra_kwargs = {} - if version.parse(transformers_version) >= version.parse("4.36.0"): - extra_kwargs["attn_implementation"] = "eager" pt_model = WhisperForConditionalGeneration.from_pretrained( - model_name_or_path, cache_dir=cache_dir, **extra_kwargs + model_name_or_path, cache_dir=cache_dir, attn_implementation="eager" ).to(device) processor = WhisperProcessor.from_pretrained(model_name_or_path, cache_dir=cache_dir) config = WhisperConfig.from_pretrained(model_name_or_path, cache_dir=cache_dir) @@ -491,12 +449,19 @@ def verify_onnx( inputs[name] = np.array([1.0], dtype=ort_to_np[dtype]) else: inputs[name] = np.array([inputs[name]], dtype=ort_to_np[dtype]) + ort_outputs = ort_session.run(None, inputs)[0][:, 0, :] ort_transcription = processor.batch_decode(ort_outputs, skip_special_tokens=True) expected_transcription_options = WhisperHelper.select_transcription_options(batch_size, prompt_mode) parity = 1 for i in range(batch_size): + pt_output, ort_output = WhisperHelper.get_outputs(pt_outputs, ort_outputs, i) + + # Check if token ids match + parity *= np.allclose(pt_output, ort_output) + + # Check if transcribed outputs match parity *= ( pt_transcription[i] in expected_transcription_options and ort_transcription[i] in expected_transcription_options @@ -505,10 +470,9 @@ def verify_onnx( if not parity: for i in range(batch_size): - if pt_outputs[i].shape != ort_outputs[i].shape: - diff = pt_outputs[i] - ort_outputs[i][:, : len(pt_outputs[i])] - else: - diff = pt_outputs[i] - ort_outputs[i] + pt_output, ort_output = WhisperHelper.get_outputs(pt_outputs, ort_outputs, i) + diff = pt_output - ort_output + max_diff_i = max(diff.min(), diff.max(), key=abs) max_diff = max(max_diff, max_diff_i) @@ -516,4 +480,4 @@ def verify_onnx( logger.warning(f"PyTorch outputs: {pt_transcription}") logger.warning(f"ONNX Runtime outputs: {ort_transcription}") - return max_diff + return 0 diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_inputs.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_inputs.py new file mode 100644 index 0000000000000..0b0882eface72 --- /dev/null +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_inputs.py @@ -0,0 +1,380 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import logging + +import numpy as np +import torch +from transformers import WhisperConfig + +from onnxruntime import InferenceSession + +logger = logging.getLogger(__name__) + + +# Create audio_features for encoder +# Shape is (batch_size, feature_size, sequence_length) = (batch_size, num_mel_filters, num_frames) +# where num_mel_filters is a model attribute and num_frames = (chunk_length * sample_rate) // hop_length. +# +# Hard-coded audio hyperparameters: +# SAMPLE_RATE = 16000 +# N_FFT = 400 +# HOP_LENGTH = 160 +# CHUNK_LENGTH = 30 (i.e. 30-second chunk of audio) +# N_SAMPLES = CHUNK_LENGTH * SAMPLE_RATE = 30 * 16000 = 480000 (i.e. 480,000 samples in a 30-second chunk of audio) +# N_FRAMES = N_SAMPLES // HOP_LENGTH = 480000 // 160 = 3000 (i.e. 3000 frames in a mel spectrogram input) +# +# N_SAMPLES_PER_TOKEN = HOP_LENGTH * 2 = 160 * 2 = 320 +# FRAMES_PER_TOKEN = SAMPLE_RATE // HOP_LENGTH = 16000 // 160 = 100 (i.e. 10 ms per audio frame) +# TOKENS_PER_SECOND = SAMPLE_RATE // N_SAMPLES_PER_TOKEN = 16000 // 320 = 50 (i.e. 20 ms per audio token) +def get_sample_audio_features( + config: WhisperConfig, + device: torch.device, + batch_size: int, + sequence_length: int = 3000, + use_fp16: bool = False, +): + torch_dtype = torch.float16 if use_fp16 else torch.float32 + audio_features = torch.randn(batch_size, config.num_mel_bins, sequence_length, device=device, dtype=torch_dtype) + return audio_features + + +# Create input_ids for decoder +# Shape is (batch_size, sequence_length) where sequence_length is the initial decoder sequence length +def get_sample_decoder_input_ids( + config: WhisperConfig, + device: torch.device, + batch_size: int, + sequence_length: int, + use_int32: bool = True, +): + torch_dtype = torch.int32 if use_int32 else torch.int64 + decoder_input_ids = torch.randint( + low=0, high=config.vocab_size, size=(batch_size, sequence_length), device=device, dtype=torch_dtype + ) + return decoder_input_ids + + +# Create encoder_hidden_states for decoder-init +# Shape is (batch_size, num_frames // 2, hidden_size) +def get_sample_encoder_hidden_states( + config: WhisperConfig, + device: torch.device, + batch_size: int, + use_fp16: bool = False, +): + torch_dtype = torch.float16 if use_fp16 else torch.float32 + encoder_hidden_states = torch.randn( + batch_size, config.max_source_positions, config.d_model, device=device, dtype=torch_dtype + ) + return encoder_hidden_states + + +# Create past_key_values +# Self-attention KV caches are of shape (batch_size, num_heads, past_sequence_length, head_size) +# Cross-attention KV caches are of shape (batch_size, num_heads, num_frames // 2, head_size) +def get_sample_past_key_values( + config: WhisperConfig, + device: torch.device, + batch_size: int, + past_seq_len: int, + use_fp16: bool = False, +): + num_heads = config.decoder_attention_heads + head_size = config.d_model // num_heads + max_source_positions = ( + config.max_source_positions + ) # equal to num_frames // 2 = encoder's sequence_length // 2 = 3000 // 2 = 1500 + torch_dtype = torch.float16 if use_fp16 else torch.float32 + self_attention_kv_caches = [ + ( + torch.rand(batch_size, num_heads, past_seq_len, head_size, device=device, dtype=torch_dtype), + torch.rand(batch_size, num_heads, past_seq_len, head_size, device=device, dtype=torch_dtype), + ) + for _ in range(config.num_hidden_layers) + ] + cross_attention_kv_caches = [ + ( + torch.rand(batch_size, num_heads, max_source_positions, head_size, device=device, dtype=torch_dtype), + torch.rand(batch_size, num_heads, max_source_positions, head_size, device=device, dtype=torch_dtype), + ) + for _ in range(config.num_hidden_layers) + ] + return flatten_past_key_values(self_attention_kv_caches, cross_attention_kv_caches) + + +# Flatten KV caches into pairs-of-4 where each pair is defined as: +# (self_attn_key_cache, self_attn_value_cache, cross_attn_key_cache, cross_attn_value_cache) +def flatten_past_key_values( + self_attn_kv_caches: list[tuple[torch.Tensor, torch.Tensor]], + cross_attn_kv_caches: list[tuple[torch.Tensor, torch.Tensor]], +): + past_key_values = [] + for (self_k_cache, self_v_cache), (cross_k_cache, cross_v_cache) in zip( + self_attn_kv_caches, cross_attn_kv_caches, strict=False + ): + layer_kv_caches = (self_k_cache, self_v_cache, cross_k_cache, cross_v_cache) + past_key_values.append(layer_kv_caches) + return past_key_values + + +# Group KV caches into two 1D lists where one list contains the self attention KV caches and +# one list contains the cross attention KV caches +def group_past_key_values( + kv_caches: list[tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]], +): + self_attn_kv_caches, cross_attn_kv_caches = [], [] + for self_k_cache, self_v_cache, cross_k_cache, cross_v_cache in kv_caches: + self_attn_kv_caches.append(self_k_cache) + self_attn_kv_caches.append(self_v_cache) + cross_attn_kv_caches.append(cross_k_cache) + cross_attn_kv_caches.append(cross_v_cache) + return self_attn_kv_caches, cross_attn_kv_caches + + +# Create alignment heads for timestamps +# Shape is (num_alignment_heads, 2) +def get_sample_alignment_heads( + config: WhisperConfig, + device: torch.device, + num_alignment_heads: int = 6, + use_int32: bool = True, +): + torch_dtype = torch.int32 if use_int32 else torch.int64 + alignment_heads = torch.ones((num_alignment_heads, 2), device=device, dtype=torch_dtype) + return alignment_heads + + +# Create length of start-of-transcription sequence for timestamps +# Shape is (1) +def get_sample_sot_sequence_length( + device: torch.device, + sot_sequence_length: int, + use_int32: bool = False, +): + torch_dtype = torch.int32 if use_int32 else torch.int64 + sot_length = torch.tensor([sot_sequence_length], device=device, dtype=torch_dtype) + return sot_length + + +# Create segment length for timestamps +# Shape is (1) +def get_sample_segment_length( + device: torch.device, + segment_length: int, + use_int32: bool = False, +): + torch_dtype = torch.int32 if use_int32 else torch.int64 + segment_size = torch.tensor([segment_length], device=device, dtype=torch_dtype) + return segment_size + + +# Create QKs for timestamps +# Shape is (batch_size, num_heads, sequence_length, num_frames // 2) +def get_sample_QKs( # noqa: N802 + config: WhisperConfig, + device: torch.device, + batch_size: int, + sequence_length: int, + use_fp16: bool = False, +): + num_heads = config.decoder_attention_heads + torch_dtype = torch.float16 if use_fp16 else torch.float32 + QKs = [ # noqa: N806 + torch.rand( + batch_size, num_heads, sequence_length, config.max_source_positions, device=device, dtype=torch_dtype + ) + for _ in range(config.num_hidden_layers) + ] + return QKs + + +# Create inputs for encoder component of Whisper +def get_sample_encoder_inputs( + config: WhisperConfig, + device: torch.device, + batch_size: int, + sequence_length: int = 3000, + use_fp16: bool = False, +): + audio_features = get_sample_audio_features(config, device, batch_size, sequence_length, use_fp16) + return {"audio_features": audio_features} + + +# Create inputs for encoder component + first pass through decoder component of Whisper +def get_sample_encoder_decoder_init_inputs( + config: WhisperConfig, + device: torch.device, + batch_size: int, + decoder_sequence_length: int, + encoder_sequence_length: int = 3000, + use_fp16: bool = False, + use_int32: bool = True, +): + audio_features = get_sample_audio_features(config, device, batch_size, encoder_sequence_length, use_fp16) + decoder_input_ids = get_sample_decoder_input_ids(config, device, batch_size, decoder_sequence_length, use_int32) + return {"audio_features": audio_features, "decoder_input_ids": decoder_input_ids} + + +# Create inputs for decoder component of Whisper +# Inputs for first pass through the decoder (i.e. decoder-init): decoder_input_ids, encoder_hidden_states +# Inputs for subsequent passes through the decoder (i.e. decoder-with-past): decoder_input_ids, past_key_values +def get_sample_decoder_inputs( + config: WhisperConfig, + device: torch.device, + batch_size: int, + past_sequence_length: int, + sequence_length: int, + use_fp16: bool = False, + use_int32: bool = True, +): + decoder_input_ids = get_sample_decoder_input_ids(config, device, batch_size, sequence_length, use_int32) + encoder_hidden_states = get_sample_encoder_hidden_states(config, device, batch_size, use_fp16) + past_key_values = get_sample_past_key_values(config, device, batch_size, past_sequence_length, use_fp16) + return { + "decoder_input_ids": decoder_input_ids, + "encoder_hidden_states": encoder_hidden_states, + "past_key_values": past_key_values, + } + + +# Create inputs for timestamps component of Whisper +def get_sample_jump_times_inputs( + config: WhisperConfig, + device: torch.device, + batch_size: int, + sequence_length: int, + num_alignment_heads: int, + sot_sequence_length: int, + segment_length: int, + use_fp16: bool = False, + use_int32: bool = True, +): + alignment_heads = get_sample_alignment_heads(config, device, num_alignment_heads, use_int32) + # lengths need to be int64 because subsequent 'Slice' ops only take int64 inputs + sot_sequence_length = get_sample_sot_sequence_length(device, sot_sequence_length) + segment_length = get_sample_segment_length(device, segment_length) + QKs = get_sample_QKs(config, device, batch_size, sequence_length, use_fp16) # noqa: N806 + return { + "alignment_heads": alignment_heads, + "sot_sequence_length": sot_sequence_length, + "segment_length": segment_length, + "QKs": QKs, + } + + +# Convert PyTorch inputs to ONNX Runtime inputs +def convert_inputs_for_ort( + inputs: dict, + model: InferenceSession, +): + self_attn_kv_caches, cross_attn_kv_caches = None, None + batch_size, num_heads, past_seq_len, head_size = 0, 0, 0, 0 + num_beams, max_seq_len = 1, 448 + if "past_key_values" in inputs: + (self_attn_kv_caches, cross_attn_kv_caches) = group_past_key_values(inputs["past_key_values"]) + batch_size, num_heads, past_seq_len, head_size = self_attn_kv_caches[0].shape + + ort_inputs = {} + model_inputs = list(map(lambda i: i.name, model.get_inputs())) # noqa: C417 + use_buffer_sharing = "cache_indirection" in model_inputs + for name in model_inputs: + if name in {"audio_features", "encoder_input_ids"}: + # Encoder input + ort_inputs[name] = inputs["audio_features"].detach().cpu().numpy() + elif name == "encoder_hidden_states": + # Encoder output + ort_inputs[name] = inputs["encoder_hidden_states"].detach().cpu().numpy() + elif name in {"decoder_input_ids", "input_ids"}: + # Decoder input + ort_inputs[name] = inputs["decoder_input_ids"].detach().cpu().numpy() + elif "past_key_self" in name or "past_value_self" in name: + # Decoder input + orig_kv_cache = self_attn_kv_caches.pop(0).detach().cpu().numpy() + if use_buffer_sharing: + new_kv_cache = np.zeros((batch_size, num_heads, max_seq_len, head_size), dtype=orig_kv_cache.dtype) + new_kv_cache[:batch_size, :num_heads, :past_seq_len, :head_size] = orig_kv_cache + ort_inputs[name] = new_kv_cache + else: + ort_inputs[name] = orig_kv_cache + elif "past_key_cross" in name or "past_value_cross" in name: + # Decoder input + orig_kv_cache = cross_attn_kv_caches.pop(0).detach().cpu().numpy() + ort_inputs[name] = orig_kv_cache + elif name == "past_sequence_length": + # Decoder input + ort_inputs[name] = np.array([past_seq_len], dtype=np.int32) + elif name == "cache_indirection": + # Decoder input + ort_inputs[name] = np.zeros((batch_size, num_beams, max_seq_len), dtype=np.int32) + elif name == "alignment_heads": + # Jump times input + ort_inputs[name] = inputs["alignment_heads"].detach().cpu().numpy() + elif name == "sot_sequence_length": + # Jump times input + ort_inputs[name] = inputs["sot_sequence_length"].detach().cpu().numpy() + elif name == "segment_length": + # Jump times input + ort_inputs[name] = inputs["segment_length"].detach().cpu().numpy() + elif "cross_qk" in name: + # Jump times input + ort_inputs[name] = inputs["QKs"].pop(0).detach().cpu().numpy() + else: + raise ValueError(f"Unknown name not recognized: {name}") + + return ort_inputs + + +# Get dynamic axes for all inputs and outputs to the model +def get_model_dynamic_axes( + config: WhisperConfig, + input_names: list[str], + output_names: list[str], +): + dynamic_axes = {} + for name in input_names + output_names: + if name in {"audio_features", "encoder_input_ids"}: + # shape is (batch_size, num_mels, num_frames) + dynamic_axes[name] = {0: "batch_size"} + elif name in {"input_ids", "decoder_input_ids"}: + # shape is (batch_size, sequence_length) + dynamic_axes[name] = {0: "batch_size", 1: "sequence_length"} + elif name == "alignment_heads": + # shape is (num_alignment_heads, 2) + dynamic_axes[name] = {0: "num_alignment_heads"} + elif name in {"sot_sequence_length", "segment_length"}: + # shape is (1) + pass + elif name == "logits": + # shape is (batch_size, sequence_length, vocab_size) + dynamic_axes[name] = {0: "batch_size", 1: "sequence_length"} + elif name == "encoder_hidden_states": + # shape is (batch_size, num_frames // 2, hidden_size) + dynamic_axes[name] = {0: "batch_size"} + elif "past_key_self" in name or "past_value_self" in name: + # shape is (batch_size, num_heads, past_sequence_length, head_size) + dynamic_axes[name] = {0: "batch_size", 2: "past_sequence_length"} + elif "present_key_self" in name or "present_value_self" in name: + # shape is (batch_size, num_heads, past_sequence_length + sequence_length, head_size), + # which is equal to (batch_size, num_heads, total_sequence_length, head_size) + dynamic_axes[name] = {0: "batch_size", 2: "total_sequence_length"} + elif ( + "past_key_cross" in name + or "past_value_cross" in name + or "present_key_cross" in name + or "present_value_cross" in name + ): + # shape is (batch_size, num_heads, num_frames // 2, head_size) + dynamic_axes[name] = {0: "batch_size"} + elif "cross_qk" in name: + # shape is (batch_size, num_heads, source_sequence_length, target_sequence_length) + dynamic_axes[name] = {0: "batch_size", 2: "sequence_length"} + elif "jump_times" in name: + # shape is (batch_size, max_length) + dynamic_axes[name] = {0: "batch_size", 1: "max_length"} + else: + raise Exception(f"Unknown input or output name found: {name}") + return dynamic_axes diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_jump_times.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_jump_times.py new file mode 100644 index 0000000000000..4765616ec2b6f --- /dev/null +++ b/onnxruntime/python/tools/transformers/models/whisper/whisper_jump_times.py @@ -0,0 +1,477 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import logging +import os +import tempfile +import textwrap +from pathlib import Path + +import numpy as np +import onnx +import torch +import torch.nn.functional as F +import torch.utils.cpp_extension +from onnx_model import OnnxModel +from transformers import WhisperConfig +from whisper_inputs import convert_inputs_for_ort, get_model_dynamic_axes, get_sample_jump_times_inputs + +from onnxruntime import InferenceSession +from onnxruntime.tools import pytorch_export_contrib_ops + +logger = logging.getLogger(__name__) + +################################################## +# Functions that have to be outside of the class +# for torch.jit.script_if_tracing to work +################################################## + + +@torch.jit.script_if_tracing +def index_QKs(alignment_heads: torch.Tensor, QKs: list[torch.Tensor]): # noqa: N802 + """ + Compute the following to get stacked QK tensor that has been indexed for the desired attention heads: + weights = torch.stack([QKs[_l][:, _h] for _l, _h in alignment_heads], dim=1) + """ + indexed_QKs = [] # noqa: N806 + for pair in alignment_heads: + # Each QK is of shape (batch_size, num_heads, sequence_length, num_frames // 2) + # The `QKs[_l]` selects the right QK from the list of QKs + # The `QKs[_l][:, _h]` selects the right attention heads from the chosen QK. The `:` is to do this for the batch dim. + # + # PyTorch: + # QKs[_l] is of shape (batch_size, num_heads, sequence_length, num_frames // 2) + # QKs[_l][:, _h] is of shape (batch_size, sequence_length, num_frames // 2) + # + # ONNX: + # QKs[_l] is of shape (batch_size, num_heads, sequence_length, num_frames // 2) + # QKs[_l][:, _h] is of shape (batch_size, 1, sequence_length, num_frames // 2) because + # the `[:, _h]` operation maps to a Gather op and that op does not reduce dimensions + _l, _h = pair[0], pair[1] + indexed_QKs.append(QKs[_l][:, _h]) + + # PyTorch: + # torch.stack will return a tensor of shape (batch_size, num_alignment_heads, sequence_length, num_frames // 2). + # + # ONNX: + # torch.stack will return a tensor of shape (batch_size, num_alignment_heads, 1, sequence_length, num_frames // 2) + # because the Gather op does not reduce dimensions. To remove the unneeded dimension, torch.squeeze with a specified + # dim (dim = 2) is added. The torch.squeeze op with a specified dim only runs if the specified dim has a size of 1. + # Since the dim won't be of size 1 in the PyTorch tensor but it is of size 1 in the ONNX tensor, it will be a no-op + # in PyTorch and an op in ONNX. Thus, the Squeeze op will only affect the ONNX model. + weights = torch.stack(indexed_QKs, dim=1) + weights = torch.squeeze(weights, dim=2) + return weights + + +def jump_timings(text_indices, time_indices): + """ + Calculate jump times from text_indices and time_indices where + text_indices and time_indices are both 1d vectors + """ + TOKENS_PER_SECOND = 50.0 # noqa: N806 + diff = text_indices[1:] - text_indices[:-1] + padding = torch.tensor([1], dtype=torch.int32) + jumps = torch.cat((padding, diff)).to(torch.bool) + jump_times = time_indices[jumps].to(torch.float) / TOKENS_PER_SECOND + return jump_times + + +def padded_jump_from_dtw(matrix_2d: torch.Tensor, max_length: torch.Tensor): + """ + Run Dynamic Time Warping (DTW) on batched tensor + """ + trace = torch.ops.onnxruntime.DynamicTimeWarping(matrix_2d) + text_indices = trace[0, :] + time_indices = trace[1, :] + jump_times = jump_timings(text_indices, time_indices) + return F.pad(jump_times, [0, int((max_length - jump_times.size(-1)).item())], mode="constant", value=-1.0) + + +@torch.jit.script_if_tracing +def batch_jump_times(matrix: torch.Tensor, max_decoded_length: torch.Tensor): + """ + Compute the following to calculate jump times for all batches: + batched_jump_times = torch.stack([self.padded_jump_from_dtw(matrix[b], max_decoded_length) for b in range(matrix.size(0))]) + """ + list_of_jump_times = [] + for b in range(matrix.size(0)): + jump_times = padded_jump_from_dtw(matrix[b], max_decoded_length) + list_of_jump_times.append(jump_times) + batched_jump_times = torch.stack(list_of_jump_times) + return batched_jump_times + + +class WhisperJumpTimes(torch.nn.Module): + """Whisper jump times component""" + + def __init__(self, config: WhisperConfig, device: torch.device, cache_dir: str | os.PathLike): + super().__init__() + self.config = config + self.device = device + self.cache_dir = cache_dir + + self.filter_width = 7 + self.qk_scale = 1.0 + + def median_filter(self, weights: torch.Tensor): + """ + Apply a median filter of width `filter_width` along the last dimension of `weights` + """ + pad_width = self.filter_width // 2 + x = F.pad(weights, (pad_width, pad_width, 0, 0), mode="reflect") + x_unfolded = torch.ops.onnxruntime.UnfoldTensor(x, -1, self.filter_width, 1) + result = torch.select(x_unfolded.sort()[0], dim=-1, index=pad_width) + return result + + def forward( + self, + alignment_heads: torch.Tensor, + sot_sequence_length: torch.Tensor, + segment_length: torch.Tensor, + QKs: list[torch.Tensor], + ): + # Get stacked QKs tensor + weights = index_QKs(alignment_heads, QKs) + weights = weights[:, :, : segment_length // 2] + weights = weights.to(torch.float32) + + weights = (weights * self.qk_scale).softmax(dim=-1) + std, mean = torch.std_mean(weights, dim=-2, keepdim=True, unbiased=False) + weights = (weights - mean) / std + weights = self.median_filter(weights) + + matrix = torch.mean(weights, 1) + matrix = -matrix[:, sot_sequence_length:-1] + + max_decoded_length = torch.tensor([matrix.size(1)], dtype=torch.int64) + batched_jump_times = batch_jump_times(matrix, max_decoded_length) + return batched_jump_times + + def input_names(self): + input_names = [ + "alignment_heads", + "sot_sequence_length", + "segment_length", + *[f"cross_qk_{i}" for i in range(self.config.num_hidden_layers)], + ] + return input_names + + def output_names(self): + output_names = ["jump_times"] + return output_names + + def inputs(self, use_fp16_inputs: bool, use_int32_inputs: bool, return_dict: bool = False): + inputs = get_sample_jump_times_inputs( + self.config, + self.device, + batch_size=2, + sequence_length=8, + num_alignment_heads=6, + sot_sequence_length=3, + segment_length=1332, + use_fp16=use_fp16_inputs, + use_int32=use_int32_inputs, + ) + if return_dict: + return inputs + return ( + inputs["alignment_heads"], + inputs["sot_sequence_length"], + inputs["segment_length"], + inputs["QKs"], + ) + + def create_torch_ops(self): + """ + 1) Create UnfoldTensor and DynamicTimeWarping as torch ops + 3) Provide a symbolic mapping from torch ops to ORT contrib ops + + See https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html#building-with-jit-compilation + for more details on how this works. + """ + # Set torch extensions directory to cache directory + os.environ["TORCH_EXTENSIONS_DIR"] = self.cache_dir + + # Try to import `jinja` pip package + try: + assert torch.utils.cpp_extension.verify_ninja_availability() + except Exception as e: + logger.error(f"An error occurred while verifying `ninja` is available: {e}", exc_info=True) # noqa: G201 + install_cmd = "pip install ninja" + logger.warning(f"Could not import `ninja`. Attempting to install `ninja` via `{install_cmd}`.") + os.system(install_cmd) + + # Create UnfoldTensor torch op + unfold_op_source = textwrap.dedent("""\ + #include "torch/script.h" + + torch::Tensor UnfoldTensor(torch::Tensor input, int64_t dim, int64_t size, int64_t step) { + return input.unfold(dim, size, step); + } + + // namespace is onnxruntime + static auto registry = torch::RegisterOperators("onnxruntime::UnfoldTensor", &UnfoldTensor); + """) + + torch.utils.cpp_extension.load_inline( + name="UnfoldTensor", + cpp_sources=unfold_op_source, + is_python_module=False, + verbose=True, + ) + + # Create DynamicTimeWarping torch op + dtw_op_source = textwrap.dedent("""\ + #include "torch/script.h" + #include "torch/torch.h" + #include + #include + #include + + torch::Tensor Backtrace(torch::Tensor trace) { + int64_t i = trace.size(0) - 1; + int64_t j = trace.size(1) - 1; + trace.index({0, torch::indexing::Slice()}) = 2; + trace.index({torch::indexing::Slice(), 0}) = 1; + + std::vector result_vec; + while (i > 0 || j > 0) { + result_vec.push_back(static_cast(i - 1)); + result_vec.push_back(static_cast(j - 1)); + int value = trace[i][j].item(); + + if (value == 0) { + i--; + j--; + } else if (value == 1) { + i--; + } else if (value == 2) { + j--; + } else { + throw std::runtime_error("Unexpected trace[i, j]"); + } + } + + // Compute result[::-1, :].T + torch::Tensor result = torch::from_blob(result_vec.data(), {static_cast(result_vec.size() / 2), 2}, torch::kInt32).clone(); + torch::Tensor reversed = result.flip(0); // result[::-1, :] + torch::Tensor transposed = reversed.transpose(0, 1); // .T + return transposed; + } + + torch::Tensor DynamicTimeWarping(torch::Tensor x) { + int64_t N = x.size(0); + int64_t M = x.size(1); + torch::Tensor cost = torch::full({N + 1, M + 1}, std::numeric_limits::infinity(), torch::dtype(torch::kFloat32)); + torch::Tensor trace = torch::full({N + 1, M + 1}, -1, torch::dtype(torch::kFloat32)); + + cost[0][0] = 0; + for (int j = 1; j < M + 1; j++) { + for (int i = 1; i < N + 1; i++) { + float c0 = cost[i - 1][j - 1].item(); + float c1 = cost[i - 1][j].item(); + float c2 = cost[i][j - 1].item(); + + float c = 0; + float t = 0; + + if (c0 < c1 && c0 < c2) { + c = c0; + t = 0; + } else if (c1 < c0 && c1 < c2) { + c = c1; + t = 1; + } else { + c = c2; + t = 2; + } + + cost[i][j] = x[i - 1][j - 1].item() + c; + trace[i][j] = t; + } + } + + return Backtrace(trace); + } + + // namespace is onnxruntime + static auto registry = torch::RegisterOperators("onnxruntime::DynamicTimeWarping", &DynamicTimeWarping); + """) + + torch.utils.cpp_extension.load_inline( + name="DynamicTimeWarping", + cpp_sources=dtw_op_source, + is_python_module=False, + verbose=True, + ) + + # Create symbolic mapping from torch ops to ORT contrib ops + pytorch_export_contrib_ops.register() + + def export_onnx( + self, + onnx_model_path: str, + provider: str, + verbose: bool = True, + use_external_data_format: bool = False, + use_fp16_inputs: bool = False, + use_int32_inputs: bool = True, + ): + """Export word-level timestamps to ONNX + + Args: + onnx_model_path (str): path to save ONNX model + provider (str): provider to use for verifying parity on ONNX model + verbose (bool, optional): print verbose information. Defaults to True. + use_external_data_format (bool, optional): use external data format or not. Defaults to False. + use_fp16_inputs (bool, optional): use float16 inputs for the audio_features. Defaults to False. + use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids. Defaults to True. + """ + # Shape of timestamps's tensors: + # Inputs: + # alignment_heads: (num_alignment_heads, 2) + # sot_sequence_length: (1) + # segment_length: (1) + # cross_qk_*: (batch_size, num_heads, sequence_length, num_frames // 2) + # Outputs: + # jump_times: (batch_size, max_length) + + # Definitions: + # alignment_heads: the attention head indices where the Q*K values are highly correlated with word-level timestamps + # (i.e. the alignment between audio and text tokens) + # This is calculated as follows: + # + # ``` + # import base64 + # import gzip + # import numpy as np + # import torch + # + # # base85-encoded (n_layers, n_heads) boolean arrays indicating the cross-attention heads that are + # # highly correlated to the word-level timing, i.e. the alignment between audio and text tokens. + # _ALIGNMENT_HEADS = { + # "tiny.en": b"ABzY8J1N>@0{>%R00Bk>$p{7v037`oCl~+#00", + # "tiny": b"ABzY8bu8Lr0{>%RKn9Fp%m@SkK7Kt=7ytkO", + # "base.en": b"ABzY8;40c<0{>%RzzG;p*o+Vo09|#PsxSZm00", + # "base": b"ABzY8KQ!870{>%RzyTQH3`Q^yNP!>##QT-?_)10{>%RpeA61k&I|OI3I$65C{;;pbCHh0B{qLQ;+}v00", + # "small": b"ABzY8DmU6=0{>%Rpa?J`kvJ6qF(V^F86#Xh7JUGMK}P%R7%R7}kK1fFL7w6%<-Pf*t^=N)Qr&0RR9", + # "large-v1": b"ABzY8r9j$a0{>%R7#4sLmoOs{s)o3~84-RPdcFk!JR%R7=D0pU<_bnWW*tkYAhobTNnu$jnkEkXqp)j;w1Tzk)UH3X%SZd&fFZ2fC2yj", + # "large-v3": b"ABzY8gWO1E0{>%R7(9S+Kn!D~%ngiGaR?*L!iJG9p-nab0JQ=-{D1-g00", + # "large": b"ABzY8gWO1E0{>%R7(9S+Kn!D~%ngiGaR?*L!iJG9p-nab0JQ=-{D1-g00", + # "large-v3-turbo": b"ABzY8j^C+e0{>%RARaKHP%t(lGR*)0g!tONPyhe`", + # "turbo": b"ABzY8j^C+e0{>%RARaKHP%t(lGR*)0g!tONPyhe`", + # } + # + # model_name = "large-v3-turbo" + # array = np.frombuffer( + # gzip.decompress(base64.b85decode(_ALIGNMENT_HEADS[model_name])), dtype=bool + # ).copy() + # mask = torch.from_numpy(array).reshape( + # self.dims.n_text_layer, self.dims.n_text_head + # ) + # self.alignment_heads = mask.to_sparse().indices().T + # ``` + # + # sot_sequence_length: the length of the start-of-transcription sequence before the first token is generated + # Typically the start-of-transcription sequence is [<|startoftranscription|>, <|language_token|>, <|task_token|>] + # so its length is 3. + # + # segment_length: the length (in frames) of the audio segment that is being transcribed + # + # cross_qk_*: the Q*K values for the cross-attention blocks in the decoder + # Every decoder layer has a self-attention block and a cross-attention block so there are `n` cross-attention blocks + # where `n` is the number of decoder layers. + # + # jump_times: the timings where jumps occur in speech + # This allows us to detect when a word began to be spoken by the speaker (start_times) and when a word was finished + # being spoken by the speaker (end_times). + + inputs = self.inputs(use_fp16_inputs=use_fp16_inputs, use_int32_inputs=use_int32_inputs) + input_names = self.input_names() + output_names = self.output_names() + dynamic_axes = get_model_dynamic_axes(self.config, input_names, output_names) + + Path(onnx_model_path).parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory() as tmp_dir_name: + temp_onnx_model_path = os.path.join(tmp_dir_name, "encoder.onnx") + Path(temp_onnx_model_path).parent.mkdir(parents=True, exist_ok=True) + out_path = temp_onnx_model_path if use_external_data_format else onnx_model_path + + # Create torch ops and map them to ORT contrib ops before export + self.create_torch_ops() + torch.onnx.export( + self, + args=inputs, + f=out_path, + export_params=True, + input_names=input_names, + output_names=output_names, + dynamic_axes=dynamic_axes, + opset_version=17, + do_constant_folding=True, + verbose=verbose, + custom_opsets={"com.microsoft": 1}, + ) + + if use_external_data_format: + model = onnx.load_model(out_path, load_external_data=use_external_data_format) + OnnxModel.save( + model, + onnx_model_path, + save_as_external_data=True, + all_tensors_to_one_file=True, + ) + + self.verify_onnx(onnx_model_path, provider, use_fp16_inputs, use_int32_inputs) + + def verify_onnx( + self, + onnx_model_path: str, + provider: str, + use_fp16_inputs: bool, + use_int32_inputs: bool, + ): + """Verify ONNX model outputs and PyTorch model outputs match + + Args: + onnx_model_path (str): path to save ONNX model + provider (str): execution provider for ONNX model + use_fp16_inputs (bool, optional): use float16 inputs for the cross_qk_{i} + use_int32_inputs (bool, optional): use int32 inputs for the alignment_heads and sot_sequence_length + """ + # Shape of jump times's tensors: + # Inputs: + # alignment_heads: (num_alignment_heads, 2) + # sot_sequence_length: (1) + # segment_length: (1) + # cross_qk_*: (batch_size, num_heads, sequence_length, num_frames // 2) + # Outputs: + # jump_times: (batch_size, max_length) + inputs = self.inputs(use_fp16_inputs=use_fp16_inputs, use_int32_inputs=use_int32_inputs, return_dict=True) + + # Run PyTorch model + pt_outputs = ( + self.forward( + inputs["alignment_heads"], inputs["sot_sequence_length"], inputs["segment_length"], inputs["QKs"] + ) + .detach() + .cpu() + .numpy() + ) + + # Run ONNX model + sess = InferenceSession(onnx_model_path, providers=[provider]) + ort_outputs = sess.run(None, convert_inputs_for_ort(inputs, sess)) + + # Calculate output difference + diff = np.abs(pt_outputs - ort_outputs) + print("Comparing batched jump_times...", flush=True) + print(f"Max diff: {np.max(diff)}", flush=True) diff --git a/onnxruntime/python/tools/transformers/models/whisper/whisper_openai_helper.py b/onnxruntime/python/tools/transformers/models/whisper/whisper_openai_helper.py deleted file mode 100644 index 8c78fb86a211e..0000000000000 --- a/onnxruntime/python/tools/transformers/models/whisper/whisper_openai_helper.py +++ /dev/null @@ -1,84 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- - -import logging - -import torch - -logger = logging.getLogger(__name__) - - -class WhisperDecoderInitOpenai(torch.nn.Module): - """WhisperDecoderInit for Openai.""" - - def __init__( - self, - model: torch.nn.Module, - decoder: torch.nn.Module, - ): - super().__init__() - self.whisper_model = model - self.whisper_decoder = decoder - self.kv_cache = {} - - @torch.no_grad() - def forward( - self, - tokens, - audio_features, - past=None, - remove_hooks=False, - ): - # Create a kv_cache for past_values - past_kv_cache = {} - if past is not None: - # Convert past values from 4D to 3D - past = [torch.transpose(val, 1, 2) for val in past] - past = [val.reshape(val.shape[:2] + (-1,)) for val in past] - half_idx = len(past) // 2 - for idx, block in enumerate(self.whisper_decoder.blocks): - past_kv_cache[block.attn.key] = past[2 * idx] - past_kv_cache[block.attn.value] = past[2 * idx + 1] - past_kv_cache[block.cross_attn.key] = past[2 * idx + half_idx] - past_kv_cache[block.cross_attn.value] = past[2 * idx + half_idx + 1] - - hooks = None - if not self.kv_cache: - self.kv_cache, hooks = self.whisper_model.install_kv_cache_hooks() - - logits = self.whisper_decoder(tokens, audio_features, kv_cache=past_kv_cache) - - # Add concat node for past values - if past is not None: - for block in self.whisper_decoder.blocks: - self.kv_cache[block.attn.key] = torch.cat( - [past_kv_cache[block.attn.key], self.kv_cache[block.attn.key]], dim=1 - ).detach() - self.kv_cache[block.attn.value] = torch.cat( - [past_kv_cache[block.attn.value], self.kv_cache[block.attn.value]], dim=1 - ).detach() - - present_self, present_cross = [], [] - # Group self and cross values - for block in self.whisper_decoder.blocks: - present_self.append(self.kv_cache[block.attn.key]) - present_self.append(self.kv_cache[block.attn.value]) - if past is None: - present_cross.append(self.kv_cache[block.cross_attn.key]) - present_cross.append(self.kv_cache[block.cross_attn.value]) - - present_self = present_self + present_cross - # Add reshape and transpose ops to convert from 3D to 4D - present_self = [ - present_val.reshape(present_val.shape[:2] + (-1, 64)).transpose(1, 2) for present_val in present_self - ] - - # Remove forward hooks to avoid model cloning step - if hooks is not None and remove_hooks: - self.kv_cache = {} - for hook in hooks: - hook.remove() - return logits, present_self diff --git a/onnxruntime/python/tools/transformers/models/t5/past_helper.py b/onnxruntime/python/tools/transformers/past_helper.py similarity index 100% rename from onnxruntime/python/tools/transformers/models/t5/past_helper.py rename to onnxruntime/python/tools/transformers/past_helper.py diff --git a/onnxruntime/test/contrib_ops/attention_op_test_helper.cc b/onnxruntime/test/contrib_ops/attention_op_test_helper.cc index 5df521bd6381d..fc65963474cdb 100644 --- a/onnxruntime/test/contrib_ops/attention_op_test_helper.cc +++ b/onnxruntime/test/contrib_ops/attention_op_test_helper.cc @@ -520,6 +520,75 @@ void GetCrossAttentionData_WithPastPassedInDirectly_NoMask(AttentionTestData& da data.fp16_output_data = data.fp32_output_data; } +void GetSelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA(AttentionTestData& data) { + int num_heads = 2; + int head_size = 32; + data.hidden_size = num_heads * head_size; + data.v_hidden_size = num_heads * head_size; + data.num_heads = num_heads; + data.batch_size = 2; + data.sequence_length = 1; + data.kv_sequence_length = 1; + data.mask_type = AttentionMaskType::MASK_2D_KEY_PADDING; + + data.past_seq_len_data = {4}; + data.cache_indir_data = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + data.num_beams = 1; + data.max_sequence_length = 6; + + data.skip_kernel_types = { + AttentionKernelType::AttentionKernel_TrtFlashAttention, + AttentionKernelType::AttentionKernel_TrtFusedCrossAttention, + AttentionKernelType::AttentionKernel_TrtFusedAttention, + AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, + }; + + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.query_data", data.query_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.key_data", data.key_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.value_data", data.value_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.bias_data", data.bias_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.past_key_data", data.past_key_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.past_value_data", data.past_value_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.fp32_output_data", data.fp32_output_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.present_key_data", data.present_key_data); + LoadTensor("SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.present_value_data", data.present_value_data); + data.is_static_kv = false; + data.buffer_share = true; +} + +void GetCrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA(AttentionTestData& data) { + int num_heads = 2; + int head_size = 32; + data.hidden_size = num_heads * head_size; + data.v_hidden_size = num_heads * head_size; + data.num_heads = num_heads; + data.batch_size = 2; + data.sequence_length = 1; + data.kv_sequence_length = 10; + data.mask_type = AttentionMaskType::MASK_NONE; + + data.past_seq_len_data = {4}; + data.cache_indir_data = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + data.num_beams = 1; + data.max_sequence_length = 6; + + data.skip_kernel_types = { + AttentionKernelType::AttentionKernel_TrtFlashAttention, + AttentionKernelType::AttentionKernel_TrtFusedCrossAttention, + AttentionKernelType::AttentionKernel_TrtFusedAttention, + AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, + }; + + LoadTensor("CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.query_data", data.query_data); + LoadTensor("CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.past_key_data", data.past_key_data); + LoadTensor("CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.past_value_data", data.past_value_data); + LoadTensor("CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.bias_data", data.bias_data); + LoadTensor("CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.fp32_output_data", data.fp32_output_data); + LoadTensor("CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.fp32_output_qk_data", data.fp32_output_qk_data); + data.is_static_kv = true; + data.buffer_share = false; +} + void GetCausal_EmptyPastState(std::vector& input, std::vector& output, std::vector& present) { LoadTensor("Causal_EmptyPastState.input_data", input); LoadTensor("Causal_EmptyPastState.output_data", output); diff --git a/onnxruntime/test/contrib_ops/attention_op_test_helper.h b/onnxruntime/test/contrib_ops/attention_op_test_helper.h index b0dbe6e7b4ac7..73e39042e7f0b 100644 --- a/onnxruntime/test/contrib_ops/attention_op_test_helper.h +++ b/onnxruntime/test/contrib_ops/attention_op_test_helper.h @@ -12,6 +12,7 @@ namespace test { struct BaseAttentionTestData { bool is_static_kv = true; + bool buffer_share = false; int hidden_size; int v_hidden_size; int num_heads; @@ -33,12 +34,20 @@ struct BaseAttentionTestData { std::vector past_key_data; std::vector past_value_data; + std::vector past_seq_len_data; + std::vector cache_indir_data; + int num_beams; + int max_sequence_length; + std::vector fp32_output_data; std::vector fp16_output_data; std::vector present_key_data; std::vector present_value_data; + std::vector fp32_output_qk_data; + std::vector fp16_output_qk_data; + std::vector skip_kernel_types; // skip some kernels if they do not supported this test case. }; @@ -86,6 +95,9 @@ void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias(Attenti void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias(AttentionTestData& data); void GetCrossAttentionData_WithPastPassedInDirectly_NoMask(AttentionTestData& data); +void GetSelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA(AttentionTestData& data); +void GetCrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA(AttentionTestData& data); + void GetCausal_EmptyPastState(std::vector& input, std::vector& output, std::vector& present); void GetAttentionDataCutlassAttnBias(AttentionTestData& data); diff --git a/onnxruntime/test/contrib_ops/decoder_masked_multihead_attention_op_test.cc b/onnxruntime/test/contrib_ops/decoder_masked_multihead_attention_op_test.cc index 208545eacf224..7cdbad3ef80a7 100644 --- a/onnxruntime/test/contrib_ops/decoder_masked_multihead_attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/decoder_masked_multihead_attention_op_test.cc @@ -752,7 +752,7 @@ static void TestDecoderMaskedMultiHeadAttention(bool is_cross_attn = true, bool int kv_sequence_length = 16; int head_size = 32; int num_heads = 12; - int beam_width = 4; + int beam_width = 1; int hidden_size = head_size * num_heads; OpTester tester("DecoderMaskedMultiHeadAttention", 1, onnxruntime::kMSDomain); @@ -766,53 +766,54 @@ static void TestDecoderMaskedMultiHeadAttention(bool is_cross_attn = true, bool tester.AddAttribute("output_qk", static_cast(is_cross_attn)); // Inputs and outputs - auto query = CreateRandom(batch_size * 1 * hidden_size); - tester.AddInput("query", {batch_size, 1, hidden_size}, query); + int batch_beam_size = batch_size * beam_width; + auto query = CreateRandom(batch_beam_size * 1 * hidden_size); + tester.AddInput("query", {batch_beam_size, 1, hidden_size}, query); if (is_cross_attn) { - auto key = CreateRandom(batch_size * num_heads * kv_sequence_length * head_size); + auto key = CreateRandom(batch_beam_size * num_heads * kv_sequence_length * head_size); std::vector reordered_key; if (use_cuda) { - reordered_key = ReorderKVCache(key, batch_size, num_heads, + reordered_key = ReorderKVCache(key, batch_beam_size, num_heads, kv_sequence_length, head_size, kv_sequence_length, false); } - auto value = CreateRandom(batch_size * num_heads * kv_sequence_length * head_size); - tester.AddInput("key", {batch_size, num_heads, kv_sequence_length, head_size}, (use_cuda ? reordered_key : key)); - tester.AddInput("value", {batch_size, num_heads, kv_sequence_length, head_size}, - CreateRandom(batch_size * num_heads * kv_sequence_length * head_size)); + auto value = CreateRandom(batch_beam_size * num_heads * kv_sequence_length * head_size); + tester.AddInput("key", {batch_beam_size, num_heads, kv_sequence_length, head_size}, (use_cuda ? reordered_key : key)); + tester.AddInput("value", {batch_beam_size, num_heads, kv_sequence_length, head_size}, + CreateRandom(batch_beam_size * num_heads * kv_sequence_length * head_size)); - const std::vector mask_index_dims = {batch_size, kv_sequence_length}; + const std::vector mask_index_dims = {batch_beam_size, kv_sequence_length}; auto mask_index = generator.Discrete(mask_index_dims, AsSpan({0, 1})); - tester.AddInput("mask_index", {batch_size, kv_sequence_length}, mask_index); + tester.AddInput("mask_index", {batch_beam_size, kv_sequence_length}, mask_index); // Calculate Softmax(Q * K^T + (Optional) mask) * V std::vector empty_attention_bias; - auto output_qk = CalculateOutputQK(query, key, mask_index, empty_attention_bias, batch_size, num_heads, + auto output_qk = CalculateOutputQK(query, key, mask_index, empty_attention_bias, batch_beam_size, num_heads, kv_sequence_length, kv_sequence_length, head_size); std::vector output_qk_float(output_qk.size()); for (size_t i = 0; i < output_qk.size(); ++i) { output_qk_float[i] = static_cast(output_qk[i]); } - auto softmax = Softmax_QK_Transpose(output_qk.data(), batch_size, num_heads, 1, kv_sequence_length); - auto output = CalculateOutput(softmax, value, batch_size, num_heads, + auto softmax = Softmax_QK_Transpose(output_qk.data(), batch_beam_size, num_heads, 1, kv_sequence_length); + auto output = CalculateOutput(softmax, value, batch_beam_size, num_heads, kv_sequence_length, kv_sequence_length, head_size); - tester.AddOutput("output", {batch_size, 1, hidden_size}, output); + tester.AddOutput("output", {batch_beam_size, 1, hidden_size}, output); tester.AddOptionalOutputEdge(); // optional present_key tester.AddOptionalOutputEdge(); // optional present_value - tester.AddOutput("qk", {batch_size, num_heads, 1, kv_sequence_length}, output_qk_float); + tester.AddOutput("qk", {batch_beam_size, num_heads, 1, kv_sequence_length}, output_qk_float); } else { int max_sequence_length = past_sequence_length + 10; int total_sequence_length = past_sequence_length + 1; - auto key = CreateRandom(batch_size * hidden_size); - auto value = CreateRandom(batch_size * hidden_size); - tester.AddInput("key", {batch_size, 1, hidden_size}, key); - tester.AddInput("value", {batch_size, 1, hidden_size}, value); + auto key = CreateRandom(batch_beam_size * hidden_size); + auto value = CreateRandom(batch_beam_size * hidden_size); + tester.AddInput("key", {batch_beam_size, 1, hidden_size}, key); + tester.AddInput("value", {batch_beam_size, 1, hidden_size}, value); - const std::vector mask_index_dims = {batch_size, total_sequence_length}; + const std::vector mask_index_dims = {batch_beam_size, total_sequence_length}; auto mask_index = generator.Discrete(mask_index_dims, AsSpan({0, 1})); - tester.AddInput("mask_index", {batch_size, total_sequence_length}, mask_index); + tester.AddInput("mask_index", {batch_beam_size, total_sequence_length}, mask_index); std::vector attention_bias_dims = {1, 1, 1, total_sequence_length}; auto attention_bias_float = random.Gaussian(attention_bias_dims, 0.0f, 0.3f); std::vector attention_bias(attention_bias_float.size()); @@ -821,28 +822,28 @@ static void TestDecoderMaskedMultiHeadAttention(bool is_cross_attn = true, bool } tester.AddInput("attention_bias", {1, 1, 1, total_sequence_length}, attention_bias); - auto past_key = CreateRandom(batch_size * num_heads * max_sequence_length * head_size); - auto past_value = CreateRandom(batch_size * num_heads * max_sequence_length * head_size); + auto past_key = CreateRandom(batch_beam_size * num_heads * max_sequence_length * head_size); + auto past_value = CreateRandom(batch_beam_size * num_heads * max_sequence_length * head_size); std::vector reordered_past_key; // For CUDA, we need to reorder past key if (use_cuda) { - reordered_past_key = ReorderKVCache(past_key, batch_size, num_heads, + reordered_past_key = ReorderKVCache(past_key, batch_beam_size, num_heads, past_sequence_length, head_size, max_sequence_length, false); } - tester.AddInput("past_key", {batch_size, num_heads, max_sequence_length, head_size}, + tester.AddInput("past_key", {batch_beam_size, num_heads, max_sequence_length, head_size}, (use_cuda ? reordered_past_key : past_key)); - tester.AddInput("past_value", {batch_size, num_heads, max_sequence_length, head_size}, past_value); + tester.AddInput("past_value", {batch_beam_size, num_heads, max_sequence_length, head_size}, past_value); // merge past key and value with current key and value - auto merged_key = MergePast(past_key, key, batch_size, num_heads, + auto merged_key = MergePast(past_key, key, batch_beam_size, num_heads, past_sequence_length, max_sequence_length, head_size); std::vector merged_reordered_key; if (use_cuda) { - merged_reordered_key = MergeReorderedKVCacheWithK(reordered_past_key, key.data(), batch_size, num_heads, + merged_reordered_key = MergeReorderedKVCacheWithK(reordered_past_key, key.data(), batch_beam_size, num_heads, past_sequence_length, max_sequence_length, head_size, false); } - auto merged_value = MergePast(past_value, value, batch_size, num_heads, + auto merged_value = MergePast(past_value, value, batch_beam_size, num_heads, past_sequence_length, max_sequence_length, head_size); tester.AddInput("past_sequence_length", {1}, {past_sequence_length}); @@ -868,15 +869,15 @@ static void TestDecoderMaskedMultiHeadAttention(bool is_cross_attn = true, bool // Calculate Softmax(Q * K^T + (Optional) mask) * V auto output_qk = CalculateOutputQK(query, (beam_width > 1 ? mod_merged_key : merged_key), mask_index, attention_bias, - batch_size, num_heads, total_sequence_length, max_sequence_length, head_size); - auto softmax = Softmax_QK_Transpose(output_qk.data(), batch_size, num_heads, 1, total_sequence_length); + batch_beam_size, num_heads, total_sequence_length, max_sequence_length, head_size); + auto softmax = Softmax_QK_Transpose(output_qk.data(), batch_beam_size, num_heads, 1, total_sequence_length); auto output = CalculateOutput(softmax, (beam_width > 1 ? mod_merged_value : merged_value), - batch_size, num_heads, total_sequence_length, max_sequence_length, head_size); + batch_beam_size, num_heads, total_sequence_length, max_sequence_length, head_size); - tester.AddOutput("output", {batch_size, 1, hidden_size}, output); - tester.AddOutput("present_key", {batch_size, num_heads, max_sequence_length, head_size}, + tester.AddOutput("output", {batch_beam_size, 1, hidden_size}, output); + tester.AddOutput("present_key", {batch_beam_size, num_heads, max_sequence_length, head_size}, (use_cuda ? merged_reordered_key : merged_key)); - tester.AddOutput("present_value", {batch_size, num_heads, max_sequence_length, head_size}, merged_value); + tester.AddOutput("present_value", {batch_beam_size, num_heads, max_sequence_length, head_size}, merged_value); } if (std::is_same::value) { diff --git a/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc b/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc index ffdf69cc149b3..7c3dc617ffb12 100644 --- a/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc @@ -25,27 +25,33 @@ namespace onnxruntime { namespace test { static void RunMultiHeadAttentionTest( - const std::vector& query_data, // query: [batch_size, sequence_length, hidden_size] - const std::vector& key_data, // key: [batch_size, kv_sequence_length, hidden_size] - const std::vector& value_data, // value: [batch_size, kv_sequence_length, v_hidden_size] - const std::vector& kv_data, // packed_kv: [batch_size, kv_sequence_length, num_heads, 2, head_size] - const std::vector& qkv_data, // packed_qkv: [batch_size, sequence_length, num_heads, 3, head_size] - const std::vector& bias_data, // bias: [hidden_size + hidden_size + v_hidden_size] or empty - const std::vector& attention_bias_data, // attention_bias: [1, num_heads, sequence_length, total_sequence_length] - const std::vector& past_key_data, // past_key: [batch_size, num_heads, kv_sequence_length, head_size] - const std::vector& past_value_data, // past_value: [batch_size, num_heads, kv_sequence_length, head_size] - const std::vector& present_key_data, // present_key: [batch_size, num_heads, total_sequence_length, head_size] - const std::vector& present_value_data, // present_value: [batch_size, num_heads, total_sequence_length, head_size] - const std::vector& key_padding_mask_data, // key_padding_mask: see below - AttentionMaskType mask_type, // 1 for [batch_size], 2 for [batch_size, kv_sequence_length] - const std::vector& output_data, // output: [batch_size, sequence_length, v_hidden_size] + const std::vector& query_data, // query: [batch_size, sequence_length, hidden_size] + const std::vector& key_data, // key: [batch_size, kv_sequence_length, hidden_size] + const std::vector& value_data, // value: [batch_size, kv_sequence_length, v_hidden_size] + const std::vector& kv_data, // packed_kv: [batch_size, kv_sequence_length, num_heads, 2, head_size] + const std::vector& qkv_data, // packed_qkv: [batch_size, sequence_length, num_heads, 3, head_size] + const std::vector& bias_data, // bias: [hidden_size + hidden_size + v_hidden_size] or empty + const std::vector& attention_bias_data, // attention_bias: [1, num_heads, sequence_length, total_sequence_length] + const std::vector& past_key_data, // past_key: [batch_size, num_heads, kv_sequence_length, head_size] + const std::vector& past_value_data, // past_value: [batch_size, num_heads, kv_sequence_length, head_size] + const std::vector& past_seq_len_data, // past_sequence_length: [1] or empty + const std::vector& cache_indir_data, // cache_indirection: [batch_size, num_beams, max_sequence_length] or empty + const std::vector& present_key_data, // present_key: [batch_size, num_heads, total_sequence_length, head_size] + const std::vector& present_value_data, // present_value: [batch_size, num_heads, total_sequence_length, head_size] + const std::vector& key_padding_mask_data, // key_padding_mask: see below + AttentionMaskType mask_type, // 1 for [batch_size], 2 for [batch_size, kv_sequence_length] + const std::vector& output_data, // output: [batch_size, sequence_length, v_hidden_size] + const std::vector& output_qk_data, // output_qk: [batch_size, num_heads, sequence_length, total_sequence_length] or empty int num_heads, int batch_size, int sequence_length, int kv_sequence_length, int hidden_size, int v_hidden_size, + int num_beams, + int max_sequence_length, bool is_static_kv = true, + bool buffer_share = false, bool use_float16 = false, bool disable_cpu = false, // some cases not supported in cpu right now. bool disable_cuda = false, @@ -53,6 +59,7 @@ static void RunMultiHeadAttentionTest( bool disable_rocm = DISABLE_ROCM, // not supported in rocm right now. bool disable_dml = false) { kv_sequence_length = (kv_sequence_length == 0 ? sequence_length : kv_sequence_length); + int past_sequence_length = (past_seq_len_data.size() == 0) ? 0 : past_seq_len_data[0]; int min_cuda_architecture = use_float16 ? 750 : 0; bool enable_cuda = HasCudaEnvironment(min_cuda_architecture) && !disable_cuda; @@ -81,15 +88,20 @@ static void RunMultiHeadAttentionTest( std::vector key_dims = {batch_size, is_static_kv ? kv_sequence_length : sequence_length, hidden_size}; std::vector value_dims = {batch_size, is_static_kv ? kv_sequence_length : sequence_length, v_hidden_size}; std::vector bias_dims = {hidden_size + hidden_size + v_hidden_size}; + // TODO(wy): Introduce past sequence length to avoid using kv_sequence_length. std::vector attention_bias_dims = {1, num_heads, sequence_length, past_key_data.size() ? sequence_length + kv_sequence_length : sequence_length}; - std::vector past_key_dims = {batch_size, num_heads, kv_sequence_length, hidden_size / num_heads}; + std::vector past_key_dims = {batch_size, num_heads, buffer_share ? max_sequence_length : kv_sequence_length, hidden_size / num_heads}; std::vector past_value_dims = past_key_dims; + std::vector past_seq_len_dims = {1}; + std::vector cache_indir_dims = {batch_size, num_beams, max_sequence_length}; + std::vector output_dims = {batch_size, sequence_length, v_hidden_size}; std::vector present_key_dims = - {batch_size, num_heads, is_static_kv ? kv_sequence_length : sequence_length + kv_sequence_length, hidden_size / num_heads}; + {batch_size, num_heads, buffer_share ? max_sequence_length : (is_static_kv ? kv_sequence_length : sequence_length + kv_sequence_length), hidden_size / num_heads}; std::vector present_value_dims = present_key_dims; + std::vector output_qk_dims = {batch_size, num_heads, sequence_length, is_static_kv ? kv_sequence_length : past_sequence_length + kv_sequence_length}; std::vector query = (qkv_data.size() > 0 ? qkv_data : query_data); std::vector key; @@ -164,6 +176,18 @@ static void RunMultiHeadAttentionTest( tester.AddOptionalInputEdge(); } + if (past_seq_len_data.size()) { + tester.AddInput("past_sequence_length", past_seq_len_dims, past_seq_len_data); + } else { + tester.AddOptionalInputEdge(); + } + + if (cache_indir_data.size()) { + tester.AddInput("cache_indirection", cache_indir_dims, cache_indir_data); + } else { + tester.AddOptionalInputEdge(); + } + constexpr float rel_error = 0.0f; constexpr float abs_error = 0.05f; tester.AddOutput("output", output_dims, ToFloat16(output_data), /*sort*/ false, rel_error, abs_error); @@ -179,6 +203,12 @@ static void RunMultiHeadAttentionTest( } else { tester.AddOptionalOutputEdge(); } + + if (output_qk_data.size()) { + tester.AddOutput("output_qk", output_qk_dims, ToFloat16(output_qk_data), /*sort*/ false, rel_error, abs_error); + } else { + tester.AddOptionalOutputEdge(); + } } else { tester.AddInput("query", query_dims, query); @@ -228,6 +258,18 @@ static void RunMultiHeadAttentionTest( tester.AddOptionalInputEdge(); } + if (past_seq_len_data.size()) { + tester.AddInput("past_sequence_length", past_seq_len_dims, past_seq_len_data); + } else { + tester.AddOptionalInputEdge(); + } + + if (cache_indir_data.size()) { + tester.AddInput("cache_indirection", cache_indir_dims, cache_indir_data); + } else { + tester.AddOptionalInputEdge(); + } + constexpr float rel_error = 0.0f; constexpr float abs_error = 0.02f; tester.AddOutput("output", output_dims, output_data, /*sort*/ false, rel_error, abs_error); @@ -243,6 +285,12 @@ static void RunMultiHeadAttentionTest( } else { tester.AddOptionalOutputEdge(); } + + if (output_qk_data.size()) { + tester.AddOutput("output_qk", output_qk_dims, output_qk_data, /*sort*/ false, rel_error, abs_error); + } else { + tester.AddOptionalOutputEdge(); + } } if (enable_cuda) { @@ -278,29 +326,35 @@ static void RunMultiHeadAttentionTest( } static void RunMultiHeadAttentionKernel( - const std::vector& query_data, // query: [batch_size, sequence_length, hidden_size] - const std::vector& key_data, // key: [batch_size, kv_sequence_length, hidden_size] - const std::vector& value_data, // value: [batch_size, kv_sequence_length, v_hidden_size] - const std::vector& kv_data, // packed_kv: [batch_size, kv_sequence_length, num_heads, 2, head_size] - const std::vector& qkv_data, // packed_qkv: [batch_size, sequence_length, num_heads, 3, head_size] - const std::vector& bias_data, // bias: [hidden_size + hidden_size + v_hidden_size] - const std::vector& attention_bias_data, // attention_bias: [1, num_heads, sequence_length, total_sequence_length] - const std::vector& past_key_data, // past_key: [batch_size, num_heads, kv_sequence_length, head_size] - const std::vector& past_value_data, // past_value: [batch_size, num_heads, kv_sequence_length, head_size] - const std::vector& present_key_data, // present_key: [batch_size, num_heads, total_sequence_length, head_size] - const std::vector& present_value_data, // present_value: [batch_size, num_heads, total_sequence_length, head_size] - const std::vector& key_padding_mask_data, // key_padding_mask: see below - AttentionMaskType mask_type, // 1 for [batch_size], 2 for [batch_size, kv_sequence_length] - const std::vector& output_data, // output: [batch_size, sequence_length, v_hidden_size] + const std::vector& query_data, // query: [batch_size, sequence_length, hidden_size] + const std::vector& key_data, // key: [batch_size, kv_sequence_length, hidden_size] + const std::vector& value_data, // value: [batch_size, kv_sequence_length, v_hidden_size] + const std::vector& kv_data, // packed_kv: [batch_size, kv_sequence_length, num_heads, 2, head_size] + const std::vector& qkv_data, // packed_qkv: [batch_size, sequence_length, num_heads, 3, head_size] + const std::vector& bias_data, // bias: [hidden_size + hidden_size + v_hidden_size] + const std::vector& attention_bias_data, // attention_bias: [1, num_heads, sequence_length, total_sequence_length] + const std::vector& past_key_data, // past_key: [batch_size, num_heads, kv_sequence_length, head_size] + const std::vector& past_value_data, // past_value: [batch_size, num_heads, kv_sequence_length, head_size] + const std::vector& past_seq_len_data, // past_sequence_length: [1] + const std::vector& cache_indir_data, // cache_indirection: [batch_size, num_beams, max_sequence_length] + const std::vector& present_key_data, // present_key: [batch_size, num_heads, total_sequence_length, head_size] + const std::vector& present_value_data, // present_value: [batch_size, num_heads, total_sequence_length, head_size] + const std::vector& key_padding_mask_data, // key_padding_mask: see below + AttentionMaskType mask_type, // 1 for [batch_size], 2 for [batch_size, kv_sequence_length] + const std::vector& output_data, // output: [batch_size, sequence_length, v_hidden_size] + const std::vector& output_qk_data, // output_qk: [batch_size, num_heads, sequence_length, total_sequence_length] + AttentionKernelType kernel_type, int num_heads, int batch_size, int sequence_length, int kv_sequence_length, int hidden_size, int v_hidden_size, - AttentionKernelType kernel_type, - bool use_float16 = true, + int num_beams, + int max_sequence_length, bool is_static_kv = true, + bool buffer_share = false, + bool use_float16 = true, bool disable_cpu = false, // some cases not supported in cpu right now. bool disable_cuda = false, bool disable_webgpu = false, @@ -316,10 +370,11 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "0"}}}; RunMultiHeadAttentionTest( query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, - past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, - mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, - hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_webgpu, - disable_rocm, disable_dml); + past_key_data, past_value_data, past_seq_len_data, cache_indir_data, + present_key_data, present_value_data, key_padding_mask_data, mask_type, + output_data, output_qk_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, num_beams, max_sequence_length, is_static_kv, buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); return; } @@ -333,10 +388,11 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, - past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, - mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, - hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_webgpu, - disable_rocm, disable_dml); + past_key_data, past_value_data, past_seq_len_data, cache_indir_data, + present_key_data, present_value_data, key_padding_mask_data, mask_type, + output_data, output_qk_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, num_beams, max_sequence_length, is_static_kv, buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); return; } @@ -350,10 +406,11 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, - past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, - mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, - hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_webgpu, - disable_rocm, disable_dml); + past_key_data, past_value_data, past_seq_len_data, cache_indir_data, + present_key_data, present_value_data, key_padding_mask_data, mask_type, + output_data, output_qk_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, num_beams, max_sequence_length, is_static_kv, buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); return; } @@ -368,10 +425,11 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "0"}}}; RunMultiHeadAttentionTest( query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, - past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, - mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, - hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_webgpu, - disable_rocm, disable_dml); + past_key_data, past_value_data, past_seq_len_data, cache_indir_data, + present_key_data, present_value_data, key_padding_mask_data, mask_type, + output_data, output_qk_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, num_beams, max_sequence_length, is_static_kv, buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); return; } #endif @@ -387,10 +445,11 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, - past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, - mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, - hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_webgpu, - disable_rocm, disable_dml); + past_key_data, past_value_data, past_seq_len_data, cache_indir_data, + present_key_data, present_value_data, key_padding_mask_data, mask_type, + output_data, output_qk_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, num_beams, max_sequence_length, is_static_kv, buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } if (kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { @@ -404,10 +463,11 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, - past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, - mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, - hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_webgpu, - disable_rocm, disable_dml); + past_key_data, past_value_data, past_seq_len_data, cache_indir_data, + present_key_data, present_value_data, key_padding_mask_data, mask_type, + output_data, output_qk_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, num_beams, max_sequence_length, is_static_kv, buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } } @@ -416,6 +476,8 @@ enum RunMultiHeadAttentionTestToggles : uint32_t { DISABLE_CPU = 1 << 0, DISABLE_CUDA = 1 << 1, DISABLE_WEBGPU = 1 << 2, + DISABLE_ROCM_MHA = 1 << 3, + DISABLE_DML = 1 << 4, }; inline RunMultiHeadAttentionTestToggles operator|(RunMultiHeadAttentionTestToggles a, RunMultiHeadAttentionTestToggles b) { return static_cast(static_cast(a) | static_cast(b)); @@ -429,6 +491,8 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu = toggles & DISABLE_CPU; bool disable_cuda = toggles & DISABLE_CUDA; bool disable_webgpu = toggles & DISABLE_WEBGPU; + bool disable_rocm = toggles & DISABLE_ROCM_MHA; + bool disable_dml = toggles & DISABLE_DML; if (data.fp32_output_data.size() > 0) { constexpr bool use_float16 = false; @@ -437,10 +501,11 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, + data.fp32_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } #if USE_MEMORY_EFFICIENT_ATTENTION @@ -450,10 +515,11 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, + data.fp32_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } } #endif @@ -461,10 +527,11 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, kernel_type = AttentionKernelType::AttentionKernel_Default; RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, + data.fp32_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } if (data.fp16_output_data.size() > 0) { @@ -473,20 +540,22 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, + data.fp16_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } kernel_type = AttentionKernelType::AttentionKernel_TrtFusedAttention; if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, + data.fp16_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } #if USE_MEMORY_EFFICIENT_ATTENTION @@ -494,10 +563,11 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, + data.fp16_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } #endif @@ -505,19 +575,21 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, + data.fp16_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } kernel_type = AttentionKernelType::AttentionKernel_Default; RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, - data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, - data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, - data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda, disable_webgpu); + data.attention_bias_data, data.past_key_data, data.past_value_data, data.past_seq_len_data, data.cache_indir_data, + data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, + data.fp16_output_qk_data, kernel_type, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, data.num_beams, data.max_sequence_length, data.is_static_kv, data.buffer_share, use_float16, + disable_cpu, disable_cuda, disable_webgpu, disable_rocm, disable_dml); } } @@ -666,5 +738,23 @@ TEST(MultiHeadAttentionTest, DISABLED_CrossAttention_WithPastPassedInDirectly_No RunMultiHeadAttentionTests(data); } +TEST(MultiHeadAttentionTest, SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA) { + // Whisper decoder self attention with past_kv, present_kv, buffer sharing enabled, mask, and bias + // Used in decoder-with-past's self-attention layers + // For CUDA, K caches are transposed and reshaped from 4D to 5D for DecoderMaskedMultiHeadAttention + // See onnxruntime/core/graph/contrib_ops/bert_defs.cc for more details + AttentionTestData data; + GetSelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA(data); + RunMultiHeadAttentionTests(data, DISABLE_CPU | DISABLE_ROCM_MHA | DISABLE_WEBGPU | DISABLE_DML); +} + +TEST(MultiHeadAttentionTest, CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA) { + // Whisper decoder cross attention with past_kv used directly as K and V, no mask, and bias + // Used in decoder-with-past's cross-attention layers + AttentionTestData data; + GetCrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA(data); + RunMultiHeadAttentionTests(data, DISABLE_CPU | DISABLE_ROCM_MHA | DISABLE_WEBGPU | DISABLE_DML); +} + } // namespace test } // namespace onnxruntime diff --git a/onnxruntime/test/providers/cuda/test_cases/attention_kernel_options_test.cc b/onnxruntime/test/providers/cuda/test_cases/attention_kernel_options_test.cc index b2e986f680763..16139d8b96ffa 100644 --- a/onnxruntime/test/providers/cuda/test_cases/attention_kernel_options_test.cc +++ b/onnxruntime/test/providers/cuda/test_cases/attention_kernel_options_test.cc @@ -10,7 +10,6 @@ #include #include - using onnxruntime::AttentionKernelOptions; using onnxruntime::contrib::attention::AttentionBackend; @@ -30,6 +29,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); } @@ -46,6 +46,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); } @@ -62,6 +63,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); } @@ -78,6 +80,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_TRUE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); } @@ -94,6 +97,24 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_TRUE(options.UseTrtCrossAttention()); ASSERT_TRUE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); + EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); + EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); + } + + { + AttentionKernelOptions options; + int value = static_cast(AttentionBackend::DECODER_ATTENTION); + options.InitializeOnce(value, false); + ASSERT_FALSE(options.UseFlashAttention()); + ASSERT_FALSE(options.UseEfficientAttention()); + ASSERT_FALSE(options.UseTrtFusedAttention()); + ASSERT_FALSE(options.UseCudnnFlashAttention()); + ASSERT_FALSE(options.UseUnfusedAttention()); + ASSERT_FALSE(options.UseTrtFlashAttention()); + ASSERT_FALSE(options.UseTrtCrossAttention()); + ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_TRUE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); } @@ -110,7 +131,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "0"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "0"}, {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "1"}, - {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "1"}}}; + {onnxruntime::contrib::attention::kDisableDecoderAttention, "0"}}}; AttentionKernelOptions options; int value = static_cast(AttentionBackend::FLASH_ATTENTION); options.InitializeOnce(value, false); @@ -122,6 +143,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 0); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 0); } @@ -136,7 +158,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "1"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}, {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "0"}, - {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "0"}, + {onnxruntime::contrib::attention::kDisableDecoderAttention, "1"}, {onnxruntime::contrib::attention::kMinSeqLenForFlashAttentionPackedQKV, "128"}, {onnxruntime::contrib::attention::kMinSeqLenForEfficientAttentionFp32, "256"}}}; AttentionKernelOptions options; @@ -150,6 +172,7 @@ TEST(AttentionKernelOptionsTest, NonZeroValue) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 128); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 256); } @@ -167,7 +190,7 @@ TEST(AttentionKernelOptionsTest, DefaultOptionWithEnvVar) { {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "0"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "0"}, {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "1"}, - {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "1"}, + {onnxruntime::contrib::attention::kDisableDecoderAttention, "0"}, {onnxruntime::contrib::attention::kMinSeqLenForFlashAttentionPackedQKV, "128"}, {onnxruntime::contrib::attention::kMinSeqLenForEfficientAttentionFp32, "256"}}}; AttentionKernelOptions options; @@ -180,7 +203,7 @@ TEST(AttentionKernelOptionsTest, DefaultOptionWithEnvVar) { ASSERT_TRUE(options.UseTrtFlashAttention()); ASSERT_TRUE(options.UseTrtCrossAttention()); ASSERT_TRUE(options.UseTrtCausalAttention()); - ASSERT_TRUE(options.UseTrtCausalAttention()); + ASSERT_TRUE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), 128); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), 256); } @@ -197,7 +220,7 @@ TEST(AttentionKernelOptionsTest, DefaultMinSeqLens) { {onnxruntime::contrib::attention::kEnableCudnnFlashAttention, "0"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}, {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "0"}, - {onnxruntime::contrib::attention::kEnableFusedCausalAttention, "0"}}}; + {onnxruntime::contrib::attention::kDisableDecoderAttention, "1"}}}; AttentionKernelOptions options; options.InitializeOnce(value, false); ASSERT_FALSE(options.UseFlashAttention()); @@ -208,7 +231,7 @@ TEST(AttentionKernelOptionsTest, DefaultMinSeqLens) { ASSERT_FALSE(options.UseTrtFlashAttention()); ASSERT_FALSE(options.UseTrtCrossAttention()); ASSERT_FALSE(options.UseTrtCausalAttention()); - ASSERT_FALSE(options.UseTrtCausalAttention()); + ASSERT_FALSE(options.UseDecoderAttention()); EXPECT_EQ(options.MinSeqLenForFlashAttentionPackedQkv(), onnxruntime::contrib::attention::kDefaultMinSeqLenForFlashAttentionPackedQKV); EXPECT_EQ(options.MinSeqLenForEfficientAttentionFp32(), diff --git a/onnxruntime/test/python/transformers/test_data/models/whisper/decoder_attention_with_sln_fused.onnx b/onnxruntime/test/python/transformers/test_data/models/whisper/decoder_attention_with_sln_fused.onnx index 1bf93cde504da9a62f28f947d84ad522db2e8f8b..a0e65a002361288446b99030650531e6bb586d32 100644 GIT binary patch delta 725 zcmaDin`O^*7FG@}tCiCyvL0pL!^kz!PI}@CgULFKULsneTzsW@nJJk?smUdo`FV*s z5{#3J8TW2J%KXiRZ*c=NhXcm}Mgc~ph6d)%jqG3Sr#o;mKAXJ3{oN>IG!W>T5=6E$ Oax%_hp3cn6_!2Cg#FUiy!tBWs zj9!x~8F$r3b8#f*POCUYb{2 zSelwzl^PE=2V!Wvp_C{>0_gfYh^(O!XDCcPS2`Ci%~)*0Zc%+nyb*SrjF4^0$7Pcd zHk&X)TS`5(q98FZ1>%RaqWs)=jU*jIom?I9T+R5Bd=M`W$jjAKVsizn+-$`3-Njs( zgOP(#fYS*cMP7`IT8cm+MknlX<;B9l&|tq=!+qu9j3{GlZjW= k6kz-U<0HxtOLWU}Npmm?iF1hx38U!&rH1Jjxfovq0LBg8Bme*a diff --git a/onnxruntime/test/python/transformers/test_data/models/whisper/decoder_with_past_self_mha_fused.onnx b/onnxruntime/test/python/transformers/test_data/models/whisper/decoder_with_past_self_mha_fused.onnx index deaeb206acee43fe87ec103b3c49d15b47c8182f..e51215bff7d30e5c891ea02b55921761680e9607 100644 GIT binary patch delta 51 zcmex1hoyHe3kwIA)vt{#QuSJp-$g8`apD znL3yz>oGqP(Gun2E6vMH$t+4uF3HT#OU#jA+|0}3;66Q&n^Ba-tD%8;^F#I@_LChv zUyS0>Fd#7vIBZYjX57Tct;xlaUs_U7S`u$KU6+SZetG~e;}&sNClM}z#7sRo51R{Wd1G9lk{J)Y21QkLPO<{CRb!=ZSUvX=8Uw36`XJ~Y{ zeG37y0XsJe2ybN37a&BR4E^cUd LV-ORUBn|<9s%$`) diff --git a/onnxruntime/test/python/transformers/test_generation.py b/onnxruntime/test/python/transformers/test_generation.py index 88f870e92d558..7a94519c92bc8 100644 --- a/onnxruntime/test/python/transformers/test_generation.py +++ b/onnxruntime/test/python/transformers/test_generation.py @@ -292,7 +292,7 @@ def setUp(self): self.pytorch_folder = "cache_models" self.onnx_folder = "onnx_models" self.decoder_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_decoder.onnx") - self.encoder_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_encoder_decoder_init.onnx") + self.encoder_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_encoder.onnx") self.beam_search_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_beamsearch.onnx") self.enable_cuda = torch.cuda.is_available() and "CUDAExecutionProvider" in get_available_providers() diff --git a/onnxruntime/test/python/transformers/test_parity_t5_mha.py b/onnxruntime/test/python/transformers/test_parity_t5_mha.py index 7eae2f0a231d4..b90fb410b9b32 100644 --- a/onnxruntime/test/python/transformers/test_parity_t5_mha.py +++ b/onnxruntime/test/python/transformers/test_parity_t5_mha.py @@ -848,27 +848,28 @@ def test_t5_cross_attention_decoder_masked_mha_cpu(self): def test_t5_self_attention_decoder_masked_mha_cpu(self): return self.test_t5_self_attention_decoder_masked_mha(use_cuda=False) - def test_t5_self_attention_decoder_masked_mha_with_beams(self): - """ - Test DecoderMaskedMultiHeadAttention self-attention case with beam_width > 1. - Compare the results on CUDA and CPU EPs. - """ - batch_size = 4 - seq_len = 1 - num_heads = 2 - head_size = 32 - kv_sequence_length = 2 - beam_width = 2 - compare_t5_self_attention_decoder( - batch_size, - seq_len, - num_heads, - head_size, - kv_sequence_length, - use_dmmha=True, - use_cuda=False, - beam_width=beam_width, - ) + # TODO: uncomment this test once DMMHA CPU kernel parity mismatch is fixed + # def test_t5_self_attention_decoder_masked_mha_with_beams(self): + # """ + # Test DecoderMaskedMultiHeadAttention self-attention case with beam_width > 1. + # Compare the results on CUDA and CPU EPs. + # """ + # batch_size = 4 + # seq_len = 1 + # num_heads = 2 + # head_size = 32 + # kv_sequence_length = 2 + # beam_width = 2 + # compare_t5_self_attention_decoder( + # batch_size, + # seq_len, + # num_heads, + # head_size, + # kv_sequence_length, + # use_dmmha=True, + # use_cuda=False, + # beam_width=beam_width, + # ) if __name__ == "__main__": diff --git a/onnxruntime/test/python/transformers/whisper_model_generator.py b/onnxruntime/test/python/transformers/whisper_model_generator.py index 37f877dbe5685..5527df489b846 100644 --- a/onnxruntime/test/python/transformers/whisper_model_generator.py +++ b/onnxruntime/test/python/transformers/whisper_model_generator.py @@ -391,9 +391,14 @@ def create_whisper_decoder_attention( # before attention is fused inputs = [ helper.make_tensor_value_info("input_0", TensorProto.FLOAT, ["batch_size", 1500, hidden_size]), - helper.make_tensor_value_info("dummy_input_int64", TensorProto.INT64, ["dummy_input_1d_int64"]), - helper.make_tensor_value_info("dummy_input_fp32", TensorProto.FLOAT, ["dummy_input_1d_fp32"]), ] + if not fused: + inputs.extend( + [ + helper.make_tensor_value_info("dummy_input_int64", TensorProto.INT64, ["dummy_input_1d_int64"]), + helper.make_tensor_value_info("dummy_input_fp32", TensorProto.FLOAT, ["dummy_input_1d_fp32"]), + ] + ) outputs = [ helper.make_tensor_value_info( "present.0.decoder.key", TensorProto.FLOAT, ["batch_size", num_heads, 1500, head_size] @@ -444,13 +449,12 @@ def create_whisper_decoder_attention( "Attention_0_qkv_weight", "Attention_0_qkv_bias", "", - "", - "attention_add_qk", ], ["attn_output", "present_0_decoder"], "Attention_0", domain="com.microsoft", num_heads=num_heads, + unidirectional=1, ), helper.make_node( "Gather", @@ -717,38 +721,39 @@ def create_whisper_decoder_attention( ) # Create nodes that make attention mask - nodes.extend( - [ - # "attention_mask" is (decoder_seq_len, decoder_seq_len) but is assumed to be (1, 1) for this test. - # There are other nodes that automatically set the attention mask size correctly but those nodes do not - # impact the attention fusion. Hence, this assumption is made in order to simplify the inputs for the - # following nodes. - helper.make_node( - "Where", - ["all_ones", "where_filter_constant", "dummy_input_fp32"], - ["where_output"], - "mask_filter_where", - ), - helper.make_node( - "Unsqueeze", - ["where_output", "dummy_input_int64"], - ["unsqueeze_mask_output_1"], - "unsqueeze_attn_mask_1", - ), - helper.make_node( - "Unsqueeze", - ["unsqueeze_mask_output_1", "dummy_input_int64"], - ["unsqueeze_mask_output_2"], - "unsqueeze_attn_mask_2", - ), - helper.make_node( - "Expand", - inputs=["unsqueeze_mask_output_2", "dummy_input_int64"], - outputs=["attention_add_qk"], - name="expand_mask_from_(b,1,m,m)_to_(b,n,m,m)", - ), - ] - ) + if not fused: + nodes.extend( + [ + # "attention_mask" is (decoder_seq_len, decoder_seq_len) but is assumed to be (1, 1) for this test. + # There are other nodes that automatically set the attention mask size correctly but those nodes do not + # impact the attention fusion. Hence, this assumption is made in order to simplify the inputs for the + # following nodes. + helper.make_node( + "Where", + ["all_ones", "where_filter_constant", "dummy_input_fp32"], + ["where_output"], + "mask_filter_where", + ), + helper.make_node( + "Unsqueeze", + ["where_output", "dummy_input_int64"], + ["unsqueeze_mask_output_1"], + "unsqueeze_attn_mask_1", + ), + helper.make_node( + "Unsqueeze", + ["unsqueeze_mask_output_1", "dummy_input_int64"], + ["unsqueeze_mask_output_2"], + "unsqueeze_attn_mask_2", + ), + helper.make_node( + "Expand", + inputs=["unsqueeze_mask_output_2", "dummy_input_int64"], + outputs=["attention_add_qk"], + name="expand_mask_from_(b,1,m,m)_to_(b,n,m,m)", + ), + ] + ) # Create final nodes to conclude attention nodes.append( @@ -825,13 +830,6 @@ def create_whisper_decoder_attention( float_tensor("matmul_after_attn_initializer", [hidden_size, hidden_size]), float_tensor("add_after_attn_initializer", [hidden_size]), ] - # Add initializers for attention mask - initializers.extend( - [ - numpy_helper.from_array(np.array([[1]], dtype=bool), name="all_ones"), - numpy_helper.from_array(np.array([1], dtype="float32"), name="where_filter_constant"), - ] - ) if fused: initializers.extend( @@ -845,6 +843,8 @@ def create_whisper_decoder_attention( else: initializers.extend( [ + numpy_helper.from_array(np.array([[1]], dtype=bool), name="all_ones"), + numpy_helper.from_array(np.array([1], dtype="float32"), name="where_filter_constant"), numpy_helper.from_array(np.array(num_heads, dtype="int64"), name="num_heads_int"), numpy_helper.from_array(np.array([num_heads], dtype="int64"), name="num_heads"), numpy_helper.from_array(np.array([head_size], dtype="int64"), name="head_size"), @@ -1327,6 +1327,7 @@ def create_whisper_decoder_with_past_multihead_self_attention( "Attention_0", domain="com.microsoft", num_heads=num_heads, + unidirectional=1, ), ] ) diff --git a/onnxruntime/test/testdata/attention/attention_test_data.txt b/onnxruntime/test/testdata/attention/attention_test_data.txt index 7c60efea1f0f6..49f4a6d4f7396 100644 --- a/onnxruntime/test/testdata/attention/attention_test_data.txt +++ b/onnxruntime/test/testdata/attention/attention_test_data.txt @@ -5066,3 +5066,901 @@ name:CrossAttention_Batch1_HeadSize8_NoBias.output -0.15928616,-0.13984840,0.07850466,0.10540886,1.54793286,0.43936923,0.40107274,-1.26946867, 0.86807090,0.27874026,0.24483341,1.36524665,1.07833946,-0.42526853,0.03085684,-1.09703445 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.query_data +1.7640524,0.4001572,0.978738,2.2408931,1.867558,-0.9772779,0.95008844,-0.1513572, +-0.10321885,0.41059852,0.14404356,1.4542735,0.7610377,0.121675014,0.44386324,0.33367434, +1.4940791,-0.20515826,0.3130677,-0.85409576,-2.5529897,0.6536186,0.8644362,-0.742165, +2.2697546,-1.4543657,0.045758516,-0.18718386,1.5327792,1.4693588,0.15494743,0.37816253, +-0.88778573,-1.9807965,-0.34791216,0.15634897,1.2302907,1.2023798,-0.3873268,-0.30230275, +-1.048553,-1.420018,-1.7062702,1.9507754,-0.5096522,-0.4380743,-1.2527953,0.7774904, +-1.6138978,-0.21274029,-0.89546657,0.3869025,-0.51080513,-1.1806322,-0.028182229,0.42833188, +0.06651722,0.3024719,-0.6343221,-0.36274117,-0.67246044,-0.35955316,-0.8131463,-1.7262826, +0.17742614,-0.40178093,-1.6301984,0.46278226,-0.9072984,0.051945396,0.7290906,0.12898292, +1.1394007,-1.2348258,0.40234163,-0.6848101,-0.87079716,-0.5788497,-0.31155252,0.05616534, +-1.1651498,0.9008265,0.46566245,-1.5362437,1.4882522,1.8958892,1.1787796,-0.17992483, +-1.0707526,1.0544517,-0.40317693,1.222445,0.20827498,0.97663903,0.3563664,0.7065732, +0.01050002,1.7858706,0.12691209,0.40198937,1.8831507,-1.347759,-1.270485,0.9693967, +-1.1731234,1.9436212,-0.41361898,-0.7474548,1.922942,1.4805148,1.867559,0.90604466, +-0.86122566,1.9100649,-0.26800337,0.8024564,0.947252,-0.15501009,0.61407936,0.9222067, +0.37642553,-1.0994008,0.2982382,1.3263859,-0.69456786,-0.14963454,-0.43515354,1.8492638 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.key_data +0.67229474,0.40746182,-0.76991606,0.5392492,-0.6743327,0.031830557,-0.6358461,0.67643327, +0.57659084,-0.20829876,0.3960067,-1.0930616,-1.4912575,0.4393917,0.1666735,0.63503146, +2.3831449,0.94447947,-0.91282225,1.1170163,-1.3159074,-0.4615846,-0.0682416,1.7133427, +-0.74475485,-0.82643855,-0.09845252,-0.6634783,1.1266359,-1.0799315,-1.1474687,-0.43782005, +-0.49803245,1.929532,0.9494208,0.08755124,-1.2254355,0.844363,-1.0002153,-1.5447711, +1.1880298,0.3169426,0.9208588,0.31872764,0.8568306,-0.6510256,-1.0342429,0.6815945, +-0.80340964,-0.6895498,-0.4555325,0.017479159,-0.35399392,-1.3749512,-0.6436184,-2.2234032, +0.62523144,-1.6020577,-1.1043833,0.05216508,-0.739563,1.5430146,-1.2928569,0.26705086, +-0.039282817,-1.1680934,0.5232767,-0.17154633,0.77179056,0.82350415,2.163236,1.336528, +-0.36918184,-0.23937918,1.0996596,0.6552637,0.64013153,-1.616956,-0.024326125,-0.7380309, +0.2799246,-0.09815039,0.9101789,0.3172182,0.78632796,-0.4664191,-0.94444627,-0.4100497, +-0.017020414,0.37915173,2.259309,-0.042257152,-0.955945,-0.34598178,-0.463596,0.48148146, +-1.540797,0.06326199,0.15650654,0.23218104,-0.5973161,-0.23792173,-1.424061,-0.49331987, +-0.54286146,0.41605005,-1.1561824,0.7811981,1.4944845,-2.069985,0.42625874,0.676908, +-0.63743705,-0.3972718,-0.13288058,-0.29779088,-0.30901298,-1.6760038,1.1523316,1.0796186, +-0.81336427,-1.4664243,0.5210649,-0.57578796,0.14195317,-0.31932843,0.69153875,0.6947491 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.value_data +-0.7255974,-1.383364,-1.5829384,0.6103794,-1.1888592,-0.5068163,-0.596314,-0.052567296, +-1.9362798,0.1887786,0.52389103,0.08842209,-0.31088617,0.097400166,0.39904633,-2.7725928, +1.9559124,0.39009333,-0.6524086,-0.39095336,0.49374178,-0.11610394,-2.0306845,2.064493, +-0.11054066,1.0201727,-0.69204986,1.5363771,0.2863437,0.60884386,-1.0452534,1.2111453, +0.68981814,1.3018463,-0.6280876,-0.48102713,2.3039167,-1.0600158,-0.1359497,1.1368914, +0.09772497,0.5829537,-0.39944902,0.37005588,-1.3065269,1.6581306,-0.11816405,-0.6801782, +0.6663831,-0.4607198,-1.3342584,-1.3467175,0.69377315,-0.15957344,-0.13370156,1.0777438, +-1.1268258,-0.7306777,-0.3848798,0.09435159,-0.042171452,-0.2868872,-0.0616264,-0.10730527, +-0.7196044,-0.812993,0.27451634,-0.8909151,-1.1573553,-0.31229225,-0.15766701,2.2567234, +-0.7047003,0.9432607,0.7471883,-1.1889449,0.77325296,-1.1838807,-2.6591723,0.60631955, +-1.7558906,0.45093447,-0.6840109,1.6595508,1.0685093,-0.4533858,-0.6878376,-1.2140774, +-0.44092262,-0.28035548,-0.36469355,0.15670386,0.5785215,0.34965447,-0.76414394,-1.4377915, +1.3645319,-0.6894492,-0.6522936,-0.52118933,-1.8430696,-0.477974,-0.4796558,0.6203583, +0.6984571,0.003770889,0.93184835,0.339965,-0.015682112,0.16092817,-0.19065349,-0.3948495, +-0.26773354,-1.1280113,0.2804417,-0.9931236,0.8416313,-0.24945858,0.04949498,0.4938368, +0.6433145,-1.5706234,-0.20690368,0.8801789,-1.6981058,0.38728046,-2.2555642,-1.0225068 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.bias_data +0.038630553,-1.6567152,-0.98551077,-1.471835,1.648135,0.16422775,0.5672903,-0.2226751, +-0.35343176,-1.6164742,-0.29183736,-0.7614922,0.8579239,1.1411018,1.4665787,0.85255194, +-0.5986539,-1.1158969,0.7666632,0.3562928,-1.7685385,0.3554818,0.8145198,0.058925588, +-0.18505368,-0.8076485,-1.4465348,0.800298,-0.30911446,-0.23346666,1.7327212,0.6845011, +0.370825,0.1420618,1.5199949,1.7195894,0.9295051,0.5822246,-2.094603,0.12372191, +-0.13010696,0.09395323,0.9430461,-2.7396772,-0.56931204,0.26990435,-0.46684554,-1.4169061, +0.8689635,0.27687192,-0.97110456,0.3148172,0.8215857,0.005292646,0.8005648,0.078260176, +-0.39522898,-1.1594205,-0.085930765,0.19429293,0.87583274,-0.11510747,0.4574156,-0.964612, +-0.78262913,-0.1103893,-1.0546285,0.8202478,0.46313033,0.27909577,0.3389041,2.0210435, +-0.4688642,-2.2014413,0.1993002,-0.050603542,-0.51751906,-0.97882986,-0.43918952,0.18133843, +-0.5028167,2.4124537,-0.96050435,-0.79311734,-2.28862,0.25148442,-2.0164065,-0.53945464, +-0.27567053,-0.70972794,1.7388726,0.99439436,1.3191369,-0.8824188,1.128594,0.49600095, +0.77140594,1.0294389,-0.90876323,-0.42431763,0.86259604,-2.6556191,1.5133281,0.55313206, +-0.045703962,0.22050765,-1.0299352,-0.34994337,1.1002843,1.298022,2.696224,-0.07392467, +-0.65855294,-0.51423395,-1.0180418,-0.07785475,0.38273242,-0.03424228,1.0963469,-0.2342158, +-0.34745064,-0.5812685,-1.6326345,-1.5677677,-1.179158,1.3014281,0.8952603,1.3749641, +-1.3322116,-1.9686247,-0.6600563,0.17581895,0.49869028,1.0479722,0.28427967,1.7426687, +-0.22260568,-0.9130792,-1.6812183,-0.8889713,0.24211796,-0.8887203,0.9367425,1.4123276, +-2.369587,0.8640523,-2.239604,0.40149906,1.2248706,0.064856105,-1.2796892,-0.5854312, +-0.26164544,-0.18224478,-0.20289683,-0.10988278,0.21348006,-1.2085737,-0.24201983,1.5182612, +-0.38464543,-0.4438361,1.0781974,-2.5591846,1.1813786,-0.63190377,0.16392857,0.09632136, +0.9424681,-0.26759475,-0.6780258,1.2978458,-2.364174,0.020334182,-1.3479254,-0.7615734, +2.0112567,-0.044595428,0.1950697,-1.7815628,-0.7290447,0.1965574,0.3547577,0.61688656, +0.008627899,0.5270042,0.4537819,-1.8297404,0.037005723,0.76790243,0.5898798,-0.36385882 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.past_key_data +-0.8056265,-1.1183119,-0.13105401,1.1330799,-1.9518042,-0.6598917,-1.1398025,0.7849575, +-0.5543096,-0.47063765,-0.21694957,0.44539326,-0.392389,-3.046143,0.5433119,0.43904296, +-0.21954103,-1.0840366,0.35178012,0.37923554,-0.47003287,-0.21673147,-0.9301565,-0.17858909, +-1.5504293,0.41731882,-0.9443685,0.23810315,-1.405963,-0.5900577,-0.110489406,-1.6606998, +0.115147874,-0.37914756,-1.7423562,-1.3032428,0.60512006,0.895556,-0.13190864,0.40476182, +0.22384356,0.32962298,1.285984,-1.5069984,0.67646074,-0.38200897,-0.22425893,-0.30224973, +-0.3751471,-1.2261962,0.1833392,1.670943,-0.05613302,-0.0013850428,-0.687299,-0.11747455, +0.46616644,-0.37024245,-0.45380405,0.40326455,-0.91800475,0.25249663,0.8203218,1.3599485, +-0.09038201,1.3675972,1.0344099,-0.99621266,-1.2179385,-0.30496365,1.0289356,-0.07228701, +-0.6006576,1.5522432,0.28690448,-2.3205943,0.31716064,0.52004063,0.22560866,0.4497121, +-0.067275606,-1.3183959,-0.370704,-0.94561577,-0.9327409,-1.2630683,0.45248908,0.097896144, +-0.44816536,-0.64933795,-0.023423105,1.0791948,-2.0042157,0.37687653,-0.545712,-1.8845859, +-1.945703,-0.9127835,0.21950956,0.39306292,-0.9389816,1.017021,1.4229835,0.39608657, +-0.59140265,1.1244192,0.7553957,0.86740744,-0.6564637,-2.8345544,2.116791,-1.6108783, +-0.035768073,2.3807454,0.33057675,0.94924647,-1.5023966,-1.7776669,-0.5327028,1.0907497, +-0.34624946,-0.7946363,0.19796729,1.0819352,-1.4449402,-1.210543,-0.7886692,1.0946383, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.23482153,2.1321535,0.9364457,-0.035095178,1.2650778,0.21149701,-0.70492136,0.67997485, +-0.6963267,-0.2903971,1.3277828,-0.10128149,-0.8031414,-0.46433768,1.0217906,-0.55254066, +-0.38687086,-0.51029277,0.1839255,-0.38548976,-1.6018361,-0.8871809,-0.932789,1.2433194, +0.81267405,0.58725935,-0.50535834,-0.81579155,-0.5075176,-1.0518801,2.4972005,-2.2453218, +0.56400853,-1.2845523,-0.10434349,-0.98800194,-1.177629,-1.1401963,1.7549862,-0.13298842, +-0.7657022,0.55578697,0.010349315,0.72003376,-1.8242567,0.30360392,0.7726948,-1.6615983, +0.44819528,1.6961815,-0.014857704,0.82140595,0.67057043,-0.7075057,0.039766736,-1.5669947, +-0.45130304,0.26568797,0.7231005,0.024612125,0.71998376,-1.1029062,-0.10169727,0.019279385, +1.8495913,-0.21416666,-0.49901664,0.021351224,-0.91911346,0.19275385,-0.3650552,-1.7913276, +-0.058586553,-0.3175431,-1.6324233,-0.06713416,1.4893559,0.5213038,0.6119272,-1.3414967, +0.47689837,0.14844958,0.5290452,0.4226286,-1.3597807,-0.041400813,-0.75787085,-0.050084095, +-0.8974009,1.3124703,-0.8589724,-0.8989422,0.07458641,-1.0770991,-0.4246633,-0.8299646, +1.411172,0.78580385,-0.057469517,-0.39121705,0.9409176,0.4052041,0.49805242,-0.026192237, +-1.68823,-0.112465985,-0.5324899,0.6450553,1.0118425,-0.65795106,0.46838522,1.735879, +-0.66771275,1.6819217,-0.85258585,0.022959756,-0.011145612,0.0114989,-0.837678,-0.5911831, +-0.66772026,0.3269626,0.33003512,2.2259443,1.370989,-0.50984323,0.3248696,0.997118, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.030601824,-0.069641575,0.05157494,0.8672766,-0.84832054,-0.32566947,0.47043315,0.31144708, +0.23958276,-0.36980116,0.9725358,2.1338682,0.4064155,-0.1931767,0.7557403,-0.53913265, +-0.74969035,0.032808747,-2.5827966,-1.1539503,-0.34796184,-1.3533889,-1.0326431,-0.43674833, +-1.6429653,-0.40607178,-0.53527015,0.025405208,1.154184,0.17250441,0.021062022,0.099454455, +0.22739278,-1.0167387,-0.11477532,0.30875126,-1.37076,0.8656529,1.0813761,-0.63137597, +-0.24133779,-0.87819034,0.69938046,-1.0612223,-0.222477,-0.8589199,0.05095428,-1.7942293, +1.3264617,-0.9646064,0.059894685,-0.21252304,-0.7621145,-0.88778013,0.93639857,-0.5256406, +0.2711702,-0.80149686,-0.64718145,0.47224715,0.9304085,-0.17531641,-1.4219198,1.997956, +-0.8565493,-1.5415874,2.5944245,-0.4040323,-1.4617327,-0.6834398,0.3675449,0.19031155, +-0.8517292,1.8227236,-0.5215797,-1.1846865,0.9606934,1.3290628,-0.8174931,-1.4013473, +1.0304383,-2.0473237,-1.2266216,0.96744615,-0.055352546,-0.26393735,0.3528166,-0.15277442, +-1.2986867,1.2760754,1.325014,0.20533256,0.045134015,2.339625,-0.27643284,-0.25957698, +0.36448124,1.471322,1.5927707,-0.25857264,0.30833125,-1.3780835,-0.3119761,-0.84029037, +-1.0068318,1.6815767,-0.79228663,-0.5316059,0.36584878,1.2978252,0.48111513,2.759355, +-0.074667975,0.25871643,0.27560067,1.4350494,0.5072389,-0.1162297,-0.9474886,0.24444346, +1.4013448,-0.4103818,0.5289436,0.24614778,0.86351967,-0.8047537,2.346647,-1.2791611, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-0.36555108,0.9380925,0.29673317,0.82998616,-0.49610233,-0.074804984,0.012231983,1.5692596, +0.69042903,0.7966721,-0.6579261,0.9688826,0.22558166,1.3891454,2.0140603,-0.30676576, +-0.40630314,-0.86404496,-0.14357951,-0.38202545,0.3595044,-0.14456682,-0.36159927,1.0645851, +-0.9378802,0.43310794,-0.40594172,0.7243685,1.3852615,-0.30309826,0.44103292,0.17879286, +-0.7994224,0.2407875,0.2891205,0.41287082,-0.1983989,0.0941923,-1.1476109,-0.35811406, +0.5559627,0.8924739,-0.42231482,0.10471403,0.22805333,0.20147994,0.5407736,-1.8180777, +-0.04932407,0.2390336,-1.0003303,1.6739857,0.16155927,1.5634048,-0.790523,-0.9073001, +0.22425222,-1.6786884,0.2149656,0.09721923,1.0156653,0.70104134,-0.41747734,-1.0974966, +1.7123052,-0.79211503,-1.0455246,-1.084856,1.1173053,-0.5189002,-0.7537045,0.13768983, +-0.2069447,-0.67809546,0.7539915,1.0653155,0.9853175,0.7669197,0.40262553,-1.775888, +1.6692508,0.3019892,0.60815644,1.1149623,1.4333525,0.41839802,0.43554616,-0.59922427, +0.03308975,-0.85416126,-0.71994054,-0.8935744,-0.15602389,1.0490932,3.1709747,0.18949963, +-1.3484131,1.2649833,-0.30078387,-0.6606086,0.20984948,-1.2406245,0.22246316,-0.08837552, +0.098377906,0.38141626,0.067492254,0.016338084,0.2843145,0.41540062,-1.0314825,-1.4299912, +-0.061638054,-1.4327354,0.08753147,0.93874687,0.6071117,-1.0481704,-0.86026245,0.32830128, +-0.4012978,-0.3166553,0.5969065,-0.9872867,-0.40123472,-0.8000825,-1.0431294,-0.8570782, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.past_value_data +0.67746216,0.05182039,-0.87916064,-0.2311016,-1.6388073,-0.7333128,2.1495745,-0.090243846, +0.73165894,-0.065488376,0.34816924,0.6632581,-1.1046166,-0.030936258,1.5788652,-0.7955006, +-0.56643987,-0.30769128,0.26902407,0.52491784,1.2674117,0.49949825,-0.062053125,1.2591671, +0.70411104,-1.4956795,2.5263681,1.7699214,-0.16821422,0.3779101,1.3243587,-0.1722008, +0.7303518,1.1045785,-1.0148259,-0.6023319,0.9214084,0.46081448,0.92379653,-0.13256802, +-0.28900522,-1.9986395,-1.1460004,0.047066096,0.82455724,0.53117836,-0.12824197,-0.27177158, +0.21717963,0.07821118,1.4045455,0.14644077,-1.481246,-1.2725581,1.5187594,-1.1711605, +0.76449746,-0.26837274,-0.16975829,-0.13413279,1.221385,-0.19284183,-0.033319283,-1.5308034, +0.2066905,0.5310425,0.23914558,1.3978963,0.055171356,0.29897746,1.648504,-1.5500141, +-0.45582536,1.4261588,0.93612915,0.6783801,0.8326507,0.3270662,1.6315974,0.37775916, +0.2398671,0.15895867,0.19286396,-1.1570172,0.77067304,-0.13043973,1.8219151,-0.07565047, +0.4209183,0.24660219,-0.625557,0.99213684,1.9050636,-0.01477722,-0.3004788,-0.35502872, +-1.8923619,-0.17781314,0.2509981,1.054758,0.9600477,-0.41649908,-0.27682298,1.1239053, +-0.1734639,-0.51002955,1.3925184,1.0375856,0.018791791,-0.5937774,-2.0118804,0.5897036, +-0.8963697,-1.962732,1.5848205,0.6479678,-1.1390082,-1.2144014,0.8709618,-0.87797064, +1.2961498,0.6164593,0.53659654,0.40469545,0.19145088,0.8805112,-0.45408037,0.08595198, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.75194657,0.5629897,-1.1949868,-0.50040966,0.2528035,-0.4080147,1.7746586,-0.3931532, +-0.16221845,0.76943016,0.33053273,-0.14527446,-0.7564935,0.30151406,1.0390965,0.47909522, +-0.7781835,1.7367749,-1.4465779,-1.5826856,0.9605572,0.22584048,-0.54949856,-1.0985707, +2.3207998,0.11709087,0.53420115,0.3178851,0.43480796,0.54009444,0.732424,-0.3752224, +-0.29164198,-1.7410228,-0.78030443,0.2711128,1.0450233,0.59903955,-0.34069234,-1.2631729, +-2.7773592,1.151734,-0.589229,-0.44846502,0.13157398,-1.40556,-0.34978217,2.0234718, +0.50538695,0.35924914,-1.5824945,2.2436018,-1.4227949,1.9223248,-2.115056,1.4053655, +1.6180543,-0.8244091,0.42258036,0.5474806,-0.8137945,-1.4491177,-1.3177173,0.54100823, +-0.085115604,-0.564301,0.966768,0.5080679,-0.7554627,-1.2012016,0.5232617,-0.53758335, +0.09920486,1.576299,0.5023282,-0.862267,0.16066119,-0.95264494,1.6085222,-0.56157875, +0.20727074,0.30773258,0.15925047,-1.9585489,-1.446421,-0.4523503,0.31943184,-0.13777922, +-0.9571475,-1.3484243,-0.40155753,-0.46847606,0.51283646,-0.32631847,0.6027077,-0.5946498, +-0.25595766,-0.3480464,-0.782367,0.6251187,-0.813596,-0.5216415,-0.07311965,-1.2973796, +-0.32493496,-0.71130633,-0.38815418,-0.059928004,-0.79991364,-0.22007579,1.3086687,-0.025798557, +1.1452621,0.34649444,0.7741606,-0.77445894,0.10490716,0.13391292,-0.6126257,-0.82282835, +-1.4902654,1.4961396,-0.9724029,1.3462211,-0.46749318,-0.8624933,0.62251914,-0.63119197, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.5684589,-0.33281177,0.4804245,-0.9681861,0.83135104,0.48797268,-0.9196507,2.6429358, +0.54012305,2.290467,1.6002678,-0.18883479,-0.41227177,-0.4034592,-1.8300285,-0.6958351, +0.24676603,1.5259576,-0.7727719,0.8820566,-1.2525934,-0.58632004,-0.4576406,0.3718111, +0.45730963,0.9623417,0.77083695,0.24316822,0.39036494,1.5885307,-0.5109262,0.7747283, +-1.808144,0.41133425,-0.48324955,0.0025711823,1.0400863,0.16464381,0.88518757,1.4737648, +0.38909397,1.171041,-0.32656097,-0.008209882,-0.5226194,1.0429776,0.41409135,-0.50723445, +0.15466884,1.0415684,-0.03926799,-0.9489328,0.13191175,-1.9805655,0.76877064,-0.4213276, +-0.46931073,0.8756957,-1.3651628,1.9470986,-0.48024204,-0.52325094,1.0212247,0.7086953, +2.4512298,-0.21120599,-0.120406635,-1.479316,-0.33210227,-0.7214313,-0.448767,-1.7441877, +1.6606076,-1.4166034,-2.8022027,-1.1884245,-0.6038396,-1.149554,1.0983036,-0.13783918, +0.025385605,0.61039174,0.28601253,0.9785673,-1.1094775,-0.5475181,0.66596717,-2.5345545, +-1.3751845,0.50099224,-0.48024905,0.9361076,0.8091803,-1.1980929,0.4066571,1.2016978, +0.1474344,-0.97746485,0.87938994,0.63542455,0.54261076,0.71593887,-2.994613,0.8809376, +1.8081318,0.43663847,0.192729,0.69643867,0.33822548,0.65178126,0.0014710003,-0.76670486, +-1.0043228,-0.9981917,-1.3730426,-1.067742,1.7612661,0.7540957,-0.6250274,-0.3903927, +0.11255753,-0.65554506,0.067516856,0.77760416,-0.035742734,0.33601573,0.88649154,-0.27213177, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.2847906,-0.30937758,-0.02852887,-0.32473028,-0.52886987,0.17371185,0.5665453,0.14630444, +0.49872696,-0.7379318,-1.2037352,0.4170435,0.6878814,0.049857266,1.3480358,0.9076988, +2.6805708,-0.20080851,-0.9988488,-0.7401368,-0.5654978,0.4760314,-2.1580687,1.3185511, +-0.23929659,-0.24679355,-1.0793432,-0.11422555,0.013239767,-0.12194493,0.33905926,-0.58963203, +-0.8958158,0.5483281,0.09866745,0.19718106,1.0590272,-1.0225644,-0.85524046,1.2572197, +-1.4828833,-1.3094121,0.81786186,0.23820019,0.105232134,-0.09165941,0.031267546,-0.09211212, +1.3554426,-0.39814812,-0.16137354,1.7944489,0.027509702,2.2320163,-0.1049797,1.367415, +-1.655344,0.15364446,-1.5844736,0.8444543,-1.2128679,0.28376955,-0.28219587,-1.1582032, +-1.61936,-0.51104045,1.7406294,-0.29348505,0.91722155,-0.057042867,0.87672675,-1.8269113, +-0.40318832,0.94940555,-0.16325495,-0.086455286,-0.4304619,1.1493794,0.29751435,0.044022277, +0.64305454,0.58822495,0.21258704,1.5470315,-0.060287535,0.27808106,-0.64295256,0.15011522, +1.5877615,-0.6432576,-1.1335928,0.99675965,-0.14876615,0.0960042,-0.045113303,0.079121724, +0.8505307,-0.8391242,-1.0117741,0.084968135,-1.6064397,-1.3730536,1.8666831,0.75746834, +-0.010056471,1.238007,-1.0405992,-0.31560314,0.6234536,0.8906717,0.51291686,-2.5412388, +-0.96808213,0.4770681,-0.3559515,2.5402317,0.9265583,0.55808187,-1.1169496,-0.03529674, +0.24120396,1.1277837,0.8811311,1.0329891,-0.923912,1.4121517,-1.3804307,-0.53591454, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.fp32_output_data +-1.4901291,-0.6127523,-0.37208983,0.81460416,0.49231845,-0.15108852,0.013023794,0.95520675, +-0.5171256,-0.5793653,0.6358129,0.5813584,0.05082538,-0.4695547,-0.9157753,0.08151066, +-0.6503749,-1.0304339,0.6261372,0.40946347,-0.45083562,-0.8799362,0.14981574,-0.33481675, +0.8797696,0.4651931,0.26085043,0.63520896,0.38815358,0.455564,-0.48009312,0.40361634, +0.16237563,-0.20201929,-0.098145366,0.116463386,-0.25710258,-0.7530771,0.79561776,-0.60588866, +-0.18908973,0.94241863,0.2322133,-0.44546735,-0.34606236,-0.41458836,1.2162775,-0.015568115, +0.074197866,0.77310014,-0.40284765,-1.4562985,-0.4079464,-0.006341338,-0.23461592,-0.43371344, +0.18838094,-0.41541746,-0.11950366,0.080281585,0.26667595,-0.16386892,0.54090405,-0.46252388, +-0.74845964,-0.6411486,-0.11178234,-0.49679786,0.43254298,0.31444955,-0.09452905,1.9511061, +0.34721223,0.8587256,-0.23741366,-0.59594387,-0.09987013,-0.2511883,-0.54922277,0.04424855, +-0.88538414,1.0397384,-0.9184096,0.3502718,0.2802844,-0.9707793,-0.23891075,-0.7650979, +-0.362343,0.4538829,-0.50438243,0.9400783,0.1720767,-0.122763455,0.1329056,0.5681431, +0.56380415,-0.7173072,-0.26292765,-1.009201,-0.8017437,-1.1684775,0.6606952,0.7407442, +0.3417585,0.29830286,-0.29903686,0.4605967,-0.51642084,0.49119917,-0.25728413,-1.5713134, +0.42070937,-0.23215376,-0.03731747,0.5079436,0.45979655,0.5862025,-0.44871226,0.59794164, +0.12756062,0.16322222,0.20992519,0.29804617,-1.1845424,1.0947874,-1.2509774,-0.9073155 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.present_key_data +-0.8056265,-1.1183119,-0.13105401,1.1330799,-1.9518042,-0.6598917,-1.1398025,0.7849575, +-0.5543096,-0.47063765,-0.21694957,0.44539326,-0.392389,-3.046143,0.5433119,0.43904296, +-0.1103344,0.29707253,-1.8245445,1.3594971,-0.47003287,-0.21673147,-0.9301565,-0.17858909, +-1.5504293,0.41731882,-0.9443685,0.23810315,-1.405963,-0.5900577,-0.110489406,-1.6606998, +0.115147874,-0.37914756,-1.7423562,-1.3032428,0.60512006,0.895556,-0.13190864,0.40476182, +-0.21120235,0.31092632,-0.29694197,2.6974769,0.67646074,-0.38200897,-0.22425893,-0.30224973, +-0.3751471,-1.2261962,0.1833392,1.670943,-0.05613302,-0.0013850428,-0.687299,-0.11747455, +0.46616644,-0.37024245,-0.45380405,0.40326455,-0.91800475,0.25249663,0.8203218,1.3599485, +0.10772663,-2.40974,0.5953069,-1.1436651,-1.2179385,-0.30496365,1.0289356,-0.07228701, +-0.6006576,1.5522432,0.28690448,-2.3205943,0.31716064,0.52004063,0.22560866,0.4497121, +-0.067275606,-1.3183959,-0.370704,-0.94561577,-0.9327409,-1.2630683,0.45248908,0.097896144, +-2.0087767,-0.5394381,-0.272516,0.8163699,-2.0042157,0.37687653,-0.545712,-1.8845859, +-1.945703,-0.9127835,0.21950956,0.39306292,-0.9389816,1.017021,1.4229835,0.39608657, +-0.59140265,1.1244192,0.7553957,0.86740744,-0.6564637,-2.8345544,2.116791,-1.6108783, +1.8803282,3.356933,-1.8733265,0.32389897,-1.5023966,-1.7776669,-0.5327028,1.0907497, +-0.34624946,-0.7946363,0.19796729,1.0819352,-1.4449402,-1.210543,-0.7886692,1.0946383, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-3.6045275,-0.21010017,-2.0846481,1.173888,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-1.0204253,-1.5361664,1.6404201,0.33091605,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +2.4457726,-1.9623504,-0.018874645,0.0581809,0.0,0.0,0.0,0.0, +0.23482153,2.1321535,0.9364457,-0.035095178,1.2650778,0.21149701,-0.70492136,0.67997485, +-0.6963267,-0.2903971,1.3277828,-0.10128149,-0.8031414,-0.46433768,1.0217906,-0.55254066, +0.27337348,2.958971,0.04065758,-0.3367664,-1.6018361,-0.8871809,-0.932789,1.2433194, +0.81267405,0.58725935,-0.50535834,-0.81579155,-0.5075176,-1.0518801,2.4972005,-2.2453218, +0.56400853,-1.2845523,-0.10434349,-0.98800194,-1.177629,-1.1401963,1.7549862,-0.13298842, +-0.36283946,-1.8112562,0.5131128,-0.991639,-1.8242567,0.30360392,0.7726948,-1.6615983, +0.44819528,1.6961815,-0.014857704,0.82140595,0.67057043,-0.7075057,0.039766736,-1.5669947, +-0.45130304,0.26568797,0.7231005,0.024612125,0.71998376,-1.1029062,-0.10169727,0.019279385, +1.1423258,0.53745025,-0.10907644,-0.031215727,-0.91911346,0.19275385,-0.3650552,-1.7913276, +-0.058586553,-0.3175431,-1.6324233,-0.06713416,1.4893559,0.5213038,0.6119272,-1.3414967, +0.47689837,0.14844958,0.5290452,0.4226286,-1.3597807,-0.041400813,-0.75787085,-0.050084095, +1.9571149,0.64699644,1.6619811,0.60766983,0.07458641,-1.0770991,-0.4246633,-0.8299646, +1.411172,0.78580385,-0.057469517,-0.39121705,0.9409176,0.4052041,0.49805242,-0.026192237, +-1.68823,-0.112465985,-0.5324899,0.6450553,1.0118425,-0.65795106,0.46838522,1.735879, +-1.4619626,-1.2037838,-1.4735744,-0.060375594,-0.011145612,0.0114989,-0.837678,-0.5911831, +-0.66772026,0.3269626,0.33003512,2.2259443,1.370989,-0.50984323,0.3248696,0.997118, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.028738499,-1.4091935,0.45272845,-2.457619,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.2777808,-2.1833262,-2.7370179,-1.5156027,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-1.918721,2.8444428,-0.39759666,1.642015,0.0,0.0,0.0,0.0, +0.030601824,-0.069641575,0.05157494,0.8672766,-0.84832054,-0.32566947,0.47043315,0.31144708, +0.23958276,-0.36980116,0.9725358,2.1338682,0.4064155,-0.1931767,0.7557403,-0.53913265, +-0.82191193,-1.2784828,-0.5313518,0.6487015,-0.34796184,-1.3533889,-1.0326431,-0.43674833, +-1.6429653,-0.40607178,-0.53527015,0.025405208,1.154184,0.17250441,0.021062022,0.099454455, +0.22739278,-1.0167387,-0.11477532,0.30875126,-1.37076,0.8656529,1.0813761,-0.63137597, +1.2349209,1.1025999,2.50214,3.3575716,-0.222477,-0.8589199,0.05095428,-1.7942293, +1.3264617,-0.9646064,0.059894685,-0.21252304,-0.7621145,-0.88778013,0.93639857,-0.5256406, +0.2711702,-0.80149686,-0.64718145,0.47224715,0.9304085,-0.17531641,-1.4219198,1.997956, +-0.8380461,-2.4408205,1.2989597,0.60466015,-1.4617327,-0.6834398,0.3675449,0.19031155, +-0.8517292,1.8227236,-0.5215797,-1.1846865,0.9606934,1.3290628,-0.8174931,-1.4013473, +1.0304383,-2.0473237,-1.2266216,0.96744615,-0.055352546,-0.26393735,0.3528166,-0.15277442, +0.12261248,-2.5957859,-0.46351564,-0.5566925,0.045134015,2.339625,-0.27643284,-0.25957698, +0.36448124,1.471322,1.5927707,-0.25857264,0.30833125,-1.3780835,-0.3119761,-0.84029037, +-1.0068318,1.6815767,-0.79228663,-0.5316059,0.36584878,1.2978252,0.48111513,2.759355, +-0.22289208,2.3143032,-0.050325453,-0.47589913,0.5072389,-0.1162297,-0.9474886,0.24444346, +1.4013448,-0.4103818,0.5289436,0.24614778,0.86351967,-0.8047537,2.346647,-1.2791611, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-1.502292,-0.21493468,-2.9608529,-0.9495044,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-0.29269093,-0.3305762,3.9981818,0.95213723,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.36319184,-1.2284006,0.66499805,0.97748244,0.0,0.0,0.0,0.0, +-0.36555108,0.9380925,0.29673317,0.82998616,-0.49610233,-0.074804984,0.012231983,1.5692596, +0.69042903,0.7966721,-0.6579261,0.9688826,0.22558166,1.3891454,2.0140603,-0.30676576, +-0.76939106,1.0927008,-0.7522567,-0.19213659,0.3595044,-0.14456682,-0.36159927,1.0645851, +-0.9378802,0.43310794,-0.40594172,0.7243685,1.3852615,-0.30309826,0.44103292,0.17879286, +-0.7994224,0.2407875,0.2891205,0.41287082,-0.1983989,0.0941923,-1.1476109,-0.35811406, +0.26527995,-2.8935409,0.089267135,0.05981219,0.22805333,0.20147994,0.5407736,-1.8180777, +-0.04932407,0.2390336,-1.0003303,1.6739857,0.16155927,1.5634048,-0.790523,-0.9073001, +0.22425222,-1.6786884,0.2149656,0.09721923,1.0156653,0.70104134,-0.41747734,-1.0974966, +-0.5885654,0.6365577,-2.1861176,0.4312547,1.1173053,-0.5189002,-0.7537045,0.13768983, +-0.2069447,-0.67809546,0.7539915,1.0653155,0.9853175,0.7669197,0.40262553,-1.775888, +1.6692508,0.3019892,0.60815644,1.1149623,1.4333525,0.41839802,0.43554616,-0.59922427, +2.594769,-0.7719629,3.1224828,0.60298336,-0.15602389,1.0490932,3.1709747,0.18949963, +-1.3484131,1.2649833,-0.30078387,-0.6606086,0.20984948,-1.2406245,0.22246316,-0.08837552, +0.098377906,0.38141626,0.067492254,0.016338084,0.2843145,0.41540062,-1.0314825,-1.4299912, +-1.29599,-0.91150576,-1.1509224,-0.37564564,0.6071117,-1.0481704,-0.86026245,0.32830128, +-0.4012978,-0.3166553,0.5969065,-0.9872867,-0.40123472,-0.8000825,-1.0431294,-0.8570782, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.07371944,-1.7102461,2.2486784,0.8454028,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-1.1608149,-2.0476928,-1.1115696,-2.1435556,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +-1.0372047,0.98209965,1.586799,2.069713,0.0,0.0,0.0,0.0 + +==== +name:SelfAttention_PastPresentBufferShare_UsingDMMHAInsideMHA.present_value_data +0.67746216,0.05182039,-0.87916064,-0.2311016,-1.6388073,-0.7333128,2.1495745,-0.090243846, +0.73165894,-0.065488376,0.34816924,0.6632581,-1.1046166,-0.030936258,1.5788652,-0.7955006, +-0.56643987,-0.30769128,0.26902407,0.52491784,1.2674117,0.49949825,-0.062053125,1.2591671, +0.70411104,-1.4956795,2.5263681,1.7699214,-0.16821422,0.3779101,1.3243587,-0.1722008, +0.7303518,1.1045785,-1.0148259,-0.6023319,0.9214084,0.46081448,0.92379653,-0.13256802, +-0.28900522,-1.9986395,-1.1460004,0.047066096,0.82455724,0.53117836,-0.12824197,-0.27177158, +0.21717963,0.07821118,1.4045455,0.14644077,-1.481246,-1.2725581,1.5187594,-1.1711605, +0.76449746,-0.26837274,-0.16975829,-0.13413279,1.221385,-0.19284183,-0.033319283,-1.5308034, +0.2066905,0.5310425,0.23914558,1.3978963,0.055171356,0.29897746,1.648504,-1.5500141, +-0.45582536,1.4261588,0.93612915,0.6783801,0.8326507,0.3270662,1.6315974,0.37775916, +0.2398671,0.15895867,0.19286396,-1.1570172,0.77067304,-0.13043973,1.8219151,-0.07565047, +0.4209183,0.24660219,-0.625557,0.99213684,1.9050636,-0.01477722,-0.3004788,-0.35502872, +-1.8923619,-0.17781314,0.2509981,1.054758,0.9600477,-0.41649908,-0.27682298,1.1239053, +-0.1734639,-0.51002955,1.3925184,1.0375856,0.018791791,-0.5937774,-2.0118804,0.5897036, +-0.8963697,-1.962732,1.5848205,0.6479678,-1.1390082,-1.2144014,0.8709618,-0.87797064, +1.2961498,0.6164593,0.53659654,0.40469545,0.19145088,0.8805112,-0.45408037,0.08595198, +-2.0578089,-3.3519888,-2.2429948,0.7861984,-0.690169,0.5411559,-0.31203434,1.6901015, +-2.1588855,-0.7243006,-1.1573272,-0.80054927,-0.06876822,-0.7913201,1.3357888,-1.3602651, +-0.4136746,1.2541456,-2.8920126,0.010545701,1.7186123,-0.051247835,-3.3103738,1.4790617, +-0.3721861,0.83792794,-0.8949467,1.4264942,0.49982375,-0.59972984,-1.2872732,2.7294064, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.75194657,0.5629897,-1.1949868,-0.50040966,0.2528035,-0.4080147,1.7746586,-0.3931532, +-0.16221845,0.76943016,0.33053273,-0.14527446,-0.7564935,0.30151406,1.0390965,0.47909522, +-0.7781835,1.7367749,-1.4465779,-1.5826856,0.9605572,0.22584048,-0.54949856,-1.0985707, +2.3207998,0.11709087,0.53420115,0.3178851,0.43480796,0.54009444,0.732424,-0.3752224, +-0.29164198,-1.7410228,-0.78030443,0.2711128,1.0450233,0.59903955,-0.34069234,-1.2631729, +-2.7773592,1.151734,-0.589229,-0.44846502,0.13157398,-1.40556,-0.34978217,2.0234718, +0.50538695,0.35924914,-1.5824945,2.2436018,-1.4227949,1.9223248,-2.115056,1.4053655, +1.6180543,-0.8244091,0.42258036,0.5474806,-0.8137945,-1.4491177,-1.3177173,0.54100823, +-0.085115604,-0.564301,0.966768,0.5080679,-0.7554627,-1.2012016,0.5232617,-0.53758335, +0.09920486,1.576299,0.5023282,-0.862267,0.16066119,-0.95264494,1.6085222,-0.56157875, +0.20727074,0.30773258,0.15925047,-1.9585489,-1.446421,-0.4523503,0.31943184,-0.13777922, +-0.9571475,-1.3484243,-0.40155753,-0.46847606,0.51283646,-0.32631847,0.6027077,-0.5946498, +-0.25595766,-0.3480464,-0.782367,0.6251187,-0.813596,-0.5216415,-0.07311965,-1.2973796, +-0.32493496,-0.71130633,-0.38815418,-0.059928004,-0.79991364,-0.22007579,1.3086687,-0.025798557, +1.1452621,0.34649444,0.7741606,-0.77445894,0.10490716,0.13391292,-0.6126257,-0.82282835, +-1.4902654,1.4961396,-0.9724029,1.3462211,-0.46749318,-0.8624933,0.62251914,-0.63119197, +0.3051727,0.8580102,0.45010978,-3.0402117,3.4852953,-1.6919196,0.027978867,1.2332127, +1.0401931,0.31535894,-1.0774748,1.6679018,-3.6707008,1.6784648,-1.4660895,-1.4417516, +2.6776397,-0.50531524,-1.1391888,-3.1282802,-0.035271525,0.036983967,0.22105613,1.6946304, +-1.1181979,-0.20367354,0.068902105,-1.7353888,-0.0051657297,0.48101524,0.52825344,-0.4711641, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.5684589,-0.33281177,0.4804245,-0.9681861,0.83135104,0.48797268,-0.9196507,2.6429358, +0.54012305,2.290467,1.6002678,-0.18883479,-0.41227177,-0.4034592,-1.8300285,-0.6958351, +0.24676603,1.5259576,-0.7727719,0.8820566,-1.2525934,-0.58632004,-0.4576406,0.3718111, +0.45730963,0.9623417,0.77083695,0.24316822,0.39036494,1.5885307,-0.5109262,0.7747283, +-1.808144,0.41133425,-0.48324955,0.0025711823,1.0400863,0.16464381,0.88518757,1.4737648, +0.38909397,1.171041,-0.32656097,-0.008209882,-0.5226194,1.0429776,0.41409135,-0.50723445, +0.15466884,1.0415684,-0.03926799,-0.9489328,0.13191175,-1.9805655,0.76877064,-0.4213276, +-0.46931073,0.8756957,-1.3651628,1.9470986,-0.48024204,-0.52325094,1.0212247,0.7086953, +2.4512298,-0.21120599,-0.120406635,-1.479316,-0.33210227,-0.7214313,-0.448767,-1.7441877, +1.6606076,-1.4166034,-2.8022027,-1.1884245,-0.6038396,-1.149554,1.0983036,-0.13783918, +0.025385605,0.61039174,0.28601253,0.9785673,-1.1094775,-0.5475181,0.66596717,-2.5345545, +-1.3751845,0.50099224,-0.48024905,0.9361076,0.8091803,-1.1980929,0.4066571,1.2016978, +0.1474344,-0.97746485,0.87938994,0.63542455,0.54261076,0.71593887,-2.994613,0.8809376, +1.8081318,0.43663847,0.192729,0.69643867,0.33822548,0.65178126,0.0014710003,-0.76670486, +-1.0043228,-0.9981917,-1.3730426,-1.067742,1.7612661,0.7540957,-0.6250274,-0.3903927, +0.11255753,-0.65554506,0.067516856,0.77760416,-0.035742734,0.33601573,0.88649154,-0.27213177, +-2.051816,-2.7816176,-0.38553995,-0.7150961,-0.65866506,0.73568,0.12661266,3.999392, +-0.92730594,0.030181527,-0.93402994,-2.0779161,1.015371,-2.0726008,-1.7224298,2.0186472, +-4.125478,1.3149867,-2.923615,2.06105,2.2933798,-0.3885297,-1.9675268,-1.7995086, +-0.70256805,-0.46260026,-0.56759036,0.04682108,0.79200155,-0.85891926,-1.0061638,0.08046973, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.2847906,-0.30937758,-0.02852887,-0.32473028,-0.52886987,0.17371185,0.5665453,0.14630444, +0.49872696,-0.7379318,-1.2037352,0.4170435,0.6878814,0.049857266,1.3480358,0.9076988, +2.6805708,-0.20080851,-0.9988488,-0.7401368,-0.5654978,0.4760314,-2.1580687,1.3185511, +-0.23929659,-0.24679355,-1.0793432,-0.11422555,0.013239767,-0.12194493,0.33905926,-0.58963203, +-0.8958158,0.5483281,0.09866745,0.19718106,1.0590272,-1.0225644,-0.85524046,1.2572197, +-1.4828833,-1.3094121,0.81786186,0.23820019,0.105232134,-0.09165941,0.031267546,-0.09211212, +1.3554426,-0.39814812,-0.16137354,1.7944489,0.027509702,2.2320163,-0.1049797,1.367415, +-1.655344,0.15364446,-1.5844736,0.8444543,-1.2128679,0.28376955,-0.28219587,-1.1582032, +-1.61936,-0.51104045,1.7406294,-0.29348505,0.91722155,-0.057042867,0.87672675,-1.8269113, +-0.40318832,0.94940555,-0.16325495,-0.086455286,-0.4304619,1.1493794,0.29751435,0.044022277, +0.64305454,0.58822495,0.21258704,1.5470315,-0.060287535,0.27808106,-0.64295256,0.15011522, +1.5877615,-0.6432576,-1.1335928,0.99675965,-0.14876615,0.0960042,-0.045113303,0.079121724, +0.8505307,-0.8391242,-1.0117741,0.084968135,-1.6064397,-1.3730536,1.8666831,0.75746834, +-0.010056471,1.238007,-1.0405992,-0.31560314,0.6234536,0.8906717,0.51291686,-2.5412388, +-0.96808213,0.4770681,-0.3559515,2.5402317,0.9265583,0.55808187,-1.1169496,-0.03529674, +0.24120396,1.1277837,0.8811311,1.0329891,-0.923912,1.4121517,-1.3804307,-0.53591454, +0.9798864,-1.1332853,0.42590374,-3.0803738,-0.66169095,-1.1098778,-0.31572723,0.71667963, +1.6409252,-0.26382387,0.25382257,1.6378108,-2.379856,0.18126236,-1.5385789,-1.1564229, +1.7435231,-1.1726068,0.4755114,-2.7746863,0.11258662,-0.05290118,0.40425268,1.1107234, +0.6519424,-1.0436192,0.24687822,-0.9495615,-1.6611001,1.1551828,-1.6656845,-1.3863657, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + +==== +name:CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.query_data +0.43077114,-0.14989159,-1.0060369,-0.82154983,-1.5482544,0.5319746,1.2605689,-0.100393504, +-0.4003488,-1.472323,0.9132019,2.2113044,-1.7974558,-1.0634329,-0.679593,-0.5643179, +0.22734594,1.6142496,1.0085973,0.52759737,-0.7239287,-1.1196282,-0.7967753,1.5480669, +-0.0617433,-0.44683626,-0.18375573,0.8246182,-1.3128496,1.4148741,0.15647626,-0.21634398, +0.44284612,0.21839707,-0.34419647,-0.25271067,-0.86886257,0.6563907,-0.5319938,-0.9562584, +0.16586353,1.3291413,-0.048344623,-0.60810125,0.40389603,1.9367125,-1.4519055,0.38220277, +0.20508662,1.1615338,0.99090916,-0.1867091,-1.6845173,0.8065638,-0.8351927,-0.9467404, +1.1483506,-0.9108504,1.4028448,0.33584473,0.3191184,0.30726478,-1.6384237,-1.7763886, +0.21555306,0.56800735,0.08261103,-0.8215345,0.018922104,-0.082034156,-0.9571581,1.0139722, +-1.7302761,0.58874243,0.38432342,1.0097119,-1.0053118,0.10140715,2.171165,0.66207427, +0.10058121,0.53916126,0.08617684,2.190898,0.9836362,-0.08561496,0.25233144,-0.390798, +1.2098501,-1.4061048,-1.6047385,1.4587147,2.1531198,0.4683049,0.11273794,0.6572677, +-0.64705354,0.17124355,0.038908705,0.62656426,-1.5579985,-0.5070348,0.8449956,-0.67559385, +-0.99336135,2.042072,0.038118,-0.57891816,-1.6923704,0.72934633,0.69913614,-0.2987596, +-1.1022302,-0.024549423,-0.8358561,-0.9420936,-0.10321275,-1.0513904,0.24664895,0.60799253, +-0.83963245,-1.3682451,1.5612797,-0.94027025,-0.6599427,0.21301717,0.59936935,-0.2563169 + +==== +name:CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.past_key_data +0.46079433,-0.40098616,-0.97117066,1.4263169,2.4884417,1.6959696,0.14180663,1.8334354, +0.3557035,-0.47728628,0.46637958,-0.09439251,-0.9831182,-0.898322,0.8020517,-1.846532, +0.60413677,-1.6295836,-2.1211765,-1.8388466,1.966764,-0.19623396,0.08658318,1.419255, +0.9341797,-1.3915052,0.86900634,0.18418126,-0.34167808,0.024290914,1.279812,-0.8859665, +0.40088567,-0.009657237,-1.7971646,-0.8022532,0.19321355,1.2973421,1.001331,0.5972125, +-0.81527567,1.801214,0.21524046,-1.0063655,-0.18290497,0.8962484,0.0076174983,0.88686466, +1.103694,0.4005307,-0.8577026,0.13545467,0.045165855,1.8593464,-1.6263219,-0.13482246, +-0.5840936,0.33510563,-2.4375644,1.1149246,0.013748487,-1.8447012,-0.36111313,0.60896236, +-1.5914478,0.0032222164,-1.0574737,-0.55598503,0.026738383,0.18345025,-0.4707425,0.2727964, +0.8179776,-0.27891427,1.4315678,1.4622141,-0.42870206,-0.63784057,-1.664173,-0.12656933, +-0.36343777,0.77905124,-1.5096616,-0.2773914,0.9687444,-0.7303571,-0.7623615,-1.4469403, +2.6205738,-0.7474732,-1.3003469,-0.8038504,-0.7742951,-0.26938978,0.8253722,-0.29832315, +-0.9228233,-1.4513385,0.021857359,0.042539075,1.5309323,0.092447735,-0.099008314,-1.0506538, +-0.30595258,-0.43847445,-0.37016416,-0.9592554,0.5383296,-0.14244542,-0.20035347,-1.7140461, +0.4936441,0.48701534,-0.8391294,0.99012136,-1.3647583,-0.021869909,-0.27120733,-1.3171748, +0.18970262,1.7025702,0.06763423,-0.46302176,0.44702417,0.10572,0.027762132,-0.4255422, +1.4219756,0.45636335,-0.52867067,-0.10800384,-0.7408667,-0.60829115,-0.64072573,-1.1343116, +0.777277,-0.29104146,0.5541276,-0.6701259,-0.060362495,-0.7110406,0.71966815,-0.2484193, +-0.7308736,-1.6417032,0.27566653,-0.70838505,-0.015779218,-0.4917301,0.9541896,0.54414475, +0.4472121,-0.6161211,0.46629006,1.7148316,-0.83218604,0.17233914,-1.649217,1.3985621, +-0.39791209,0.7825789,-1.7232282,1.7975394,-0.35687152,0.54565734,0.1508182,-0.25547078, +1.6857923,-1.6480463,0.29871365,0.91064566,-0.029856121,-0.11817078,-0.14268771,-1.2276365, +0.038127385,0.51271755,0.068599224,-0.2722761,-0.48972502,-0.27929667,1.2577442,-2.0866349, +0.040071458,-0.3277549,1.4558079,0.055492226,1.4849256,-2.12389,0.4595849,0.28005785, +1.3905339,-1.6413486,-0.15503581,0.06606026,-0.4957955,1.2165778,-0.33868217,2.0347626, +1.0541779,0.9508337,0.559299,-1.0636955,-0.43109635,0.57275134,0.67755705,1.3071839, +-0.46744102,-0.8601534,0.8591042,-0.8096266,0.8733118,1.1997361,0.45615304,-0.35757902, +0.041082226,0.5934659,0.010185518,2.1982963,-0.9906709,-1.0026686,-0.9768954,-0.58957994, +-2.1789315,-0.6296504,-0.6532847,0.078514025,0.41780058,-1.2402164,0.9000542,1.8022423, +-0.20828511,1.5743712,0.1989895,1.9887319,1.1172835,-1.5639046,0.01862737,1.054325, +0.030546581,-0.03688353,1.2697648,-0.7098542,0.017515613,0.32362577,-0.33379096,-0.020129103, +0.7750233,0.43283764,-0.80871755,-1.104124,-0.7891022,0.0012484558,-0.15993978,-0.8319575, +-0.59815043,-1.5200393,0.4178537,-0.040018726,-1.2597873,0.028620504,1.342622,-0.7399359, +1.3151376,-0.32345748,0.19782817,0.097750805,1.4015235,0.15843384,-1.1419014,-1.3109704, +-1.5329211,-1.7119702,0.04613506,-0.9583745,-0.08081161,-0.70385903,-0.7707843,-0.48084533, +0.70358557,0.92914516,0.37117255,-0.98982257,0.6436313,0.68889666,0.2746472,-0.6036204, +0.70885956,0.42281857,-3.1168566,0.64445204,-1.9137427,0.6635616,-0.1540724,1.1936116, +-0.09816121,-0.88661426,-0.14735366,1.0598063,0.026246618,-0.11433516,0.7435535,0.21035936, +-0.005927406,1.36606,1.555114,0.61332625,-0.28595915,1.496911,1.1831195,0.71889716, +-1.2160766,0.14067191,-0.7436722,-0.15901226,0.24005693,0.10015941,-0.4751751,1.2729537, +-1.6961312,0.73018354,-1.8574833,0.38259813,-0.8869043,0.87830377,0.08645252,0.24770638, +-1.0182793,-0.65457016,0.2072174,0.58356994,2.9290962,0.22285832,0.9760375,-1.5569339, +-1.3298919,-0.35549477,-1.1974277,1.4863993,-0.4102187,1.3821819,1.4867824,0.04277972, +0.50179976,-0.056099474,0.538437,0.48334184,-0.12364963,0.50496995,1.7236962,0.7130162, +0.3257996,0.124769524,-1.0126731,-1.0272969,0.32335654,-1.3693911,-0.7663276,1.2815113, +1.9142298,-1.665956,1.6266496,-0.2114383,-0.0150050875,-0.11341163,1.0805441,-1.6076766, +0.45616361,-0.9448702,0.5707885,1.5427964,-0.0004173264,0.37415507,0.40955177,-0.7995935, +1.5116394,1.7064682,0.70178336,0.07328543,-0.46189383,-0.62649024,1.7108365,1.414415, +-0.063661486,-1.5799305,-2.832012,-1.0834267,-0.13062039,1.400689,-0.6516562,0.50481546, +1.3031809,0.12853631,-0.14244787,-1.3087635,-1.2024753,0.41609964,-0.20090753,0.12253132, +-0.047277715,0.66414404,-0.7846874,-0.33558065,1.8961822,-0.79978615,-0.28157544,-0.5893867, +0.44478136,1.0223923,-0.49821162,-0.43141434,-0.2789816,0.5298338,-0.7393953,-0.37595996, +-2.3721938,-1.381745,-0.11244375,0.89786416,0.29507577,-1.0987685,-1.4002562,0.1746801, +-1.6528037,1.0659268,0.063896194,-1.6073202,-0.9659539,-0.7243113,-0.7731925,-1.489933, +-0.8746625,-0.6844016,-0.71128577,1.1279566,0.10482781,-0.9932572,-0.3346216,-0.8795571, +-0.30000666,0.87550914,0.2522708,2.2856011,0.37592742,-0.9135945,0.8097407,1.0799313, +1.094167,-1.0942409,-0.14763741,1.131812,-1.684729,-0.49941677,-1.4269377,-0.9325702, +-1.0124571,1.2505698,-0.23453803,-0.8633556,-1.0356058,0.14166717,-0.0111356275,1.3440744, +0.5000167,-1.4317977,-0.6289807,1.0700725,-0.6210827,1.7345722,-1.0982895,0.57261336, +-0.86121553,-0.50959516,1.0985817,-0.12706716,0.81345224,0.4732906,0.75386566,-0.8881882, +-0.2215744,0.42425263,-0.8490729,1.6295,-0.77722806,-0.3000036,-1.006559,-2.1433082, +1.7969185,-0.20433894,-0.44791484,-0.19871506,1.4198639,-0.9651066,0.6795679,-0.42378825, +-0.59667087,0.5670582,0.9882406,-0.51390296,-0.76884913,-1.1690958,1.1035038,-0.575256, +-1.8491307,1.4099522,-1.3698595,0.77946055,0.18342865,0.28791544,-0.58437526,0.36559147, +-1.6677799,0.5880377,1.55701,0.8840272,-2.01954,-0.984209,-0.18779492,0.4869373, +-0.10665268,-0.4932144,0.5953003,1.1641518,-0.23229401,0.7289299,-2.5790508,-0.93750936, +-0.32125893,-0.48856622,0.3327982,1.0137506,0.50666904,-0.62222546,-1.5227681,0.5569641, +-1.8381767,0.6530373,-0.18844908,-1.175835,0.2872573,-0.0028761027,-0.036597293,-0.0842233, +0.4195241,0.924434,0.4966152,1.0121332,-0.04413972,1.6184593,0.57110983,-0.543694, +-1.0938951,0.20579681,-1.3065215,-0.973376,0.23908707,-0.60788745,-0.93331623,-0.034475047, +0.072677895,-0.20583403,-0.3775469,0.85464275,0.34242734,-0.22342612,2.4643219,0.19383174, +1.1320051,-0.560981,-1.3629409,-0.7917565,-0.26800978,-0.4966082,1.3363862,-0.120041125, +0.46146888,-0.046481155,-0.43355432,0.037996013,1.7140515,-0.76794857,0.7669904,-1.0260073, +-0.45962644,0.0035832059,0.3263751,1.4831287,-0.050082643,-0.8436156,0.650042,-0.3641698, +0.23868157,-0.11622244,-1.9434569,0.5082992,0.583368,0.92660475,1.8004627,-1.1951038, +0.51650745,0.409295,-0.419082,0.39710623,0.49964696,-1.2186838,0.24622276,-0.9179843, +-0.6518565,-1.7747449,-0.47336093,-0.20357068,0.54985684,0.00089992664,-1.5422882,0.86214805, +-0.11858662,0.4883706,0.9659361,1.4226048,1.9612269,-0.07223876,0.31112444,-1.078361, +1.0616002,-1.1848874,-1.8052517,0.830386,-0.5216965,0.77760726,0.40807465,-1.6300026, +-2.7196794,-1.0966017,0.016491488,-1.2217764,-0.65276146,-1.4589407,0.16987796,0.09082593, +-0.48139262,1.3970653,1.497715,0.5652672,-1.7997712,-1.1046902,0.40713033,-0.62855756, +-0.48709142,0.8989674,0.5108748,1.3141544,-0.4292093,1.3752254,-0.55413127,1.4994915, +0.10583464,-0.86050975,-1.6312195,-0.3014723,-0.2562327,0.8576619,-0.1105905,-0.43243197, +1.0770375,-0.22482656,-0.5762418,0.5746089,-0.48982823,0.65880215,-0.5969171,-0.22295918, +0.15217698,-0.37412632,-0.013451469,0.81547195,0.4106018,0.48096985,-0.63543046,0.85282975, +0.66956234,1.0044192,-0.7263658,-0.1724586,0.6335339,-0.60881513,-0.22612247,1.9258057, +1.951761,1.2399405,0.93858516,-1.0192511,0.5125622,-0.35911658,-1.0585719,-0.50900584, +0.11566507,-0.5473556,-0.5507994,0.7920415,0.14410649,0.23345809,0.1118724,-0.67570317, +-1.370572,0.3105647,-0.5070366,-2.0107822,-0.39256725,-1.0922179,0.69865024,0.5216252, +0.49689314,-0.6650416,0.7315516,0.3196498,-0.40985453,-0.45333743,0.8927082,-0.47360405, +0.30365646,1.033957,1.9093426,1.6638731,0.90082276,-1.5059114,-0.6890484,-0.5480872, +1.6531498,-0.69931793,0.38616636,0.10086706,-0.9351272,0.38182402,0.3982961,-1.2557749, +1.2228775,-2.08651,-0.59075713,0.9719703,-1.1932578,0.35026592,-1.2963604,-0.09302414, +-2.3137732,-0.8425717,-1.5429214,-0.40176374,-0.4152314,-0.67366415,0.7979132,-0.8868796, +0.63438666,1.6292758,0.13906415,-0.8576702,-1.2493385,-0.7097851,0.7046427,0.15559073, +0.93679523,0.7703309,0.14081065,0.47348827,1.8552462,1.4156562,-0.30274603,0.98967946, +0.58585083,1.1363881,0.67161655,-0.9741674,-1.6196846,0.572627,1.9026182,-0.7756641, +-0.18808974,-1.0357478,1.1778295,-2.305167,-2.2636602,0.3750199,-0.082343645,-0.47962302, +-0.3010948,0.5369879,-0.413804,-1.096925,-0.9273629,0.88833886,-0.52474195,-1.3852776, +0.10217833,0.50499475,1.3289608,0.21790339,-0.65971124,0.47400787,0.7271749,-0.038905308, +-0.04459939,0.2601329,-0.069856495,0.2501139,-1.0219133,-1.1504377,-0.83611137,0.64221096, +0.25879756,1.040239,-0.18669093,-1.1436414,1.1445535,-0.018767055,1.283455,0.59794647, +2.1886187,-0.21977298,0.90072393,0.8913641,-0.55512637,-0.17248231,-1.4617383,-1.5487962, +0.1265688,0.7930071,0.63802403,0.3400246,0.86301714,-0.5896978,-0.27253276,0.7375215, +0.43311873,-0.21018882,1.3207943,-1.2920012,-0.51867867,-0.28339776,0.8165349,0.002385198, +-1.2614918,0.5140042,1.0875463,0.73930454,0.61915493,-1.8743135,-0.8998865,0.4820806, +-0.054888185,0.5225576,-1.2663426,-0.061494764,-1.389781,-1.9536786,0.29577908,0.8425888, +0.24561642,-0.03299648,-1.5620143,1.0061071,-0.044044897,1.9595621,0.9423143,-2.0051255, +0.7550497,-1.3965353,-0.7594955,-0.25075668,-0.09406245,0.39756522,-1.022855,-1.150692, +0.6006052,-0.013250268,0.17437305,-2.1936834,-0.17713739,-0.8907292,-0.9206264,0.9219348, +-1.0956712,-1.0928966,-0.3310106,0.45028883,-0.8840147,1.2341441,1.4498476,-0.8814471, +-0.24508175,-0.7786755,-1.6853821,0.30301106,0.7335949,2.0118642,-0.8974095,1.336235, +1.3423537,0.19785331,0.6021635,0.8732731,1.9741,0.47780856,-0.060137887,-0.8661688, +0.30532077,1.0241649,0.24461035,-0.77992326,0.089076206,-0.12915348,0.26473877,-1.6618484, +0.55078864,0.59542316,0.44485343,-0.0037628172,-1.8059362,-0.019322792,1.060715,-0.8601289, +-1.9892695,-1.540558,0.3140257,0.37287602,0.8862932,-0.055258997,-1.5003284,-0.81850415, +0.8188394,0.14049591,0.6498296,0.4347888,-0.20496055,-0.17400683,1.8571023,0.41467425, +-0.12858754,0.45542,0.22290581,-2.1573563,0.6500845,1.8209393,-0.7802799,1.4540358, +-0.2568697,0.2934714,1.0703601,-0.72000146,1.2424939,-1.2142173,-0.87515473,-0.59352034, +0.66200536,-0.3408744,-1.5199745,-0.21653287,-0.7842214,0.7312936,-0.34323505,0.07077408, +-0.40547246,0.43393898,-0.18359077,0.3251987,-2.5933886,0.09725088,0.41391367,-0.19928005, +0.66939247,0.73860705,1.3042139,0.10481161,-1.9138007,-2.2854993,-1.601841,-0.03790706, +-0.15730529,0.27623984,-0.6252459,-0.73649114,0.5550479,0.65592444,-0.25665015,-0.038476657, +0.40431434,0.50434357,-1.1439807,-0.71957386,-1.230546,-0.5069066,0.8123336,0.54627186, +-1.0980979,0.51226676,0.08584311,-0.4939267,-1.4064597,-0.17482337,0.679944,-2.1630976, +-0.3961232,2.2542837,0.67263675,0.2598325,-0.7371852,-0.6783298,-0.083288394,1.6028637, +0.4655892,-0.8721584,1.176787,-0.2925942,1.6973464,-0.566603,-1.0032657,0.17462958, +0.982327,1.0374448,0.15919177,-0.9880967,-0.5053407,-2.018282,-0.9131215,-0.17845681, +0.38900214,-0.33945432,-0.056979056,-0.39618546,0.7510253,-0.89911294,0.8375479,1.9608808, +0.47278965,-0.5270916,-0.53627014,1.2098372,-1.1265894,-0.95380443,-1.1644485,-1.2785138, +-1.0448164,0.78990495,1.1022825,-0.6970731,0.20733404,0.7591567,0.100564204,-0.95494276, +-1.4704018,1.0104276,0.4961794,0.5769559,-1.107647,0.23497719,0.6289996,0.31403384, +-0.7450232,1.0122606,-1.527632,0.92874193,1.081056,1.5723304,-0.3424922,-0.99943, +0.79388034,-0.6992153,0.04399551,-0.3174622,-0.90207195,0.32099947,-1.3920159,0.5922057, +-0.9669311,-1.7317313,-0.05010746,0.43163386,0.5769346,0.8183537,-2.3536403,-1.0051445, +0.1066523,1.5190033,0.7837445,1.90134,-0.5249394,0.27441698,-1.0999708,-0.40435222, +-0.7352957,-0.6339887,-0.39344913,0.00271754,0.022212664,0.54345345,0.13998847,-0.34404564, +-0.52257854,-0.3071317,-0.44903713,0.49097106,0.8655252,1.2740445,-0.7977028,0.4693722, +-1.3946797,0.37317473,1.0826722,-0.14958951,1.072636,-1.1385679,-0.8886453,-0.13580984, +1.0222104,-0.41742945,-0.4535531,-0.99162835,0.20288104,1.2466952,0.70068014,0.6966507, +-0.20697448,-0.5633094,0.6772459,-0.031911075,-0.17360823,0.8982406,-0.19778745,-0.83777624, +0.9091885,0.08071989,-1.0370294,-1.1129059,0.095411874,2.3374097,-0.3928206,-0.33627385, +1.5237712,-0.0572812,-1.4484669,-1.5727965,1.226664,0.66635454,0.8261257,-0.057756558, +-0.72671205,-0.21716312,0.13603121,-0.83831114,0.5614499,-1.2595961,-0.33275875,-0.20400788, +-0.69101983,-2.2055054,0.44786966,-0.7557508,1.3257079,-0.34198228,-0.5413596,0.09152195, +1.0534397,-0.56340766,1.0147377,1.4403037,0.9903228,1.6264315,1.292646,1.5148823, +1.6043264,0.20806953,-0.4292239,-2.2622437,-1.3227332,-0.4482828,-0.3817351,-0.15279447, +-1.0007604,-1.5957776,-0.13022317,-0.18941793,-0.80755407,-0.74215215,-0.9401566,-0.39652374, +-0.8563028,1.2598753,0.24099673,-0.97231793,-0.28044778,-1.1802856,1.0121683,1.3841867, +1.252002,-1.1446927,-0.09126702,-0.40157068,0.5620131,-1.0079098,-0.6758917,-0.41321704, +0.15328847,0.6941287,-0.3287277,0.66396505,0.8220764,-0.21321523,-1.2456582,-1.1711904, +0.59172696,-0.47622442,-1.7126293,0.61295235,0.12955453,-1.4059671,1.17942,0.836636, +0.13874525,-1.2743194,-1.4023305,-0.3070685,-1.7139153,0.40508026,-1.4108233,0.16491273, +-0.28813145,0.71178526,-0.9379476,0.27372944,-1.3948402,0.7955496,-0.114961766,0.49585068, +-1.3205253,0.49908426,0.3062034,0.3636979,0.31263396,-0.19346388,1.2412993,-0.15589799, +-0.7391692,-0.05872619,-0.95051795,-0.4639964,-0.17724662,-0.37955412,0.19939707,1.9457614, +0.57094985,1.0723007,-0.50370944,-0.5870163,-0.37817806,0.8528891,-2.1481185,-1.0331647, +0.10233585,-0.22409236,1.9677297,0.44768322,-0.66219145,-1.577607,-0.34056005,-1.30322, +0.46675065,0.16110632,0.32003194,2.0791767,-0.907466,-0.19240421,-1.2125157,-0.08059852, +1.5932736,0.5687224,-0.114487045,0.25163025,-1.2108556,-0.3937337,0.085252576,0.099421985 + +==== +name:CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.past_value_data +-1.5306163,0.3276232,0.2791965,-0.3770512,0.004174999,-1.4834915,-1.4797956,0.13468726, +-0.6677232,-0.01155552,0.83949065,-0.17392993,-2.810668,-0.15065365,-0.48104402,-0.23469436, +0.8997308,-1.5785302,0.24395663,1.5703039,-0.6259431,0.4723279,0.9663058,0.21023144, +-0.685097,-0.709521,0.74380016,0.5921491,-0.7864684,-1.1764731,-1.2808067,1.6616518, +-0.06794512,2.3602285,0.5555456,0.43952233,0.30627248,0.99914986,-0.9660632,2.1600132, +-0.100301705,-0.7034001,0.302561,1.0923389,-1.0075549,0.5668694,-0.71644413,-0.5062735, +-0.48948243,0.76354146,-1.1090727,0.1926161,-0.34341785,-0.84721017,-1.2135236,-1.2028884, +-1.633796,0.8961672,-0.24165316,0.15865193,1.1781894,-1.2201172,-0.94154567,0.25471553, +-1.8240795,-0.5787085,-0.9248931,0.32952243,-0.42581588,2.0081494,0.93789136,-0.85323846, +-0.38731343,-0.34758452,3.3065743,-1.5101997,0.2035397,-2.0844321,-0.0069374414,1.9098905, +-0.40845543,1.1045544,-0.06611522,-0.4224987,-0.25165635,-0.5869026,-0.6260583,-1.3301944, +1.5068008,-0.3930764,0.2937743,-0.87653184,1.1169906,-0.2735558,-0.09103267,-1.8289766, +0.39597622,1.8115057,-0.86907756,-0.45822915,-1.1383239,0.12916218,0.064024195,0.7050811, +0.55147356,-0.81251603,0.22494805,-0.3283011,-1.091033,-0.12685588,3.8016603,2.3151705, +0.1398266,1.7388572,-0.045383364,-0.053138338,-1.9495717,-0.96010554,-0.78349924,0.10751903, +0.013984535,-0.57894236,-0.5888132,-0.16615313,-1.3814117,-0.61263853,-0.38128987,-1.2489489, +-0.3302379,-0.83480716,1.2353824,-0.2438038,-0.18954566,0.4280281,0.55696833,-1.7362418, +-0.37678412,-0.90903234,-0.14517024,-0.53633255,0.15706946,-0.9804593,-0.56776726,-0.59115964, +1.0825914,0.36800367,0.3688887,-0.28631827,-0.38471785,0.5610029,0.77743393,0.015146785, +1.1416479,1.274155,-1.664698,0.43037888,-0.042601928,0.38828883,1.1159766,-0.9205382, +-1.6202741,1.1061915,-0.9984847,-0.6862195,0.2046209,-0.6861018,-1.5922107,0.034189768, +-0.78148466,0.59785986,-0.5060766,-0.68844616,-0.21000054,1.0521535,0.9079041,-1.0932262, +2.7997077,-0.32577634,-1.1524158,0.888232,-0.36167246,2.1537194,0.84740835,-0.19871984, +1.5753069,0.8491152,-1.2288952,0.8883941,-0.5164874,-0.08332629,0.13105445,-0.87909603, +-1.3333423,0.36778402,-1.3882335,-2.5752027,-0.8361056,0.33109242,-0.26988113,1.267131, +0.18375349,-0.7663097,-0.43958354,-1.4365413,1.0857972,-1.3811,-0.92040765,-0.16028622, +0.0023532645,-1.5026504,-0.9055358,0.2650406,1.1297233,0.34900355,-0.025809761,-1.5624087, +-0.61734235,0.52149427,1.0809467,0.8893759,0.13807164,1.2046005,2.8814607,-0.59386194, +-0.7631158,1.5184829,0.23546453,0.11230769,0.39237434,-0.6544865,-1.0347953,-0.77714753, +1.2459463,-1.4366406,0.49865463,-0.55768746,-0.35336688,0.742951,0.8439889,0.34297654, +-1.8731197,1.5709647,1.3101965,0.09143683,0.010257817,1.8014492,0.94722426,-0.029294403, +-0.29233867,-0.19353712,1.177232,1.0399917,-1.613423,0.4646424,0.8641213,-1.5064632, +-0.0029647513,-1.7770436,0.12949283,-2.0832345,-0.6817455,-0.6110659,-0.70884985,1.4515281, +0.53551054,-0.39956886,-0.9330778,-0.23877631,-1.0291129,0.97308,1.996766,1.0531999, +0.33169034,-0.16562878,-0.40510628,1.7452846,-0.5759356,1.5610986,-1.1315392,-0.29623166, +-1.7140566,0.1592342,-1.2637277,1.6650494,0.41227227,0.5373967,0.28267846,-1.0925409, +0.12411829,1.8370807,0.008554926,-1.0170162,-1.8523426,-0.713327,-1.7622288,0.83051735, +0.78116727,-0.8756818,0.6139813,-0.57645464,-0.045614284,0.37195554,-0.44396,0.41820335, +-1.6857281,0.11747499,-0.034952022,-2.0463932,-1.8096902,-1.8595237,0.41430682,0.12395962, +0.27395758,-1.3263785,1.1389738,0.9828412,-0.76696306,1.1760603,-0.2509224,-1.7762051, +-1.6326947,0.73372346,-0.10404881,0.88122493,-0.088373125,0.2676709,2.1235263,1.396849, +-0.43282726,0.37496874,0.49444544,0.76139116,0.07100881,-0.49353185,-0.0036228173,-0.4802871, +1.6833673,1.2407262,-0.20361502,0.42829227,-0.16545926,1.1932411,1.0488805,0.56861085, +0.8712643,0.6605708,1.1740619,0.5311314,0.15190053,-0.5772256,-1.5717508,-0.02784838, +-0.74105555,0.060009066,1.1404884,0.17282468,-0.41500166,-0.8531286,-1.4301353,1.3328053, +-1.776691,-0.93478304,-2.313202,-0.31614158,-0.34228456,-0.40429443,-0.0631299,-0.8212651, +-0.91365564,1.8178264,-0.33406293,0.90765864,-0.8367711,1.6127286,1.5141821,0.23101868, +-1.0995317,0.08700138,0.0473045,0.23962392,-0.97822064,-1.5230001,0.16236304,-0.010291317, +0.0020750219,1.0268006,-1.4751605,1.0106937,-0.74322754,-0.39522207,-0.8257794,0.08961986, +-1.9058179,-0.56808573,-0.51575655,1.2639302,0.15069814,0.6955183,0.0059388145,-1.0489004, +0.90720487,-0.84544134,-0.5262433,0.18209977,0.9455388,-0.20138454,1.5105247,-0.5714784, +0.6655893,0.0036163009,1.5466719,0.21440601,-1.8773128,1.0883352,-0.08154851,-0.5530619, +1.2229648,-0.33130863,0.59998673,-0.7683833,-0.83613014,1.8105818,-0.7870327,-0.5847709, +-1.7083207,1.6299822,0.39799833,0.23777963,0.9751384,-1.3293365,-0.5410468,-0.091437735, +-1.5484711,1.3114271,-0.01842905,-0.32328865,0.23622549,-0.7525823,0.045113005,3.4275386, +0.604682,1.6683111,-0.3550831,-0.751569,0.3097036,-1.341705,-2.3069577,0.7315925, +0.64133817,0.8338512,0.028169874,1.9783727,-0.08732819,-0.55396473,-3.0064988,-0.047165867, +0.83187777,0.0068611987,1.1242217,2.294881,-0.17335021,1.2312535,-1.5858526,1.0313191, +0.06349048,-0.2213905,-0.16339892,-0.15630347,-0.3088029,0.19867297,-0.17429213,-1.1557925, +0.41705388,-0.60786796,1.0479866,-0.033826966,0.12702395,-2.049232,-1.2566801,0.9396144, +-0.73381674,-0.5324377,-0.27793998,1.3637426,0.374138,1.3102646,-0.2677478,0.21317627, +-1.2032435,1.1780312,0.1086482,0.0441291,0.33831555,1.4467921,-0.21449511,1.663039, +-0.85152256,0.42218462,2.0092185,-0.48981473,0.24525586,0.87750506,-0.1378997,-1.5003532, +-1.0559593,0.5809326,0.8915153,0.7845553,1.146432,0.07198519,0.20823318,-1.5188687, +0.31732896,0.6126808,-0.5832113,0.6440017,-1.8158889,0.7510996,0.30028433,2.1106086, +1.4130856,1.5069803,0.8173971,0.6466156,-1.1816313,-0.3350913,1.8267285,-1.4561645, +-0.45028183,-1.419234,1.4509518,-0.56578135,1.5445343,-0.41376248,-0.5041321,1.2785292, +0.93883175,-2.7162802,0.4511408,0.60016686,0.20980693,-0.657658,0.028408445,-0.39806148, +0.21132302,-0.20239426,-0.62192816,0.16377045,0.8024389,0.2890059,-0.5536424,0.33625403, +1.0697924,1.5954041,1.2075526,0.5373802,-1.009124,-1.3655528,-0.20238121,-1.4091848, +-0.78478473,-0.17012231,-0.48421043,-0.32791805,-1.3280046,0.23146676,0.99650806,-0.5481375, +0.72575533,2.6627266,-0.09181103,0.65121,0.19677009,0.96962374,-1.7186499,-1.0569568, +0.14346392,0.8869626,0.13052402,-1.6645732,-0.8236133,-0.7947061,0.38899195,-0.76203895, +-0.6808071,1.0847476,1.3353163,-0.4132748,0.42490268,-1.8814838,0.19832706,1.189978, +0.5267817,0.101060845,-0.38864297,-0.646792,-0.17908241,-1.5514412,1.610459,0.56421065, +-0.102437034,-0.6198048,-0.07033962,0.79779494,1.0114479,-0.90369093,-0.97352874,2.07823, +1.1365929,0.70851994,-0.13864625,0.92402035,-1.2732332,1.5317684,-0.035772223,0.7908615, +0.64621776,-0.1315709,-0.17536636,1.2215831,1.0264974,-1.7722311,-1.6924057,-0.94622064, +-0.8935454,-1.1185259,0.27211064,-0.46370444,1.2061247,1.4528778,-0.028683238,1.683458, +0.02421431,-0.43479064,0.06478574,0.94486,-1.614461,-0.20859933,0.29740566,0.36308467, +-0.36843634,0.48878574,0.29212162,-0.5919081,2.1815987,0.4395502,-0.33118334,-0.57171905, +1.0294089,0.10205979,2.5481126,-0.4359241,-1.242607,-0.02769846,0.17506745,-2.1184506, +-0.30916852,-0.36841545,-0.36876354,-0.6302257,-1.3431926,0.75803804,-0.58384085,-1.0237014, +-0.75993425,-0.47232324,0.10864712,0.668339,-0.9531795,-0.4792974,-1.3455077,-3.3923, +0.15579394,1.5200036,0.5220833,-0.50705993,0.09647914,-1.1748201,-0.122292355,-0.42770925, +-0.85271424,0.40565223,2.599867,1.6654495,-0.07207302,0.8841147,0.86270744,-0.647538, +0.6439041,-1.4409921,-0.8052984,0.23875287,-0.41478765,1.7564787,0.6480404,-0.38203812, +-0.4705797,0.1869706,-1.0555313,0.59561193,-1.375302,0.6230102,-0.16459472,0.41461352, +-1.0125859,0.24498521,2.4123478,-0.45721674,0.31739986,1.505567,0.76170415,0.43188548, +-1.0136893,-1.2775884,0.053432442,-0.46323586,-0.019058215,0.20565668,-0.67642784,0.494103, +1.8585562,-1.009341,-0.46954635,-0.04961066,1.1404597,-1.186382,-1.0651481,-2.163661, +-0.44036222,0.68014574,1.0652248,0.35715365,-0.600957,0.7064716,0.2043186,-1.9207056, +-1.2280948,1.5118653,0.3222051,-1.3747944,0.8199531,1.061435,-0.43503404,0.6576821, +-3.7401006,0.9735768,1.1751554,-1.1247027,0.2820854,-0.33812055,-0.10252948,-0.42488045, +-1.3322954,1.8904037,-0.31031084,0.104755044,-1.0094006,-1.0368671,0.4125984,0.5263921, +0.87792414,1.103774,-0.21020754,-0.44420308,0.74681383,-0.6374392,0.8717585,0.37450027, +1.1550264,0.6703917,-1.0544459,-0.86563367,0.7324853,1.9070559,-1.3228117,0.023211604, +0.28167456,-1.5257775,0.478125,-0.093122795,-2.0965574,1.621728,-0.86320823,-1.2825034, +0.4201416,0.5574868,0.7364114,-0.38600338,-0.010914338,-0.73080677,-1.3101974,1.0791306, +-0.102762684,-0.18231426,-1.9992676,-0.1783711,-0.8424945,-0.17461365,-0.21924415,-0.44646478, +0.93883866,0.44705415,1.1271545,-1.3248273,-0.64895594,-0.04028082,-0.40663898,-0.07925773, +-1.1821034,-0.71617806,-1.641554,-0.89002556,0.69417673,-0.21420689,1.5057533,-0.59553385, +0.11907108,-1.2132523,2.6006718,-0.17862059,0.82962984,0.41338503,-0.5838788,-1.3309013, +0.15614313,-0.55678976,-0.1555043,0.65130204,0.078241155,0.3771163,0.15004657,-1.4672493, +1.3960623,1.1758523,-1.1361649,0.50530064,-0.66202426,-0.74691635,-0.0048416615,1.7476683, +1.0579575,0.60522133,-1.1506057,2.5544493,0.873731,-2.3488374,0.39947432,-0.48869473, +0.40998235,0.40064037,-0.9185191,1.8258858,0.19978462,0.9413479,1.3514236,-0.7381576, +-0.9117685,1.1219074,1.3928374,-1.3770186,2.011243,-0.23550332,0.6917845,0.5643882, +-0.9713423,-0.8640481,-2.0835924,-1.1511501,-1.482476,0.040190514,1.3694022,-0.027144931, +0.33885416,0.7780035,0.67970943,-0.3858315,-1.463345,-0.42980552,0.06295936,-0.8716452, +0.3619607,-0.2927121,0.6218215,-0.80323946,-0.9219677,1.7740563,0.028756239,0.55296385, +-1.0984223,-0.37726447,0.6821695,1.5656159,-0.7244851,-0.8029174,-0.022668941,-1.5243951, +-0.030133307,-0.06472839,0.72474915,1.4146098,0.5698443,0.74155104,0.05227895,-0.35974458, +-1.9959769,-0.8862208,0.21726668,-1.6455938,0.24288982,-0.4008347,-1.0215598,-0.47002432, +0.7287815,0.8855011,-1.9370214,-0.14948401,0.91388464,-0.25789487,0.10881527,-1.4954109, +-0.48003367,1.8287754,-0.78806806,-1.4406323,0.14947176,0.78862935,1.1938105,-0.51772267, +0.22247557,0.54435486,0.6492105,-0.54720277,1.7127249,-0.68729705,0.70787215,-0.021911236, +-0.5872186,-0.6428513,-0.5863469,-0.44687107,-1.0188856,0.6974097,-0.7035153,-0.6150209, +0.48869058,-0.107961945,-1.4219036,-0.9360095,-0.19655724,-0.5749878,0.75048256,-0.76440203, +-0.9671271,-1.0105462,0.40665725,0.48347172,-1.6724446,0.6220752,0.8609733,-1.6909977, +-0.6904314,1.4288924,1.0061017,0.02479266,0.5012494,2.1120195,0.50279695,-1.2208089, +1.364939,-0.8709389,0.9939022,0.6562707,0.88951355,1.540933,-1.4659144,-0.06958856, +1.9460495,0.9763817,0.17715834,-1.0231731,0.10672049,-0.9118813,-1.468367,0.5764787, +0.065305606,-0.7735128,0.39494818,-0.50388986,1.7795591,-0.030572444,1.5770882,-0.8128021, +0.61334914,1.8436999,0.27109098,1.1364477,-1.7383319,0.7071347,0.030386131,0.76500195, +0.86766523,-2.2562501,-0.44360274,-0.67002326,0.15216419,-1.9405334,-1.0905087,1.0019207, +0.17689244,-1.0880145,-0.25321737,1.098273,-1.8395668,-0.21142861,-0.22966324,0.18697941, +0.5037795,1.9103425,0.5537812,-0.58748144,1.25795,-0.8586684,0.4361871,1.5714631, +1.0773149,0.8110897,-2.2315376,-0.101002514,-0.58737504,1.3248683,0.8406485,0.2611062, +0.79444164,-0.6496165,0.6342845,0.095002666,-1.6832068,0.34404615,0.707158,1.1934146, +0.5273885,1.006704,-1.7323273,-0.37341216,-0.1425104,-0.32974237,-0.08904212,-0.5773963, +0.73616546,-0.9912056,0.12517461,0.07315271,0.14393723,-0.94772434,1.3992299,-0.22612372, +-1.4388542,0.801301,-0.0033314459,-0.09694156,-0.09587145,0.39543697,-0.05324304,-0.7734996, +-1.4191855,0.30345193,-1.5182067,1.1197077,-0.95386094,-0.849614,-0.9818997,-1.3630776, +-0.77259856,-0.28362545,-2.327604,-2.4452274,-0.71586496,0.88339686,-1.3004398,-0.07633908, +1.4305568,-1.3234086,-0.43835616,-0.7431525,0.8919676,0.46387276,0.6176608,2.496417, +1.6294752,-0.0990447,-0.20199196,-1.4488258,-1.7141647,-0.049641572,-1.2993954,0.6253554, +-0.7917193,-0.5829434,-1.5526805,2.1101534,0.75882953,-0.70993024,0.15114704,1.3230913, +-0.9278251,1.9065987,-1.032175,-0.17736149,-1.6503783,-2.538511,1.0100908,0.08570209, +-1.733861,-1.6406012,1.1453614,-0.15059511,1.4314432,0.6365868,-0.06656285,0.03232998, +-0.5550736,0.097786106,-0.06098498,0.83751667,-0.16341844,0.82355547,0.9206323,0.1807626, +-1.3129684,-0.1604767,-1.9060746,-1.2066216,0.7304183,0.49489278,-0.0032088785,-0.30243316, +-0.7394009,-0.5128121,0.9652515,0.47667927,-1.3712165,0.19885284,0.13996284,1.6486734, +-1.7575518,-0.7831295,0.97362584,-1.1109322,2.3856215,-1.1789442,0.029122146,0.55954754, +0.8810371,0.7152085,-0.46207753,0.913207,-0.7546525,-0.53497714,0.45664245,1.5095769, +-0.22817124,-0.8903415,1.2097719,-1.2648001,1.8381815,-0.9840827,0.6409485,0.92669123, +0.78503406,0.22700264,0.049529552,-1.6531805,-0.78081965,0.72464466,0.6633692,-1.0378813, +0.34697902,0.252031,1.7509189,-0.41840115,-0.5198573,-0.92344296,-0.9992785,0.37494835, +-0.7043411,1.0747038,-0.6272991,1.5339956,0.41772544,0.25838363,-1.1504285,0.3291142, +0.04552198,0.6320826,-0.5108473,-1.4536299,0.2752216,0.13978724,0.24389236,1.0056502, +-0.93964064,-2.38175,0.475027,0.40591252,-0.4770563,0.17059821,-1.0477808,-2.106197, +-1.6929115,0.04236114,1.3827105,-0.38951838,0.8139379,-0.594332,-0.05543902,0.7965607, +0.13317989,-0.54167837,-0.8653024,-0.09252813,1.1821021,-1.5706546,0.8593308,0.283647, +-0.9691123,-0.01837373,-0.20403545,-0.9477404,-0.5394351,-1.2562873,-2.0715237,0.15123644, +1.0444895,1.6333491,-1.1113786,2.147365,1.5263067,1.423475,-0.7856664,-0.5622516, +-1.9383575,0.19115923,-0.39360294,0.16179068,-0.834518,0.67287046,0.3431881,-1.1441231, +-0.045887947,0.2846845,2.0084414,0.09578085,-0.940409,-0.31626305,-0.031223467,-0.13359529, +-1.8414719,-0.33157688,-0.6933089,-0.26051295,2.1209624,-0.8322906,1.437941,1.1606182, +0.68349785,0.0031104183,0.65439343,-0.4499198,-0.54645914,-0.7478617,0.27390158,-0.20977058, +-0.23958507,1.4202288,-0.7047485,0.7353649,-0.5219276,-1.592195,-1.4259504,-0.49155238 + +==== +name:CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.bias_data +0.6296115,0.6417864,-0.24068715,0.61842173,0.07626311,-0.26149032,0.85473126,1.1878939, +1.0160275,-0.30687296,0.5677076,-2.1292458,0.19506693,0.36100236,0.1519752,-0.22227272, +1.3047732,-0.0932377,-0.13953793,-0.24093674,1.0341054,-0.29245964,-0.8343494,-0.10875854, +1.7077137,-0.30068612,0.61577165,-0.27811074,-0.2767468,-0.5608414,-1.2163041,-0.10978163, +0.71845573,1.576193,0.4418695,-0.8168611,0.7455046,0.45402917,1.3983632,2.0896103, +1.2146077,-0.3927582,-0.15922955,1.1579405,-0.5076931,-0.14048347,0.6343402,1.0706061, +0.22291076,-2.8925197,0.33936596,-0.3120492,-0.975921,0.024130166,1.1204642,-1.1298772, +1.589923,0.9787301,0.93416363,-0.8147086,-0.25124246,-0.38283488,0.00034095792,-0.0622048, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, +0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + +==== +name:CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.fp32_output_data +-0.6003144,0.5046919,-0.12049955,-0.92507327,-0.42686504,0.072453946,-0.5814661,0.5313442, +0.1532953,-0.656893,0.029914446,-0.47042838,-0.21011704,-0.112559795,0.16661634,0.109792024, +0.044871077,0.05542153,-0.32573918,0.19370267,-0.2627771,0.34857383,-0.08189575,-0.5832793, +-0.2708692,0.3207512,-0.12878786,0.7165755,-0.029289871,0.2647196,0.6524202,-0.82146287, +-0.3520299,-0.25118023,-0.038025014,0.78544146,0.09237215,0.79537904,-0.5381446,0.3168583, +-0.97991526,0.8569559,-0.055078603,0.16906464,0.14160854,0.41692847,-0.26472932,0.62255543, +-0.79614085,0.5630065,0.9804111,-0.22339875,-0.07803835,0.68520164,0.33540013,-0.5185654, +-0.5656776,0.75473773,0.5266086,0.5193186,0.4887605,-0.2469342,-0.33267665,-0.8284849, +-0.14604083,0.3660654,-0.15639517,-0.5218262,0.1303009,0.74157655,-0.044350415,0.081228435, +-1.144964,-0.25515392,0.41934747,-0.6562912,-0.5374121,0.057686627,-0.25775802,-0.6835696, +0.19294256,0.37835988,-0.059078366,-0.23943216,-0.078009665,0.0029286146,-0.20156968,-0.1876947, +-0.2378927,0.46250412,-0.3916942,-0.02140814,-0.19658206,-0.05838166,0.3902902,-0.7092172, +0.19089642,0.7120326,0.17214371,0.1678071,-0.41189647,0.44862992,-0.065859206,0.0844535, +-0.12370446,-0.5356797,-0.13798991,-0.0020032525,0.71459025,-0.1703992,-0.13581733,0.74633443, +0.43537667,0.30747345,-0.17322245,-0.2525632,-0.527473,-0.550586,-0.27879256,-0.31048977, +-0.54378724,-0.12629068,0.5371106,-0.15989208,0.6806373,-0.43645537,0.16498,-0.057793662 + +==== +name:CrossAttention_DiffSequenceLengths_UsingDMMHAInsideMHA.fp32_output_qk_data +-1.2014943,0.6843257,-0.6116703,-0.5371384,0.66629004,0.033044804,0.9717946,0.15667602, +0.6141628,0.16917382,-0.566475,1.8491349,-0.024795728,1.3970505,-0.019675655,3.1860712, +-2.741984,1.6077112,-0.07165447,-0.03905407,-1.2188541,-0.5628502,0.09844631,1.32231, +1.332324,0.58346725,-0.86279655,1.3619442,1.4080318,-1.0267601,1.0768844,-0.0887926, +0.028943084,-1.9949476,0.7381273,-1.2816228,0.25567636,0.59148777,-0.11591597,0.7770739 diff --git a/onnxruntime/test/testdata/dmmha_cross_attn.onnx b/onnxruntime/test/testdata/dmmha_cross_attn.onnx new file mode 100644 index 0000000000000000000000000000000000000000..2717d129448e15361e5f5df0c89384d252ce8ade GIT binary patch literal 667 zcmb7B!AiqG5befR(rLwZr5bzCBJ`kA5f36gsR$LMCvUkdn`GOBG}$D(sp41o34V${ z;=edsJhY{tGVEbz-@Kjoo(;qI8hjBTIgl9094bH6%(&7_iJZ+u3g8Kzu$L&%AvApM zhk`|E5EVc?N+hjdS$W(&eh|J4L^0+n7Qwij>F81L;7)6i>PV(1zX8r#P*2N*g*c@g z>w{RPBTJo?n&q)WOs5Bji{-LHDCA`-H7=^5Dk53rW8uK{&rtHGB2Nn9jd_MHOQ_BO2|DRG_U6jokFE1A$6xW=KY zwf!1&;j9T#L5J=o{ME#}EYU+l1qvfO0o0qtn1`D}fS`zlmg F?Qgs=v%3HQ literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/dmmha_inside_mha_cross_attn.onnx b/onnxruntime/test/testdata/dmmha_inside_mha_cross_attn.onnx new file mode 100644 index 0000000000000000000000000000000000000000..e04a317cd640cc12b3bf6c5c2bddab1899e0aaef GIT binary patch literal 585 zcmb7B!AiqG5Y5Ia>9lG)QY<}46?(7|5f36gsh0}Uleb*LCRv-M$!?q76!B9$`6c3~ zIVm1$=|Nc*mYFwi-+SZ1=(7gz4A=tL4A>G_1kTTC&bhIn5sNSr3K}twQxQs)$O4&0 zhmO0L^>9*VRz3=z+*>P@m0F!`sSR6DS7jci1TF9F$5DortR`o^>56kM?7o zU*<9{w9zjXPm?@Pxi6KGiSVmu)iFM|R{7I{&(q+FE77GZ44*yL`uioe_ZWn TTWrVJvD)%%Q^rFLoL2iAk=mNi literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/dmmha_inside_mha_data.py b/onnxruntime/test/testdata/dmmha_inside_mha_data.py new file mode 100644 index 0000000000000..a7edbaf0d34ab --- /dev/null +++ b/onnxruntime/test/testdata/dmmha_inside_mha_data.py @@ -0,0 +1,195 @@ +import numpy as np + +import onnxruntime as ort +from onnxruntime import OrtValue + +np.random.seed(0) + + +# Whisper decoder self attention with past_kv, present_kv, buffer sharing enabled, mask, and bias +# Used in decoder-with-past's self-attention layers +# For CUDA, K caches are transposed and reshaped from 4D to 5D for DecoderMaskedMultiHeadAttention +# See onnxruntime/core/graph/contrib_ops/bert_defs.cc for more details +def dmmha_inside_mha_self_attn(): + batch_size, num_heads, head_size = 2, 2, 32 + hidden_size = num_heads * head_size + past_sequence_length, sequence_length, max_sequence_length = 4, 1, 6 + num_beams = 1 + device = "cuda" + + inputs = { + "q": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "k": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "v": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "b": np.random.randn(hidden_size * 3).astype(np.float32), + "past_k": np.zeros((batch_size, num_heads, max_sequence_length, head_size)).astype(np.float32), + "past_v": np.zeros((batch_size, num_heads, max_sequence_length, head_size)).astype(np.float32), + "past_seq_len": np.array([past_sequence_length]).astype(np.int32), + "cache_indir": np.zeros((batch_size, num_beams, max_sequence_length)).astype(np.int32), + } + inputs["past_k"][:batch_size, :num_heads, :past_sequence_length, :head_size] = np.random.randn( + batch_size, num_heads, past_sequence_length, head_size + ).astype(np.float32) + inputs["past_v"][:batch_size, :num_heads, :past_sequence_length, :head_size] = np.random.randn( + batch_size, num_heads, past_sequence_length, head_size + ).astype(np.float32) + print_vals(inputs) + + sess = ort.InferenceSession("dmmha_inside_mha_self_attn.onnx", providers=[f"{device.upper()}ExecutionProvider"]) + io_binding = sess.io_binding() + past_k_ortvalue, past_v_ortvalue = None, None + for k, v in inputs.items(): + v_device = OrtValue.ortvalue_from_numpy(v, device_type=device.lower(), device_id=0) + io_binding.bind_ortvalue_input(k, v_device) + if k == "past_k": + past_k_ortvalue = v_device + elif k == "past_v": + past_v_ortvalue = v_device + for output in sess.get_outputs(): + name = output.name + if name == "present_k": + io_binding.bind_ortvalue_output(name, past_k_ortvalue) + elif name == "present_v": + io_binding.bind_ortvalue_output(name, past_v_ortvalue) + else: + io_binding.bind_output(name, device_type=device.lower(), device_id=0) + + sess.run_with_iobinding(io_binding) + outputs = io_binding.copy_outputs_to_cpu() + + print_vals(outputs) + + +# Whisper decoder self attention with past_kv, present_kv, buffer sharing enabled, mask, and bias +# Used in decoder-with-past's self-attention layers +# For CUDA, K caches are transposed and reshaped from 4D to 5D for DecoderMaskedMultiHeadAttention +# See onnxruntime/core/graph/contrib_ops/bert_defs.cc for more details +def dmmha_self_attn(): + batch_size, num_heads, head_size = 2, 2, 32 + hidden_size = num_heads * head_size + past_sequence_length, sequence_length, max_sequence_length = 4, 1, 6 + num_beams = 1 + device = "cuda" + + inputs = { + "q": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "k": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "v": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "b": np.random.randn(hidden_size * 3).astype(np.float32), + "past_k": np.zeros((batch_size, num_heads, max_sequence_length, head_size)).astype(np.float32), + "past_v": np.zeros((batch_size, num_heads, max_sequence_length, head_size)).astype(np.float32), + "past_seq_len": np.array([past_sequence_length]).astype(np.int32), + "beam_width": np.array([num_beams]).astype(np.int32), + "cache_indir": np.zeros((batch_size, num_beams, max_sequence_length)).astype(np.int32), + } + inputs["past_k"][:batch_size, :num_heads, :past_sequence_length, :head_size] = np.random.randn( + batch_size, num_heads, past_sequence_length, head_size + ).astype(np.float32) + inputs["past_v"][:batch_size, :num_heads, :past_sequence_length, :head_size] = np.random.randn( + batch_size, num_heads, past_sequence_length, head_size + ).astype(np.float32) + print_vals(inputs) + + sess = ort.InferenceSession("dmmha_self_attn.onnx", providers=[f"{device.upper()}ExecutionProvider"]) + io_binding = sess.io_binding() + past_k_ortvalue, past_v_ortvalue = None, None + for k, v in inputs.items(): + v_device = OrtValue.ortvalue_from_numpy(v, device_type=device.lower(), device_id=0) + io_binding.bind_ortvalue_input(k, v_device) + if k == "past_k": + past_k_ortvalue = v_device + elif k == "past_v": + past_v_ortvalue = v_device + for output in sess.get_outputs(): + name = output.name + if name == "present_k": + io_binding.bind_ortvalue_output(name, past_k_ortvalue) + elif name == "present_v": + io_binding.bind_ortvalue_output(name, past_v_ortvalue) + else: + io_binding.bind_output(name, device_type=device.lower(), device_id=0) + + sess.run_with_iobinding(io_binding) + outputs = io_binding.copy_outputs_to_cpu() + + print_vals(outputs) + + +# Whisper decoder cross attention with past_kv used directly as K and V, no mask, and bias +# Used in decoder-with-past's cross-attention layers +def dmmha_inside_mha_cross_attn(): + batch_size, num_heads, head_size = 2, 2, 32 + hidden_size = num_heads * head_size + past_sequence_length, sequence_length, kv_sequence_length, max_sequence_length = 4, 1, 10, 6 + num_beams = 1 + device = "cuda" + + inputs = { + "q": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "k": np.random.randn(batch_size, num_heads, kv_sequence_length, head_size).astype(np.float32), + "v": np.random.randn(batch_size, num_heads, kv_sequence_length, head_size).astype(np.float32), + "b": np.zeros(hidden_size * 3).astype(np.float32), + "past_seq_len": np.array([past_sequence_length]).astype(np.int32), + "cache_indir": np.zeros((batch_size, num_beams, max_sequence_length)).astype(np.int32), + } + inputs["b"][:hidden_size] = np.random.randn(hidden_size).astype(np.float32) + print_vals(inputs) + + sess = ort.InferenceSession("dmmha_inside_mha_cross_attn.onnx", providers=[f"{device.upper()}ExecutionProvider"]) + outputs = sess.run(None, inputs) + + print_vals(outputs) + + +# Whisper decoder cross attention with past_kv used directly as K and V, no mask, and bias +# Used in decoder-with-past's cross-attention layers +def dmmha_cross_attn(): + batch_size, num_heads, head_size = 2, 2, 32 + hidden_size = num_heads * head_size + past_sequence_length, sequence_length, kv_sequence_length, max_sequence_length = 4, 1, 10, 6 + num_beams = 1 + device = "cuda" + + inputs = { + "q": np.random.randn(batch_size, sequence_length, hidden_size).astype(np.float32), + "k": np.random.randn(batch_size, num_heads, kv_sequence_length, head_size).astype(np.float32), + "v": np.random.randn(batch_size, num_heads, kv_sequence_length, head_size).astype(np.float32), + "b": np.zeros(hidden_size * 3).astype(np.float32), + "past_seq_len": np.array([past_sequence_length]).astype(np.int32), + "beam_width": np.array([num_beams]).astype(np.int32), + "cache_indir": np.zeros((batch_size, num_beams, max_sequence_length)).astype(np.int32), + } + inputs["b"][:hidden_size] = np.random.randn(hidden_size).astype(np.float32) + print_vals(inputs) + + sess = ort.InferenceSession("dmmha_cross_attn.onnx", providers=[f"{device.upper()}ExecutionProvider"]) + outputs = sess.run(None, inputs) + + print_vals(outputs) + + +# Print values in format for onnxruntime/test/testdata/attention/attention_test_data.txt +def print_vals(L): + if isinstance(L, list): + for idx, elm in enumerate(L): + print(f"\nOutput {idx}:", flush=True) + for i, entry in enumerate(elm.flatten()): + print(entry, end=",", flush=True) + if i % 8 == 0 and i != 0: + print("\n", end="", flush=True) + elif isinstance(L, dict): + for key, val in L.items(): + print(f"\n{key}:", flush=True) + for i, entry in enumerate(val.flatten()): + print(entry, end=",", flush=True) + if i % 8 == 0 and i != 0: + print("\n", end="", flush=True) + + print("\n=====================================================", flush=True) + + +dmmha_inside_mha_self_attn() +dmmha_inside_mha_cross_attn() + +dmmha_self_attn() +dmmha_cross_attn() diff --git a/onnxruntime/test/testdata/dmmha_inside_mha_graph.py b/onnxruntime/test/testdata/dmmha_inside_mha_graph.py new file mode 100644 index 0000000000000..c019afe9a6c17 --- /dev/null +++ b/onnxruntime/test/testdata/dmmha_inside_mha_graph.py @@ -0,0 +1,235 @@ +from onnx import TensorProto, helper, save_model + + +# Whisper decoder self attention with past_kv, present_kv, buffer sharing enabled, mask, and bias +# Used in decoder-with-past's self-attention layers +def dmmha_inside_mha_self_attn(): + num_heads, head_size = 2, 32 + hidden_size = num_heads * head_size + + # Inputs + q = helper.make_tensor_value_info("q", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + k = helper.make_tensor_value_info("k", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + v = helper.make_tensor_value_info("v", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + b = helper.make_tensor_value_info("b", TensorProto.FLOAT, [hidden_size * 3]) + past_k = helper.make_tensor_value_info( + "past_k", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + past_v = helper.make_tensor_value_info( + "past_v", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + past_seq_len = helper.make_tensor_value_info("past_seq_len", TensorProto.INT32, [1]) + cache_indir = helper.make_tensor_value_info( + "cache_indir", TensorProto.INT32, ["batch_size", "num_beams", "max_sequence_length"] + ) + inputs = [q, k, v, b, past_k, past_v, past_seq_len, cache_indir] + + # Outputs + o = helper.make_tensor_value_info("o", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + present_k = helper.make_tensor_value_info( + "present_k", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + present_v = helper.make_tensor_value_info( + "present_v", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + outputs = [o, present_k, present_v] + + model = helper.make_model( + helper.make_graph( + [ + helper.make_node( + "MultiHeadAttention", + inputs=["q", "k", "v", "b", "", "", "past_k", "past_v", "past_seq_len", "cache_indir"], + outputs=["o", "present_k", "present_v"], + name="MultiHeadAttention", + domain="com.microsoft", + num_heads=num_heads, + unidirectional=1, + ) + ], + "dmmha-inside-mha-self-attn-graph", + inputs, + outputs, + ), + opset_imports=[helper.make_opsetid("", 17)], + ) + save_model(model, "dmmha_inside_mha_self_attn.onnx") + + +# Whisper decoder self attention with past_kv, present_kv, buffer sharing enabled, mask, and bias +# Used in decoder-with-past's self-attention layers +def dmmha_self_attn(): + num_heads, head_size = 2, 32 + hidden_size = num_heads * head_size + + # Inputs + q = helper.make_tensor_value_info("q", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + k = helper.make_tensor_value_info("k", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + v = helper.make_tensor_value_info("v", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + b = helper.make_tensor_value_info("b", TensorProto.FLOAT, [hidden_size * 3]) + past_k = helper.make_tensor_value_info( + "past_k", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + past_v = helper.make_tensor_value_info( + "past_v", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + past_seq_len = helper.make_tensor_value_info("past_seq_len", TensorProto.INT32, [1]) + beam_width = helper.make_tensor_value_info("beam_width", TensorProto.INT32, [1]) + cache_indir = helper.make_tensor_value_info( + "cache_indir", TensorProto.INT32, ["batch_size", "num_beams", "max_sequence_length"] + ) + inputs = [q, k, v, b, past_k, past_v, past_seq_len, beam_width, cache_indir] + + # Outputs + o = helper.make_tensor_value_info("o", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + present_k = helper.make_tensor_value_info( + "present_k", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + present_v = helper.make_tensor_value_info( + "present_v", TensorProto.FLOAT, ["batch_size", num_heads, "max_sequence_length", head_size] + ) + outputs = [o, present_k, present_v] + + model = helper.make_model( + helper.make_graph( + [ + helper.make_node( + "DecoderMaskedMultiHeadAttention", + inputs=[ + "q", + "k", + "v", + "", + "", + "past_k", + "past_v", + "past_seq_len", + "beam_width", + "cache_indir", + "b", + ], + outputs=["o", "present_k", "present_v"], + name="DecoderMaskedMultiHeadAttention", + domain="com.microsoft", + num_heads=num_heads, + past_present_share_buffer=1, + ) + ], + "dmmha-self-attn-graph", + inputs, + outputs, + ), + opset_imports=[helper.make_opsetid("", 17)], + ) + save_model(model, "dmmha_self_attn.onnx") + + +# Whisper decoder cross attention with past_kv used directly as K and V, no mask, and bias +# Used in decoder-with-past's cross-attention layers +def dmmha_inside_mha_cross_attn(): + num_heads, head_size = 2, 32 + hidden_size = num_heads * head_size + encoder_seq_len = 10 + + # Inputs + q = helper.make_tensor_value_info("q", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + past_k = helper.make_tensor_value_info( + "k", TensorProto.FLOAT, ["batch_size", num_heads, encoder_seq_len, head_size] + ) + past_v = helper.make_tensor_value_info( + "v", TensorProto.FLOAT, ["batch_size", num_heads, encoder_seq_len, head_size] + ) + b = helper.make_tensor_value_info("b", TensorProto.FLOAT, [hidden_size * 3]) + past_seq_len = helper.make_tensor_value_info("past_seq_len", TensorProto.INT32, [1]) + cache_indir = helper.make_tensor_value_info( + "cache_indir", TensorProto.INT32, ["batch_size", "num_beams", "max_sequence_length"] + ) + inputs = [q, past_k, past_v, b, past_seq_len, cache_indir] + + # Outputs + o = helper.make_tensor_value_info("o", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + qk = helper.make_tensor_value_info( + "qk", TensorProto.FLOAT, ["batch_size", "num_heads", "sequence_length", "total_sequence_length"] + ) + outputs = [o, qk] + + model = helper.make_model( + helper.make_graph( + [ + helper.make_node( + "MultiHeadAttention", + inputs=["q", "k", "v", "b", "", "", "", "", "past_seq_len", "cache_indir"], + outputs=["o", "", "", "qk"], + name="MultiHeadAttention", + domain="com.microsoft", + num_heads=num_heads, + unidirectional=0, + ) + ], + "dmmha-inside-mha-cross-attn-graph", + inputs, + outputs, + ), + opset_imports=[helper.make_opsetid("", 17)], + ) + save_model(model, "dmmha_inside_mha_cross_attn.onnx") + + +# Whisper decoder cross attention with past_kv used directly as K and V, no mask, and bias +# Used in decoder-with-past's cross-attention layers +def dmmha_cross_attn(): + num_heads, head_size = 2, 32 + hidden_size = num_heads * head_size + encoder_seq_len = 10 + + # Inputs + q = helper.make_tensor_value_info("q", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + past_k = helper.make_tensor_value_info( + "k", TensorProto.FLOAT, ["batch_size", num_heads, encoder_seq_len, head_size] + ) + past_v = helper.make_tensor_value_info( + "v", TensorProto.FLOAT, ["batch_size", num_heads, encoder_seq_len, head_size] + ) + b = helper.make_tensor_value_info("b", TensorProto.FLOAT, [hidden_size * 3]) + past_seq_len = helper.make_tensor_value_info("past_seq_len", TensorProto.INT32, [1]) + beam_width = helper.make_tensor_value_info("beam_width", TensorProto.INT32, [1]) + cache_indir = helper.make_tensor_value_info( + "cache_indir", TensorProto.INT32, ["batch_size", "num_beams", "max_sequence_length"] + ) + inputs = [q, past_k, past_v, b, past_seq_len, beam_width, cache_indir] + + # Outputs + o = helper.make_tensor_value_info("o", TensorProto.FLOAT, ["batch_size", "sequence_length", hidden_size]) + qk = helper.make_tensor_value_info( + "qk", TensorProto.FLOAT, ["batch_size", "num_heads", "sequence_length", "total_sequence_length"] + ) + outputs = [o, qk] + + model = helper.make_model( + helper.make_graph( + [ + helper.make_node( + "DecoderMaskedMultiHeadAttention", + inputs=["q", "k", "v", "", "", "", "", "past_seq_len", "beam_width", "cache_indir", "b"], + outputs=["o", "", "", "qk"], + name="DecoderMaskedMultiHeadAttention", + domain="com.microsoft", + num_heads=num_heads, + output_qk=1, + past_present_share_buffer=0, + ) + ], + "dmmha-cross-attn-graph", + inputs, + outputs, + ), + opset_imports=[helper.make_opsetid("", 17)], + ) + save_model(model, "dmmha_cross_attn.onnx") + + +dmmha_inside_mha_self_attn() +dmmha_inside_mha_cross_attn() + +dmmha_self_attn() +dmmha_cross_attn() diff --git a/onnxruntime/test/testdata/dmmha_inside_mha_self_attn.onnx b/onnxruntime/test/testdata/dmmha_inside_mha_self_attn.onnx new file mode 100644 index 0000000000000000000000000000000000000000..959910677225d3985f04b0f96e19dba63a3aa7fa GIT binary patch literal 805 zcmbV~&rSj{5XR|>WEoJQhJ7ngRzsWbhsSAUb3cL{@b0AY7IgkKKxGFPdtUvwSbEq%wM$G+KXsB_< zBjHOO%9N6XR%fX&LZjg4n0M%77F+osSa@qKW@Vy}{)qJ&P}Q08BYbGu&MR?xE!fYr z#NvV%Di*g1h6j5*QD;i>G%?B8(r&0!#5}2u424%5jflq{vsQbPl+B{iIrc?Q;lw5M z80r)PW_jcr`7EGG53rj|XfBGDCN=`c9Ttk|#)^D1MFSzz8dTBMF6_APWOVbzn_fa6 z!`_-%$914Z4;6dzf1B=p%k%Bzoz>}50N1V1GV&m!`_)-r!xg43*6h{jVt|2Q%KYOq aK(NV1n1UfJeXDJ_ELYeL&0QHvjpheJP literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/dmmha_self_attn.onnx b/onnxruntime/test/testdata/dmmha_self_attn.onnx new file mode 100644 index 0000000000000000000000000000000000000000..bcf369e0faea9d06084dcd5221cc869b67df5c27 GIT binary patch literal 869 zcmbVK%SyvQ6z#-XrneQ_kwWdpBDk;;@c|+Qp^BiJ{y;awB)MrqnxxH4qWCp_ir?Yh z|8P>QrWKKvSe*oEJk8hohB$T()gcc);YLGJ9aP`3K^g?Oee~JMB&^jrAz%dI{dGo z*MMr2hTPLA**0E@(d)wgoY>++>4^lnmAWn_ZK5msJ9ZqNhQ6J|GIkYfIbrAtQ{u!m zg;J3@PQ=t3ooVdb_TM^I;A31xd+`Y#AgwyR~Q7}=O>A8W}59ps2$ZA7*nqLKSq zgQ{k=4O{e$jBXZ Date: Sun, 16 Mar 2025 12:21:45 -0700 Subject: [PATCH 109/266] Windows: Show more useful DLL load errors to say exactly what DLL is missing (#24053) ### Description When we fail to load a provider shared DLL in windows, the error is not very specific. Users have to figure out if the onnxruntime file is missing, a cuda file, or cudnn is not installed (and perhaps others). And this is just the cuda provider. It would be far more useful if it would say exactly what file is missing so the user can fix the actual problem. Plus, this will likely result in many fewer github issues regarding this problem, but if they do, they will be much easier to fix. This fix adds a function that will try loading a dll and its dependencies recursively to figure out which file is missing. It uses the OS dbghelp library to do it and is not very complex. This also fixes a many year old bug that was introduced in the change to use FormatMessage in env.cc, where the system error would always be an empty string `error 126 ""` due to passing 0 as the format buffer length. We will now see the more useful `The specified module could not be found.` style error messages. ### Motivation and Context Previously if we fail to load the cuda provider, the error would look like this, which is limited: `unknown file: error: C++ exception with description " onnxruntime::ProviderLibrary::Get [ONNXRuntimeError] : 1 : FAIL : LoadLibrary failed with error 126 "" when trying to load "C:\Example\Path\To\Library\onnxruntime_providers_cuda.dll"` Now it will look like this if cudnn is not installed: `unknown file: error: C++ exception with description onnxruntime::ProviderLibrary::Get [ONNXRuntimeError] : 1 : FAIL : Error loading "C:\Example\Path\To\Library\onnxruntime_providers_cuda.dll" which depends on "cudnn64_9.dll" which is missing. (Error 126: "The specified module could not be found.")` If cuda is not installed: `unknown file: error: C++ exception with description onnxruntime::ProviderLibrary::Get [ONNXRuntimeError] : 1 : FAIL : Error loading "C:\Example\Path\To\Library\onnxruntime_providers_cuda.dll" which depends on "cudart64_12.dll" which is missing. (Error 126: "The specified module could not be found.")` And if onnxruntime_providers_cuda.dll is not installed: `unknown file: error: C++ exception with description onnxruntime::ProviderLibrary::Get [ONNXRuntimeError] : 1 : FAIL : Error loading "C:\Example\Path\To\Library\onnxruntime_providers_cuda.dll" which is missing. (Error 126: "The specified module could not be found.") ` --- .../core/platform/windows/dll_load_error.cc | 61 +++++++++++++++++++ .../core/platform/windows/dll_load_error.h | 1 + onnxruntime/core/platform/windows/env.cc | 12 ++-- 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 onnxruntime/core/platform/windows/dll_load_error.cc create mode 100644 onnxruntime/core/platform/windows/dll_load_error.h diff --git a/onnxruntime/core/platform/windows/dll_load_error.cc b/onnxruntime/core/platform/windows/dll_load_error.cc new file mode 100644 index 0000000000000..94471e76ffd71 --- /dev/null +++ b/onnxruntime/core/platform/windows/dll_load_error.cc @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include +#pragma comment(lib, "dbghelp.lib") +#include +#include +#include +#include "dll_load_error.h" + +struct HMODULE_Deleter { + typedef HMODULE pointer; + void operator()(HMODULE h) { FreeLibrary(h); } +}; + +using ModulePtr = std::unique_ptr; + +// If a DLL fails to load, this will try loading the DLL and then its dependencies recursively +// until it finds a missing file, then will report which file is missing and what the dependency +// chain is. +std::wstring DetermineLoadLibraryError(const wchar_t* filename_in, DWORD flags) { + std::wstring error(L"Error loading"); + + std::wstring filename{filename_in}; + while (filename.size()) { + error += std::wstring(L" \"") + filename + L"\""; + + // We use DONT_RESOLVE_DLL_REFERENCES instead of LOAD_LIBRARY_AS_DATAFILE because the latter will not process the import table + // and will result in the IMAGE_IMPORT_DESCRIPTOR table names being uninitialized. + ModulePtr hModule = ModulePtr{LoadLibraryExW(filename.c_str(), NULL, flags | DONT_RESOLVE_DLL_REFERENCES)}; + if (!hModule) { + error += L" which is missing."; + return error; + } + + // Get the address of the Import Directory + ULONG size{}; + IMAGE_IMPORT_DESCRIPTOR* import_desc = reinterpret_cast(ImageDirectoryEntryToData(hModule.get(), TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size)); + if (!import_desc) { + error += L" No import directory found."; // This is unexpected, and I'm not sure how it could happen but we handle it just in case. + return error; + } + + // Iterate through the import descriptors to see which dependent DLL can't load + filename.clear(); + flags = 0; // Dependent libraries are relative, and flags like LOAD_WITH_ALTERED_SEARCH_PATH is undefined for those. + for (; import_desc->Characteristics; import_desc++) { + const char* dll_name = reinterpret_cast(reinterpret_cast(hModule.get()) + import_desc->Name); + // Try to load the dependent DLL, and if it fails, we loop again with this as the DLL and we'll be one step closer to the missing file. + ModulePtr hDepModule{LoadLibrary(dll_name)}; + if (!hDepModule) { + filename = std::wstring(dll_name, dll_name + strlen(dll_name)); + error += L" which depends on"; + break; + } + } + } + error += L" But no dependency issue could be determined."; + return error; +} diff --git a/onnxruntime/core/platform/windows/dll_load_error.h b/onnxruntime/core/platform/windows/dll_load_error.h new file mode 100644 index 0000000000000..019adfd9e16e4 --- /dev/null +++ b/onnxruntime/core/platform/windows/dll_load_error.h @@ -0,0 +1 @@ +std::wstring DetermineLoadLibraryError(const wchar_t* filename, DWORD flags); diff --git a/onnxruntime/core/platform/windows/env.cc b/onnxruntime/core/platform/windows/env.cc index 4fccad6dfeb37..9fdd323b365d6 100644 --- a/onnxruntime/core/platform/windows/env.cc +++ b/onnxruntime/core/platform/windows/env.cc @@ -39,6 +39,7 @@ limitations under the License. #include #include "core/platform/path_lib.h" // for LoopDir() +#include "core/platform/windows/dll_load_error.h" EXTERN_C IMAGE_DOS_HEADER __ImageBase; @@ -704,17 +705,18 @@ Status WindowsEnv::LoadDynamicLibrary(const PathString& wlibrary_filename, bool static constexpr DWORD bufferLength = 64 * 1024; std::wstring s(bufferLength, '\0'); FormatMessageW( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)s.data(), - 0, NULL); + bufferLength, NULL); + s.erase(std::remove(s.begin(), s.end(), L'\r'), s.end()); + s.erase(std::remove(s.begin(), s.end(), L'\n'), s.end()); std::wostringstream oss; - oss << L"LoadLibrary failed with error " << error_code << L" \"" << s.c_str() << L"\" when trying to load \"" << wlibrary_filename << L"\""; + oss << DetermineLoadLibraryError(wlibrary_filename.c_str(), LOAD_WITH_ALTERED_SEARCH_PATH) + << L" (Error " << error_code << ": \"" << s.c_str() << "\")"; std::wstring errmsg = oss.str(); - // TODO: trim the ending '\r' and/or '\n' common::Status status(common::ONNXRUNTIME, common::FAIL, ToUTF8String(errmsg)); return status; } From 2bc73ca8f5911ce55b821964ddf211bedee283f7 Mon Sep 17 00:00:00 2001 From: Yifan Li <109183385+yf711@users.noreply.github.com> Date: Mon, 17 Mar 2025 09:28:50 -0700 Subject: [PATCH 110/266] Extend CMAKE_CUDA_FLAGS with all Blackwell compute capacity (#23928) ### Description * Update range to build SASS on all arch and PTX on highest arch * when cuda>=12.8, build all arch (including latest blackwell) ### Motivation and Context https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list --- cmake/CMakeLists.txt | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 4a39a5b208a24..d520f4ac9212a 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1547,32 +1547,21 @@ if (onnxruntime_USE_CUDA) endif() find_package(CUDAToolkit REQUIRED) if (NOT CMAKE_CUDA_ARCHITECTURES) + # Note that we generate SASS+PTX code for specified cuda architectures by assigning "xy" + # To add SASS only, assign "xy-real" + # To add PTX only, assign "xy-virtual" if (CMAKE_LIBRARY_ARCHITECTURE STREQUAL "aarch64-linux-gnu") # Support for Jetson/Tegra ARM devices - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_53,code=sm_53") # TX1, Nano - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_62,code=sm_62") # TX2 - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_72,code=sm_72") # AGX Xavier, NX Xavier - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_87,code=sm_87") # AGX Orin, NX Orin + set(CMAKE_CUDA_ARCHITECTURES "53-real;62-real;72-real;87") # TX1/Nano, TX2, Xavier, Orin else() if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12) # 37, 50 still work in CUDA 11 but are marked deprecated and will be removed in future CUDA version. - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_37,code=sm_37") # K80 - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_50,code=sm_50") # M series - endif() - # Note that we generate SASS code for specified cuda architectures. It does not support forward compatibility. - # To add PTX for future GPU architectures >= XX, append -gencode=arch=compute_XX,code=compute_XX. - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_52,code=sm_52") # M60 - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_60,code=sm_60") # P series - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_70,code=sm_70") # V series - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_75,code=sm_75") # T series - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_80,code=sm_80") # A series - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_86,code=sm_86") - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_89,code=sm_89") - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_90,code=sm_90") # H series - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_120,code=sm_120") # B series - endif() + set(CMAKE_CUDA_ARCHITECTURES "37-real;50-real;52-real;60-real;70-real;75-real;80-real;86-real;89") + elseif (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12.8) + set(CMAKE_CUDA_ARCHITECTURES "52-real;60-real;70-real;75-real;80-real;86-real;89-real;90") + else() + # https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html + set(CMAKE_CUDA_ARCHITECTURES "all") # Supporting all, including latest Blackwell B series & RTX 50 series endif() endif() endif() From f5812d0efb124569efbc0eda576e0b3ec5b0d728 Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Tue, 18 Mar 2025 01:08:13 +0800 Subject: [PATCH 111/266] [WebGPU] Reduce staging buffers for uploading intializers (#23968) This change reduces the number of staging buffers used for uploading initializers to the GPU. On the one hand, we early release the upload staging buffers. On the other hand, we use the BufferMapExtendedUsages feature of Dawn on UMA GPUs, which allows us to directly write into the dest GPU buffer without the need of a staging buffer. To achieve this, we need to ensure the UMA GPU buffers are mapped at creation. We have BufferManager to be awared of OnSessionInitializationEnd(), so that it can handle buffer Create() and Upload() calls properly. Credits to @fs-eire for the overall design of implementation. --- .../core/providers/webgpu/allocator.cc | 11 ++++- onnxruntime/core/providers/webgpu/allocator.h | 3 ++ .../core/providers/webgpu/buffer_manager.cc | 47 +++++++++++++++++-- .../core/providers/webgpu/buffer_manager.h | 5 +- .../core/providers/webgpu/webgpu_context.cc | 10 +++- .../core/providers/webgpu/webgpu_context.h | 3 ++ .../webgpu/webgpu_execution_provider.cc | 11 ++++- .../webgpu/webgpu_execution_provider.h | 3 ++ 8 files changed, 85 insertions(+), 8 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/allocator.cc b/onnxruntime/core/providers/webgpu/allocator.cc index 51a06ad7643f6..91cae111a708a 100644 --- a/onnxruntime/core/providers/webgpu/allocator.cc +++ b/onnxruntime/core/providers/webgpu/allocator.cc @@ -13,7 +13,12 @@ void* GpuBufferAllocator::Alloc(size_t size) { return nullptr; } - auto buffer = context_.BufferManager().Create(size); + WGPUBuffer buffer; + if (!session_initialized_ && context_.SupportsBufferMapExtendedUsages()) { + buffer = context_.BufferManager().CreateUMA(size); + } else { + buffer = context_.BufferManager().Create(size); + } stats_.num_allocs++; return buffer; @@ -30,5 +35,9 @@ void GpuBufferAllocator::GetStats(AllocatorStats* stats) { *stats = stats_; } +void GpuBufferAllocator::OnSessionInitializationEnd() { + session_initialized_ = true; +} + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/allocator.h b/onnxruntime/core/providers/webgpu/allocator.h index 51ca65a8b4822..d98661884c659 100644 --- a/onnxruntime/core/providers/webgpu/allocator.h +++ b/onnxruntime/core/providers/webgpu/allocator.h @@ -25,9 +25,12 @@ class GpuBufferAllocator : public IAllocator { virtual void Free(void* p) override; void GetStats(AllocatorStats* stats) override; + void OnSessionInitializationEnd(); + private: AllocatorStats stats_; const WebGpuContext& context_; + bool session_initialized_ = false; }; } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.cc b/onnxruntime/core/providers/webgpu/buffer_manager.cc index de71566324efd..adb37f54f2e8f 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.cc +++ b/onnxruntime/core/providers/webgpu/buffer_manager.cc @@ -7,10 +7,20 @@ namespace onnxruntime { namespace webgpu { +namespace { + constexpr size_t NormalizeBufferSize(size_t size) { return (size + 15) / 16 * 16; } +void EnforceBufferUnmapped(WebGpuContext& context, WGPUBuffer buffer) { + if (context.ValidationMode() > ValidationMode::Basic) { + ORT_ENFORCE(wgpuBufferGetMapState(buffer) == WGPUBufferMapState_Unmapped, "Buffer is still mapped."); + } +} + +} // namespace + class DisabledCacheManager : public IBufferCacheManager { size_t CalculateBufferSize(size_t request_size) override { return NormalizeBufferSize(request_size); @@ -244,6 +254,16 @@ BufferManager::BufferManager(WebGpuContext& context, BufferCacheMode storage_buf } void BufferManager::Upload(void* src, WGPUBuffer dst, size_t size) { + // If the buffer is mapped, we can directly write to it. + wgpu::Buffer dst_buffer = dst; + auto mapped_data = dst_buffer.GetMappedRange(); + if (mapped_data) { + memcpy(mapped_data, src, size); + dst_buffer.Unmap(); + return; + } + + // Otherwise, we need to use a staging buffer to upload data. auto buffer_size = NormalizeBufferSize(size); wgpu::BufferDescriptor desc{}; @@ -252,18 +272,20 @@ void BufferManager::Upload(void* src, WGPUBuffer dst, size_t size) { desc.mappedAtCreation = true; auto staging_buffer = context_.Device().CreateBuffer(&desc); - auto mapped_data = staging_buffer.GetMappedRange(); + mapped_data = staging_buffer.GetMappedRange(); memcpy(mapped_data, src, size); staging_buffer.Unmap(); auto& command_encoder = context_.GetCommandEncoder(); context_.EndComputePass(); command_encoder.CopyBufferToBuffer(staging_buffer, 0, dst, 0, buffer_size); - pending_staging_buffers_.push_back(staging_buffer); + context_.Flush(); } void BufferManager::MemCpy(WGPUBuffer src, WGPUBuffer dst, size_t size) { ORT_ENFORCE(src != dst, "Source and destination buffers must be different."); + EnforceBufferUnmapped(context_, src); + EnforceBufferUnmapped(context_, dst); auto buffer_size = NormalizeBufferSize(size); ORT_ENFORCE(buffer_size <= wgpuBufferGetSize(src) && buffer_size <= wgpuBufferGetSize(dst), @@ -297,11 +319,31 @@ WGPUBuffer BufferManager::Create(size_t size, wgpu::BufferUsage usage) { return buffer; } +WGPUBuffer BufferManager::CreateUMA(size_t size, wgpu::BufferUsage usage) { + ORT_ENFORCE(usage & wgpu::BufferUsage::Storage, "UMA buffer must have storage usage."); + auto& cache = GetCacheManager(static_cast(usage)); + auto buffer_size = cache.CalculateBufferSize(size); + + wgpu::BufferDescriptor desc{}; + desc.size = buffer_size; + // Ensure the buffer is mapped for writing at creation. + desc.usage = usage | wgpu::BufferUsage::MapWrite; + desc.mappedAtCreation = true; + auto buffer = context_.Device().CreateBuffer(&desc).MoveToCHandle(); + + ORT_ENFORCE(buffer, "Failed to create GPU buffer: size=", buffer_size, ", usage=", uint64_t(usage), "."); + + cache.RegisterBuffer(buffer, size); + return buffer; +} + void BufferManager::Release(WGPUBuffer buffer) { + EnforceBufferUnmapped(context_, buffer); GetCacheManager(buffer).ReleaseBuffer(buffer); } void BufferManager::Download(WGPUBuffer src, void* dst, size_t size) { + EnforceBufferUnmapped(context_, src); auto buffer_size = NormalizeBufferSize(size); wgpu::BufferDescriptor desc{}; @@ -325,7 +367,6 @@ void BufferManager::Download(WGPUBuffer src, void* dst, size_t size) { } void BufferManager::RefreshPendingBuffers() { - pending_staging_buffers_.clear(); storage_cache_->OnRefresh(); uniform_cache_->OnRefresh(); query_resolve_cache_->OnRefresh(); diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.h b/onnxruntime/core/providers/webgpu/buffer_manager.h index a5bba53c6798b..6a8ebdd60a1ec 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.h +++ b/onnxruntime/core/providers/webgpu/buffer_manager.h @@ -62,6 +62,9 @@ class BufferManager { void Upload(void* src, WGPUBuffer dst, size_t size); void MemCpy(WGPUBuffer src, WGPUBuffer dst, size_t size); WGPUBuffer Create(size_t size, wgpu::BufferUsage usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst); + // Create a buffer mapped for writing. + WGPUBuffer CreateUMA(size_t size, wgpu::BufferUsage usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc | + wgpu::BufferUsage::CopyDst); void Release(WGPUBuffer buffer); void Download(WGPUBuffer src, void* dst, size_t size); void RefreshPendingBuffers(); @@ -75,8 +78,6 @@ class BufferManager { std::unique_ptr uniform_cache_; std::unique_ptr query_resolve_cache_; std::unique_ptr default_cache_; - - std::vector pending_staging_buffers_; }; class BufferManagerFactory { diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 97144573dde2d..82ba00f8d09e7 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -143,6 +143,10 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi ORT_ENFORCE(Device().GetLimits(&device_supported_limits)); device_limits_ = device_supported_limits.limits; +#if !defined(__wasm__) + supports_buffer_map_extended_usages_ = device_.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages); +#endif + // create buffer manager buffer_mgr_ = BufferManagerFactory::Create(*this, buffer_cache_config.storage.mode, @@ -491,7 +495,11 @@ std::vector WebGpuContext::GetAvailableRequiredFeatures(const #endif wgpu::FeatureName::TimestampQuery, wgpu::FeatureName::ShaderF16, - wgpu::FeatureName::Subgroups}; + wgpu::FeatureName::Subgroups, +#if !defined(__wasm__) + wgpu::FeatureName::BufferMapExtendedUsages, +#endif + }; for (auto feature : features) { if (adapter.HasFeature(feature)) { required_features.push_back(feature); diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 15819033d2573..a221bbcec95c3 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -143,6 +143,8 @@ class WebGpuContext final { Status Run(ComputeContext& context, const ProgramBase& program); void OnRunEnd(); + bool SupportsBufferMapExtendedUsages() const { return supports_buffer_map_extended_usages_; } + private: enum class TimestampQueryType { None = 0, @@ -231,6 +233,7 @@ class WebGpuContext final { #if defined(ENABLE_PIX_FOR_WEBGPU_EP) std::unique_ptr pix_frame_generator_ = nullptr; #endif // ENABLE_PIX_FOR_WEBGPU_EP + bool supports_buffer_map_extended_usages_ = false; }; } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 0ff07f0581475..aee36c0e54918 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -759,7 +759,9 @@ std::vector WebGpuExecutionProvider::CreatePreferredAllocators() { return std::make_unique(context_); }, 0, false); - return std::vector{CreateAllocator(gpuBufferAllocatorCreationInfo)}; + auto preferred_allocators = std::vector{CreateAllocator(gpuBufferAllocatorCreationInfo)}; + allocator_ = reinterpret_cast(preferred_allocators[0].get()); + return preferred_allocators; } std::vector> WebGpuExecutionProvider::GetCapability( @@ -843,6 +845,13 @@ std::unique_ptr WebGpuExecutionProvider::GetProfiler() { return profiler; } +Status WebGpuExecutionProvider::OnSessionInitializationEnd() { + if (allocator_ != nullptr) { + allocator_->OnSessionInitializationEnd(); + } + return Status::OK(); +} + Status WebGpuExecutionProvider::OnRunStart(const onnxruntime::RunOptions& /*run_options*/) { if (context_.ValidationMode() >= ValidationMode::Basic) { context_.PushErrorScope(); diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h index e2e23b6a307cf..15aec16210f16 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.h @@ -20,6 +20,7 @@ KernelCreateInfo BuildKernelCreateInfo(); class WebGpuContext; enum class BufferCacheMode; class WebGpuProfiler; +class GpuBufferAllocator; } // namespace webgpu struct WebGpuExecutionProviderConfig { @@ -63,6 +64,7 @@ class WebGpuExecutionProvider : public IExecutionProvider { bool ConcurrentRunSupported() const override { return false; } std::vector CreatePreferredAllocators() override; + Status OnSessionInitializationEnd() override; Status OnRunStart(const onnxruntime::RunOptions& run_options) override; Status OnRunEnd(bool sync_stream, const onnxruntime::RunOptions& run_options) override; @@ -88,6 +90,7 @@ class WebGpuExecutionProvider : public IExecutionProvider { bool is_graph_captured_ = false; int regular_run_count_before_graph_capture_ = 0; const int min_num_runs_before_cuda_graph_capture_ = 1; // required min regular runs before graph capture for the necessary memory allocations. + webgpu::GpuBufferAllocator* allocator_ = nullptr; }; } // namespace onnxruntime From 154e3b7d3da84d38c2cf7e28115e6dfb2e563a5f Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Mon, 17 Mar 2025 12:15:45 -0700 Subject: [PATCH 112/266] [WebGPU EP] Implement Remaining Reduction Ops (#24045) ### Description Adds naive implementations of ReduceMin, ReduceProd, ReduceL1, ReduceL2, ReduceLogSum, ReduceSumSquare, and ReduceLogSumExp. Will optimize to use shared memory in a later PR. ### Motivation and Context Increases WebGPU EP operator coverage. --- .../webgpu/reduction/reduction_ops.cc | 126 ++++++++++++++++-- .../webgpu/reduction/reduction_ops.h | 42 ++++++ .../webgpu/webgpu_execution_provider.cc | 76 ++++++----- .../cpu/reduction/reduction_ops_test.cc | 1 + 4 files changed, 200 insertions(+), 45 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index 255ad9cdf66c6..1a56cafdb3952 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -38,12 +38,50 @@ REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 1, 10); REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 11, 11); REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 12, 12); REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMax, 18); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 18, 19); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMax, 20); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 11, 11); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 12, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 13, 17); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 18, 19); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMin, 20); REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSum, 1, 10); REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSum, 11, 12); REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceSum, 13); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceProd, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceProd, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceProd, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceProd, 18); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL1, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL1, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL1, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceL1, 18); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL2, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL2, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL2, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceL2, 18); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSum, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSum, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSum, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceLogSum, 18); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSumSquare, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSumSquare, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSumSquare, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceSumSquare, 18); + +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSumExp, 1, 10); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSumExp, 11, 12); +REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSumExp, 13, 17); +REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceLogSumExp, 18); + Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); if (is_input_empty_) { @@ -126,14 +164,28 @@ Status ReduceKernel::ComputeInternal(ComputeContext& context) if (input_axes.empty()) { if (noop_with_empty_axes_ || rank == 0) { // If axes is empty and noop_with_empty_axes_ is true, it is a no-op according to the spec - // If input tensor is a scalar, return the input tensor as is. - // This is not correct for ReduceLogSum and ReduceSumSquare - // TODO handle these cases separately. - auto output = context.Output(0, input_tensor->Shape()); - if (output->DataRaw() != input_tensor->DataRaw()) { - ORT_RETURN_IF_ERROR(Info().GetDataTransferManager().CopyTensor(*input_tensor, *output)); + // If input tensor is a scalar and it's not a ReduceLogSum or ReduceSumSquare, return the input tensor as is. + if (rank == 0 && (name_ == "ReduceLogSum" || name_ == "ReduceSumSquare" || name_ == "ReduceL1" || name_ == "ReduceL2")) { + // For ReduceLogSum with scalar input, output = log(input) + // For ReduceSumSquare with scalar input, output = input * input + auto output = context.Output(0, input_tensor->Shape()); + // We need to run the operation even for scalar inputs for these ops + const auto code = GetOpSpecificCode(input_tensor); + ReduceKernelProgram program(name_, keepdims_, noop_with_empty_axes_, input_axes, code, false); + std::vector reduce_axes = {0}; + program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .AddOutput({output, ProgramTensorMetadataDependency::TypeAndRank}) + .SetDispatchGroupSize(1) + .AddUniformVariables({{1}, {static_cast(noop_with_empty_axes_ ? 1 : 0)}, {reduce_axes}}); + return context.RunProgram(program); + } else { + // For other ops, or when axes is empty with noop_with_empty_axes_ true, just copy the input + auto output = context.Output(0, input_tensor->Shape()); + if (output->DataRaw() != input_tensor->DataRaw()) { + ORT_RETURN_IF_ERROR(Info().GetDataTransferManager().CopyTensor(*input_tensor, *output)); + } + return Status::OK(); } - return Status::OK(); } else { // If axes is empty and noop_with_empty_axes_ is false, it is a reduction over all axes input_axes.resize(rank); @@ -211,6 +263,14 @@ ReduceOpSpecificCode ReduceMax::GetOpSpecificCode(const Tensor* input_tensor) co ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); return code; } +ReduceOpSpecificCode ReduceMin::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var min_element = first_element;"; + std::string loop_body = "min_element = min(min_element, current_element);"; + std::string loop_footer = "let output_value = output_value_t(min_element);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} ReduceOpSpecificCode ReduceSum::GetOpSpecificCode(const Tensor* input_tensor) const { ORT_UNUSED_PARAMETER(input_tensor); std::string loop_header = "var sum = f32(0);"; @@ -219,6 +279,54 @@ ReduceOpSpecificCode ReduceSum::GetOpSpecificCode(const Tensor* input_tensor) co ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); return code; } +ReduceOpSpecificCode ReduceProd::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var prod = f32(1);"; + std::string loop_body = "prod *= f32(current_element);"; + std::string loop_footer = "let output_value = output_value_t(prod);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} +ReduceOpSpecificCode ReduceL1::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var l1 = f32(0);"; + std::string loop_body = "l1 += abs(f32(current_element));"; + std::string loop_footer = "let output_value = output_value_t(l1);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} +ReduceOpSpecificCode ReduceL2::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var l2 = f32(0);"; + std::string loop_body = "let t = f32(current_element); l2 += (t * t);"; + std::string loop_footer = "l2 = sqrt(l2); let output_value = output_value_t(l2);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} +ReduceOpSpecificCode ReduceLogSum::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var sum = f32(0);"; + std::string loop_body = "sum += f32(current_element);"; + std::string loop_footer = "let log_sum = log(sum); let output_value = output_value_t(log_sum);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} +ReduceOpSpecificCode ReduceSumSquare::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var sum_square = f32(0);"; + std::string loop_body = "let t = f32(current_element); sum_square += (t * t);"; + std::string loop_footer = "let output_value = output_value_t(sum_square);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} +ReduceOpSpecificCode ReduceLogSumExp::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string loop_header = "var sum_exp = f32(0);"; + std::string loop_body = "sum_exp += exp(f32(current_element));"; + std::string loop_footer = "let log_sum_exp = log(sum_exp); let output_value = output_value_t(log_sum_exp);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} } // namespace webgpu -} // namespace onnxruntime +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h index 1c7dba89b7144..291d931f41c05 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h @@ -71,11 +71,53 @@ class ReduceMax final : public ReduceKernel { ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; }; +class ReduceMin final : public ReduceKernel { + public: + ReduceMin(const OpKernelInfo& info) : ReduceKernel(info, "ReduceMin") {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + class ReduceSum final : public ReduceKernel { public: ReduceSum(const OpKernelInfo& info) : ReduceKernel(info, "ReduceSum", true) {} ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; }; +class ReduceProd final : public ReduceKernel { + public: + ReduceProd(const OpKernelInfo& info) : ReduceKernel(info, "ReduceProd", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceL1 final : public ReduceKernel { + public: + ReduceL1(const OpKernelInfo& info) : ReduceKernel(info, "ReduceL1", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceL2 final : public ReduceKernel { + public: + ReduceL2(const OpKernelInfo& info) : ReduceKernel(info, "ReduceL2", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceLogSum final : public ReduceKernel { + public: + ReduceLogSum(const OpKernelInfo& info) : ReduceKernel(info, "ReduceLogSum", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceSumSquare final : public ReduceKernel { + public: + ReduceSumSquare(const OpKernelInfo& info) : ReduceKernel(info, "ReduceSumSquare", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ReduceLogSumExp final : public ReduceKernel { + public: + ReduceLogSumExp(const OpKernelInfo& info) : ReduceKernel(info, "ReduceLogSumExp", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index aee36c0e54918..dfb2e4b6ce665 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -144,7 +144,8 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxD class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 11, ReduceMax); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 12, 12, ReduceMax); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 17, ReduceMax); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 18, ReduceMax); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 18, 19, ReduceMax); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 20, ReduceMax); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, ReduceMean); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, ReduceMean); @@ -155,7 +156,8 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxD class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 11, ReduceMin); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 12, 12, ReduceMin); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 17, ReduceMin); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 18, ReduceMin); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 18, 19, ReduceMin); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 20, ReduceMin); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, ReduceProd); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, ReduceProd); @@ -517,7 +519,8 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -528,45 +531,46 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, KERNEL_CREATE_INFO_VERSIONED(9, 15, Where), KERNEL_CREATE_INFO(16, Where), diff --git a/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc b/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc index 61a16d41e3e59..4bc97d035c7f7 100644 --- a/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc +++ b/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc @@ -6044,6 +6044,7 @@ void test_empty_set(const std::string& op, int opset, bool axes_as_input, float kQnnExecutionProvider, kRocmExecutionProvider, kTensorrtExecutionProvider, + kWebGpuExecutionProvider, }); } From a46d2127fb0b1a1a75b771f98810c01235f7be06 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Tue, 18 Mar 2025 08:22:40 -0700 Subject: [PATCH 113/266] add bool support to EPContext schema to unblock some models (#24065) ### Description add bool support to EPContext schema to unblock some models --- docs/ContribOperators.md | 2 +- onnxruntime/core/graph/contrib_ops/contrib_defs.cc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index b64641230f249..f582abca34706 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -1625,7 +1625,7 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T : tensor(int8), tensor(int16), tensor(int32), tensor(int64), tensor(uint8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(float16), tensor(float), tensor(double), tensor(bfloat16)
+
T : tensor(bool), tensor(int8), tensor(int16), tensor(int32), tensor(int64), tensor(uint8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(float16), tensor(float), tensor(double), tensor(bfloat16)
Constrain input and output types.
diff --git a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc index e45787299f3ad..7b4a45ce8aa0f 100644 --- a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc @@ -3361,7 +3361,8 @@ void RegisterContribSchemas() { OpSchema::NonDifferentiable) .TypeConstraint( "T", - {"tensor(int8)", + {"tensor(bool)", + "tensor(int8)", "tensor(int16)", "tensor(int32)", "tensor(int64)", From b3aa5a3c21d3a5fd0e22e6ae0907086ddf582c6f Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 18 Mar 2025 14:50:28 -0700 Subject: [PATCH 114/266] [WebGPU EP] fix for reduce min/max error on MacOS CI (#24077) ### Error ```Traceback /onnxruntime/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc:146 [allow_multi_axes = true] Axes values must be in the range [-rank, rank-1]. Got: 446098880 ``` --- .../webgpu/reduction/reduction_ops.cc | 99 ++++++++++--------- .../onnx_backend_test_series_filters.jsonc | 4 +- 2 files changed, 57 insertions(+), 46 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index 1a56cafdb3952..a0213f63494d3 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -11,7 +11,7 @@ namespace onnxruntime { namespace webgpu { -#define REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceOp, begin, end) \ +#define REGISTER_REDUCE_VERSIONED_KERNEL(ReduceOp, begin, end) \ ONNX_OPERATOR_VERSIONED_KERNEL_EX( \ ReduceOp, \ kOnnxDomain, \ @@ -20,7 +20,16 @@ namespace webgpu { (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedNumberTypes()), \ ReduceOp); -#define REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceOp, version) \ +#define REGISTER_REDUCE_VERSIONED_KERNEL_WITH_AXIS_IN_INPUT(ReduceOp, begin, end) \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX( \ + ReduceOp, \ + kOnnxDomain, \ + begin, end, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedNumberTypes()).InputMemoryType(OrtMemTypeCPUInput, 1), \ + ReduceOp); + +#define REGISTER_REDUCE_KERNEL(ReduceOp, version) \ ONNX_OPERATOR_KERNEL_EX( \ ReduceOp, \ kOnnxDomain, \ @@ -29,58 +38,58 @@ namespace webgpu { (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedNumberTypes()).InputMemoryType(OrtMemTypeCPUInput, 1), \ ReduceOp); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMean, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMean, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMean, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMean, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMean, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceMean, 18); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 11, 11); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 12, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 13, 17); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMax, 18, 19); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMax, 20); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMax, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMax, 11, 11); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMax, 12, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMax, 13, 17); +REGISTER_REDUCE_VERSIONED_KERNEL_WITH_AXIS_IN_INPUT(ReduceMax, 18, 19); +REGISTER_REDUCE_KERNEL(ReduceMax, 20); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 11, 11); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 12, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 13, 17); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceMin, 18, 19); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceMin, 20); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMin, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMin, 11, 11); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMin, 12, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceMin, 13, 17); +REGISTER_REDUCE_VERSIONED_KERNEL_WITH_AXIS_IN_INPUT(ReduceMin, 18, 19); +REGISTER_REDUCE_KERNEL(ReduceMin, 20); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSum, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSum, 11, 12); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceSum, 13); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceSum, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceSum, 11, 12); +REGISTER_REDUCE_KERNEL(ReduceSum, 13); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceProd, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceProd, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceProd, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceProd, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceProd, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceProd, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceProd, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceProd, 18); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL1, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL1, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL1, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceL1, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceL1, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceL1, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceL1, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceL1, 18); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL2, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL2, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceL2, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceL2, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceL2, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceL2, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceL2, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceL2, 18); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSum, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSum, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSum, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceLogSum, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSum, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSum, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSum, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceLogSum, 18); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSumSquare, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSumSquare, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceSumSquare, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceSumSquare, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceSumSquare, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceSumSquare, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceSumSquare, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceSumSquare, 18); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSumExp, 1, 10); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSumExp, 11, 12); -REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ReduceLogSumExp, 13, 17); -REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceLogSumExp, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSumExp, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSumExp, 11, 12); +REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSumExp, 13, 17); +REGISTER_REDUCE_KERNEL(ReduceLogSumExp, 18); Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); diff --git a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc index e261d66a0d22a..d62ffe644e4cc 100644 --- a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc +++ b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc @@ -694,7 +694,9 @@ "^test_gelu_tanh_2_expanded_cpu", "^test_dynamicquantizelinear_expanded_cpu", "^test_center_crop_pad_crop_negative_axes_hwc*", // failed due to new types or shape infer with negative axis for CenterCropPad. - "^test_center_crop_pad_crop_negative_axes_hwc_expanded*" // failed due to new types or shape infer with negative axis for CenterCropPad. + "^test_center_crop_pad_crop_negative_axes_hwc_expanded*", // failed due to new types or shape infer with negative axis for CenterCropPad. + "^test_reduce_max_empty_set", + "^test_reduce_min_empty_set" ], "current_failing_tests_pure_DML": [ "^test_negative_log_likelihood_loss_input_shape_is_NCd1d2d3_none_no_weight_negative_ignore_index_cpu", From e495750a3413daaa9d98aa8639c61ad28a8a3516 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 18 Mar 2025 18:24:34 -0400 Subject: [PATCH 115/266] Upgrade current MacOS-13 to 14 (#23293) ### Description Upgrade current MacOS-13 to 14 ### Motivation and Context - [x] Update the RN to 0.73.x+ to have the newer version of boost --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- cmake/CMakePresets.json | 23 +++++++++++++++++++ js/react_native/e2e/.detoxrc.js | 4 ++-- .../coreml/builders/impl/base_op_builder.cc | 3 +++ .../core/providers/coreml/model/host_utils.h | 8 ++++++- .../core/providers/coreml/model/model.mm | 3 +-- .../mac-ios-packaging-pipeline.yml | 2 +- .../nodejs/templates/test_macos.yml | 2 +- .../nuget/templates/test_macos.yml | 2 +- .../azure-pipelines/post-merge-jobs.yml | 4 ++-- .../py-package-test-pipeline.yml | 2 +- .../stages/py-cpu-packaging-stage.yml | 2 +- .../templates/android-java-api-aar-test.yml | 2 ++ .../azure-pipelines/templates/c-api-cpu.yml | 6 ++--- .../templates/mac-cpu-packaging-pipeline.yml | 2 +- .../templates/mac-cpu-packing-jobs.yml | 2 +- .../templates/react-native-ci.yml | 6 ++--- .../templates/use-xcode-version.yml | 2 +- 17 files changed, 54 insertions(+), 21 deletions(-) diff --git a/cmake/CMakePresets.json b/cmake/CMakePresets.json index 4987edaf85513..8d63912f6eaee 100644 --- a/cmake/CMakePresets.json +++ b/cmake/CMakePresets.json @@ -109,6 +109,29 @@ "rhs": "Darwin" } }, + { + "name": "arm64-osx", + "inherits": [ + "unit-test" + ], + "generator": "Xcode", + "binaryDir": "${sourceParentDir}/cmake_build/arm64-osx", + "installDir": "${sourceParentDir}/cmake_build/out", + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "arm64", + "onnxruntime_BUILD_SHARED_LIB": true, + "onnxruntime_USE_XNNPACK": false, + "onnxruntime_USE_COREML": true, + "onnxruntime_BUILD_OBJC": true, + "onnxruntime_BUILD_APPLE_FRAMEWORK": true, + "CMAKE_CONFIGURATION_TYPES": "Debug;Release" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + } + }, { "name": "x64-osx-vcpkg", "inherits": [ diff --git a/js/react_native/e2e/.detoxrc.js b/js/react_native/e2e/.detoxrc.js index e886a363d378b..1d49f06213e51 100644 --- a/js/react_native/e2e/.detoxrc.js +++ b/js/react_native/e2e/.detoxrc.js @@ -38,8 +38,8 @@ module.exports = { simulator: { type: 'ios.simulator', device: { - type: 'iPhone 14', - os: 'iOS 16.4', + type: 'iPhone 15', + os: 'iOS 17.4', }, }, attached: { diff --git a/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.cc index 2817f34bc64f2..9e7fcd788664c 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.cc @@ -6,6 +6,7 @@ #include "core/providers/coreml/builders/helper.h" #include "core/providers/coreml/builders/impl/base_op_builder.h" #include "core/providers/coreml/builders/model_builder.h" +#include "core/providers/coreml/model/host_utils.h" #include "core/providers/shared/utils/utils.h" using namespace CoreML::Specification; @@ -113,10 +114,12 @@ bool BaseOpBuilder::IsInputDtypeSupport(const Node& node, size_t idx, return true; } +#if CAN_BUILD_COREML6_OR_LATER // only MLProgram support FP16 if (input_params.create_mlprogram && input_type == ONNX_NAMESPACE::TensorProto_DataType_FLOAT16) { return true; } +#endif LOGS(logger, VERBOSE) << "[" << node.OpType() << "] Input type: [" << input_type << "] is not currently supported"; return false; diff --git a/onnxruntime/core/providers/coreml/model/host_utils.h b/onnxruntime/core/providers/coreml/model/host_utils.h index 145c64e5320d3..31ee2bd3e2494 100644 --- a/onnxruntime/core/providers/coreml/model/host_utils.h +++ b/onnxruntime/core/providers/coreml/model/host_utils.h @@ -43,7 +43,13 @@ #define API_AVAILABLE_COREML7 API_AVAILABLE(macos(14), ios(17)) #define API_AVAILABLE_COREML8 API_AVAILABLE(macos(15), ios(18)) -// @available is used in implementation code +// The previous macros are used in header files to declare the availability of the APIs. +// The following macros are used in build time checks to determine if the APIs are available. +#define CAN_BUILD_COREML8_OR_LATER (__MAC_OS_X_VERSION_MAX_ALLOWED >= 150000 && __IPHONE_OS_VERSION_MAX_ALLOWED >= 180000) +#define CAN_BUILD_COREML7_OR_LATER (__MAC_OS_X_VERSION_MAX_ALLOWED >= 140000 && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000) +#define CAN_BUILD_COREML6_OR_LATER (__MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 && __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000) + +// @available is used in implementation code to check the availability of the APIs at runtime. // Base required OS to run CoreML Specification Version 4 (Core ML 3) #define HAS_COREML3_OR_LATER @available(macOS 10.15, iOS 13, *) #define HAS_COREML4_OR_LATER @available(macOS 11, iOS 14, *) diff --git a/onnxruntime/core/providers/coreml/model/model.mm b/onnxruntime/core/providers/coreml/model/model.mm index 5211b89ec17c6..71664021ea2fb 100644 --- a/onnxruntime/core/providers/coreml/model/model.mm +++ b/onnxruntime/core/providers/coreml/model/model.mm @@ -363,13 +363,12 @@ void ProfileComputePlan(NSURL* compileUrl, MLModelConfiguration* config) { #endif } -#if __has_include() +#if __has_include() && CAN_BUILD_COREML8_OR_LATER #define HAS_COREMLOPTIMIZATIONHINT 1 #else #define HAS_COREMLOPTIMIZATIONHINT 0 #endif -API_AVAILABLE_COREML8 void ConfigureOptimizationHints(MLModelConfiguration* config, const CoreMLOptions& coreml_options) { #if HAS_COREMLOPTIMIZATIONHINT MLOptimizationHints* optimizationHints = [[MLOptimizationHints alloc] init]; diff --git a/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml index 23c968f35a27f..70d8e954808a5 100644 --- a/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml @@ -56,7 +56,7 @@ extends: # Update the pool with your team's 1ES hosted pool. pool: name: "Azure Pipelines" - image: "macOS-13" + image: "macOS-14" os: macOS sdl: sourceAnalysisPool: diff --git a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml index 4518a168879a2..a2a0e3bcace9f 100644 --- a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml +++ b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml @@ -11,7 +11,7 @@ stages: clean: all timeoutInMinutes: 120 pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' variables: - name: OnnxRuntimeBuildDirectory diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml index 07d21333270a8..a6e38d0bc93f3 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml @@ -11,7 +11,7 @@ stages: workspace: clean: all pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' variables: - name: OnnxRuntimeBuildDirectory diff --git a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml index 6b421184c490e..78c07c28d6f4e 100644 --- a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml +++ b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml @@ -427,7 +427,7 @@ stages: - job: IosDynamicFramework timeoutInMinutes: 120 pool: - vmImage: "macOS-13" + vmImage: "macOS-14" steps: - task: UsePythonVersion@0 @@ -463,7 +463,7 @@ stages: - job: IosMinimalTrainingBuild timeoutInMinutes: 120 pool: - vmImage: "macOS-13" + vmImage: "macOS-14" steps: - task: UsePythonVersion@0 diff --git a/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml index 7a78c6ba0fcdf..01c1366107292 100644 --- a/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml @@ -29,7 +29,7 @@ stages: parameters: job_name: Test_MAC_Wheels machine_pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' itemPattern: '*/*mac*x86_64.whl' arch: 'x86_64' - template: templates/py-package-smoking-test.yml diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml index 5e783607e3622..d64ee07aa2131 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml @@ -201,7 +201,7 @@ stages: clean: all pool: name: "Azure Pipelines" - image: "macOS-13" + image: "macOS-14" os: macOS variables: MACOSX_DEPLOYMENT_TARGET: '13.3' diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml index 3886ceb1ed58f..366ee3fcf4e92 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml @@ -24,6 +24,8 @@ jobs: pool: 'onnxruntime-Ubuntu2204-AMD-CPU' workspace: clean: all + pool: + vmImage: 'macOS-14' variables: runCodesignValidationInjection: false ANDROID_AVD_HOME: $(Agent.TempDirectory) diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index c4559d4e0b918..7a46bdc7cde0a 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -117,7 +117,7 @@ stages: workspace: clean: all pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' timeoutInMinutes: 300 steps: - template: set-version-number-variables-step.yml @@ -788,7 +788,7 @@ stages: - template: ../nuget/templates/test_macos.yml parameters: - AgentPool : macOS-13 + AgentPool : macOS-14 ArtifactSuffix: 'CPU' - template: ../nodejs/templates/test_win.yml @@ -824,4 +824,4 @@ stages: OS: MacOS BuildId: ${{ parameters.BuildId }} SpecificArtifact: ${{ parameters.SpecificArtifact }} - PoolName: 'macOS-13' + PoolName: 'macOS-14' diff --git a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml index ab31e592d7d71..8c725c1d6b9a0 100644 --- a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml @@ -68,7 +68,7 @@ stages: jobs: - job: MacOS_C_API_Package_Publish pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' steps: - checkout: none - template: flex-downloadPipelineArtifact.yml diff --git a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml index 32908753f2909..c7ae7bb3a0026 100644 --- a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml +++ b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml @@ -37,7 +37,7 @@ jobs: PROTO_CACHE_DIR: $(Pipeline.Workspace)/ccache_proto ORT_CACHE_DIR: $(Pipeline.Workspace)/ccache_ort pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' timeoutInMinutes: 300 steps: - checkout: self diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index 58ebdd52998ea..c1309d345d819 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -64,11 +64,11 @@ stages: - job: ReactNative_CI_iOS ${{ if eq(parameters.is1ES, false) }}: pool: - vmImage: 'macOS-13' + vmImage: 'macOS-14' ${{ if eq(parameters.is1ES, true) }}: pool: name: 'Azure Pipelines' - image: 'macOS-13' + image: 'macOS-14' os: 'macOS' timeoutInMinutes: 120 @@ -212,7 +212,7 @@ stages: scheme: 'OnnxruntimeModuleTest' packageApp: false destinationPlatformOption: 'iOS' - destinationSimulators: 'iPhone 14,OS=16.4' + destinationSimulators: 'iPhone 15,OS=17.4' workingDirectory: '$(Build.SourcesDirectory)/js/react_native/ios' xcprettyArgs: '--output build/reports/test-results.xml' publishJUnitResults: true diff --git a/tools/ci_build/github/azure-pipelines/templates/use-xcode-version.yml b/tools/ci_build/github/azure-pipelines/templates/use-xcode-version.yml index 2cf698aefa8bd..3c1bfcd60fedd 100644 --- a/tools/ci_build/github/azure-pipelines/templates/use-xcode-version.yml +++ b/tools/ci_build/github/azure-pipelines/templates/use-xcode-version.yml @@ -3,7 +3,7 @@ parameters: - name: xcodeVersion type: string - default: "14.3.1" + default: "15.3.0" steps: - bash: | From c6a267543a4e8dce5bab0168e3ac2d4acc98a352 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Wed, 19 Mar 2025 08:50:28 +1000 Subject: [PATCH 116/266] Fix CUDA EP Abs and Sign bfloat16 support (#23914) ### Description Abs and Sign had bfloat16 kernels created but not registered with the CUDA EP. Additionally Sign bfloat16 didn't work. * register bfloat16 kernels with CUDA EP * fix incorrectly named macro by adding 'X' as they add bfloat16 registration * add specialization for bfloat16 to _Sign * copied existing pattern. not sure if there's a better way * update tests ### Motivation and Context #23875 --- docs/OperatorKernels.md | 4 ++-- .../core/providers/cuda/cu_inc/common.cuh | 3 +++ .../providers/cuda/cuda_execution_provider.cc | 4 ++++ .../cuda/math/unary_elementwise_ops.cc | 20 ++++++++-------- .../cpu/math/element_wise_ops_test.cc | 23 ++++++++++++++++--- .../test/providers/cpu/math/sign_test.cc | 10 ++++++-- 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 91c68a1f5afb6..8d256a2088279 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -582,7 +582,7 @@ Do not modify directly.* | Op Name | Parameters | OpSet Version | Types Supported | |---------|------------|---------------|-----------------| |**Operator Domain:** *ai.onnx*|||| -|Abs|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Abs|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Add|*in* A:**T**
*in* B:**T**
*out* C:**T**|14+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||13|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| @@ -839,7 +839,7 @@ Do not modify directly.* |Shrink|*in* input:**T**
*out* output:**T**|9+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Sigmoid|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| -|Sign|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Sign|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |SimplifiedLayerNormalization|*in* X:**T**
*in* scale:**V**
*out* Y:**V**
*out* inv_std_var:**U**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**U** = tensor(double), tensor(float)
**V** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |Sin|*in* input:**T**
*out* output:**T**|7+|**T** = tensor(double), tensor(float), tensor(float16)| |Size|*in* data:**T**
*out* size:**T1**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| diff --git a/onnxruntime/core/providers/cuda/cu_inc/common.cuh b/onnxruntime/core/providers/cuda/cu_inc/common.cuh index 55935a9eae86d..2d2551a156099 100644 --- a/onnxruntime/core/providers/cuda/cu_inc/common.cuh +++ b/onnxruntime/core/providers/cuda/cu_inc/common.cuh @@ -441,6 +441,9 @@ __device__ __inline__ T _Sign(T a) { return _Signum(a, std::is_signed()); } template <> __device__ __inline__ half _Sign(half a) { return _Signum(a, std::true_type()); } +template <> +__device__ __inline__ BFloat16 _Sign(BFloat16 a) { return _Signum(static_cast(a), std::true_type()); } + template __device__ __inline__ T _Normcdf(T a); diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc index 54fb4429c0536..886fddd8f8a27 100644 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc @@ -1013,6 +1013,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, float, Abs); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, double, Abs); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, MLFloat16, Abs); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, BFloat16, Abs); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, int8_t, Neg); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, int16_t, Neg); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, int32_t, Neg); @@ -1188,6 +1189,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, float, Sign); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, double, Sign); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, MLFloat16, Sign); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, BFloat16, Sign); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, 13, BFloat16, Add); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 13, 13, BFloat16, Sub); @@ -1996,6 +1998,7 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -2169,6 +2172,7 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/core/providers/cuda/math/unary_elementwise_ops.cc b/onnxruntime/core/providers/cuda/math/unary_elementwise_ops.cc index fb03b4326c4e8..86a1b0f5b6102 100644 --- a/onnxruntime/core/providers/cuda/math/unary_elementwise_ops.cc +++ b/onnxruntime/core/providers/cuda/math/unary_elementwise_ops.cc @@ -213,19 +213,19 @@ Status IsNaN::ComputeInternal(OpKernelContext* context) const { UNARY_OP_TYPED(name, ver, float) \ UNARY_OP_TYPED(name, ver, double) -#define UNARY_OP_CSILHFD(name, ver) \ +#define UNARY_OP_CSILHFDX(name, ver) \ UNARY_OP_TYPED(name, ver, int8_t) \ UNARY_OP_TYPED(name, ver, int16_t) \ UNARY_OP_TYPED(name, ver, int32_t) \ UNARY_OP_TYPED(name, ver, int64_t) \ UNARY_OP_HFDX(name, ver) -#define UNARY_OP_BWUZCSILHFD(name, ver) \ - UNARY_OP_TYPED(name, ver, uint8_t) \ - UNARY_OP_TYPED(name, ver, uint16_t) \ - UNARY_OP_TYPED(name, ver, uint32_t) \ - UNARY_OP_TYPED(name, ver, uint64_t) \ - UNARY_OP_CSILHFD(name, ver) +#define UNARY_OP_BWUZCSILHFDX(name, ver) \ + UNARY_OP_TYPED(name, ver, uint8_t) \ + UNARY_OP_TYPED(name, ver, uint16_t) \ + UNARY_OP_TYPED(name, ver, uint32_t) \ + UNARY_OP_TYPED(name, ver, uint64_t) \ + UNARY_OP_CSILHFDX(name, ver) UNARY_OP_VERSIONED_BWUZCSILHFD(Abs, 6, 12) UNARY_OP_VERSIONED_CSILHFD(Neg, 6, 12) @@ -237,8 +237,8 @@ UNARY_OP_VERSIONED_HFD(Log, 6, 12) UNARY_OP_VERSIONED_HFD(Exp, 6, 12) UNARY_OP_VERSIONED_HFD(Erf, 9, 12) -UNARY_OP_BWUZCSILHFD(Abs, 13) -UNARY_OP_CSILHFD(Neg, 13) +UNARY_OP_BWUZCSILHFDX(Abs, 13) +UNARY_OP_CSILHFDX(Neg, 13) UNARY_OP_HFD(Floor, 13) UNARY_OP_HFD(Ceil, 13) UNARY_OP_HFD(Reciprocal, 13) @@ -246,7 +246,7 @@ UNARY_OP_HFDX(Sqrt, 13) UNARY_OP_HFD(Log, 13) UNARY_OP_HFDX(Exp, 13) UNARY_OP_HFDX(Erf, 13) -UNARY_OP_BWUZCSILHFD(Sign, 13) +UNARY_OP_BWUZCSILHFDX(Sign, 13) UNARY_LOGICALOP_NOT_TYPED(1, bool) UNARY_OP_HFD(Round, 11) diff --git a/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc b/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc index d87ee861752c7..30e7f63919216 100644 --- a/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc +++ b/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc @@ -968,8 +968,15 @@ TEST(MathOpTest, Abs) { test.Run(); } -#ifdef USE_DNNL +#if defined(USE_CUDA) || defined(USE_DNNL) TEST(MathOpTest, Abs_bfloat16) { +#ifdef USE_CUDA + int min_cuda_architecture = 530; + if (!HasCudaEnvironment(min_cuda_architecture)) { + LOGS_DEFAULT(WARNING) << "Hardware does NOT support BF16"; + return; + } +#endif #ifdef USE_DNNL if (!DnnlHasBF16Support()) { LOGS_DEFAULT(WARNING) << "Hardware does NOT support BF16"; @@ -980,9 +987,19 @@ TEST(MathOpTest, Abs_bfloat16) { std::vector dims{2, 2}; test_bf16.AddInput("X", dims, MakeBFloat16({1.0f, -2.0f, -0.0f, -10.0f})); test_bf16.AddOutput("Y", dims, MakeBFloat16({1.0f, 2.0f, 0.0f, 10.0f})); - test_bf16.Run(); + + std::vector> execution_providers; +#if defined(USE_CUDA) + execution_providers.push_back(DefaultCudaExecutionProvider()); +#endif + +#if defined(USE_DNNL) + execution_providers.push_back(DefaultDnnlExecutionProvider()); +#endif + + test_bf16.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); } -#endif // USE_DNNL +#endif // USE_CUDA || USE_DNNL TEST(MathOpTest, Abs_int8) { OpTester test("Abs"); diff --git a/onnxruntime/test/providers/cpu/math/sign_test.cc b/onnxruntime/test/providers/cpu/math/sign_test.cc index a01c2b26ea8b5..0da6a2ed55f2c 100644 --- a/onnxruntime/test/providers/cpu/math/sign_test.cc +++ b/onnxruntime/test/providers/cpu/math/sign_test.cc @@ -207,7 +207,7 @@ TEST(MathOpTest, Sign_MLFloat16) { // test.Run(OpTester::ExpectResult::kExpectSuccess); //} -#if defined(USE_DNNL) +#if defined(USE_CUDA) || defined(USE_DNNL) TEST(MathOpTest, Sign_bfloat16) { #ifdef USE_DNNL if (!DnnlHasBF16Support()) { @@ -228,9 +228,15 @@ TEST(MathOpTest, Sign_bfloat16) { TestImpl(input.cbegin(), input.cend(), std::back_inserter(output)); test.AddOutput("output", input_dims, output); std::vector> execution_providers; + +#if defined(USE_CUDA) + execution_providers.push_back(DefaultCudaExecutionProvider()); +#endif + #if defined(USE_DNNL) execution_providers.push_back(DefaultDnnlExecutionProvider()); -#endif // USE_DNNL +#endif + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); } #endif From 12fea57253942991cf4f3de15f505cd03eaa9f2f Mon Sep 17 00:00:00 2001 From: Justin Chu Date: Tue, 18 Mar 2025 16:04:13 -0700 Subject: [PATCH 117/266] Improve typing for OrtValue and other public Python interfaces (#24086) ### Description Improve the OrtValue interface typing and changed `staticmethod` to `classmethod` for constructors to follow python conventions (https://google.github.io/styleguide/pyguide.html#2174-decision). --- .../onnxruntime_inference_collection.py | 140 ++++++++++-------- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/onnxruntime/python/onnxruntime_inference_collection.py b/onnxruntime/python/onnxruntime_inference_collection.py index 6b5f7526cc506..785eb9c485d25 100644 --- a/onnxruntime/python/onnxruntime_inference_collection.py +++ b/onnxruntime/python/onnxruntime_inference_collection.py @@ -15,6 +15,9 @@ from onnxruntime.capi import _pybind_state as C if typing.TYPE_CHECKING: + import numpy as np + import numpy.typing as npt + import onnxruntime @@ -59,22 +62,22 @@ def export_adapter(self, file_path: os.PathLike): """ self._adapter.export_adapter(file_path) - def get_format_version(self): + def get_format_version(self) -> int: return self._adapter.format_version - def set_adapter_version(self, adapter_version: int): + def set_adapter_version(self, adapter_version: int) -> None: self._adapter.adapter_version = adapter_version - def get_adapter_version(self): + def get_adapter_version(self) -> int: return self._adapter.adapter_version - def set_model_version(self, model_version: int): + def set_model_version(self, model_version: int) -> None: self._adapter.model_version = model_version - def get_model_version(self): + def get_model_version(self) -> int: return self._adapter.model_version - def set_parameters(self, params: dict[str, OrtValue]): + def set_parameters(self, params: dict[str, OrtValue]) -> None: self._adapter.parameters = {k: v._ortvalue for k, v in params.items()} def get_parameters(self) -> dict[str, OrtValue]: @@ -174,27 +177,27 @@ def __init__(self): self._sess = None self._enable_fallback = True - def get_session_options(self): + def get_session_options(self) -> onnxruntime.SessionOptions: "Return the session options. See :class:`onnxruntime.SessionOptions`." return self._sess_options - def get_inputs(self): + def get_inputs(self) -> Sequence[onnxruntime.NodeArg]: "Return the inputs metadata as a list of :class:`onnxruntime.NodeArg`." return self._inputs_meta - def get_outputs(self): + def get_outputs(self) -> Sequence[onnxruntime.NodeArg]: "Return the outputs metadata as a list of :class:`onnxruntime.NodeArg`." return self._outputs_meta - def get_overridable_initializers(self): + def get_overridable_initializers(self) -> Sequence[onnxruntime.NodeArg]: "Return the inputs (including initializers) metadata as a list of :class:`onnxruntime.NodeArg`." return self._overridable_initializers - def get_modelmeta(self): + def get_modelmeta(self) -> onnxruntime.ModelMetadata: "Return the metadata. See :class:`onnxruntime.ModelMetadata`." return self._model_meta - def get_providers(self): + def get_providers(self) -> Sequence[str]: "Return list of registered execution providers." return self._providers @@ -202,7 +205,7 @@ def get_provider_options(self): "Return registered execution providers' configurations." return self._provider_options - def set_providers(self, providers=None, provider_options=None): + def set_providers(self, providers=None, provider_options=None) -> None: """ Register the input list of execution providers. The underlying session is re-created. @@ -224,13 +227,13 @@ def set_providers(self, providers=None, provider_options=None): # recreate the underlying C.InferenceSession self._reset_session(providers, provider_options) - def disable_fallback(self): + def disable_fallback(self) -> None: """ Disable session.run() fallback mechanism. """ self._enable_fallback = False - def enable_fallback(self): + def enable_fallback(self) -> None: """ Enable session.Run() fallback mechanism. If session.Run() fails due to an internal Execution Provider failure, reset the Execution Providers enabled for this session. @@ -249,7 +252,7 @@ def _validate_input(self, feed_input_names): f"Required inputs ({missing_input_names}) are missing from input feed ({feed_input_names})." ) - def run(self, output_names, input_feed, run_options=None): + def run(self, output_names, input_feed, run_options=None) -> Sequence[np.ndarray | SparseTensor | list | dict]: """ Compute the predictions. @@ -308,7 +311,7 @@ def callback(results: np.ndarray, user_data: MyData, err: str) -> None: output_names = [output.name for output in self._outputs_meta] return self._sess.run_async(output_names, input_feed, callback, user_data, run_options) - def run_with_ort_values(self, output_names, input_dict_ort_values, run_options=None): + def run_with_ort_values(self, output_names, input_dict_ort_values, run_options=None) -> Sequence[OrtValue]: """ Compute the predictions. @@ -367,7 +370,7 @@ def get_profiling_start_time_ns(self): """ return self._sess.get_profiling_start_time_ns - def io_binding(self): + def io_binding(self) -> IOBinding: "Return an onnxruntime.IOBinding object`." return IOBinding(self) @@ -550,7 +553,7 @@ def _create_inference_session(self, providers, provider_options, disabled_optimi self._provider_options = self._sess.get_provider_options() self._profiling_start_time_ns = self._sess.get_profiling_start_time_ns - def _reset_session(self, providers, provider_options): + def _reset_session(self, providers, provider_options) -> None: "release underlying session object." # meta data references session internal structures # so they must be set to None to decrement _sess reference count. @@ -721,7 +724,7 @@ class OrtValue: This class provides APIs to construct and deal with OrtValues. """ - def __init__(self, ortvalue, numpy_obj=None): + def __init__(self, ortvalue: C.OrtValue, numpy_obj: np.ndarray | None = None): if isinstance(ortvalue, C.OrtValue): self._ortvalue = ortvalue # Hold a ref count to the numpy object if the OrtValue is backed directly @@ -733,11 +736,11 @@ def __init__(self, ortvalue, numpy_obj=None): "`Provided ortvalue` needs to be of type `onnxruntime.capi.onnxruntime_pybind11_state.OrtValue`" ) - def _get_c_value(self): + def _get_c_value(self) -> C.OrtValue: return self._ortvalue - @staticmethod - def ortvalue_from_numpy(numpy_obj, device_type="cpu", device_id=0): + @classmethod + def ortvalue_from_numpy(cls, numpy_obj: np.ndarray, /, device_type="cpu", device_id=0) -> OrtValue: """ Factory method to construct an OrtValue (which holds a Tensor) from a given Numpy object A copy of the data in the Numpy object is held by the OrtValue only if the device is NOT cpu @@ -749,7 +752,7 @@ def ortvalue_from_numpy(numpy_obj, device_type="cpu", device_id=0): # Hold a reference to the numpy object (if device_type is 'cpu') as the OrtValue # is backed directly by the data buffer of the numpy object and so the numpy object # must be around until this OrtValue instance is around - return OrtValue( + return cls( C.OrtValue.ortvalue_from_numpy( numpy_obj, C.OrtDevice( @@ -761,8 +764,8 @@ def ortvalue_from_numpy(numpy_obj, device_type="cpu", device_id=0): numpy_obj if device_type.lower() == "cpu" else None, ) - @staticmethod - def ortvalue_from_numpy_with_onnx_type(data, onnx_element_type: int): + @classmethod + def ortvalue_from_numpy_with_onnx_type(cls, data: np.ndarray, /, onnx_element_type: int) -> OrtValue: """ This method creates an instance of OrtValue on top of the numpy array. No data copy is made and the lifespan of the resulting OrtValue should never @@ -771,12 +774,14 @@ def ortvalue_from_numpy_with_onnx_type(data, onnx_element_type: int): when we want to use an ONNX data type that is not supported by numpy. :param data: numpy.ndarray. - :param onnx_elemenet_type: a valid onnx TensorProto::DataType enum value + :param onnx_element_type: a valid onnx TensorProto::DataType enum value """ - return OrtValue(C.OrtValue.ortvalue_from_numpy_with_onnx_type(data, onnx_element_type), data) + return cls(C.OrtValue.ortvalue_from_numpy_with_onnx_type(data, onnx_element_type), data) - @staticmethod - def ortvalue_from_shape_and_type(shape, element_type, device_type: str = "cpu", device_id: int = 0): + @classmethod + def ortvalue_from_shape_and_type( + cls, shape: Sequence[int], element_type, device_type: str = "cpu", device_id: int = 0 + ) -> OrtValue: """ Factory method to construct an OrtValue (which holds a Tensor) from given shape and element_type @@ -788,7 +793,7 @@ def ortvalue_from_shape_and_type(shape, element_type, device_type: str = "cpu", # Integer for onnx element type (see https://onnx.ai/onnx/api/mapping.html). # This is helpful for some data type (like TensorProto.BFLOAT16) that is not available in numpy. if isinstance(element_type, int): - return OrtValue( + return cls( C.OrtValue.ortvalue_from_shape_and_onnx_type( shape, element_type, @@ -800,7 +805,7 @@ def ortvalue_from_shape_and_type(shape, element_type, device_type: str = "cpu", ) ) - return OrtValue( + return cls( C.OrtValue.ortvalue_from_shape_and_type( shape, element_type, @@ -812,77 +817,77 @@ def ortvalue_from_shape_and_type(shape, element_type, device_type: str = "cpu", ) ) - @staticmethod - def ort_value_from_sparse_tensor(sparse_tensor): + @classmethod + def ort_value_from_sparse_tensor(cls, sparse_tensor: SparseTensor) -> OrtValue: """ The function will construct an OrtValue instance from a valid SparseTensor The new instance of OrtValue will assume the ownership of sparse_tensor """ - return OrtValue(C.OrtValue.ort_value_from_sparse_tensor(sparse_tensor._get_c_tensor())) + return cls(C.OrtValue.ort_value_from_sparse_tensor(sparse_tensor._get_c_tensor())) - def as_sparse_tensor(self): + def as_sparse_tensor(self) -> SparseTensor: """ The function will return SparseTensor contained in this OrtValue """ return SparseTensor(self._ortvalue.as_sparse_tensor()) - def data_ptr(self): + def data_ptr(self) -> int: """ Returns the address of the first element in the OrtValue's data buffer """ return self._ortvalue.data_ptr() - def device_name(self): + def device_name(self) -> str: """ Returns the name of the device where the OrtValue's data buffer resides e.g. cpu, cuda, cann """ return self._ortvalue.device_name().lower() - def shape(self): + def shape(self) -> Sequence[int]: """ Returns the shape of the data in the OrtValue """ return self._ortvalue.shape() - def data_type(self): + def data_type(self) -> str: """ - Returns the data type of the data in the OrtValue + Returns the data type of the data in the OrtValue. E.g. 'tensor(int64)' """ return self._ortvalue.data_type() - def element_type(self): + def element_type(self) -> int: """ Returns the proto type of the data in the OrtValue if the OrtValue is a tensor. """ return self._ortvalue.element_type() - def has_value(self): + def has_value(self) -> bool: """ Returns True if the OrtValue corresponding to an optional type contains data, else returns False """ return self._ortvalue.has_value() - def is_tensor(self): + def is_tensor(self) -> bool: """ Returns True if the OrtValue contains a Tensor, else returns False """ return self._ortvalue.is_tensor() - def is_sparse_tensor(self): + def is_sparse_tensor(self) -> bool: """ Returns True if the OrtValue contains a SparseTensor, else returns False """ return self._ortvalue.is_sparse_tensor() - def is_tensor_sequence(self): + def is_tensor_sequence(self) -> bool: """ Returns True if the OrtValue contains a Tensor Sequence, else returns False """ return self._ortvalue.is_tensor_sequence() - def numpy(self): + def numpy(self) -> np.ndarray: """ Returns a Numpy object from the OrtValue. Valid only for OrtValues holding Tensors. Throws for OrtValues holding non-Tensors. @@ -890,7 +895,7 @@ def numpy(self): """ return self._ortvalue.numpy() - def update_inplace(self, np_arr): + def update_inplace(self, np_arr) -> None: """ Update the OrtValue in place with a new Numpy array. The numpy contents are copied over to the device memory backing the OrtValue. It can be used @@ -948,7 +953,7 @@ class SparseTensor: depending on the format """ - def __init__(self, sparse_tensor): + def __init__(self, sparse_tensor: C.SparseTensor): """ Internal constructor """ @@ -960,11 +965,17 @@ def __init__(self, sparse_tensor): "`Provided object` needs to be of type `onnxruntime.capi.onnxruntime_pybind11_state.SparseTensor`" ) - def _get_c_tensor(self): + def _get_c_tensor(self) -> C.SparseTensor: return self._tensor - @staticmethod - def sparse_coo_from_numpy(dense_shape, values, coo_indices, ort_device): + @classmethod + def sparse_coo_from_numpy( + cls, + dense_shape: npt.NDArray[np.int64], + values: np.ndarray, + coo_indices: npt.NDArray[np.int64], + ort_device: OrtDevice, + ) -> SparseTensor: """ Factory method to construct a SparseTensor in COO format from given arguments @@ -985,12 +996,17 @@ def sparse_coo_from_numpy(dense_shape, values, coo_indices, ort_device): For strings and objects, it will create a copy of the arrays in CPU memory as ORT does not support those on other devices and their memory can not be mapped. """ - return SparseTensor( - C.SparseTensor.sparse_coo_from_numpy(dense_shape, values, coo_indices, ort_device._get_c_device()) - ) + return cls(C.SparseTensor.sparse_coo_from_numpy(dense_shape, values, coo_indices, ort_device._get_c_device())) - @staticmethod - def sparse_csr_from_numpy(dense_shape, values, inner_indices, outer_indices, ort_device): + @classmethod + def sparse_csr_from_numpy( + cls, + dense_shape: npt.NDArray[np.int64], + values: np.ndarray, + inner_indices: npt.NDArray[np.int64], + outer_indices: npt.NDArray[np.int64], + ort_device: OrtDevice, + ) -> SparseTensor: """ Factory method to construct a SparseTensor in CSR format from given arguments @@ -1011,7 +1027,7 @@ def sparse_csr_from_numpy(dense_shape, values, inner_indices, outer_indices, ort For strings and objects, it will create a copy of the arrays in CPU memory as ORT does not support those on other devices and their memory can not be mapped. """ - return SparseTensor( + return cls( C.SparseTensor.sparse_csr_from_numpy( dense_shape, values, @@ -1021,7 +1037,7 @@ def sparse_csr_from_numpy(dense_shape, values, inner_indices, outer_indices, ort ) ) - def values(self): + def values(self) -> np.ndarray: """ The method returns a numpy array that is backed by the native memory if the data type is numeric. Otherwise, the returned numpy array that contains @@ -1093,19 +1109,19 @@ def format(self): """ return self._tensor.format - def dense_shape(self): + def dense_shape(self) -> npt.NDArray[np.int64]: """ Returns a numpy array(int64) containing a dense shape of a sparse tensor """ return self._tensor.dense_shape() - def data_type(self): + def data_type(self) -> str: """ Returns a string data type of the data in the OrtValue """ return self._tensor.data_type() - def device_name(self): + def device_name(self) -> str: """ Returns the name of the device where the SparseTensor data buffers reside e.g. cpu, cuda """ From a85977dd4f1b66ced92276e8fe22ace2b82465ee Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Wed, 19 Mar 2025 07:46:10 +0800 Subject: [PATCH 118/266] [webgpu] Limit that K must be divisible by 128 to apply dp4a matmul (#24078) The DP4AMatMulQuantize shader needs to make sure that K is divisible by 128. Otherwise, we need align the scale to have shape [M, ceil(K / 128)]. To simplify the shader, we limit that K must be divisible by 128 to apply dp4a matmul. --- .../webgpu/quantization/dp4a_matmul_nbits.cc | 16 +++------------- .../webgpu/quantization/dp4a_matmul_nbits.h | 1 - .../test/contrib_ops/matmul_4bits_test.cc | 2 ++ 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc index 05cbfb1f99c48..65807b072bc80 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc @@ -12,21 +12,12 @@ Status DP4AMatMulQuantizeProgram::GenerateShaderCode(ShaderHelper& shader) const shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); shader.AddOutput("output", ShaderUsage::UseUniform); shader.AddOutput("scales", ShaderUsage::UseUniform); - shader.AdditionalImplementation() << R"ADDNL_FN( - fn readInput(offset: u32) -> input_a_value_t - { - if (offset > uniforms.input_size) { - return input_a_value_t(0); - } - return input_a[offset]; - } - )ADDNL_FN"; shader.MainFunctionBody() << R"MAIN_FN( var local_a : array, 32>; var max_value:vec4 = vec4(0); for (var idx:u32=0;idx<32;idx+=1) { - local_a[idx] = readInput(workgroup_idx*32 + idx); + local_a[idx] = input_a[workgroup_idx*32 + idx]; max_value = max(max_value, abs(local_a[idx])); } var scale = max(max_value.x, max_value.y); @@ -279,8 +270,7 @@ Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor Tensor a_scale = context.CreateGPUTensor(a->DataType(), a_scales_dims); quantize_program.AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec4Components)}}) .AddOutputs({{&a_quant, ProgramTensorMetadataDependency::Rank, a_quant.Shape(), 1}, - {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), 1}}) - .AddUniformVariable({static_cast(M * K / kVec4Components)}); + {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), 1}}); ORT_RETURN_IF_ERROR(context.RunProgram(quantize_program)); constexpr uint32_t kTileSize = 64; @@ -317,7 +307,7 @@ bool CanApplyDP4AMatrixMatMulNBits(onnxruntime::webgpu::ComputeContext& context, bool use_dp4a = context.Device().HasFeature(wgpu::FeatureName::Subgroups) && context.AdapterInfo().backendType != wgpu::BackendType::Metal; return (accuracy_level == 4 && block_size % 32 == 0 && - batch_count == 1 && components_k == 4 && K % 64 == 0 && N % 16 == 0 && + batch_count == 1 && components_k == 4 && K % 128 == 0 && N % 16 == 0 && !has_zero_points && use_dp4a); } diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h index 15b86d78301ad..7e4a8f5d68437 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h @@ -16,7 +16,6 @@ class DP4AMatMulQuantizeProgram final : public Program { diff --git a/onnxruntime/test/contrib_ops/matmul_4bits_test.cc b/onnxruntime/test/contrib_ops/matmul_4bits_test.cc index b1779ded4a675..8187253311ed3 100644 --- a/onnxruntime/test/contrib_ops/matmul_4bits_test.cc +++ b/onnxruntime/test/contrib_ops/matmul_4bits_test.cc @@ -389,6 +389,7 @@ TEST(MatMulNBits, Float32_Accuracy4) { TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); + TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); @@ -458,6 +459,7 @@ TEST(MatMulNBits, Float16_Accuracy4) { TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); + TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); TestMatMulNBitsTyped(); From d98046b36f208da486032fe71de3b76fa28826ed Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:53:57 -0700 Subject: [PATCH 119/266] Add macOS ARM64 pipeline for webgpu (#24060) ### Description Add macOS ARM64 pipeline for webgpu. This pipeline is a temporary one. I created this pipeline because the current code already fails on macOS ARM64 for WebGPU EP. Adding this pipeline allows to check the status of the fix, and eventually when the build passes, this pipeline will be merged with the existing macOS arm64 pipeline. --- .github/workflows/mac.yml | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 50dd25898ad35..fe7c7fb7ab4c8 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -154,6 +154,46 @@ jobs: --use_xnnpack \ --use_binskim_compliant_compile_flags + ARM64-Xcode16-webgpu: + runs-on: macos-15 + + env: + xcode_version: 16 + + timeout-minutes: 60 + + steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ env.python_version }} + + - name: Verify ARM64 machine + shell: python + run: | + import platform + assert platform.machine() == "arm64", "This job expects to be run on an ARM64 machine." + + - name: Use Xcode ${{ env.xcode_version }} + shell: bash + run: | + XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - uses: actions/checkout@v4 + + - name: Build and test + shell: bash + run: | + python ./tools/ci_build/build.py \ + --build_dir ./build \ + --update \ + --build --parallel \ + --test \ + --build_shared_lib \ + --build_nodejs \ + --use_webgpu \ + --use_binskim_compliant_compile_flags + ARM64-Xcode16-targeting-iphonesimulator: runs-on: macos-15 From eceae8b2e7447820c22c4a4cf73f7bbc6717c807 Mon Sep 17 00:00:00 2001 From: Enrico Galli Date: Tue, 18 Mar 2025 23:09:06 -0700 Subject: [PATCH 120/266] [WebNN/WebGPU JS] Fix shared Module methods overriding each other (#23998) - Renamed all conflicting WebNN methods from `jsep*` to `webnn*`. - WebNN doesn't need flush(), therefore it doesn't need to set `jsepBackend`. This PR addresses issue microsoft/webnn-developer-preview#78 --- js/web/lib/wasm/wasm-core-impl.ts | 28 +++++------ js/web/lib/wasm/wasm-types.ts | 44 ++++++++++++------ onnxruntime/core/providers/webnn/allocator.cc | 4 +- .../core/providers/webnn/builders/model.cc | 6 +-- .../providers/webnn/builders/model_builder.cc | 16 +++---- .../core/providers/webnn/data_transfer.cc | 6 +-- .../webnn/webnn_execution_provider.cc | 10 ++-- onnxruntime/wasm/pre-jsep.js | 46 ++++++++++--------- 8 files changed, 89 insertions(+), 71 deletions(-) diff --git a/js/web/lib/wasm/wasm-core-impl.ts b/js/web/lib/wasm/wasm-core-impl.ts index 3979af7fa1ec9..bb532e0fbae74 100644 --- a/js/web/lib/wasm/wasm-core-impl.ts +++ b/js/web/lib/wasm/wasm-core-impl.ts @@ -309,12 +309,12 @@ export const createSession = async ( if (context) { wasm.currentContext = context as MLContext; } else if (gpuDevice) { - wasm.currentContext = await wasm.jsepCreateMLContext!(gpuDevice); + wasm.currentContext = await wasm.webnnCreateMLContext!(gpuDevice); } else { - wasm.currentContext = await wasm.jsepCreateMLContext!({ deviceType, powerPreference }); + wasm.currentContext = await wasm.webnnCreateMLContext!({ deviceType, powerPreference }); } } else { - wasm.currentContext = await wasm.jsepCreateMLContext!(); + wasm.currentContext = await wasm.webnnCreateMLContext!(); } break; } @@ -330,7 +330,7 @@ export const createSession = async ( // clear current MLContext after session creation if (wasm.currentContext) { - wasm.jsepRegisterMLContext!(sessionHandle, wasm.currentContext); + wasm.webnnRegisterMLContext!(sessionHandle, wasm.currentContext); wasm.currentContext = undefined; wasm.shouldTransferToMLTensor = true; } @@ -454,6 +454,7 @@ export const releaseSession = (sessionId: number): void => { } wasm.jsepOnReleaseSession?.(sessionId); + wasm.webnnOnReleaseSession?.(sessionId); wasm.webgpuOnReleaseSession?.(sessionId); inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); @@ -520,7 +521,7 @@ export const prepareInputOutputTensor = async ( const mlTensor = tensor[2].mlTensor as MLTensor; dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!; - const registerMLTensor = wasm.jsepRegisterMLTensor; + const registerMLTensor = wasm.webnnRegisterMLTensor; if (!registerMLTensor) { throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.'); } @@ -540,7 +541,7 @@ export const prepareInputOutputTensor = async ( wasm.setValue(rawData + i * ptrSize, allocWasmString(data[i], allocs), '*'); } } else { - const isGraphInput = wasm.jsepIsGraphInput; + const isGraphInput = wasm.webnnIsGraphInput; if (dataType !== 'string' && isGraphInput) { const tensorNameUTF8 = wasm._OrtGetInputName(sessionId, index); const tensorName = wasm.UTF8ToString(tensorNameUTF8); @@ -549,8 +550,8 @@ export const prepareInputOutputTensor = async ( const dataTypeEnum = tensorDataTypeStringToEnum(dataType); dataByteLength = calculateTensorSizeInBytes(dataTypeEnum, dims)!; actualLocation = 'ml-tensor'; - const createTemporaryTensor = wasm.jsepCreateTemporaryTensor; - const uploadTensor = wasm.jsepUploadTensor; + const createTemporaryTensor = wasm.webnnCreateTemporaryTensor; + const uploadTensor = wasm.webnnUploadTensor; if (!createTemporaryTensor || !uploadTensor) { throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.'); } @@ -722,6 +723,7 @@ export const run = async ( } wasm.jsepOnRunStart?.(sessionHandle); + wasm.webnnOnRunStart?.(sessionHandle); let errorCode: number; if (!BUILD_DEFS.DISABLE_JSEP && ioBindingState) { @@ -862,8 +864,8 @@ export const run = async ( ]); } } else if (preferredLocation === 'ml-tensor' && size > 0) { - const ensureTensor = wasm.jsepEnsureTensor; - const isInt64Supported = wasm.jsepIsInt64Supported; + const ensureTensor = wasm.webnnEnsureTensor; + const isInt64Supported = wasm.webnnIsInt64Supported; if (!ensureTensor || !isInt64Supported) { throw new Error('preferredLocation "ml-tensor" is not supported without using WebNN.'); } @@ -890,9 +892,9 @@ export const run = async ( dims, { mlTensor, - download: wasm.jsepCreateMLTensorDownloader!(dataOffset, type), + download: wasm.webnnCreateMLTensorDownloader!(dataOffset, type), dispose: () => { - wasm.jsepReleaseTensorId!(dataOffset); + wasm.webnnReleaseTensorId!(dataOffset); wasm._OrtReleaseTensor(tensor); }, }, @@ -915,7 +917,7 @@ export const run = async ( if (!keepOutputTensor) { wasm._OrtReleaseTensor(tensor); } - wasm.jsepOnRunEnd?.(sessionHandle); + wasm.webnnOnRunEnd?.(sessionHandle); } } diff --git a/js/web/lib/wasm/wasm-types.ts b/js/web/lib/wasm/wasm-types.ts index 6de54078af031..752bac28d7efb 100644 --- a/js/web/lib/wasm/wasm-types.ts +++ b/js/web/lib/wasm/wasm-types.ts @@ -156,12 +156,26 @@ export declare namespace JSEP { */ shouldTransferToMLTensor: boolean; + /** + * [exported from pre-jsep.js] Called when InferenceSession.run started. This function will be called before + * _OrtRun[WithBinding]() is called. + * @param sessionId - specify the session ID. + */ + webnnOnRunStart: (sessionId: number) => void; + /** + * [exported from pre-jsep.js] Release a session. This function will be called before _OrtReleaseSession() is + * called. + * @param sessionId - specify the session ID. + * @returns + */ + webnnOnReleaseSession: (sessionId: number) => void; + /** * [exported from pre-jsep.js] Called when InferenceSession.run finished. This function will be called after * _OrtRun[WithBinding]() is called. * @param sessionId - specify the session ID. */ - jsepOnRunEnd: (sessionId: number) => void; + webnnOnRunEnd: (sessionId: number) => void; /** * [exported from pre-jsep.js] Register MLContext for a session. @@ -169,18 +183,18 @@ export declare namespace JSEP { * @param context - specify the MLContext. * @returns */ - jsepRegisterMLContext: (sessionId: number, context: MLContext) => void; + webnnRegisterMLContext: (sessionId: number, context: MLContext) => void; /** * [exported from pre-jsep.js] Reserve a MLTensor ID attached to the current session. * @returns the MLTensor ID. */ - jsepReserveTensorId: () => number; + webnnReserveTensorId: () => number; /** * [exported from pre-jsep.js] Release an MLTensor ID from use and destroys underlying MLTensor if no longer in use. * @param tensorId - specify the MLTensor ID. * @returns */ - jsepReleaseTensorId: (tensorId: number) => void; + webnnReleaseTensorId: (tensorId: number) => void; /** * [exported from pre-jsep.js] Ensure that an MLTensor of a given type and shape exists for a MLTensor ID. * @param sessionId - specify the session ID or current active session ID if undefined. @@ -190,7 +204,7 @@ export declare namespace JSEP { * @param copyOld - specify whether to copy the old tensor if a new tensor was created. * @returns the MLTensor associated with the tensor ID. */ - jsepEnsureTensor: ( + webnnEnsureTensor: ( sessionId: number | undefined, tensorId: number, dataType: DataType, @@ -203,20 +217,20 @@ export declare namespace JSEP { * @param data - specify the data to upload. It can be a TensorProto::data_type or a WebNN MLOperandDataType. * @returns */ - jsepUploadTensor: (tensorId: number, data: Uint8Array) => void; + webnnUploadTensor: (tensorId: number, data: Uint8Array) => void; /** * [exported from pre-jsep.js] Download data from an MLTensor. * @param tensorId - specify the MLTensor ID. * @returns the downloaded data. */ - jsepDownloadTensor: (tensorId: number, dstBuffer: ArrayBufferView | ArrayBuffer) => Promise; + webnnDownloadTensor: (tensorId: number, dstBuffer: ArrayBufferView | ArrayBuffer) => Promise; /** * [exported from pre-jsep.js] Creates a downloader function to download data from an MLTensor. * @param tensorId - specify the MLTensor ID. * @param type - specify the data type. * @returns the downloader function. */ - jsepCreateMLTensorDownloader: ( + webnnCreateMLTensorDownloader: ( tensorId: number, type: Tensor.MLTensorDataTypes, ) => () => Promise; @@ -228,7 +242,7 @@ export declare namespace JSEP { * @param dimensions - specify the dimensions. * @returns the MLTensor ID for the external MLTensor. */ - jsepRegisterMLTensor: ( + webnnRegisterMLTensor: ( sessionId: number, tensor: MLTensor, onnxDataType: DataType, @@ -240,7 +254,7 @@ export declare namespace JSEP { * @param optionsOrGpuDevice - specify the options or GPUDevice. * @returns */ - jsepCreateMLContext(optionsOrGpuDevice?: MLContextOptions | GPUDevice): Promise; + webnnCreateMLContext(optionsOrGpuDevice?: MLContextOptions | GPUDevice): Promise; /** * [exported from pre-jsep.js] Register a WebNN Constant operand from external data. @@ -252,7 +266,7 @@ export declare namespace JSEP { * @param shouldConvertInt64ToInt32 - specify whether to convert int64 to int32. * @returns the WebNN Constant operand for the specified external data. */ - jsepRegisterMLConstant( + webnnRegisterMLConstant( externalFilePath: string, dataOffset: number, dataLength: number, @@ -265,14 +279,14 @@ export declare namespace JSEP { * [exported from pre-jsep.js] Register a WebNN graph input. * @param inputName - specify the input name. */ - jsepRegisterGraphInput: (inputName: string) => void; + webnnRegisterGraphInput: (inputName: string) => void; /** * [exported from pre-jsep.js] Check if a graph input is a WebNN graph input. * @param sessionId - specify the session ID. * @param inputName - specify the input name. * @returns whether the input is a WebNN graph input. */ - jsepIsGraphInput: (sessionId: number, inputName: string) => boolean; + webnnIsGraphInput: (sessionId: number, inputName: string) => boolean; /** * [exported from pre-jsep.js] Create a temporary MLTensor for a session. * @param sessionId - specify the session ID. @@ -280,13 +294,13 @@ export declare namespace JSEP { * @param shape - specify the shape. * @returns the MLTensor ID for the temporary MLTensor. */ - jsepCreateTemporaryTensor: (sessionId: number, dataType: DataType, shape: readonly number[]) => Promise; + webnnCreateTemporaryTensor: (sessionId: number, dataType: DataType, shape: readonly number[]) => Promise; /** * [exported from pre-jsep.js] Check if a session's associated WebNN Context supports int64. * @param sessionId - specify the session ID. * @returns whether the WebNN Context supports int64. */ - jsepIsInt64Supported: (sessionId: number) => boolean; + webnnIsInt64Supported: (sessionId: number) => boolean; } } diff --git a/onnxruntime/core/providers/webnn/allocator.cc b/onnxruntime/core/providers/webnn/allocator.cc index 9c5cd651e1f00..8cf5b8cd72a5c 100644 --- a/onnxruntime/core/providers/webnn/allocator.cc +++ b/onnxruntime/core/providers/webnn/allocator.cc @@ -16,7 +16,7 @@ void* WebNNTensorAllocator::Alloc(size_t size) { // We don't need to transfer the tensor to an MLTensor, so we don't need to allocate an MLTensor id. return nullptr; } - void* p = EM_ASM_PTR({ return Module.jsepReserveTensorId(); }); + void* p = EM_ASM_PTR({ return Module.webnnReserveTensorId(); }); allocations_[p] = size; stats_.num_allocs++; stats_.bytes_in_use += SafeInt(size); @@ -27,7 +27,7 @@ void WebNNTensorAllocator::Free(void* p) { if (p == nullptr) { return; } - EM_ASM({ Module.jsepReleaseTensorId($0); }, p); + EM_ASM({ Module.webnnReleaseTensorId($0); }, p); size_t size = allocations_[p]; stats_.bytes_in_use -= size; allocations_.erase(p); diff --git a/onnxruntime/core/providers/webnn/builders/model.cc b/onnxruntime/core/providers/webnn/builders/model.cc index 35964d85862e4..492e2f717e30e 100644 --- a/onnxruntime/core/providers/webnn/builders/model.cc +++ b/onnxruntime/core/providers/webnn/builders/model.cc @@ -157,7 +157,7 @@ onnxruntime::common::Status Model::Compute(const InlinedHashMap& inputs, const InlinedHashMap& outputs) { - auto jsepEnsureTensor = emscripten::val::module_property("jsepEnsureTensor"); + auto webnnEnsureTensor = emscripten::val::module_property("webnnEnsureTensor"); auto promises = emscripten::val::array(); for (const auto& [_, tensor] : inputs) { emscripten::val shape = emscripten::val::array(); @@ -165,7 +165,7 @@ onnxruntime::common::Status Model::Dispatch(const InlinedHashMap(dim); shape.call("push", dim_val); } - auto ml_tensor = jsepEnsureTensor(emscripten::val::undefined(), reinterpret_cast(tensor.buffer), tensor.tensor_info.data_type, shape, true); + auto ml_tensor = webnnEnsureTensor(emscripten::val::undefined(), reinterpret_cast(tensor.buffer), tensor.tensor_info.data_type, shape, true); promises.call("push", ml_tensor); } for (const auto& [_, tensor] : outputs) { @@ -174,7 +174,7 @@ onnxruntime::common::Status Model::Dispatch(const InlinedHashMap(dim); shape.call("push", dim_val); } - auto ml_tensor = jsepEnsureTensor(emscripten::val::undefined(), reinterpret_cast(tensor.buffer), tensor.tensor_info.data_type, shape, false); + auto ml_tensor = webnnEnsureTensor(emscripten::val::undefined(), reinterpret_cast(tensor.buffer), tensor.tensor_info.data_type, shape, false); promises.call("push", ml_tensor); } auto ml_tensors = emscripten::val::global("Promise").call("all", promises).await(); diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index 661b2ad7056c2..ed6ab7d2d7115 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -140,13 +140,13 @@ Status ModelBuilder::RegisterInitializers() { ORT_RETURN_IF_ERROR(utils::GetExternalDataInfo( tensor, graph_viewer_.ModelPath(), external_file_path, data_offset, tensor_byte_size)); - auto jsepRegisterMLConstant = emscripten::val::module_property("jsepRegisterMLConstant"); - operand = jsepRegisterMLConstant(emscripten::val(external_file_path), - static_cast(data_offset), - static_cast(tensor_byte_size), - wnn_builder_, - desc, - should_convert_int64_to_int32); + auto webnnRegisterMLConstant = emscripten::val::module_property("webnnRegisterMLConstant"); + operand = webnnRegisterMLConstant(emscripten::val(external_file_path), + static_cast(data_offset), + static_cast(tensor_byte_size), + wnn_builder_, + desc, + should_convert_int64_to_int32); } else { if (tensor.has_raw_data()) { tensor_ptr = reinterpret_cast(const_cast(tensor.raw_data().c_str())); @@ -288,7 +288,7 @@ Status ModelBuilder::RegisterModelInputOutput(const NodeArg& node_arg, bool is_i desc.set("dataType", emscripten::val("int32")); } wnn_operands_.insert(std::make_pair(name, wnn_builder_.call("input", name, desc))); - emscripten::val::module_property("jsepRegisterGraphInput")(name); + emscripten::val::module_property("webnnRegisterGraphInput")(name); input_names_.push_back(name); } else { output_names_.push_back(name); diff --git a/onnxruntime/core/providers/webnn/data_transfer.cc b/onnxruntime/core/providers/webnn/data_transfer.cc index 44e9bf9edf3d9..aa85277b72453 100644 --- a/onnxruntime/core/providers/webnn/data_transfer.cc +++ b/onnxruntime/core/providers/webnn/data_transfer.cc @@ -29,11 +29,11 @@ common::Status DataTransfer::CopyTensor(const Tensor& src, Tensor& dst) const { const auto& dst_device = dst.Location().device; if (dst_device.Type() == OrtDevice::GPU) { - EM_ASM({ Module.jsepUploadTensor($0, HEAPU8.subarray($1, $1 + $2)); }, dst_data, reinterpret_cast(src_data), bytes); + EM_ASM({ Module.webnnUploadTensor($0, HEAPU8.subarray($1, $1 + $2)); }, dst_data, reinterpret_cast(src_data), bytes); } else { - auto jsepDownloadTensor = emscripten::val::module_property("jsepDownloadTensor"); + auto webnnDownloadTensor = emscripten::val::module_property("webnnDownloadTensor"); auto subarray = emscripten::typed_memory_view(bytes, static_cast(dst_data)); - jsepDownloadTensor(reinterpret_cast(src_data), subarray).await(); + webnnDownloadTensor(reinterpret_cast(src_data), subarray).await(); } } diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index 7410ff66add30..c527ba213e55b 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -284,7 +284,7 @@ class WebNNMemcpy : public OpKernel { explicit WebNNMemcpy(const OpKernelInfo& info) : OpKernel(info) {} Status Compute(OpKernelContext* context) const override { - auto jsepEnsureTensor = emscripten::val::module_property("jsepEnsureTensor"); + auto webnnEnsureTensor = emscripten::val::module_property("webnnEnsureTensor"); const auto* X = context->Input(0); ORT_ENFORCE(X != nullptr, "Memcpy: input tensor is null"); auto* Y = context->Output(0, X->Shape()); @@ -294,10 +294,10 @@ class WebNNMemcpy : public OpKernel { shape.call("push", SafeInt(dim).Ref()); } - jsepEnsureTensor(emscripten::val::undefined(), - reinterpret_cast(Y->MutableDataRaw()), - Y->GetElementType(), - shape, false) + webnnEnsureTensor(emscripten::val::undefined(), + reinterpret_cast(Y->MutableDataRaw()), + Y->GetElementType(), + shape, false) .await(); const auto* data_transfer = Info().GetDataTransferManager().GetDataTransfer(X->Location().device, Y->Location().device); diff --git a/onnxruntime/wasm/pre-jsep.js b/onnxruntime/wasm/pre-jsep.js index a11c6d741d110..cca8da0525fbe 100644 --- a/onnxruntime/wasm/pre-jsep.js +++ b/onnxruntime/wasm/pre-jsep.js @@ -97,41 +97,40 @@ Module["jsepInit"] = (name, params) => { // Functions called via emscripten::val::module_property need to be assigned by name so that the minifier doesn't // change the name. + const backend = params[0]; [ - Module.jsepBackend, - Module.jsepReserveTensorId, - Module.jsepReleaseTensorId, - Module["jsepEnsureTensor"], - Module.jsepUploadTensor, - Module["jsepDownloadTensor"], - ] = params; + Module.webnnReserveTensorId, + Module.webnnReleaseTensorId, + Module["webnnEnsureTensor"], + Module.webnnUploadTensor, + Module["webnnDownloadTensor"], + ] = params.slice(1); // This function is called from both JS and an EM_ASM block, it needs both a minifiable name and an explicit name. - Module["jsepReleaseTensorId"] = Module.jsepReleaseTensorId; - Module["jsepUploadTensor"] = Module.jsepUploadTensor; + Module["webnnReleaseTensorId"] = Module.webnnReleaseTensorId; + Module["webnnUploadTensor"] = Module.webnnUploadTensor; // Functions called from JS also need to have explicit names. - const backend = Module.jsepBackend; - Module["jsepOnRunStart"] = (sessionId) => { + Module["webnnOnRunStart"] = (sessionId) => { return backend["onRunStart"](sessionId); }; - Module["jsepOnRunEnd"] = backend["onRunEnd"].bind(backend); - Module["jsepRegisterMLContext"] = (sessionId, mlContext) => { + Module["webnnOnRunEnd"] = backend["onRunEnd"].bind(backend); + Module["webnnRegisterMLContext"] = (sessionId, mlContext) => { backend["registerMLContext"](sessionId, mlContext); }; - Module["jsepOnReleaseSession"] = (sessionId) => { + Module["webnnOnReleaseSession"] = (sessionId) => { backend["onReleaseSession"](sessionId); }; - Module["jsepCreateMLTensorDownloader"] = (tensorId, type) => { + Module["webnnCreateMLTensorDownloader"] = (tensorId, type) => { return backend["createMLTensorDownloader"](tensorId, type); }; - Module["jsepRegisterMLTensor"] = (sessionId, tensor, dataType, shape) => { + Module["webnnRegisterMLTensor"] = (sessionId, tensor, dataType, shape) => { return backend["registerMLTensor"](sessionId, tensor, dataType, shape); }; - Module["jsepCreateMLContext"] = (optionsOrGpuDevice) => { + Module["webnnCreateMLContext"] = (optionsOrGpuDevice) => { return backend["createMLContext"](optionsOrGpuDevice); }; - Module["jsepRegisterMLConstant"] = ( + Module["webnnRegisterMLConstant"] = ( externalFilePath, dataOffset, dataLength, @@ -149,9 +148,12 @@ Module["jsepInit"] = (name, params) => { shouldConvertInt64ToInt32, ); }; - Module['jsepRegisterGraphInput'] = backend['registerGraphInput'].bind(backend); - Module['jsepIsGraphInput'] = backend['isGraphInput'].bind(backend); - Module['jsepCreateTemporaryTensor'] = backend['createTemporaryTensor'].bind(backend); - Module['jsepIsInt64Supported'] = backend['isInt64Supported'].bind(backend); + Module["webnnRegisterGraphInput"] = + backend["registerGraphInput"].bind(backend); + Module["webnnIsGraphInput"] = backend["isGraphInput"].bind(backend); + + Module["webnnCreateTemporaryTensor"] = + backend["createTemporaryTensor"].bind(backend); + Module["webnnIsInt64Supported"] = backend["isInt64Supported"].bind(backend); } }; From 7fc7d5ec750decb1ff546184f94d90719ccdb00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erick=20Mu=C3=B1oz?= Date: Wed, 19 Mar 2025 02:27:25 -0600 Subject: [PATCH 121/266] Enable multithreading on FP16 to FP32 cast operator (#23619) ### Description Enables multithreading on FP16 to FP32 cast operator. ### Motivation and Context Improves CPU performance on FP16 models that require casting to FP32. --- .../core/providers/cpu/tensor/cast_op.cc | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/cpu/tensor/cast_op.cc b/onnxruntime/core/providers/cpu/tensor/cast_op.cc index 35f3b12aeba35..639a49cb43a4f 100644 --- a/onnxruntime/core/providers/cpu/tensor/cast_op.cc +++ b/onnxruntime/core/providers/cpu/tensor/cast_op.cc @@ -254,11 +254,32 @@ struct TensorCasterNoSat { // tensor MLFloat16 -> float template <> struct TensorCaster { - void Cast(const OpKernelContext&, const TensorShape& shape, const Tensor& in, Tensor& out) const { + void Cast(const OpKernelContext& ctx, const TensorShape& shape, const Tensor& in, Tensor& out) const { auto out_data = out.MutableData(); auto in_data = in.Data(); const size_t shape_size = narrow(shape.Size()); - MlasConvertHalfToFloatBuffer(in_data, out_data, shape_size); + + // Check if the tensor is long enough to use threads + if (shape_size <= 128000) { + MlasConvertHalfToFloatBuffer(in_data, out_data, shape_size); + return; + } + // Calculate the number of compute cyles per implementation + auto cpu_info = CPUIDInfo::GetCPUIDInfo(); + double num_compute_cycles; + if (cpu_info.HasSSE3()) { + num_compute_cycles = static_cast(shape_size >> 1); + } else if (cpu_info.HasAVX2()) { + num_compute_cycles = static_cast(shape_size >> 2); + } else { + num_compute_cycles = static_cast(shape_size * 10); + } + + concurrency::ThreadPool::TryParallelFor(ctx.GetOperatorThreadPool(), shape_size, + {shape_size * 2.f, shape_size * 4.f, num_compute_cycles}, + [in_data, out_data](std::ptrdiff_t first_span, std::ptrdiff_t last_span) { + MlasConvertHalfToFloatBuffer(in_data + first_span, out_data + first_span, static_cast(last_span - first_span)); + }); } }; From 3488ba39f7fc8c847cdf55f44f5ebe09c3026614 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Wed, 19 Mar 2025 09:32:50 -0700 Subject: [PATCH 122/266] Move Android CI Pipeline to Github Actions (#24094) ### Description Move Android CI Pipeline to Github Actions --- .github/actions/setup-android-ndk/action.yml | 98 +++++++ .github/workflows/android.yml | 147 +++++++++++ ...ndroid-x86_64-crosscompile-ci-pipeline.yml | 241 ------------------ tools/python/util/android/android.py | 42 ++- 4 files changed, 275 insertions(+), 253 deletions(-) create mode 100644 .github/actions/setup-android-ndk/action.yml create mode 100644 .github/workflows/android.yml delete mode 100644 tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml diff --git a/.github/actions/setup-android-ndk/action.yml b/.github/actions/setup-android-ndk/action.yml new file mode 100644 index 0000000000000..fea9745396e81 --- /dev/null +++ b/.github/actions/setup-android-ndk/action.yml @@ -0,0 +1,98 @@ +# .github/actions/setup-android-ndk/action.yml +name: 'Setup Android NDK' +description: 'Installs and configures a specific version of the Android NDK' +inputs: + ndk-version: + description: 'The version of the Android NDK to install (e.g., 27.2.12479018)' + required: true + default: '27.2.12479018' + android-sdk-root: + description: 'The root directory of the Android SDK' + required: true + default: '/usr/local/lib/android/sdk' + +runs: + using: "composite" # Use a composite action for multiple shell commands + steps: + - name: Install coreutils and ninja + shell: bash + run: sudo apt-get update -y && sudo apt-get install -y coreutils ninja-build + + - name: Install Android NDK + shell: bash + run: | + set -e + "${{ inputs.android-sdk-root }}/cmdline-tools/latest/bin/sdkmanager" --install "ndk;${{ inputs.ndk-version }}" + + NDK_PATH="${{ inputs.android-sdk-root }}/ndk/${{ inputs.ndk-version }}" + if [[ ! -d "${NDK_PATH}" ]]; then + echo "NDK directory is not in expected location: ${NDK_PATH}" + exit 1 + fi + + # Use standard environment variable setting in bash and add to GITHUB_ENV + echo "ANDROID_NDK_HOME=${NDK_PATH}" >> $GITHUB_ENV + echo "ANDROID_NDK_ROOT=${NDK_PATH}" >> $GITHUB_ENV + echo "ANDROID_NDK_HOME: ${NDK_PATH}" + echo "ANDROID_NDK_ROOT: ${NDK_PATH}" + + - name: Check if emulator are installed and add to PATH + shell: bash + run: | + if [[ ":$PATH:" == *":${ANDROID_SDK_ROOT}/emulator:"* ]]; then + echo "${ANDROID_SDK_ROOT}/emulator is in PATH" + else + ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "emulator" + echo "${ANDROID_SDK_ROOT}/emulator" >> $GITHUB_PATH + fi + + - name: Check if platform tools are installed and add to PATH + shell: bash + run: | + if [[ ":$PATH:" == *":${ANDROID_SDK_ROOT}/platform-tools:"* ]]; then + echo "${ANDROID_SDK_ROOT}/platform-tools is in PATH" + else + ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "platform-tools" + echo "${ANDROID_SDK_ROOT}/platform-tools" >> $GITHUB_PATH + fi + ls -R "${ANDROID_SDK_ROOT}/platform-tools" + + - name: Create Android Emulator + shell: bash + env: + ANDROID_AVD_HOME: ${{ runner.temp }}/android-avd + run: | + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --create-avd --system-image "system-images;android-31;default;x86_64" + + - name: List Android AVDs + shell: bash + env: + ANDROID_AVD_HOME: ${{ runner.temp }}/android-avd + run: | + "${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/avdmanager" list avd + + - name: Check emulator.pid does not exist + shell: bash + run: | + if test -f ./emulator.pid; then + echo "Emulator PID file was not expected to exist but does and has pid: `cat ./emulator.pid`" + exit 1 + fi + + - name: Start Android Emulator + shell: bash + env: + ANDROID_AVD_HOME: ${{ runner.temp }}/android-avd + run: | + set -e -x + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --start --emulator-extra-args="-partition-size 2047" \ + --emulator-pid-file ./emulator.pid + echo "Emulator PID: `cat ./emulator.pid`" + + - name: View Android ENVs + shell: bash + run: env | grep ANDROID \ No newline at end of file diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000000000..64c40946c49c5 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,147 @@ +name: Android CI +# This workflow is used to build and test on Android Emulator on Linux + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + android_nnapi_ep: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + steps: + - uses: actions/checkout@v4 + + - name: Use jdk 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 27.2.12479018 + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: NNAPI EP, Build, Test on Android Emulator + run: >- + python3 tools/ci_build/build.py + --enable_lto + --android + --build_dir build_nnapi + --android_sdk_path "$ANDROID_HOME" + --android_ndk_path "$ANDROID_NDK_HOME" + --android_abi=x86_64 + --android_api=29 + --skip_submodule_sync + --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache + --use_nnapi + --build_shared_lib + --cmake_generator=Ninja + --build_java + shell: bash + + + - name: Build Minimal ORT with NNAPI and run tests + run: tools/ci_build/github/linux/ort_minimal/nnapi_minimal_build_minimal_ort_and_run_tests.sh "$(pwd)" + shell: bash + + - name: Install psutil for emulator shutdown by run_android_emulator.py + if: always() + run: python3 -m pip install psutil + shell: bash + + - name: Stop Android Emulator + if: always() + run: | + env | grep ANDROID + if test -f ${{ github.workspace }}/emulator.pid; then + echo "Emulator PID:"`cat ${{ github.workspace }}/emulator.pid` + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --stop \ + --emulator-pid-file ${{ github.workspace }}/emulator.pid + rm ${{ github.workspace }}/emulator.pid + else + echo "Emulator PID file was expected to exist but does not." + fi + shell: bash + + android_cpu_ep: + name: Android CI Pipeline + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + steps: + - uses: actions/checkout@v4 + + - name: Use jdk 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 27.2.12479018 + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: CPU EP, Build and Test + run: >- + python3 tools/ci_build/build.py + --enable_lto + --android + --build_dir build + --android_sdk_path $ANDROID_HOME + --android_ndk_path $ANDROID_NDK_HOME + --android_abi=x86_64 + --android_api=30 + --skip_submodule_sync + --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache + --cmake_generator=Ninja + --build_java + shell: bash + + - name: Install psutil for emulator shutdown by run_android_emulator.py + if: always() + run: python3 -m pip install psutil + shell: bash + + - name: Stop Android Emulator + if: always() + run: | + if test -f ${{ github.workspace }}/emulator.pid; then + echo "Emulator PID:"`cat ${{ github.workspace }}/emulator.pid` + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --stop \ + --emulator-pid-file ${{ github.workspace }}/emulator.pid + rm ${{ github.workspace }}/emulator.pid + else + echo "Emulator PID file was expected to exist but does not." + fi + shell: bash diff --git a/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml deleted file mode 100644 index 3cceadd1b8ef5..0000000000000 --- a/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml +++ /dev/null @@ -1,241 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -# Known Limits -# 1. Anchors are not supported in GHA -# https://github.community/t/support-for-yaml-anchors/16128/90 -# 2. today most cloud-based CI services are still lacking hardware acceleration support from the host VM, -# which is the no.1 blocker for running tests on modern Android Emulators (especially on recent API levels) on CI. - -# It'd better to check out https://github.com/microsoft/onnxruntime/wiki/Leverage-Existing-Artifacts -# to save debugging time. -parameters: -- name: specificArtifact - displayName: Use Specific Artifact - type: boolean - default: false -- name: runId - displayName: Specific Artifact's RunId - type: number - default: 0 - -stages: -# Separate stage for building CPU vs NNAPI as we only want CodeQL to run on one of them so we don't get duplicate -# issues for code that is built in both. We pick NNAPI as that includes the NNAPI EP code. -- stage: BUILD_AND_TEST_CPU - dependsOn: [] - variables: - Codeql.Enabled: false - ANDROID_AVD_HOME: $(Agent.TempDirectory) - jobs: - - job: BUILD_AND_TEST_CPU - pool: onnxruntime-Ubuntu2204-AMD-CPU - workspace: - clean: all - timeoutInMinutes: 30 - steps: - - task: JavaToolInstaller@0 - displayName: Use jdk 17 - inputs: - versionSpec: '17' - jdkArchitectureOption: 'x64' - jdkSourceOption: 'PreInstalled' - - - script: sudo apt-get update -y && sudo apt-get install -y coreutils ninja-build - displayName: Install coreutils and ninja - - - template: templates/use-android-ndk.yml - - template: templates/use-android-emulator.yml - parameters: - create: true - start: true - - script: | - env | grep ANDROID - displayName: View Android ENVs - - script: | - python3 tools/ci_build/build.py \ - --enable_lto \ - --android \ - --build_dir build \ - --android_sdk_path $ANDROID_HOME \ - --android_ndk_path $ANDROID_NDK_HOME \ - --android_abi=x86_64 \ - --android_api=30 \ - --skip_submodule_sync \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --cmake_generator=Ninja \ - --build_java - displayName: CPU EP, Build and Test - - template: templates/use-android-emulator.yml - parameters: - stop: true - - - template: templates/clean-agent-build-directory-step.yml - -- stage: BUILD_AND_TEST_NNAPI_EP - dependsOn: [] - condition: notIn(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') - variables: - ANDROID_AVD_HOME: $(Agent.TempDirectory) - Codeql.ProjectConfigPath: .github/workflows - Codeql.Enabled: true - Codeql.Language: cpp - ${{ if variables['Codeql.Enabled'] }}: - JobsTimeout: 120 - ${{ else }}: - JobsTimeout: 60 - jobs: - - job: BUILD_AND_TEST_NNAPI_EP - pool: onnxruntime-Ubuntu2204-AMD-CPU - timeoutInMinutes: ${{ variables.JobsTimeout }} - workspace: - clean: all - steps: - - task: JavaToolInstaller@0 - displayName: Use jdk 17 - inputs: - versionSpec: '17' - jdkArchitectureOption: 'x64' - jdkSourceOption: 'PreInstalled' - - - script: sudo apt-get update -y && sudo apt-get install -y coreutils ninja-build - displayName: Install coreutils and ninja - - template: templates/use-android-emulator.yml - parameters: - create: true - start: true - - - script: | - env | grep ANDROID - displayName: View Android ENVs - - - script: | - python3 tools/ci_build/build.py \ - --enable_lto \ - --android \ - --build_dir build_nnapi \ - --android_sdk_path $ANDROID_HOME \ - --android_ndk_path $ANDROID_NDK_HOME \ - --android_abi=x86_64 \ - --android_api=29 \ - --skip_submodule_sync \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --use_nnapi \ - --build_shared_lib \ - --cmake_generator=Ninja \ - --build_java - displayName: NNAPI EP, Build, Test on Android Emulator - - - script: /bin/bash tools/ci_build/github/linux/ort_minimal/nnapi_minimal_build_minimal_ort_and_run_tests.sh $(pwd) - # Build Minimal ORT with NNAPI and reduced Ops, run unit tests on Android Emulator - displayName: Build Minimal ORT with NNAPI and run tests - - - template: templates/use-android-emulator.yml - parameters: - stop: true - - - template: templates/clean-agent-build-directory-step.yml - -- stage: MAIN_BUILD_STAGE - # The below jobs only run on build of main branch. - # because coverage report is hard to support in cross machines. - displayName: NNAPI MAIN BUILD&TEST - dependsOn: [] - condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') - variables: - ANDROID_AVD_HOME: $(Agent.TempDirectory) - jobs: - - job: NNAPI_EP_MASTER - pool: onnxruntime-Ubuntu2204-AMD-CPU - timeoutInMinutes: 180 - workspace: - clean: all - condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') - steps: - - task: JavaToolInstaller@0 - displayName: Use jdk 17 - inputs: - versionSpec: '17' - jdkArchitectureOption: 'x64' - jdkSourceOption: 'PreInstalled' - - - template: templates/use-android-ndk.yml - - - template: templates/use-android-emulator.yml - parameters: - create: true - start: true - - - script: | - python3 tools/ci_build/build.py \ - --enable_lto \ - --android \ - --build_dir build_nnapi \ - --android_sdk_path $ANDROID_HOME \ - --android_ndk_path $ANDROID_NDK_HOME \ - --android_abi=x86_64 \ - --android_api=29 \ - --skip_submodule_sync \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --use_nnapi \ - --build_shared_lib \ - --cmake_generator=Ninja \ - --build_java \ - --code_coverage - displayName: NNAPI EP, Build, Test, CodeCoverage on Android Emulator - - # We need to use llvm-cov from the NDK. - - script: | - export GCOV="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-cov gcov" - python3 -m pip install gcovr - python3 tools/ci_build/coverage.py --build_dir build_nnapi --android_sdk_path $ANDROID_HOME - displayName: Retrieve runtime code coverage files from the emulator and analyze - - - script: cat '$(Build.SourcesDirectory)/build_nnapi/Debug/coverage_rpt.txt' - displayName: Print coverage report - - # - task: AzureCLI@2 - # displayName: 'Post Android Code Coverage To DashBoard' - # inputs: - # azureSubscription: AIInfraBuild - # scriptType: bash - # scriptPath: $(Build.SourcesDirectory)/tools/ci_build/github/linux/upload_code_coverage_data.sh - # arguments: '"$(Build.SourcesDirectory)/build_nnapi/Debug/coverage_rpt.txt" "https://dev.azure.com/onnxruntime/onnxruntime/_build/results?buildId=$(Build.BuildId)" arm android nnapi' - # workingDirectory: '$(Build.BinariesDirectory)' - - - script: /bin/bash tools/ci_build/github/linux/ort_minimal/nnapi_minimal_build_minimal_ort_and_run_tests.sh $(pwd) - # Build Minimal ORT with NNAPI and reduced Ops, run unit tests on Android Emulator - displayName: Build Minimal ORT with NNAPI and run tests - - - template: templates/use-android-emulator.yml - parameters: - stop: true - - - template: templates/clean-agent-build-directory-step.yml diff --git a/tools/python/util/android/android.py b/tools/python/util/android/android.py index 8f3ed97cae53f..cd420ca1483c7 100644 --- a/tools/python/util/android/android.py +++ b/tools/python/util/android/android.py @@ -46,18 +46,36 @@ def filename(name, windows_extension): def create_virtual_device(sdk_tool_paths: SdkToolPaths, system_image_package_name: str, avd_name: str): run(sdk_tool_paths.sdkmanager, "--install", system_image_package_name, input=b"y") - - run( - sdk_tool_paths.avdmanager, - "create", - "avd", - "--name", - avd_name, - "--package", - system_image_package_name, - "--force", - input=b"no", - ) + android_avd_home = os.environ["ANDROID_AVD_HOME"] + + if android_avd_home is not None: + if not os.path.exists(android_avd_home): + os.makedirs(android_avd_home) + run( + sdk_tool_paths.avdmanager, + "create", + "avd", + "--name", + avd_name, + "--package", + system_image_package_name, + "--force", + "--path", + android_avd_home, + input=b"no", + ) + else: + run( + sdk_tool_paths.avdmanager, + "create", + "avd", + "--name", + avd_name, + "--package", + system_image_package_name, + "--force", + input=b"no", + ) _process_creationflags = subprocess.CREATE_NEW_PROCESS_GROUP if is_windows() else 0 From 7444feebe4465743bc36e6a644239ca66e7eda26 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Wed, 19 Mar 2025 09:42:31 -0700 Subject: [PATCH 123/266] Cleanup CoreML EP's code to remove COREML_ENABLE_MLPROGRAM (#23490) ### Description Cleanup CoreML EP's code to remove the COREML_ENABLE_MLPROGRAM macro. Also, increase MINIMUM_COREML_VERSION(first version we support) to 5 . --- .../builders/impl/activation_op_builder.cc | 5 +-- .../coreml/builders/impl/argmax_op_builder.cc | 7 +--- .../builders/impl/batch_norm_op_builder.cc | 5 +-- .../coreml/builders/impl/binary_op_builder.cc | 7 +--- .../coreml/builders/impl/builder_utils.cc | 2 - .../coreml/builders/impl/builder_utils.h | 2 - .../coreml/builders/impl/cast_op_builder.cc | 8 +--- .../coreml/builders/impl/clip_op_builder.cc | 5 +-- .../coreml/builders/impl/concat_op_builder.cc | 2 - .../coreml/builders/impl/conv_op_builder.cc | 12 +----- .../builders/impl/convtranspose_op_builder.cc | 2 - .../builders/impl/depthtospace_op_builder.cc | 2 - .../coreml/builders/impl/gemm_op_builder.cc | 10 +---- .../builders/impl/gridsample_op_builder.cc | 2 - .../builders/impl/normalization_op_builder.cc | 4 -- .../coreml/builders/impl/pool_op_builder.cc | 5 +-- .../builders/impl/reduction_op_builder.cc | 5 +-- .../builders/impl/reshape_op_builder.cc | 5 +-- .../coreml/builders/impl/resize_op_builder.cc | 5 +-- .../coreml/builders/impl/shape_op_builder.cc | 5 +-- .../coreml/builders/impl/slice_op_builder.cc | 18 +++------ .../builders/impl/softmax_op_builder.cc | 5 +-- .../coreml/builders/impl/split_op_builder.cc | 5 +-- .../builders/impl/squeeze_op_builder.cc | 8 +--- .../builders/impl/transpose_op_builder.cc | 5 +-- .../coreml/builders/impl/unary_op_builder.cc | 5 +-- .../coreml/builders/model_builder.cc | 37 ++----------------- .../providers/coreml/builders/model_builder.h | 12 ------ .../core/providers/coreml/coreml_options.cc | 12 ------ .../core/providers/coreml/model/host_utils.h | 3 +- .../core/providers/xnnpack/nn/max_pool.cc | 2 +- .../test/contrib_ops/layer_norm_op_test.cc | 2 +- .../providers/coreml/coreml_basic_test.cc | 2 +- .../cpu/activation/activation_op_test.cc | 6 +-- .../cpu/activation/activation_op_test.h | 2 +- .../cpu/math/element_wise_ops_test.cc | 8 ++-- .../test/providers/cpu/math/matmul_test.cc | 4 +- .../providers/cpu/nn/batch_norm_op_test.cc | 2 +- .../test/providers/cpu/nn/conv_fp16_test.cc | 4 +- .../providers/cpu/nn/group_norm_op_test.cc | 2 +- .../providers/cpu/nn/instance_norm_op_test.cc | 2 +- .../providers/cpu/nn/pool_fp16_op_test.cc | 2 +- .../test/providers/cpu/nn/pool_op_test.cc | 2 +- .../cpu/reduction/reduction_ops_test.cc | 6 +-- 44 files changed, 55 insertions(+), 201 deletions(-) diff --git a/onnxruntime/core/providers/coreml/builders/impl/activation_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/activation_op_builder.cc index 4481a5172966b..3fffc6d0a68c4 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/activation_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/activation_op_builder.cc @@ -97,7 +97,6 @@ Status ActivationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const logging::Logger& logger) const { const auto& op_type(node.OpType()); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#module-coremltools.converters.mil.mil.ops.defs.iOS15.activation @@ -166,9 +165,7 @@ Status ActivationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, model_builder.AddOperation(std::move(op)); - } else -#endif // (COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); if (op_type == "Sigmoid") { diff --git a/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc index 6169090a36014..dfa01c8187741 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc @@ -32,7 +32,6 @@ Status ArgMaxOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const int64_t keepdims = helper.Get("keepdims", 1); const bool removedim = keepdims != 1; -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#module-coremltools.converters.mil.mil.ops.defs.iOS15.reduction @@ -46,9 +45,7 @@ Status ArgMaxOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // the output of ArgMax must be int32 AddOperationOutput(*op, *node.OutputDefs()[0], output_datatype); model_builder.AddOperation(std::move(op)); - } else -#endif // (COREML_ENABLE_MLPROGRAM) - { + } else { auto* coreml_argmax = layer->mutable_argmax(); coreml_argmax->set_axis(axis); coreml_argmax->set_removedim(removedim); @@ -91,11 +88,9 @@ bool ArgMaxOpBuilder::IsOpSupportedImpl(const Node& node, return false; } -#if defined(COREML_ENABLE_MLPROGRAM) if (input_params.create_mlprogram) { return true; } -#endif // If there are multiple downstream nodes and cast (toint32) is one of them // not supported, exit here diff --git a/onnxruntime/core/providers/coreml/builders/impl/batch_norm_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/batch_norm_op_builder.cc index 442194cb31cbc..e547f2e42e527 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/batch_norm_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/batch_norm_op_builder.cc @@ -57,7 +57,6 @@ Status BatchNormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_bu const auto eps = helper.Get("epsilon", 1e-5f); const auto channels = scale_tensor.dims()[0]; -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#coremltools.converters.mil.mil.ops.defs.iOS15.normalization.batch_norm @@ -78,9 +77,7 @@ Status BatchNormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_bu AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); - } else -#endif // (COREML_ENABLE_MLPROGRAM) - { + } else { auto* coreml_batch_norm = layer->mutable_batchnorm(); coreml_batch_norm->set_channels(channels); coreml_batch_norm->set_epsilon(eps); diff --git a/onnxruntime/core/providers/coreml/builders/impl/binary_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/binary_op_builder.cc index 0482620b269a4..d7c78e05362ed 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/binary_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/binary_op_builder.cc @@ -56,7 +56,6 @@ bool CheckIfBothInputShapesMatch(const Node& node, const logging::Logger& logger } } // namespace -#if defined(COREML_ENABLE_MLPROGRAM) static std::vector InferOutputShape(const std::vector& a, const std::vector& b) { std::vector output_shape; int64_t i_a = 0, j_b = 0; @@ -112,14 +111,12 @@ static void AddVariadicInputs(std::unique_ptr layer = model_builder.CreateNNLayer(node); if (op_type == "Add") { diff --git a/onnxruntime/core/providers/coreml/builders/impl/builder_utils.cc b/onnxruntime/core/providers/coreml/builders/impl/builder_utils.cc index 6f9bb35c27d80..684653aa21273 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/builder_utils.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/builder_utils.cc @@ -150,7 +150,6 @@ void CreateCoreMLWeight(CoreML::Specification::WeightParams& weight, gsl::span data); -#if defined(COREML_ENABLE_MLPROGRAM) // // MLProgram utils // @@ -174,6 +173,5 @@ void AddOperationOutput(COREML_SPEC::MILSpec::Operation& op, const NodeArg& outp /// Number of spatial dims in input. Generally rank - 2 (ignore N and C dims). void AddPadTypeAndPads(COREML_SPEC::MILSpec::Operation& op, ModelBuilder& model_builder, std::string_view op_type, const NodeAttrHelper& helper, int num_spatial_dims); -#endif // defined(COREML_ENABLE_MLPROGRAM) } // namespace coreml } // namespace onnxruntime diff --git a/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc index 7c7363d4c81ad..8abee92451338 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc @@ -27,9 +27,8 @@ class CastOpBuilder : public BaseOpBuilder { Status CastOpBuilder::AddToModelBuilderImpl([[maybe_unused]] ModelBuilder& model_builder, [[maybe_unused]] const Node& node, [[maybe_unused]] const logging::Logger& logger) const { -// This is a special handling case for ArgMax Op, where argmax is followed by a cast to int32 type. -// The ArgMax is fused with the Cast node and produces an int32 output. -#if defined(COREML_ENABLE_MLPROGRAM) + // This is a special handling case for ArgMax Op, where argmax is followed by a cast to int32 type. + // The ArgMax is fused with the Cast node and produces an int32 output. if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#coremltools.converters.mil.mil.ops.defs.iOS15.elementwise_unary.cast @@ -73,7 +72,6 @@ Status CastOpBuilder::AddToModelBuilderImpl([[maybe_unused]] ModelBuilder& model AddOperationOutput(*op, *node.OutputDefs()[0], cast_to_type); model_builder.AddOperation(std::move(op)); } -#endif return Status::OK(); } @@ -134,7 +132,6 @@ bool CastOpBuilder::HasSupportedInputsImpl(const Node& node, [[maybe_unused]] co return false; } -#if defined(COREML_ENABLE_MLPROGRAM) if (input_params.create_mlprogram) { if ((input_type == ONNX_NAMESPACE::TensorProto_DataType_INT32 || input_type == ONNX_NAMESPACE::TensorProto_DataType_INT64 || @@ -152,7 +149,6 @@ bool CastOpBuilder::HasSupportedInputsImpl(const Node& node, [[maybe_unused]] co return false; } } -#endif // only support int64 coming from ArgMax (check for ArgMax is done in IsOpSupportedImpl()) if (input_type != ONNX_NAMESPACE::TensorProto_DataType_INT64) { diff --git a/onnxruntime/core/providers/coreml/builders/impl/clip_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/clip_op_builder.cc index f7046c213a8cb..9e68070a0e693 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/clip_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/clip_op_builder.cc @@ -64,7 +64,6 @@ Status ClipOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, bool has_min = min != std::numeric_limits::lowest(); bool has_max = max != std::numeric_limits::max(); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -121,9 +120,7 @@ Status ClipOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, AddOperationOutput(*op, output); model_builder.AddOperation(std::move(op)); - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { // TODO: CoreML has a Clip layer for NeuralNetwork. Added in CoreML 4. We could potentially use that if available // to simplify. // https://apple.github.io/coremltools/mlmodel/Format/NeuralNetwork.html#cliplayerparams diff --git a/onnxruntime/core/providers/coreml/builders/impl/concat_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/concat_op_builder.cc index 9ea0030290abd..34ce2438095ad 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/concat_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/concat_op_builder.cc @@ -26,7 +26,6 @@ class ConcatOpBuilder : public BaseOpBuilder { Status ConcatOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const { -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // NOLINT @@ -45,7 +44,6 @@ Status ConcatOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); } else // NOLINT -#endif // defined(COREML_ENABLE_MLPROGRAM) { std::unique_ptr layer = model_builder.CreateNNLayer(node); diff --git a/onnxruntime/core/providers/coreml/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/conv_op_builder.cc index 38125957bf481..18823bcc78d19 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/conv_op_builder.cc @@ -52,7 +52,6 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N NodeAttrHelper helper(node); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -89,9 +88,7 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N AddOperationOutput(*conv_op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(conv_op)); - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); auto strides = helper.Get("strides", std::vector{1, 1}); @@ -225,14 +222,11 @@ bool ConvOpBuilder::IsOpSupportedImpl(const Node& node, const OpBuilderInputPara const auto& weight_name = input_defs[1]->Name(); const auto* weight = input_params.graph_viewer.GetConstantInitializer(weight_name); -#if defined(COREML_ENABLE_MLPROGRAM) if (input_params.create_mlprogram) { // ML Program supports non-const weight, 1D, 2D and 3D. // keep to 1D and 2D for consistency with the NeuralNetwork implementation for now. // add 3D support as/when needed. - } else -#endif // defined (COREML_ENABLE_MLPROGRAM) - { + } else { if (!weight) { LOGS(logger, VERBOSE) << "The weight of Conv [" << name << "] must be a constant initializer"; return false; @@ -257,7 +251,6 @@ bool ConvOpBuilder::IsOpSupportedImpl(const Node& node, const OpBuilderInputPara NodeAttrHelper helper(node); -#if defined(COREML_ENABLE_MLPROGRAM) // spec says same_lower is supported in CoreML 5. it lies. CoreML 6 is required otherwise you get // `Unexpected value for parameter pad_type[0] "same_lower" not in ("custom", "same", "valid").` // We _could_ manually calculate the pads, but not implementing that until we have a real use case to justify @@ -269,7 +262,6 @@ bool ConvOpBuilder::IsOpSupportedImpl(const Node& node, const OpBuilderInputPara return false; } } -#endif // there's no equivalent to allow a manual kernel shape in CoreML. // it's OK if a specified kernel_shape matches kH and kW dims of the weight input. diff --git a/onnxruntime/core/providers/coreml/builders/impl/convtranspose_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/convtranspose_op_builder.cc index 5b6d9d72ab3c9..2e2c898b0e10a 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/convtranspose_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/convtranspose_op_builder.cc @@ -28,7 +28,6 @@ class ConvTransposeOpBuilder : public BaseOpBuilder { Status ConvTransposeOpBuilder::AddToModelBuilderImpl([[maybe_unused]] ModelBuilder& model_builder, [[maybe_unused]] const Node& node, const logging::Logger& /*logger*/) const { -#if defined(COREML_ENABLE_MLPROGRAM) using namespace CoreML::Specification::MILSpec; // NOLINT const auto input_defs = node.InputDefs(); const auto output_defs = node.OutputDefs(); @@ -80,7 +79,6 @@ Status ConvTransposeOpBuilder::AddToModelBuilderImpl([[maybe_unused]] ModelBuild AddOperationOutput(*op, *output_defs[0]); model_builder.AddOperation(std::move(op)); -#endif // defined(COREML_ENABLE_MLPROGRAM) return Status::OK(); } diff --git a/onnxruntime/core/providers/coreml/builders/impl/depthtospace_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/depthtospace_op_builder.cc index fec14dfd093a0..1a74b1eea97fe 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/depthtospace_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/depthtospace_op_builder.cc @@ -33,7 +33,6 @@ Status DepthToSpaceOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, NodeAttrHelper helper(node); int64_t blocksize = *helper.GetInt64("blocksize"); // required attribute -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // NOLINT @@ -105,7 +104,6 @@ Status DepthToSpaceOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, model_builder.AddOperation(std::move(reshape2)); } } else // NOLINT -#endif // if defined(COREML_ENABLE_MLPROGRAM) { const auto& output_name = output_defs[0]->Name(); std::unique_ptr layer = model_builder.CreateNNLayer(node); diff --git a/onnxruntime/core/providers/coreml/builders/impl/gemm_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/gemm_op_builder.cc index e685c09ef43ca..4f84f7c36259c 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/gemm_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/gemm_op_builder.cc @@ -33,7 +33,6 @@ void GemmOpBuilder::AddInitializersToSkip(ModelBuilder& model_builder, const Nod const auto& input_defs(node.InputDefs()); const bool is_gemm = op == "Gemm"; -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { // we have to transpose the weight input of Gemm if transB is false, and potentially override the bias shape if (is_gemm) { @@ -58,9 +57,7 @@ void GemmOpBuilder::AddInitializersToSkip(ModelBuilder& model_builder, const Nod } } } - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { // We have already embedded the weights (matrix B and C(if any)) into the coreml layer // No need to copy them later to reduce memory consumption model_builder.AddInitializerToSkip(input_defs[1]->Name()); @@ -123,7 +120,6 @@ Status GemmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N const auto K = transB ? b1 : b0; const auto N = transB ? b0 : b1; // we already checked it and dtype must be existed. -#if defined(COREML_ENABLE_MLPROGRAM) auto input_dtype = a.TypeAsProto()->tensor_type().elem_type(); if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -207,9 +203,7 @@ Status GemmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N AddOperationOutput(*matmul_op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(matmul_op)); } - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { auto* coreml_inner_product = layer->mutable_innerproduct(); *layer->mutable_input()->Add() = a.Name(); diff --git a/onnxruntime/core/providers/coreml/builders/impl/gridsample_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/gridsample_op_builder.cc index 6dcf14c16f111..f558f423752e8 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/gridsample_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/gridsample_op_builder.cc @@ -42,7 +42,6 @@ class GridSampleOpBuilder : public BaseOpBuilder { Status GridSampleOpBuilder::AddToModelBuilderImpl([[maybe_unused]] ModelBuilder& model_builder, [[maybe_unused]] const Node& node, [[maybe_unused]] const logging::Logger& logger) const { -#if defined(COREML_ENABLE_MLPROGRAM) using namespace CoreML::Specification::MILSpec; // NOLINT // https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#coremltools.converters.mil.mil.ops.defs.iOS15.image_resizing.resample @@ -80,7 +79,6 @@ Status GridSampleOpBuilder::AddToModelBuilderImpl([[maybe_unused]] ModelBuilder& AddOperationOutput(*op, *output_defs[0]); model_builder.AddOperation(std::move(op)); -#endif return Status::OK(); } diff --git a/onnxruntime/core/providers/coreml/builders/impl/normalization_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/normalization_op_builder.cc index b4dc8d1647ad0..c0db144602ee2 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/normalization_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/normalization_op_builder.cc @@ -49,7 +49,6 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl( if (node.OpType() == "GroupNormalization") { return AddGroupNormToModelBuilderImpl(model_builder, node, logger); } -#if defined(COREML_ENABLE_MLPROGRAM) const auto& input_defs = node.InputDefs(); NodeAttrHelper helper(node); const auto& scale_tensor = *model_builder.GetConstantInitializer(input_defs[1]->Name()); @@ -94,7 +93,6 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl( AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); } -#endif // (COREML_ENABLE_MLPROGRAM) return Status::OK(); } @@ -103,7 +101,6 @@ Status NormalizationOpBuilder::AddGroupNormToModelBuilderImpl( [[maybe_unused]] ModelBuilder& model_builder, [[maybe_unused]] const Node& node, [[maybe_unused]] const logging::Logger& logger) const { -#if defined(COREML_ENABLE_MLPROGRAM) const auto& input_defs = node.InputDefs(); NodeAttrHelper helper(node); // Coreml hasn't supported GroupNorm yet. @@ -184,7 +181,6 @@ Status NormalizationOpBuilder::AddGroupNormToModelBuilderImpl( model_builder.AddOperation(std::move(mul)); model_builder.AddOperation(std::move(add)); } -#endif // (COREML_ENABLE_MLPROGRAM) return Status::OK(); } diff --git a/onnxruntime/core/providers/coreml/builders/impl/pool_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/pool_op_builder.cc index 17910ba6fd486..e43eef75007cc 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/pool_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/pool_op_builder.cc @@ -29,7 +29,6 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const auto& op_type = node.OpType(); const auto& input_defs = node.InputDefs(); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -91,9 +90,7 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); auto* coreml_pool = layer->mutable_pooling(); diff --git a/onnxruntime/core/providers/coreml/builders/impl/reduction_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/reduction_op_builder.cc index d533b867bd454..a4609eb2a0584 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/reduction_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/reduction_op_builder.cc @@ -71,7 +71,6 @@ Status ReductionOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, co const bool keepdims = helper.Get("keepdims", 1) != 0; const bool noop_with_empty_axes = helper.Get("noop_with_empty_axes", 0) != 0; -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -103,9 +102,7 @@ Status ReductionOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, co AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); - } else -#endif // (COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); if (op_type == "ReduceSum") { diff --git a/onnxruntime/core/providers/coreml/builders/impl/reshape_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/reshape_op_builder.cc index 27d24d9c21893..b35d6971623ed 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/reshape_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/reshape_op_builder.cc @@ -50,7 +50,6 @@ Status ReshapeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // ReshapeHelper applies the ONNX rules to create the concrete output shape ReshapeHelper helper(TensorShape(input_shape), new_shape); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -64,9 +63,7 @@ Status ReshapeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, AddOperationOutput(*reshape_op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(reshape_op)); - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); *layer->mutable_reshapestatic()->mutable_targetshape() = {new_shape.cbegin(), new_shape.cend()}; diff --git a/onnxruntime/core/providers/coreml/builders/impl/resize_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/resize_op_builder.cc index 7ff66e4a79e37..837573003e515 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/resize_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/resize_op_builder.cc @@ -212,7 +212,6 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const num_sizes = output_sizes.size(); } -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // NOLINT @@ -279,9 +278,7 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const AddOperationOutput(*op, *output_defs[0]); model_builder.AddOperation(std::move(op)); - } else // NOLINT -#endif - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); auto* coreml_upsample = layer->mutable_upsample(); diff --git a/onnxruntime/core/providers/coreml/builders/impl/shape_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/shape_op_builder.cc index 243f949bdd48e..d1c87b033d323 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/shape_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/shape_op_builder.cc @@ -25,7 +25,6 @@ Status ShapeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const const logging::Logger& /*logger*/) const { const auto& input_defs = node.InputDefs(); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; NodeAttrHelper node_attr_helper{node}; @@ -63,9 +62,7 @@ Status ShapeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const AddOperationOutput(*op, *node.OutputDefs()[0], output_datatype); model_builder.AddOperation(std::move(op)); } - } else // NOLINT -#endif - { + } else { auto layer = model_builder.CreateNNLayer(node); layer->mutable_getshape(); *layer->mutable_input()->Add() = input_defs[0]->Name(); diff --git a/onnxruntime/core/providers/coreml/builders/impl/slice_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/slice_op_builder.cc index 6b3fe75fa592d..368e47e40f831 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/slice_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/slice_op_builder.cc @@ -127,7 +127,6 @@ Status SliceOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const SliceOp::PrepareForComputeMetadata compute_metadata{data_shape}; ORT_RETURN_IF_ERROR(PrepareSliceComputeMetadata(node, model_builder.GetGraphViewer(), compute_metadata)); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; // NOLINT // https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#coremltools.converters.mil.mil.ops.defs.iOS15.tensor_transformation.slice_by_index @@ -178,9 +177,7 @@ Status SliceOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const model_builder.AddOperation(std::move(op)); - } else // NOLINT -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { auto layer = model_builder.CreateNNLayer(node); *layer->mutable_input()->Add() = input_defs[0]->Name(); *layer->mutable_output()->Add() = output_defs[0]->Name(); @@ -222,7 +219,6 @@ bool SliceOpBuilder::HasSupportedInputsImpl(const Node& node, return false; } -#ifdef COREML_ENABLE_MLPROGRAM // The [Doc](https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html#coremltools.converters.mil.mil.ops.defs.iOS15.tensor_transformation.slice_by_index) // says ML Program slice_by_index supports fp16 in CoreML 5 (iOS 15). // It's incorrect and CoreML 6+ (iOS16, CoreML spec version >= 7) is required otherwise only float is supported. @@ -230,13 +226,11 @@ bool SliceOpBuilder::HasSupportedInputsImpl(const Node& node, // CoreML 6:https://github.com/apple/coremltools/blob/c3ea4cf56fef1176417246c1b85363417f3e713d/coremltools/converters/mil/mil/ops/defs/iOS15/tensor_transformation.py#L495 if (input_params.create_mlprogram && input_params.coreml_version >= 6 && input_type == ONNX_NAMESPACE::TensorProto_DataType_FLOAT16) { - } else -#endif // nolint - if (input_type != ONNX_NAMESPACE::TensorProto_DataType_FLOAT && - input_type != ONNX_NAMESPACE::TensorProto_DataType_INT64) { - LOGS(logger, VERBOSE) << "[" << node.OpType() << "] Input type: [" << input_type << "] is not supported"; - return false; - } + } else if (input_type != ONNX_NAMESPACE::TensorProto_DataType_FLOAT && + input_type != ONNX_NAMESPACE::TensorProto_DataType_INT64) { + LOGS(logger, VERBOSE) << "[" << node.OpType() << "] Input type: [" << input_type << "] is not supported"; + return false; + } return true; } diff --git a/onnxruntime/core/providers/coreml/builders/impl/softmax_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/softmax_op_builder.cc index c6e331feed326..2411cd459fecd 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/softmax_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/softmax_op_builder.cc @@ -37,7 +37,6 @@ Status SoftmaxOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const auto axis = helper.Get("axis", axis_default_value); auto axis_nonnegative = HandleNegativeAxis(axis, data_shape.size()); -#if defined(COREML_ENABLE_MLPROGRAM) // CoreML's softmax match onnx's softmax behavior since opset 13. // For opset < 13, we need to reshape to 2D and set axis to -1 to simulate onnx softmax behavior. // [B,D,...](onnx softmax opset 12, axis=1)->[B,D*...](CoreML softmax, axis=-1)->[B,D,...](reshape back) @@ -78,9 +77,7 @@ Status SoftmaxOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, AddOperationOutput(*reshape2, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(reshape2)); } - } else // NOLINT -#endif - { + } else { if (node.SinceVersion() >= 13 || (data_shape.size() == 2)) { auto* coreml_softmaxnd = layer->mutable_softmaxnd(); coreml_softmaxnd->set_axis(axis); diff --git a/onnxruntime/core/providers/coreml/builders/impl/split_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/split_op_builder.cc index 6372f3136123b..717d344982473 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/split_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/split_op_builder.cc @@ -56,7 +56,6 @@ Status SplitOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, return std::make_tuple(remainder, chunk_size); }; -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; std::unique_ptr split_op = model_builder.CreateOperation(node, "split"); @@ -95,9 +94,7 @@ Status SplitOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } model_builder.AddOperation(std::move(split_op)); - } else -#endif - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); auto* coreml_splitnd = layer->mutable_splitnd(); coreml_splitnd->set_axis(axis); diff --git a/onnxruntime/core/providers/coreml/builders/impl/squeeze_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/squeeze_op_builder.cc index a1b3a18265c70..81bef11906b74 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/squeeze_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/squeeze_op_builder.cc @@ -58,7 +58,6 @@ void SqueezeOpBuilder::AddInitializersToSkip(ModelBuilder& model_builder, const } } -#if defined(COREML_ENABLE_MLPROGRAM) void HandleX86ArchUnsqueezeScalarInput(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) { const auto& input_defs(node.InputDefs()); @@ -74,7 +73,6 @@ void HandleX86ArchUnsqueezeScalarInput(ModelBuilder& model_builder, AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); } -#endif Status SqueezeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, @@ -83,7 +81,7 @@ Status SqueezeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, auto* coreml_squeeze = layer->mutable_squeeze(); TensorShapeVector axes; GetAxes(model_builder, node, axes); -#if defined(COREML_ENABLE_MLPROGRAM) + const auto& input_defs(node.InputDefs()); if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -105,9 +103,7 @@ Status SqueezeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); - } else // NOLINT -#endif - { + } else { if (axes.empty()) { coreml_squeeze->set_squeezeall(true); } else { diff --git a/onnxruntime/core/providers/coreml/builders/impl/transpose_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/transpose_op_builder.cc index 831c4cf4d08ba..5bb7e4c11967a 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/transpose_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/transpose_op_builder.cc @@ -34,7 +34,6 @@ Status TransposeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, ORT_RETURN_IF_NOT(perm.size() == input_dims, "Perm and input should have same dimension"); } -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -44,9 +43,7 @@ Status TransposeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); - } else -#endif // defined(COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); *layer->mutable_transpose()->mutable_axes() = {perm.cbegin(), perm.cend()}; diff --git a/onnxruntime/core/providers/coreml/builders/impl/unary_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/unary_op_builder.cc index bc3cad004aec1..dd495894ab8bb 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/unary_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/unary_op_builder.cc @@ -25,7 +25,6 @@ Status UnaryOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const const auto& op_type(node.OpType()); const auto& input_defs(node.InputDefs()); -#if defined(COREML_ENABLE_MLPROGRAM) if (model_builder.CreateMLProgram()) { using namespace CoreML::Specification::MILSpec; @@ -58,9 +57,7 @@ Status UnaryOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const AddOperationOutput(*op, *node.OutputDefs()[0]); model_builder.AddOperation(std::move(op)); - } else // NOLINT -#endif // defined (COREML_ENABLE_MLPROGRAM) - { + } else { std::unique_ptr layer = model_builder.CreateNNLayer(node); if (op_type == "Sqrt") { diff --git a/onnxruntime/core/providers/coreml/builders/model_builder.cc b/onnxruntime/core/providers/coreml/builders/model_builder.cc index f8952301d59a9..3551f5759201e 100644 --- a/onnxruntime/core/providers/coreml/builders/model_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/model_builder.cc @@ -17,20 +17,17 @@ #include "core/providers/coreml/shape_utils.h" #include "core/optimizer/initializer.h" -#if defined(COREML_ENABLE_MLPROGRAM) // includes from coremltools-src in _deps #include "modelpackage/src/ModelPackage.hpp" #include "mlmodel/src/MILBlob/Blob/StorageWriter.hpp" using MILBlob::Blob::StorageWriter; -#endif - using namespace CoreML::Specification; namespace onnxruntime { namespace coreml { namespace { -#if defined(COREML_ENABLE_MLPROGRAM) + // Should the initializer be written to file or kept as an immediate value bool ShouldWriteInitializerToWeightsFile(const ONNX_NAMESPACE::TensorProto& tensor_proto) { // https://github.com/apple/coremltools/blob/dbb0094fd0cb936469e35320bf37e866ef7a1da4/coremltools/converters/mil/backend/mil/load.py#L51-L57 @@ -388,8 +385,6 @@ void CreateEmptyFile(const std::string& filename) { ORT_ENFORCE(file.is_open(), "Failed to open file ", filename); } -#endif // defined(COREML_ENABLE_MLPROGRAM) - std::string GetModelOutputPath(const CoreMLOptions& coreml_options, const GraphViewer& graph_viewer, const logging::Logger& logger) { @@ -479,7 +474,6 @@ ModelBuilder::ModelBuilder(const GraphViewer& graph_viewer, const logging::Logge } if (create_ml_program_) { -#if defined(COREML_ENABLE_MLPROGRAM) coreml_model_->set_specificationversion(CoreMLSpecVersion()); MILSpec::Program& mlprogram = *coreml_model_->mutable_mlprogram(); mlprogram.set_version(1); @@ -503,12 +497,6 @@ ModelBuilder::ModelBuilder(const GraphViewer& graph_viewer, const logging::Logge "CoreML Model Weights"); auto weights_info = mlpackage_->findItem(weights_id); weights_file_writer_ = std::make_unique(weights_info->path() + "/weight.bin"); -#else - // should never happen due to handling in coreml_execution_provider.cc - // throw here so all other code in this class can assume create_ml_program_ is only ever true in a build - // where ML Program support is enabled. - ORT_THROW("ML Program is not enabled in this build"); -#endif } else { // We support CorelML Specification Version 4 (Core ML 3) coreml_model_->set_specificationversion(4); @@ -561,7 +549,6 @@ void ModelBuilder::AddLayer(std::unique_ptr layer) { /* * ML Program related helpers */ -#if defined(COREML_ENABLE_MLPROGRAM) const std::string& ModelBuilder::GetSafeName(const std::string& name) { // Check the name is valid according to the MILSpec rules // `Identifiers, generally used for names and keys, must match the regular expression [A-Za-z\_][A-Za-z0-9\_@]*.` @@ -737,8 +724,6 @@ std::string_view ModelBuilder::AddConstantImpl(std::string_view op_type, std::st return AddTensorValueAsConstantOperation(op_type, value_type, std::move(input_value)); } -#endif // defined(COREML_ENABLE_MLPROGRAM) - /* * General implementation */ @@ -775,13 +760,10 @@ Status ModelBuilder::RegisterInitializers() { continue; } -#if defined(COREML_ENABLE_MLPROGRAM) if (create_ml_program_) { MILSpec::Value coreml_tensor = OnnxTensorToCoreMLTensor(tensor, *weights_file_writer_); ORT_IGNORE_RETURN_VALUE(AddConstantOperation(name, std::move(coreml_tensor))); - } else -#endif - { + } else { std::unique_ptr layer = std::make_unique(); layer->set_name(GetUniqueName("initializer_" + name)); @@ -915,7 +897,6 @@ Status ModelBuilder::RegisterModelInputOutput(const NodeArg& node_arg, bool is_i return Status::OK(); } -#if defined(COREML_ENABLE_MLPROGRAM) if (create_ml_program_) { if (is_input) { // the model inputs need to be wired up as args to the 'main' function. @@ -935,7 +916,6 @@ Status ModelBuilder::RegisterModelInputOutput(const NodeArg& node_arg, bool is_i *mlprogram_main_block_->mutable_outputs()->Add() = name; } } -#endif // defined(COREML_ENABLE_MLPROGRAM) return Status::OK(); } @@ -980,11 +960,9 @@ Status ModelBuilder::CreateModel() { ORT_RETURN_IF_ERROR(ProcessNodes()); ORT_RETURN_IF_ERROR(RegisterModelOutputs()); -#if defined(COREML_ENABLE_MLPROGRAM) if (create_ml_program_) { SanitizeNames(); } -#endif return Status::OK(); } @@ -992,7 +970,6 @@ Status ModelBuilder::CreateModel() { Status ModelBuilder::SaveModel() { std::string output_path = model_output_path_; -#if defined(COREML_ENABLE_MLPROGRAM) if (create_ml_program_) { // we need to jump through some hoops to get the model path the ML Program load wants. std::string tmp_model_path = model_output_path_ + "/tmp/model.mlmodel"; @@ -1003,7 +980,6 @@ Status ModelBuilder::SaveModel() { auto model_info = mlpackage_->findItem(model_id); output_path = model_info->path(); } -#endif // scope this so the stream is closed and flushed by the ofstream dtor { @@ -1012,19 +988,16 @@ Status ModelBuilder::SaveModel() { ORT_RETURN_IF_NOT(coreml_model_->SerializeToOstream(&stream), "Saving the CoreML model failed. Path=", output_path); } -#if defined(COREML_ENABLE_MLPROGRAM) // need to delete the ModelPackage instance for it to write out the manifest. clear out the other ML Program // related types as well. mlprogram_main_block_ = nullptr; mlpackage_.reset(); weights_file_writer_.reset(); -#endif return Status::OK(); } Status ModelBuilder::LoadModel(std::unique_ptr& model) { -#if defined(COREML_ENABLE_MLPROGRAM) if (create_ml_program_) { // we need to provide the sanitized names for model inputs/outputs so that info is captured. // the input/output matching when we execute the model from the CoreML EP is based on order, so the change @@ -1058,9 +1031,7 @@ Status ModelBuilder::LoadModel(std::unique_ptr& model) { std::move(scalar_outputs_), std::move(int64_outputs_), logger_, coreml_options_); - } else -#endif - { + } else { model = std::make_unique(model_output_path_, std::move(onnx_input_names_), std::move(onnx_output_names_), @@ -1073,7 +1044,6 @@ Status ModelBuilder::LoadModel(std::unique_ptr& model) { return model->LoadModel(); // load using CoreML API, including compilation } -#if defined(COREML_ENABLE_MLPROGRAM) std::string_view ModelBuilder::AddConstant(std::string_view op_type, std::string_view value_type, const ONNX_NAMESPACE::TensorProto& tensor, std::optional> shape) { @@ -1114,7 +1084,6 @@ std::string_view ModelBuilder::AddConstant(std::string_view op_type, std::string return ret; } -#endif // static Status ModelBuilder::Build(const GraphViewer& graph_viewer, const logging::Logger& logger, int32_t coreml_version, const CoreMLOptions& coreml_options, diff --git a/onnxruntime/core/providers/coreml/builders/model_builder.h b/onnxruntime/core/providers/coreml/builders/model_builder.h index 28c7dc42da581..f3012e8137e8c 100644 --- a/onnxruntime/core/providers/coreml/builders/model_builder.h +++ b/onnxruntime/core/providers/coreml/builders/model_builder.h @@ -9,7 +9,6 @@ #include "core/providers/coreml/model/model.h" #include "core/providers/coreml/coreml_options.h" -#if defined(COREML_ENABLE_MLPROGRAM) // coremltools classes namespace MPL { class ModelPackage; @@ -20,7 +19,6 @@ namespace Blob { class StorageWriter; } } // namespace MILBlob -#endif namespace onnxruntime { namespace coreml { @@ -58,11 +56,7 @@ class ModelBuilder { // Returns true if we are creating an ML Program bool CreateMLProgram() const { -#if defined(COREML_ENABLE_MLPROGRAM) return create_ml_program_; -#else - return false; -#endif } /* @@ -76,7 +70,6 @@ class ModelBuilder { // Add layer to the Core ML NeuralNetwork model void AddLayer(std::unique_ptr layer); -#if defined(COREML_ENABLE_MLPROGRAM) /* * MLProgram helpers */ @@ -147,7 +140,6 @@ class ModelBuilder { // add the operation to the main function void AddOperation(std::unique_ptr operation); -#endif /* * General helpers @@ -176,7 +168,6 @@ class ModelBuilder { const logging::Logger& Logger() const { return logger_; } private: -#if defined(COREML_ENABLE_MLPROGRAM) template std::string_view AddConstantImpl(std::string_view op_type, std::string_view value_type, gsl::span value, std::optional> shape = std::nullopt); @@ -190,7 +181,6 @@ class ModelBuilder { const std::string& AddConstantOperation(std::string_view name, COREML_SPEC::MILSpec::Value&& initializer); const std::string& AddTensorValueAsConstantOperation(std::string_view op_type, std::string_view value_type, COREML_SPEC::MILSpec::Value&& input_value); -#endif // Convert the ONNX model in graph_viewer_ to a CoreML::Specification::Model and serialize to disk. // We then load it using CoreML in order compile it. @@ -237,7 +227,6 @@ class ModelBuilder { uint32_t name_token_{0}; std::unordered_set unique_names_; -#if defined(COREML_ENABLE_MLPROGRAM) // mlprogram_main_ is the main block of the CoreML ML Program. // It is set in CreateModel to the CoreML Model.mlprogram.functions['main'].block_specializations['CoreML'] // entry we create. @@ -254,7 +243,6 @@ class ModelBuilder { // This means an op builder author doesn't need to be aware of the renaming. // https://github.com/apple/coremltools/blob/8b37641f243b1a3e81452feea311c6e30dcc9287/coremltools/converters/mil/mil/passes/defs/preprocess.py#L146-L149 std::unordered_map values_to_rename_; -#endif }; } // namespace coreml diff --git a/onnxruntime/core/providers/coreml/coreml_options.cc b/onnxruntime/core/providers/coreml/coreml_options.cc index 14ae55de9266b..c441a2eff56e0 100644 --- a/onnxruntime/core/providers/coreml/coreml_options.cc +++ b/onnxruntime/core/providers/coreml/coreml_options.cc @@ -15,18 +15,6 @@ CoreMLOptions::CoreMLOptions(uint32_t coreml_flags) { create_mlprogram_ = (coreml_flags & COREML_FLAG_CREATE_MLPROGRAM) != 0; enable_on_subgraph_ = (coreml_flags & COREML_FLAG_ENABLE_ON_SUBGRAPH) != 0; -#if defined(COREML_ENABLE_MLPROGRAM) - if (coreml::util::CoreMLVersion() < MINIMUM_COREML_MLPROGRAM_VERSION && create_mlprogram_ != 0) { - LOGS_DEFAULT(WARNING) << "ML Program is not supported on this OS version. Falling back to NeuralNetwork."; - create_mlprogram_ = false; - } -#else - if (create_mlprogram_ != 0) { - LOGS_DEFAULT(WARNING) << "ML Program is not supported in this build. Falling back to NeuralNetwork."; - create_mlprogram_ = false; - } -#endif - compute_units_ = 0; // 0 for all if (coreml_flags & COREML_FLAG_USE_CPU_ONLY) { diff --git a/onnxruntime/core/providers/coreml/model/host_utils.h b/onnxruntime/core/providers/coreml/model/host_utils.h index 31ee2bd3e2494..f654b4d5701b9 100644 --- a/onnxruntime/core/providers/coreml/model/host_utils.h +++ b/onnxruntime/core/providers/coreml/model/host_utils.h @@ -60,8 +60,7 @@ #endif -#define MINIMUM_COREML_VERSION 3 // first version we support -#define MINIMUM_COREML_MLPROGRAM_VERSION 5 // first version where ML Program was available +#define MINIMUM_COREML_VERSION 5 // first version we support namespace onnxruntime { namespace coreml { diff --git a/onnxruntime/core/providers/xnnpack/nn/max_pool.cc b/onnxruntime/core/providers/xnnpack/nn/max_pool.cc index c828ae9400174..8d972f7d63bc1 100644 --- a/onnxruntime/core/providers/xnnpack/nn/max_pool.cc +++ b/onnxruntime/core/providers/xnnpack/nn/max_pool.cc @@ -57,7 +57,7 @@ bool MaxPool::IsOnnxNodeSupported(const NodeUnit& node_unit, // input of maxpool could be fp16/fp32/fp64,i8/u8 according to ONNX if (x_type == nullptr || (x_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType_FLOAT && -// because pool_fp16_op_test can be enabled by other preprocessor, for example, COREML_ENABLE_MLPROGRAM +// because pool_fp16_op_test can be enabled by other preprocessor, for example, USE_COREML #ifdef XNNPACK_FP16_SUPPORTED x_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType_FLOAT16 && #endif diff --git a/onnxruntime/test/contrib_ops/layer_norm_op_test.cc b/onnxruntime/test/contrib_ops/layer_norm_op_test.cc index 4611dc9082734..e22445edc0f5b 100644 --- a/onnxruntime/test/contrib_ops/layer_norm_op_test.cc +++ b/onnxruntime/test/contrib_ops/layer_norm_op_test.cc @@ -404,7 +404,7 @@ TYPED_TEST(LayerNormTest, LayerNorm17_opset) { // Execution provider entry invalid. // when other EPs support layer-norm fp16, this test should be updated to include them. if (std::is_same::value) { -#if !defined(COREML_ENABLE_MLPROGRAM) +#if !defined(USE_COREML) return; #endif } diff --git a/onnxruntime/test/providers/coreml/coreml_basic_test.cc b/onnxruntime/test/providers/coreml/coreml_basic_test.cc index a9aa78b7a3229..3505193b77683 100644 --- a/onnxruntime/test/providers/coreml/coreml_basic_test.cc +++ b/onnxruntime/test/providers/coreml/coreml_basic_test.cc @@ -246,7 +246,7 @@ TEST(CoreMLExecutionProviderTest, TestOrtFormatModel) { #endif } -#if defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_COREML) // Names in CoreML cannot start with [0-9] or contain anything but "[a-z][A-Z][0-9]_" // Test that we fix invalid names in model inputs, initializers and outputs. // This is only enforced for ML Program, so we only do name sanitization when creating an ML Program format model. diff --git a/onnxruntime/test/providers/cpu/activation/activation_op_test.cc b/onnxruntime/test/providers/cpu/activation/activation_op_test.cc index 724118d7419d2..9201da348e75c 100644 --- a/onnxruntime/test/providers/cpu/activation/activation_op_test.cc +++ b/onnxruntime/test/providers/cpu/activation/activation_op_test.cc @@ -125,7 +125,7 @@ TEST_F(ActivationOpTest, Relu) { {}, {}, /*is_tensorrt_supported=*/false, /*opset_version= */ 14); -#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) TestActivationOp( "Relu", input_values_fp16, @@ -139,7 +139,7 @@ TEST_F(ActivationOpTest, Relu) { #endif // MLAS_F16VEC_INTRINSICS_SUPPORTED } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST_F(ActivationOpTest, Sigmoid_fp16) { #ifdef USE_CUDA int min_cuda_architecture = 530; @@ -413,7 +413,7 @@ TEST_F(ActivationOpTest, LeakyRelu) { {{"alpha", alpha}}, {}); } -#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) TEST_F(ActivationOpTest, LeakyRelu_fp16) { OpTester test("LeakyRelu", 11); float alpha = 0.01f; // oneDNN set alpha equal to 0.01 diff --git a/onnxruntime/test/providers/cpu/activation/activation_op_test.h b/onnxruntime/test/providers/cpu/activation/activation_op_test.h index 59813f433dc41..04d116e29d3b0 100644 --- a/onnxruntime/test/providers/cpu/activation/activation_op_test.h +++ b/onnxruntime/test/providers/cpu/activation/activation_op_test.h @@ -105,7 +105,7 @@ class ActivationOpTest : public ::testing::Test { std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution dist(low, high); -#ifdef COREML_ENABLE_MLPROGRAM +#ifdef USE_COREML // please check onnxruntime/onnxruntime/core/providers/coreml/builders/helper.cc:81 std::vector batch_size_list = {1, 2, 4, 9, 100}; #else diff --git a/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc b/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc index 30e7f63919216..fbd9d10a56c77 100644 --- a/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc +++ b/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc @@ -32,7 +32,7 @@ void TestBinaryFloat16(const char* op_name, bool enable_bf16 = true) { { std::vector> execution_providers; -#ifdef COREML_ENABLE_MLPROGRAM +#ifdef USE_COREML execution_providers.push_back(DefaultCoreMLExecutionProvider(true)); #elif USE_CUDA execution_providers.push_back(DefaultCudaExecutionProvider()); @@ -76,7 +76,7 @@ void TestUnaryFloat16(const char* op_name, bool run_bf16 = true) { { std::vector> execution_providers; -#ifdef COREML_ENABLE_MLPROGRAM +#ifdef USE_COREML execution_providers.push_back(DefaultCoreMLExecutionProvider(true)); #elif USE_CUDA execution_providers.push_back(DefaultCudaExecutionProvider()); @@ -1426,7 +1426,7 @@ TEST(MathOpTest, Pow_float16_float16) { dims, {1.0f, 256.0f, 2.0f, 1.0f}, false); } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST(MathOpTest, Pow_float_float16) { OpTester test("Pow", 12); std::vector dims{4}; @@ -1440,7 +1440,7 @@ TEST(MathOpTest, Pow_float_float16) { execution_providers.push_back(DefaultCudaExecutionProvider()); #elif USE_ROCM execution_providers.push_back(DefaultRocmExecutionProvider()); -#elif COREML_ENABLE_MLPROGRAM +#elif USE_COREML execution_providers.push_back(DefaultCoreMLExecutionProvider(true)); #endif test.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); diff --git a/onnxruntime/test/providers/cpu/math/matmul_test.cc b/onnxruntime/test/providers/cpu/math/matmul_test.cc index 298e870f348fc..dd8cbed15e5ef 100644 --- a/onnxruntime/test/providers/cpu/math/matmul_test.cc +++ b/onnxruntime/test/providers/cpu/math/matmul_test.cc @@ -210,7 +210,7 @@ TEST(MathOpTest, MatMulFloatType) { RunMatMulTest(7, false, true); } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) || defined(USE_XNNPACK) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) || defined(USE_XNNPACK) TEST(MathOpTest, MatMulFloat16) { #ifdef USE_CUDA int min_cuda_architecture = 530; @@ -276,7 +276,7 @@ TEST(MathOpTest, MatMulZeroKInt32Type) { RunMatMulZeroKTest(); } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) || defined(USE_XNNPACK) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) || defined(USE_XNNPACK) TEST(MathOpTest, MatMul_Float16) { #ifdef USE_CUDA int min_cuda_architecture = 530; diff --git a/onnxruntime/test/providers/cpu/nn/batch_norm_op_test.cc b/onnxruntime/test/providers/cpu/nn/batch_norm_op_test.cc index f8ebca5ff9a1b..a529d572d7cca 100644 --- a/onnxruntime/test/providers/cpu/nn/batch_norm_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/batch_norm_op_test.cc @@ -704,7 +704,7 @@ TEST(BatchNormTest, NonSpatial_Complicated) { } // Only CUDA and ROCm kernels have float 16 support -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST(BatchNormTest, BatchNorm2d_fp16) { vector X{-0.91221f, -0.283559f, 0.937637f, 2.09818f, -0.100199f, -0.608113f, 0.444562f, -1.07505f, 0.940591f, -0.922262f, 0.0931303f, 0.69611f, 1.55187f, 0.159808f, 0.914874f, -1.24856f, -1.98928f, -0.331621f, diff --git a/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc b/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc index 4253e36e02548..d1350db8ec12e 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc @@ -3,7 +3,7 @@ #include "core/mlas/inc/mlas.h" -#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(COREML_ENABLE_MLPROGRAM) || defined(USE_XNNPACK) +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) || defined(USE_XNNPACK) #include "gtest/gtest.h" #include "test/providers/provider_test_utils.h" @@ -30,7 +30,7 @@ struct ConvOpAndTestAttributes { /* Please notice that, we have predefined macros in the head of the file -#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) When we have these two macro defines, this UT will turn into green light and work. If attributes.activation is set the NhwcFusedConv contrib op is used. diff --git a/onnxruntime/test/providers/cpu/nn/group_norm_op_test.cc b/onnxruntime/test/providers/cpu/nn/group_norm_op_test.cc index ac517193a2c77..3d8d188867023 100644 --- a/onnxruntime/test/providers/cpu/nn/group_norm_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/group_norm_op_test.cc @@ -6,7 +6,7 @@ #include "test/common/tensor_op_test_utils.h" #include "test/util/include/default_providers.h" -#ifdef COREML_ENABLE_MLPROGRAM +#ifdef USE_COREML using namespace std; namespace onnxruntime { namespace test { diff --git a/onnxruntime/test/providers/cpu/nn/instance_norm_op_test.cc b/onnxruntime/test/providers/cpu/nn/instance_norm_op_test.cc index 341bb8a4fc957..46b74f2c2eb9d 100644 --- a/onnxruntime/test/providers/cpu/nn/instance_norm_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/instance_norm_op_test.cc @@ -121,7 +121,7 @@ TEST(InstanceNormalizationOpTest, InstanceNormBatch2) { } // Only CUDA and ROCm kernels have float 16 support -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST(InstanceNormalizationOpTest, InstanceNormBatch1_fp16) { OpTester test("InstanceNormalization"); diff --git a/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc b/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc index d4e0af5011525..c14fc1fb62ae5 100644 --- a/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc @@ -3,7 +3,7 @@ #include "core/mlas/inc/mlas.h" -#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(COREML_ENABLE_MLPROGRAM) || defined(USE_XNNPACK) +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) || defined(USE_XNNPACK) #include "core/providers/cpu/nn/pool.h" #include "gtest/gtest.h" diff --git a/onnxruntime/test/providers/cpu/nn/pool_op_test.cc b/onnxruntime/test/providers/cpu/nn/pool_op_test.cc index 24a8c8491b632..f1d612276174f 100644 --- a/onnxruntime/test/providers/cpu/nn/pool_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/pool_op_test.cc @@ -70,7 +70,7 @@ TEST(PoolTest, MaxPool) { // Only CUDA kernel has float 16 support // Disable for now, still investigating the issue with cudnn lib -#if defined(USE_CUDA) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_COREML) TEST(PoolTest, MaxPool_F16) { #if defined(USE_CUDA) int min_cuda_architecture = 530; diff --git a/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc b/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc index 4bc97d035c7f7..92cd82c2c9420 100644 --- a/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc +++ b/onnxruntime/test/providers/cpu/reduction/reduction_ops_test.cc @@ -1375,7 +1375,7 @@ TEST(ReductionOpTest, ReduceMax_double) { test.Run(); } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST(ReductionOpTest, ReduceMax_half) { OpTester test("ReduceMax"); test.AddAttribute("axes", std::vector{1, 2}); @@ -2158,7 +2158,7 @@ TEST(ReductionOpTest, ReduceMin_double) { test.Run(); } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST(ReductionOpTest, ReduceMin_half) { OpTester test("ReduceMin"); test.AddAttribute("axes", std::vector{0, 2}); @@ -2356,7 +2356,7 @@ TEST(ReductionOpTest, ReduceSum_int32) { test.Run(); } -#if defined(USE_CUDA) || defined(USE_ROCM) || defined(COREML_ENABLE_MLPROGRAM) +#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_COREML) TEST(ReductionOpTest, ReduceSumHalfHalf) { OpTester test("ReduceSum"); test.AddAttribute("keepdims", (int64_t)0); From b626409ee4ef0e659fb16461b96d4a1d266933c3 Mon Sep 17 00:00:00 2001 From: Guenther Schmuelling Date: Wed, 19 Mar 2025 09:52:26 -0700 Subject: [PATCH 124/266] webgpu ep support for argmax/argmin (#24089) --- .../webgpu/reduction/reduction_ops.cc | 33 ++++++++++++++++++- .../webgpu/reduction/reduction_ops.h | 12 +++++++ .../webgpu/webgpu_execution_provider.cc | 24 +++++++------- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index a0213f63494d3..9548386ded06c 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -91,6 +91,14 @@ REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSumExp, 11, 12); REGISTER_REDUCE_VERSIONED_KERNEL(ReduceLogSumExp, 13, 17); REGISTER_REDUCE_KERNEL(ReduceLogSumExp, 18); +REGISTER_REDUCE_VERSIONED_KERNEL(ArgMax, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ArgMax, 11, 12); +REGISTER_REDUCE_KERNEL(ArgMax, 13); + +REGISTER_REDUCE_VERSIONED_KERNEL(ArgMin, 1, 10); +REGISTER_REDUCE_VERSIONED_KERNEL(ArgMin, 11, 12); +REGISTER_REDUCE_KERNEL(ArgMin, 13); + Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); if (is_input_empty_) { @@ -114,6 +122,9 @@ Status ReduceKernelProgram::GenerateShaderCode(ShaderHelper& shader) const { std::stringstream ss; std::string index = "i" + std::to_string(i); ss << "for (var " << index << " : u32 = 0; " << index << " < " << input.IndicesGet("uniforms.input_shape", i) << "; " << index << "++) {\n"; + if (loop_body.find("last_index") != std::string::npos) { + ss << "let last_index = " + index + ";\n"; + } ss << input.IndicesSet("input_indices", i, index) << ";\n"; ss << loop_body << "\n"; ss << "}\n"; @@ -337,5 +348,25 @@ ReduceOpSpecificCode ReduceLogSumExp::GetOpSpecificCode(const Tensor* input_tens return code; } +ReduceOpSpecificCode ArgMin::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string op = (select_last_index_) ? "<=" : "<"; + std::string loop_header = "var best_element = first_element; var best_index = u32(0);"; + std::string loop_body = "if (current_element " + op + " best_element) { best_element = current_element; best_index = last_index; };"; + std::string loop_footer = "let output_value = output_value_t(best_index);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} + +ReduceOpSpecificCode ArgMax::GetOpSpecificCode(const Tensor* input_tensor) const { + ORT_UNUSED_PARAMETER(input_tensor); + std::string op = (select_last_index_) ? ">=" : ">"; + std::string loop_header = "var best_element = first_element; var best_index = u32(0);"; + std::string loop_body = "if (current_element " + op + " best_element) { best_element = current_element; best_index = last_index; };"; + std::string loop_footer = "let output_value = output_value_t(best_index);"; + ReduceOpSpecificCode code({loop_header, loop_body, loop_footer}); + return code; +} + } // namespace webgpu -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h index 291d931f41c05..70ae6d3c71eb9 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h @@ -119,5 +119,17 @@ class ReduceLogSumExp final : public ReduceKernel { ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; }; +class ArgMin final : public ReduceKernel { + public: + ArgMin(const OpKernelInfo& info) : ReduceKernel(info, "ArgMin", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + +class ArgMax final : public ReduceKernel { + public: + ArgMax(const OpKernelInfo& info) : ReduceKernel(info, "ArgMax", true) {} + ReduceOpSpecificCode GetOpSpecificCode(const Tensor* input_tensor) const override; +}; + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index dfb2e4b6ce665..6f81bead5e5b1 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -297,12 +297,12 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 12, MatMul); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, MatMul); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, float, ArgMax); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, float, ArgMax); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, float, ArgMax); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, float, ArgMin); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, float, ArgMin); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, float, ArgMin); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, ArgMax); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, ArgMax); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, ArgMax); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, ArgMin); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, ArgMin); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, ArgMin); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, Softmax); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, Softmax); @@ -624,13 +624,13 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, From d8ed4da1dfee781919247d9ce001f246489c8f90 Mon Sep 17 00:00:00 2001 From: Caroline Zhu Date: Wed, 19 Mar 2025 10:30:44 -0700 Subject: [PATCH 125/266] [mobile/reactnative] Remove namespace from AndroidManifest.XML to resolve warning (#23847) ### Description Removes namespace from AndroidManifest.XML ### Motivation and Context - Resolves #21681 --- js/react_native/android/src/main/AndroidManifest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/react_native/android/src/main/AndroidManifest.xml b/js/react_native/android/src/main/AndroidManifest.xml index c6e3cb45e16e5..a2f47b6057db7 100644 --- a/js/react_native/android/src/main/AndroidManifest.xml +++ b/js/react_native/android/src/main/AndroidManifest.xml @@ -1,3 +1,2 @@ - + From 80441e4ec8a3bc9e74eb251ffac4b9456ba0b5f3 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 19 Mar 2025 11:03:14 -0700 Subject: [PATCH 126/266] [WebGPU EP] fix implementation of Pow (#24088) ### Description Use custom implementation for Pow to fix test failures. --- .../webgpu/math/binary_elementwise_ops.cc | 37 +++++++++++++++++-- .../webgpu/math/binary_elementwise_ops.h | 16 ++++++-- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc index 13004af25726d..6891b8159b090 100644 --- a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc @@ -4,15 +4,18 @@ #include "core/providers/common.h" #include "core/providers/webgpu/math/binary_elementwise_ops.h" #include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/string_macros.h" #include "core/providers/webgpu/webgpu_supported_types.h" namespace onnxruntime { namespace webgpu { Status BinaryElementwiseProgram::GenerateShaderCode(ShaderHelper& shader) const { - const auto& a = shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); - const auto& b = shader.AddInput("input_b", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + const auto& a = shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& b = shader.AddInput("input_b", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); const auto& c = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + shader.AdditionalImplementation() << additional_impl_; + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size"); // check whether can use element-wise mode. @@ -142,8 +145,15 @@ Status BinaryElementwise::ComputeInternal(ComputeContext& context) const { } uint32_t vec_size = onnxruntime::narrow((size + 3) / 4); + + std::string additional_impl; + if (get_additional_impl_) { + additional_impl = get_additional_impl_(lhs_tensor->GetElementType(), rhs_tensor->GetElementType()); + } + BinaryElementwiseProgram program{kernel_name_, expression_, + additional_impl, is_broadcast, is_lhs_scalar, is_rhs_scalar, @@ -273,7 +283,28 @@ WEBGPU_BINARY_VERSIONED_KERNEL(Sub, 7, 12, Sub, WebGpuSupportedNumberTypes()) WEBGPU_BINARY_VERSIONED_KERNEL(Sub, 13, 13, Sub, WebGpuSupportedNumberTypes()) WEBGPU_BINARY_KERNEL(Sub, 14, Sub, WebGpuSupportedNumberTypes()) -WEBGPU_BINARY_IMPL(Pow, "output_value_t(pow(vec4(a), vec4(b)))") +std::string GetPowImpl(int lhs_element_type, int /* rhs_element_type */) { + SS(s, 1024); + std::string round_str; + if (lhs_element_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32) { + round_str = "round"; + } + + s << "fn pow_custom(a : input_a_element_t, b : f32) -> input_a_element_t {\n" + " if (b == 0.0) {\n" + " return input_a_element_t(1.0);\n" + " } else if (a < input_a_element_t(0.0) && b != floor(b)) {\n" + " return input_a_element_t(pow(f32(a), b)); // NaN\n" + " }\n" + << " return select(sign(a), input_a_element_t(1.0), round(abs(b) % 2.0) != 1.0) * input_a_element_t(" << round_str << "(pow(f32(abs(a)), b)));\n" + << "}\n" + "fn pow_v(a : vec4, b : vec4) -> vec4 {\n" + " return vec4(pow_custom(a.x, f32(b.x)), pow_custom(a.y, f32(b.y)), pow_custom(a.z, f32(b.z)), pow_custom(a.w, f32(b.w)));\n" + "}\n"; + return SS_GET(s); +} + +WEBGPU_BINARY_IMPL(Pow, "pow_v(a, b)", GetPowImpl) WEBGPU_BINARY_VERSIONED_KERNEL(Pow, 7, 11, Pow, WebGpuSupportedNumberTypes()) WEBGPU_BINARY_VERSIONED_KERNEL_2(Pow, 12, 12, Pow, WebGpuSupportedNumberTypes(), WebGpuSupportedNumberTypes()) WEBGPU_BINARY_VERSIONED_KERNEL_2(Pow, 13, 14, Pow, WebGpuSupportedNumberTypes(), WebGpuSupportedNumberTypes()) diff --git a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.h b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.h index 84cbcdf3244d8..f80accfb934f8 100644 --- a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.h +++ b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.h @@ -14,11 +14,13 @@ class BinaryElementwiseProgram final : public Program public: BinaryElementwiseProgram(const std::string& kernel_name, const std::string& expression, + const std::string& additional_impl, const bool is_broadcast, const bool is_lhs_scalar, const bool is_rhs_scalar, const bool vectorize) : Program{kernel_name}, expression_{expression}, + additional_impl_{additional_impl}, is_broadcast_{is_broadcast}, is_lhs_scalar_{is_lhs_scalar}, is_rhs_scalar_{is_rhs_scalar}, @@ -29,7 +31,8 @@ class BinaryElementwiseProgram final : public Program WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"vec_size", ProgramUniformVariableDataType::Uint32}); private: - std::string expression_; + std::string_view expression_; + std::string_view additional_impl_; bool is_broadcast_; bool is_lhs_scalar_; bool is_rhs_scalar_; @@ -38,11 +41,15 @@ class BinaryElementwiseProgram final : public Program class BinaryElementwise : public WebGpuKernel { public: + using GetAdditionalImplementationFunction = std::string (*)(int lhs_element_type, int rhs_element_type); + BinaryElementwise(const OpKernelInfo& info, const std::string& kernel_name, - const std::string& expression) : WebGpuKernel{info}, - kernel_name_{kernel_name}, - expression_{expression} {} + const std::string& expression, + const GetAdditionalImplementationFunction get_additional_impl = nullptr) : WebGpuKernel{info}, + kernel_name_{kernel_name}, + expression_{expression}, + get_additional_impl_{get_additional_impl} {} protected: Status ComputeInternal(ComputeContext& context) const final; @@ -50,6 +57,7 @@ class BinaryElementwise : public WebGpuKernel { private: std::string kernel_name_; std::string expression_; + const GetAdditionalImplementationFunction get_additional_impl_; }; } // namespace webgpu From 731b27e25d95258b959fa963117e2a6ef11f0050 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 19 Mar 2025 15:48:51 -0700 Subject: [PATCH 127/266] Increase timeout to 90min for ARM64-Xcode16-targeting-iphonesimulator (#24091) ### Description There are still some timeout for the pipeline. further extend the timeout to 90 minutes for ARM64-Xcode16-targeting-iphonesimulator. It takes quite a while if all build cache is missing. ### Motivation and Context The pipeline sometimes failed because of timeout. There is a previous PR #24030 to increase the timeout from 60min to 75 min but it looks like not enough. --- .github/workflows/mac.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index fe7c7fb7ab4c8..86b1cd5ee90e7 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -204,7 +204,7 @@ jobs: matrix: target_arch: [x86_64, arm64] - timeout-minutes: 75 + timeout-minutes: 90 steps: - uses: actions/setup-python@v5 From da7874c856019a9bb8e841f88de42162e8af3e8d Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 19 Mar 2025 16:23:18 -0700 Subject: [PATCH 128/266] [WebGPU] fix test failure in Reduce operators on macOS ARM64 (#24108) ### Description fix test failure in Reduce operators on macOS ARM64 ``` [E:onnxruntime:ReduceL1, sequential_executor.cc:572 ExecuteKernel] Non-zero status code returned while running ReduceL1 node. Name:'node1' Status Message: webgpu_context.cc:259 Run Uniform variable[0] (output_size) data type mismatch in program "ReduceL1", Expected: u32, Actual: i32 ``` --- onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index 9548386ded06c..11fa30c798809 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -191,12 +191,13 @@ Status ReduceKernel::ComputeInternal(ComputeContext& context) auto output = context.Output(0, input_tensor->Shape()); // We need to run the operation even for scalar inputs for these ops const auto code = GetOpSpecificCode(input_tensor); + constexpr uint32_t output_size = 1; + constexpr uint32_t reduce_axes = 0; ReduceKernelProgram program(name_, keepdims_, noop_with_empty_axes_, input_axes, code, false); - std::vector reduce_axes = {0}; program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}) .AddOutput({output, ProgramTensorMetadataDependency::TypeAndRank}) .SetDispatchGroupSize(1) - .AddUniformVariables({{1}, {static_cast(noop_with_empty_axes_ ? 1 : 0)}, {reduce_axes}}); + .AddUniformVariables({{output_size}, {static_cast(noop_with_empty_axes_ ? 1 : 0)}, {reduce_axes}}); return context.RunProgram(program); } else { // For other ops, or when axes is empty with noop_with_empty_axes_ true, just copy the input From 8d21bf727c96a59425d8e80e4ca1a0a321f220ef Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 19 Mar 2025 16:28:31 -0700 Subject: [PATCH 129/266] [WebGPU EP] Implements CumSum Operator (#24047) Increases WebGPU EP op coverage. --- .../core/providers/webgpu/math/cum_sum.cc | 98 +++++++++++++++++++ .../core/providers/webgpu/math/cum_sum.h | 39 ++++++++ .../webgpu/webgpu_execution_provider.cc | 4 +- 3 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/math/cum_sum.cc create mode 100644 onnxruntime/core/providers/webgpu/math/cum_sum.h diff --git a/onnxruntime/core/providers/webgpu/math/cum_sum.cc b/onnxruntime/core/providers/webgpu/math/cum_sum.cc new file mode 100644 index 0000000000000..bc4cd70a238fc --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/cum_sum.cc @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/math/cum_sum.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +namespace onnxruntime { +namespace webgpu { + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + CumSum, + kOnnxDomain, + 11, 13, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()) + .TypeConstraint("T2", {DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType()}) + .InputMemoryType(OrtMemTypeCPU, 1), + CumSum); + +ONNX_OPERATOR_KERNEL_EX( + CumSum, + kOnnxDomain, + 14, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()) + .TypeConstraint("T2", {DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType()}) + .InputMemoryType(OrtMemTypeCPU, 1), + CumSum); + +Status CumSumProgram::GenerateShaderCode(ShaderHelper& shader) const { + const ShaderVariableHelper& input = shader.AddInput("input", ShaderUsage::UseUniform); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "var input_indices = " << input.OffsetToIndices("global_idx") << ";\n" + << "var sum : output_value_t = 0;\n" + << "var first : i32 = 0;\n" + << "if (uniforms.reverse == 1) {\n" + << " first = i32(" + input.IndicesGet("input_indices", "uniforms.axis") + ");\n" + << " if (uniforms.exclusive == 1) { first += 1; }\n" + << "}\n\n" + << "var last : i32 = 0;\n" + << "if (uniforms.reverse == 1) {\n" + << " last = i32(" << GetElementAt("uniforms.input_shape", "uniforms.axis", input.Rank()) << ");\n" + << "} else {\n" + << " last = i32(" + input.IndicesGet("input_indices", "uniforms.axis") + ");\n" + << " if (uniforms.exclusive == 0) { last += 1; }\n" + << "}\n\n" + << "for (var i : i32 = first; i < last; i++) {\n" + << " " << input.IndicesSet("input_indices", "uniforms.axis", "u32(i)") << ";\n" + << " sum = sum + " << input.GetByIndices("input_indices") << ";\n" + << "}\n" + << output.SetByOffset("global_idx", "sum"); + + return Status::OK(); +} + +Status CumSum::ComputeInternal(ComputeContext& context) const { + const auto* input_tensor = context.Input(0); + const TensorShape& input_shape = input_tensor->Shape(); + int64_t input_rank = input_shape.NumDimensions(); + + const auto* axis_tensor = context.Input(1); + const auto* axis_data = axis_tensor->Data(); + int64_t axis = static_cast(axis_data[0]); + + ORT_ENFORCE(-input_rank <= axis && axis < input_rank, "Axes attribute must be within range -input_rank <= axis < input_rank."); + // Handle negative axis + if (axis < 0) { + axis += input_rank; + } + + auto* output_tensor = context.Output(0, input_shape); + int64_t output_size = output_tensor->Shape().Size(); + + if (output_size == 0) { + return Status::OK(); + } + + CumSumProgram program{}; + program + .AddInput({input_tensor}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::TypeAndRank}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({{static_cast(output_size)}, + {static_cast(axis)}, + {static_cast(exclusive_)}, + {static_cast(reverse_)}}); + return context.RunProgram(program); +} + +} // namespace webgpu +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/math/cum_sum.h b/onnxruntime/core/providers/webgpu/math/cum_sum.h new file mode 100644 index 0000000000000..6a66ee0ed7b04 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/cum_sum.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" + +namespace onnxruntime { +namespace webgpu { + +class CumSumProgram final : public Program { + public: + CumSumProgram() : Program{"CumSum"} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, + {"axis", ProgramUniformVariableDataType::Uint32}, + {"exclusive", ProgramUniformVariableDataType::Uint32}, + {"reverse", ProgramUniformVariableDataType::Uint32}); +}; + +class CumSum final : public WebGpuKernel { + public: + CumSum(const OpKernelInfo& info) : WebGpuKernel(info) { + exclusive_ = info.GetAttrOrDefault("exclusive", 0); + reverse_ = info.GetAttrOrDefault("reverse", 0); + } + + Status ComputeInternal(ComputeContext& context) const override; + + private: + int64_t exclusive_; + int64_t reverse_; +}; + +} // namespace webgpu +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 6f81bead5e5b1..aacbcc5fb4f0a 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -713,8 +713,8 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, From 81a892042d06c7fcab0aca0f0b724fa1a4b92630 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Thu, 20 Mar 2025 07:55:30 +0800 Subject: [PATCH 130/266] [webgpu] Use 1d dispatch group size (#24084) This PR uses 1d disptach group size and uses workgroup_idx instead of workgroup.x|workgroup.y in case they are normalized. --- .../contrib_ops/webgpu/bert/flash_attention.cc | 10 ++++++---- .../contrib_ops/webgpu/bert/flash_attention.h | 3 ++- .../webgpu/quantization/dp4a_matmul_nbits.cc | 13 +++++++------ .../webgpu/quantization/dp4a_matmul_nbits.h | 3 ++- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 58ddf60df79f0..52c705abb1003 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -224,12 +224,12 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { // Shader is designed to be dispatched as Dispatch(num_heads, new_sequence_length / workgroup_size_x, 1) // Each lane/thread is responsible for a single q. shader.MainFunctionBody() << R"MAIN_FN( - let head_idx = workgroup_id.x; + let head_idx = u32(workgroup_idx / uniforms.num_seq_tile); let capped_sg_id = min(sg_id, max_k_step); let capped_sg_size = min(sg_size, max_k_step); // Load Q - let q_idx_global = workgroup_id.y * workgroup_size_x + local_idx; + let q_idx_global = (workgroup_idx % uniforms.num_seq_tile) * workgroup_size_x + local_idx; let valid_q = q_idx_global < uniforms.new_sequence_length; if (valid_q) { @@ -445,7 +445,8 @@ Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, co std::string cache_hint = std::to_string(has_attention_bias) + std::to_string(parameters.head_size_) + std::to_string(parameters.num_heads_); - program.SetDispatchGroupSize(parameters.num_heads_, (parameters.sequence_length_ + tile_size - 1) / tile_size, 1) + const uint32_t num_seq_tile = (parameters.sequence_length_ + tile_size - 1) / tile_size; + program.SetDispatchGroupSize(parameters.num_heads_ * num_seq_tile) .SetWorkgroupSize(tile_size) .CacheHint(cache_hint) .AddUniformVariables({{static_cast(parameters.sequence_length_)}, @@ -454,7 +455,8 @@ Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, co {static_cast(parameters.total_sequence_length_ - parameters.kv_sequence_length_)}, {static_cast(parameters.is_gqa_ ? 1 : 0)}, {static_cast(parameters.n_reps)}, - {alpha}}); + {alpha}, + {num_seq_tile}}); return context.RunProgram(program); } diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h index 2c2b888538843..8931403641a81 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h @@ -52,7 +52,8 @@ class FlashAttentionProgram final : public Program { {"past_sequence_length", ProgramUniformVariableDataType::Uint32}, {"is_gqa", ProgramUniformVariableDataType::Uint32}, {"n_reps", ProgramUniformVariableDataType::Uint32}, - {"alpha", ProgramUniformVariableDataType::Float32}); + {"alpha", ProgramUniformVariableDataType::Float32}, + {"num_seq_tile", ProgramUniformVariableDataType::Uint32}); private: bool has_attention_bias_; diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc index 65807b072bc80..a25d8e68f11cd 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc @@ -138,8 +138,8 @@ Status DP4AMatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { shader.MainFunctionBody() << R"MAIN_FN( // During the load phase we use all 256 threads to load 64 rows of A/B. // For each row we load tile_size_k_vec (2) vectorized elements, which are 32 elements of K. - let a_global_base = workgroup_id.x * tile_size; - let b_global_base = workgroup_id.y * tile_size; + let a_global_base = u32(workgroup_idx / uniforms.num_N_tile) * tile_size; + let b_global_base = (workgroup_idx % uniforms.num_N_tile) * tile_size; let load_AorB = u32(local_idx/128); let load_row = u32((local_idx%128)/2); let load_col = u32(local_idx%2); @@ -275,11 +275,11 @@ Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor constexpr uint32_t kTileSize = 64; TensorShape reshaped_y_shape{1, M, N / kVec4Components}; + uint32_t num_M_tile = (M + kTileSize - 1) / kTileSize; + uint32_t num_N_tile = (N + kTileSize - 1) / kTileSize; DP4AMatMulNBitsProgram mul_program{block_size}; mul_program.SetWorkgroupSize(256); - mul_program.SetDispatchGroupSize( - (M + kTileSize - 1) / kTileSize, - (N + kTileSize - 1) / kTileSize, 1); + mul_program.SetDispatchGroupSize(num_M_tile * num_N_tile); mul_program.AddInputs({{&a_quant, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec4Components)}, {&a_scale, ProgramTensorMetadataDependency::TypeAndRank, 1}, {b, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec2Components * kU32Components)}, @@ -288,7 +288,8 @@ Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor {static_cast(N)}, {static_cast(K)}, {static_cast(K / 8)}, - {static_cast(K / 16)}}) + {static_cast(K / 16)}, + {num_N_tile}}) .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, static_cast(kVec4Components)}) .CacheHint("Block" + std::to_string(block_size)); return context.RunProgram(mul_program); diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h index 7e4a8f5d68437..f0157ca3e8c97 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h @@ -27,7 +27,8 @@ class DP4AMatMulNBitsProgram final : public Program { {"N", ProgramUniformVariableDataType::Uint32}, {"K", ProgramUniformVariableDataType::Uint32}, {"K8", ProgramUniformVariableDataType::Uint32}, - {"K16", ProgramUniformVariableDataType::Uint32}); + {"K16", ProgramUniformVariableDataType::Uint32}, + {"num_N_tile", ProgramUniformVariableDataType::Uint32}); private: uint32_t block_size_; From 9dcb99cdf73f112e9bf2c6c1613897ffc31b6477 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:32:11 -0700 Subject: [PATCH 131/266] [WebGPU] fix test failure in MatMulNBits on macOS ARM64 (#24109) ### Description abs_error is slightly loosen from 0.02 to 0.03 to allow test cases on macOS arm64 to pass. --- onnxruntime/test/contrib_ops/matmul_4bits_test.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/onnxruntime/test/contrib_ops/matmul_4bits_test.cc b/onnxruntime/test/contrib_ops/matmul_4bits_test.cc index 8187253311ed3..81323cb51a887 100644 --- a/onnxruntime/test/contrib_ops/matmul_4bits_test.cc +++ b/onnxruntime/test/contrib_ops/matmul_4bits_test.cc @@ -530,8 +530,10 @@ TEST(MatMulNBits, Float16Cuda) { for (auto K : {16, 32, 64, 128, 256, 1024, 93, 1234}) { for (auto block_size : {16, 32, 64, 128}) { for (auto has_gidx : has_gidx_options) { -#ifdef USE_DML +#if defined(USE_DML) RunTest(M, N, K, block_size, 0, false, true, has_gidx, true, 0.04f); +#elif defined(USE_WEBGPU) + RunTest(M, N, K, block_size, 0, false, true, has_gidx, true, 0.03f); #else RunTest(M, N, K, block_size, 0, false, true, has_gidx); RunTest(M, N, K, block_size, 0, true, true, has_gidx, false); From 4d5e274f0e45533227cbc2a2eed2bec83d42949b Mon Sep 17 00:00:00 2001 From: chuteng-quic Date: Thu, 20 Mar 2025 10:37:16 +0800 Subject: [PATCH 132/266] [QNN-EP] Add support for Sum operator with 2 inputs (#24098) ### Description * Add Sum to op builder in QNN-EP * Now we can limit the support to Sum with 2 inputs. ### Motivation and Context * Enhance QNN-EP support for Sum with two inputs --- .../providers/qnn/builder/op_builder_factory.cc | 1 + .../qnn/builder/opbuilder/base_op_builder.h | 1 + .../qnn/builder/opbuilder/simple_op_builder.cc | 13 ++++++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc b/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc index 3d66003fb2bca..77579dfc793ee 100644 --- a/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc +++ b/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc @@ -47,6 +47,7 @@ OpBuilderRegistrations::OpBuilderRegistrations() { CreateSimpleOpBuilder("Sin", *this); CreateSimpleOpBuilder("Sqrt", *this); CreateSimpleOpBuilder("Sub", *this); + CreateSimpleOpBuilder("Sum", *this); CreateSimpleOpBuilder("Tanh", *this); CreateSimpleOpBuilder("Concat", *this); diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h index a79f4056083c5..df9d0de8e0e3e 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h @@ -158,6 +158,7 @@ class BaseOpBuilder : public IOpBuilder { {"Softmax", QNN_OP_SOFTMAX}, {"Sqrt", QNN_OP_ELEMENT_WISE_SQUARE_ROOT}, {"Sub", QNN_OP_ELEMENT_WISE_SUBTRACT}, + {"Sum", QNN_OP_ELEMENT_WISE_ADD}, {"Tanh", QNN_OP_TANH}, {"Transpose", QNN_OP_TRANSPOSE}, {"GridSample", QNN_OP_GRID_SAMPLE}, diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/simple_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/simple_op_builder.cc index 48c637cd2e951..229d86082f6dc 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/simple_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/simple_op_builder.cc @@ -56,11 +56,18 @@ Status SimpleOpBuilder::ExplicitOpCheck(QnnModelWrapper& qnn_model_wrapper, padding_mode.c_str()); } - // ONNX's Min and Max operators accept a variable number of inputs (i.e., variadic). - // However, QNN's Min and Max operators must take in exactly two inputs. + // ONNX's Min, Max, and Sum operators accept a variable number of inputs (i.e., variadic). + // However, QNN's Min, Max, and Add operators must take in exactly two inputs. if (op_type == "Min" || op_type == "Max") { ORT_RETURN_IF_NOT(node_unit.Inputs().size() == 2, - "QNN EP only supports Min and Max operators with exactly 2 inputs."); + "QNN EP only supports ", op_type.c_str(), " operator with exactly 2 inputs."); + } + + if (op_type == "Sum") { + size_t inputs_num = node_unit.Inputs().size(); + ORT_RETURN_IF_NOT(inputs_num == 2, + "QNN EP supports Sum operator with QNN_OP_ELEMENT_WISE_ADD, which takes exactly 2 inputs. Got ONNX's Sum operator with ", + std::to_string(inputs_num).c_str(), " inputs."); } if (op_type == "DequantizeLinear") { From 5d43f0ab1997d7f99b4aca94e49e24707c2a7566 Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Thu, 20 Mar 2025 16:10:54 +0800 Subject: [PATCH 133/266] [WebNN] Replace narrow with SafeInt for consistently in integer handling (#24059) Remove redundant header files BTW. --- .../providers/webnn/builders/impl/argmax_min_op_builder.cc | 4 ++-- .../core/providers/webnn/builders/impl/builder_utils.cc | 1 - .../providers/webnn/builders/impl/concat_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/conv_op_builder.cc | 1 - .../providers/webnn/builders/impl/cumsum_op_builder.cc | 5 ++--- .../builders/impl/dynamicQuantizeLinear_op_builder.cc | 1 - .../providers/webnn/builders/impl/einsum_op_builder.cc | 1 - .../providers/webnn/builders/impl/expand_op_builder.cc | 1 - .../providers/webnn/builders/impl/flatten_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/gemm_op_builder.cc | 7 +++---- .../webnn/builders/impl/normalization_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/pad_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/pool_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/qdq_op_builder.cc | 1 - .../providers/webnn/builders/impl/reduction_op_builder.cc | 1 - .../providers/webnn/builders/impl/reshape_op_builder.cc | 1 - .../providers/webnn/builders/impl/resize_op_builder.cc | 1 - .../webnn/builders/impl/rotaryEmbedding_op_builder.cc | 2 +- .../core/providers/webnn/builders/impl/slice_op_builder.cc | 1 - .../providers/webnn/builders/impl/softmax_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/split_op_builder.cc | 5 ++--- .../webnn/builders/impl/squeeze_unsqueeze_op_builder.cc | 1 - .../core/providers/webnn/builders/impl/tile_op_builder.cc | 1 - .../providers/webnn/builders/impl/transpose_op_builder.cc | 1 - .../providers/webnn/builders/impl/triangular_op_builder.cc | 2 +- onnxruntime/core/providers/webnn/builders/model.cc | 1 - onnxruntime/core/providers/webnn/builders/model_builder.cc | 1 - .../core/providers/webnn/webnn_execution_provider.cc | 1 - 28 files changed, 11 insertions(+), 36 deletions(-) diff --git a/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc index 6814b019f699c..08580ab2861d7 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc @@ -54,9 +54,9 @@ Status ArgMaxMinOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const auto& op_type = node.OpType(); if (op_type == "ArgMax") { - output = model_builder.GetBuilder().call("argMax", input, narrow(axis), options); + output = model_builder.GetBuilder().call("argMax", input, SafeInt(axis).Ref(), options); } else if (op_type == "ArgMin") { - output = model_builder.GetBuilder().call("argMin", input, narrow(axis), options); + output = model_builder.GetBuilder().call("argMin", input, SafeInt(axis).Ref(), options); } else { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "ArgMaxMinOpBuilder, unknown op: ", op_type); } diff --git a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc index 113cc3df5438d..63e2345243282 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include #include #include "core/providers/shared/utils/utils.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc index 1bbe56ef9b477..ee2512ddd8b5a 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc index 1361b7dd5c14b..4c393e8a9bdba 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc index be30c5520d62e..99be8f75771ad 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" @@ -64,8 +63,8 @@ Status CumSumOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const options.set("label", node.Name()); emscripten::val output = emscripten::val::object(); - output = model_builder.GetBuilder().call("cumulativeSum", input, gsl::narrow(webnn_axis), - options); + output = model_builder.GetBuilder().call("cumulativeSum", input, + SafeInt(webnn_axis).Ref(), options); model_builder.AddOperand(node.OutputDefs()[0]->Name(), std::move(output)); return Status::OK(); } diff --git a/onnxruntime/core/providers/webnn/builders/impl/dynamicQuantizeLinear_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/dynamicQuantizeLinear_op_builder.cc index 55746bb1f61f0..f3363b1e186d5 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/dynamicQuantizeLinear_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/dynamicQuantizeLinear_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc index 1f51e26fecfa5..6cee04bac3e2b 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc index 8402f05d8e234..3f813f08279e7 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/flatten_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/flatten_op_builder.cc index d0ece026a7048..c4ff280b95b6e 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/flatten_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/flatten_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc index c5cc8e86bb308..1f24124745a19 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" @@ -86,9 +85,9 @@ Status GemmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N else if (extended_a_shape) { std::vector new_shape; for (size_t i = 0; i < b_shape.size() - 2; i++) { - new_shape.push_back(narrow(b_shape[i])); + new_shape.push_back(SafeInt(b_shape[i])); } - new_shape.push_back(narrow(b_shape.back())); + new_shape.push_back(SafeInt(b_shape.back())); output = model_builder.GetBuilder().call("reshape", output, emscripten::val::array(new_shape), @@ -98,7 +97,7 @@ Status GemmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N else if (extended_b_shape) { std::vector new_shape; for (size_t i = 0; i < a_shape.size() - 1; i++) { - new_shape.push_back(narrow(a_shape[i])); + new_shape.push_back(SafeInt(a_shape[i])); } output = model_builder.GetBuilder().call("reshape", output, diff --git a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc index a090c21fe3356..5b57df7f184e7 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc index d8373a45e4423..e8f26af928ab3 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc index b338d27986279..79ad3574e07e9 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc index 1bb6523c6f86a..ed62b2bd69618 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc index 93ad933d71c34..b23fbeba1ddc8 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc index 0a438e98ad737..2fc47430a1c66 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc index 58515d2df54ec..eec6911a686cf 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc @@ -4,7 +4,6 @@ #include -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/framework/tensorprotoutils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc index 1688dfc97a0c4..0a84835ee9fc0 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc @@ -89,7 +89,7 @@ Status RotaryEmbeddingOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_build emscripten::val wnn_builder = model_builder.GetBuilder(); NodeAttrHelper helper(node); - const bool interleaved = gsl::narrow_cast(helper.Get("interleaved", 0)); + const bool interleaved = static_cast(helper.Get("interleaved", 0)); uint32_t num_heads = helper.Get("num_heads", 0); uint32_t rotary_embedding_dim = helper.Get("rotary_embedding_dim", 0); diff --git a/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc index 4adc5920de7fa..468c0e24a3e88 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc index b1b737b114998..0e754b53e78d1 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc index 06dbacf995a28..21b44b1066694 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" @@ -75,8 +74,8 @@ Status SplitOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Check that the splits evenly divide. if (split_count > 0 && splits.empty() && input_shape[axis] % split_count != 0) { // Divide inputs into variable size outputs: - splits.insert(splits.end(), split_count - 1, narrow(input_shape[axis]) / split_count); - splits.insert(splits.end(), narrow(input_shape[axis]) % split_count); + splits.insert(splits.end(), split_count - 1, SafeInt(input_shape[axis]) / split_count); + splits.insert(splits.end(), SafeInt(input_shape[axis]) % split_count); } if (splits.empty()) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc index a3be9d7e2ceee..5687b1133c628 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc index 672a3a510d54d..259bb0552b7c7 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/optimizer/initializer.h" #include "core/providers/common.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc index ac440e0119bac..452071f469c4f 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/transpose_op_builder.cc @@ -2,7 +2,6 @@ // Copyright (c) Intel Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/safeint.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/webnn/builders/helper.h" #include "core/providers/webnn/builders/model_builder.h" diff --git a/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc index 0c818533918a4..f2092d6163713 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc @@ -59,7 +59,7 @@ Status TriangularOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, std::vector unpacked_tensor; ORT_RETURN_IF_ERROR(onnxruntime::utils::UnpackInitializerData(diagonal_tensor, unpacked_tensor)); const auto diagonal = *reinterpret_cast(unpacked_tensor.data()); - options.set("diagonal", narrow(diagonal)); + options.set("diagonal", SafeInt(diagonal).Ref()); } output = model_builder.GetBuilder().call("triangular", input, options); diff --git a/onnxruntime/core/providers/webnn/builders/model.cc b/onnxruntime/core/providers/webnn/builders/model.cc index 492e2f717e30e..40fdfc609e6a1 100644 --- a/onnxruntime/core/providers/webnn/builders/model.cc +++ b/onnxruntime/core/providers/webnn/builders/model.cc @@ -8,7 +8,6 @@ #include "core/common/common.h" #include "core/common/inlined_containers.h" #include "core/common/logging/logging.h" -#include "core/common/safeint.h" #include "core/graph/onnx_protobuf.h" #include "core/providers/common.h" #include "model.h" diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index ed6ab7d2d7115..399cc5faf6273 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -9,7 +9,6 @@ #include "helper.h" #include "op_builder_factory.h" -#include "core/common/safeint.h" #include "core/framework/tensorprotoutils.h" #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index c527ba213e55b..2da7c6499933a 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -10,7 +10,6 @@ #include "core/framework/kernel_registry.h" #include "core/graph/graph_viewer.h" #include "core/session/onnxruntime_cxx_api.h" -#include "core/common/safeint.h" #include "core/providers/webnn/allocator.h" #include "core/providers/webnn/data_transfer.h" #include "core/providers/partitioning_utils.h" From 6bdbf08c3a8efe7c463001e1ce734eb3d1f4abf6 Mon Sep 17 00:00:00 2001 From: chuteng-quic Date: Fri, 21 Mar 2025 00:26:37 +0800 Subject: [PATCH 134/266] [QNN-EP] Add Lora Support with offline QNN context binary (#24026) ### Description - Add the new run option called lora_config to feed the information from lora binary - Parse and apply the lora binary in OnRunStart ### Motivation and Context - Support Lora Adapter Binary with QNN Context Binary Usage --- .../onnxruntime_run_options_config_keys.h | 3 + .../qnn/builder/qnn_backend_manager.cc | 64 +++++++++++++++++++ .../qnn/builder/qnn_backend_manager.h | 2 + .../providers/qnn/qnn_execution_provider.cc | 6 ++ 4 files changed, 75 insertions(+) diff --git a/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h index c80b8c0c164b6..f40ea6591059e 100644 --- a/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h @@ -43,6 +43,9 @@ static const char* const kOrtRunOptionsConfigQnnPerfModePostRun = "qnn.htp_perf_ // Set RPC control latency for QNN HTP backend static const char* const kOrtRunOptionsConfigQnnRpcControlLatency = "qnn.rpc_control_latency"; +// Set QNN Lora Config File for apply Lora in QNN context binary +static const char* const kOrtRunOptionsConfigQnnLoraConfig = "qnn.lora_config"; + // Set graph annotation id for CUDA EP. Use with enable_cuda_graph=true. // The value should be an integer. If the value is not set, the default value is 0 and // ORT session only captures one cuda graph before another capture is requested. diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc index 0328f6c2014fa..6b9f6a5e73e0f 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc @@ -52,6 +52,70 @@ static const char* DlError() { #endif } +Status ReadBinaryFromFile(const std::string& file_path, uint8_t* buffer, size_t buffer_size) { + ORT_RETURN_IF(nullptr == buffer, "Binary buffer is nullptr"); + std::ifstream in(file_path, std::ifstream::binary); + ORT_RETURN_IF(!in, "Failed to open input file: ", file_path.c_str()); + ORT_RETURN_IF(!in.read(reinterpret_cast(buffer), buffer_size), "Failed to read the contents of: ", file_path.c_str()); + return Status::OK(); +} + +Status QnnBackendManager::ParseLoraConfig(std::string lora_config_path) { + LOGS_DEFAULT(INFO) << "Acquiring the QnnInterface " << lora_config_path; + + // QNN Lora Config file format should be a single line, with the graph name first, + // followed by the qnn lora context binary path, separated by a semicolon (;) + // Example: ; + LOGS_DEFAULT(INFO) << "Loading Lora Config " << lora_config_path; + std::ifstream file(lora_config_path); + std::string line; + + if (file.is_open()) { + if (std::getline(file, line)) { + std::istringstream ss(line); + std::string graph_name; + std::string lora_adapter_bin_path; + + if (std::getline(ss, graph_name, ';') && std::getline(ss, lora_adapter_bin_path)) { + size_t buffer_size = std::filesystem::file_size(lora_adapter_bin_path.c_str()); + + ORT_RETURN_IF(0 == buffer_size, "Received path to an empty file. Nothing to deserialize."); + std::unique_ptr buffer = std::make_unique(buffer_size); + void* voidBufferPtr = static_cast(buffer.get()); + QnnContext_Buffer_t contextBuffer{QNN_CONTEXT_BUFFER_VERSION_1, + {QNN_CONTEXTMEMTYPE_RAW, {{voidBufferPtr, buffer_size}}}}; + + auto status = ReadBinaryFromFile(lora_adapter_bin_path, + reinterpret_cast(buffer.get()), + buffer_size); + + ORT_RETURN_IF(status != Status::OK(), "Failed to read binary data."); + Qnn_GraphHandle_t graph; + bool graph_retrieve_success = false; + for (size_t cIdx = 0; cIdx < contexts_.size(); cIdx++) { + auto graph_retrieve_rt = qnn_interface_.graphRetrieve(contexts_[cIdx], graph_name.c_str(), &graph); + if (QNN_SUCCESS != graph_retrieve_rt) { + continue; + } + + graph_retrieve_success = true; + + auto context_apply_binary_section_rt = qnn_interface_.contextApplyBinarySection( + contexts_[cIdx], graph, QNN_CONTEXT_SECTION_UPDATABLE, &contextBuffer, profile_backend_handle_, nullptr); + ORT_RETURN_IF(QNN_SUCCESS != context_apply_binary_section_rt, "Failed to apply binary section."); + break; + } + ORT_RETURN_IF_NOT(graph_retrieve_success, "Failed to retrieve graph: ", graph_name, " and apply binary section."); + } + } + file.close(); + } else { + LOGS_DEFAULT(ERROR) << "Unable to load Lora Config " << lora_config_path; + } + + return Status::OK(); +} + template Status QnnBackendManager::GetQnnInterfaceProvider(const char* lib_path, const char* interface_provider_name, diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h index bd451d9ba9c1d..137b3856d431d 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h @@ -139,6 +139,8 @@ class QnnBackendManager : public std::enable_shared_from_this const Qnn_Tensor_t& qnn_tensor, Qnn_MemHandle_t& mem_handle); + Status ParseLoraConfig(std::string lora_config); + private: Status LoadBackend(); diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index e5b88a77b334c..2606ace8127d3 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -1194,6 +1194,12 @@ Status QNNExecutionProvider::OnRunStart(const onnxruntime::RunOptions& run_optio } } + std::string lora_config = ""; + if (TryGetConfigEntry(config_options, kOrtRunOptionsConfigQnnLoraConfig, lora_config)) { + LOGS_DEFAULT(VERBOSE) << "lora_config: " << lora_config; + ORT_RETURN_IF_ERROR(qnn_backend_manager_->ParseLoraConfig(lora_config)); + } + return Status::OK(); } From 440d17a70545855883fcf1c1f30d4e86b3b27de7 Mon Sep 17 00:00:00 2001 From: Yifan Li <109183385+yf711@users.noreply.github.com> Date: Thu, 20 Mar 2025 09:45:06 -0700 Subject: [PATCH 135/266] [TensorRT EP] support TensorRT 10.9-GA (#23905) ### Description * Update to trt10.9 * oss parser tested (here's testing method https://onnxruntime.ai/docs/build/eps.html#note-to-ort-1210-open-sourced-parser-users) ### Motivation and Context --- cmake/deps.txt | 4 ++-- onnxruntime/python/tools/tensorrt/perf/build/build_image.py | 4 ++-- .../linux-gpu-tensorrt-daily-perf-pipeline.yml | 6 +++--- .../github/azure-pipelines/templates/common-variables.yml | 2 +- .../templates/jobs/download_win_gpu_library.yml | 6 +++--- .../github/azure-pipelines/templates/jobs/set-winenv.yml | 4 ++-- .../github/linux/docker/Dockerfile.manylinux2_28_cuda | 2 +- .../linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 | 2 +- .../docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch | 2 +- .../github/linux/docker/Dockerfile.package_ubuntu_2004_gpu | 2 +- .../linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg | 2 +- .../linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv | 2 +- .../github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 | 2 +- .../github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 | 4 ++-- .../github/linux/docker/Dockerfile.ubuntu_tensorrt_bin | 2 +- .../linux/docker/inference/x86_64/python/cuda/Dockerfile | 2 +- tools/ci_build/github/windows/setup_env_gpu.bat | 4 ++-- tools/ci_build/github/windows/setup_env_trt.bat | 2 +- 18 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cmake/deps.txt b/cmake/deps.txt index c7db8ef51505d..82b4128e4cf8d 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -36,8 +36,8 @@ microsoft_wil;https://github.com/microsoft/wil/archive/refs/tags/v1.0.230629.1.z mimalloc;https://github.com/microsoft/mimalloc/archive/refs/tags/v2.1.1.zip;d5ee7d34223d0567892db5179849939c8769dc41 mp11;https://github.com/boostorg/mp11/archive/refs/tags/boost-1.82.0.zip;9bc9e01dffb64d9e0773b2e44d2f22c51aace063 onnx;https://github.com/onnx/onnx/archive/refs/tags/v1.17.0.zip;13a60ac5217c104139ce0fd024f48628e7bcf5bc -# Use the latest commit of 10.8-GA -onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/c5ca8912f30e9ad630a0ef565e3d5f4bd5e91563.zip;588b294aaa9e84679ed5815cea1d399210ac98c2 +# Use the latest commit of 10.9-GA +onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/d5dce67db7c2e64b07e055571f5ec06f7f254de2.zip;01114d3b67650857281fa50faa2e412130a63b69 protobuf;https://github.com/protocolbuffers/protobuf/archive/refs/tags/v21.12.zip;7cf2733949036c7d52fda017badcab093fe73bfa protoc_win64;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win64.zip;b4521f7ada5b260380f94c4bd7f1b7684c76969a protoc_win32;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win32.zip;3688010318192c46ce73213cdfb6b3e5656da874 diff --git a/onnxruntime/python/tools/tensorrt/perf/build/build_image.py b/onnxruntime/python/tools/tensorrt/perf/build/build_image.py index 7af34447f1f66..3e913094628c3 100644 --- a/onnxruntime/python/tools/tensorrt/perf/build/build_image.py +++ b/onnxruntime/python/tools/tensorrt/perf/build/build_image.py @@ -16,8 +16,8 @@ import sys TRT_DOCKER_FILES = { - "10.8_cuda11.8_cudnn8": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10", - "10.8_cuda12.6_cudnn9": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10", + "10.9_cuda11.8_cudnn8": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10", + "10.9_cuda12.8_cudnn9": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10", "BIN": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin", } diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml index c44d3cff09e96..2dc597fcb2351 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml @@ -8,10 +8,10 @@ parameters: - name: TrtVersion displayName: TensorRT Version type: string - default: 10.8_cuda12.6_cudnn9 + default: 10.9_cuda12.8_cudnn9 values: - - 10.8_cuda11.8_cudnn8 - - 10.8_cuda12.6_cudnn9 + - 10.9_cuda11.8_cudnn8 + - 10.9_cuda12.8_cudnn9 - BIN - name: UseTensorrtOssParser diff --git a/tools/ci_build/github/azure-pipelines/templates/common-variables.yml b/tools/ci_build/github/azure-pipelines/templates/common-variables.yml index eb22d003c462e..39a958e848784 100644 --- a/tools/ci_build/github/azure-pipelines/templates/common-variables.yml +++ b/tools/ci_build/github/azure-pipelines/templates/common-variables.yml @@ -1,5 +1,5 @@ variables: - common_trt_version: '10.8.0.43' + common_trt_version: '10.9.0.34' # As for Debian installation, replace '-1.' by '-1+' when assigning trt version below linux_trt_version_cuda11: ${{ variables.common_trt_version }}-1.cuda11.8 linux_trt_version_cuda12: ${{ variables.common_trt_version }}-1.cuda12.8 diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml index ba1373fa6e338..674f16d8e9332 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml @@ -13,10 +13,10 @@ parameters: - 12.2 - name: TrtVersion type: string - default: '10.8.0.43' + default: '10.9.0.34' values: - 8.6.1.6 - - 10.8.0.43 + - 10.9.0.34 steps: - ${{ if eq(parameters.DownloadCUDA, true) }}: @@ -42,7 +42,7 @@ steps: - powershell: | Write-Host "##vso[task.setvariable variable=trtCudaVersion;]12.0" displayName: Set trtCudaVersion - - ${{ if and(eq(parameters.CudaVersion, '12.2'), eq(parameters.TrtVersion, '10.8.0.43')) }}: + - ${{ if and(eq(parameters.CudaVersion, '12.2'), eq(parameters.TrtVersion, '10.9.0.34')) }}: - powershell: | Write-Host "##vso[task.setvariable variable=trtCudaVersion;]12.8" displayName: Set trtCudaVersion diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml index 1a0b8d7f867a6..142b76ee43b99 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml @@ -15,10 +15,10 @@ parameters: default: '11.8' - name: win_trt_folder_cuda11 type: string - default: 'TensorRT-10.8.0.43.Windows10.x86_64.cuda-11.8' + default: 'TensorRT-10.9.0.34.Windows10.x86_64.cuda-11.8' - name: win_trt_folder_cuda12 type: string - default: 'TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8' + default: 'TensorRT-10.9.0.34.Windows10.x86_64.cuda-12.8' steps: - ${{ if eq(parameters.DownloadCUDA, 'true') }}: diff --git a/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda b/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda index c42042b0ec639..6552c423617b5 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda +++ b/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda @@ -5,7 +5,7 @@ ARG BASEIMAGE=nvidia/cuda:12.5.1-cudnn-devel-ubi8 FROM $BASEIMAGE -ARG TRT_VERSION +ARG TRT_VERSION=10.9.0.34-1.cuda12.8 #Install TensorRT only if TRT_VERSION is not empty RUN if [ -n "$TRT_VERSION" ]; then \ diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 index 7abc7a6d35ec3..1933fd371d3bc 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:12.5.1-cudnn-devel-ubi8 -ARG TRT_VERSION=10.8.0.43-1.cuda12.8 +ARG TRT_VERSION=10.9.0.34-1.cuda12.8 FROM $BASEIMAGE AS base ARG TRT_VERSION ENV PATH=/opt/python/cp310-cp310/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/src/tensorrt/bin:${PATH} diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch index 2df43197b7d39..62562705c92b2 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubi8 -ARG TRT_VERSION=10.8.0.43-1.cuda11.8 +ARG TRT_VERSION=10.9.0.34-1.cuda11.8 FROM $BASEIMAGE AS base ARG TRT_VERSION ENV PATH=/opt/python/cp310-cp310/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/src/tensorrt/bin:${PATH} diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu index 64186e83f001a..9b392fa0e3a68 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04 -ARG TRT_VERSION=10.8.0.43-1+cuda11.8 +ARG TRT_VERSION=10.9.0.34-1+cuda11.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg index a563a1926ed39..5cbfe70331803 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 -ARG TRT_VERSION=10.8.0.43-1+cuda11.8 +ARG TRT_VERSION=10.9.0.34-1+cuda11.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv index 7f5e8f871f415..4baf4b0bb0010 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 -ARG TRT_VERSION=10.8.0.43-1+cuda11.8 +ARG TRT_VERSION=10.9.0.34-1+cuda11.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 index f454d21164ac4..f68f488a9d8b8 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 +++ b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 @@ -31,7 +31,7 @@ RUN pip install --upgrade pip RUN pip install psutil setuptools>=68.2.2 # Install TensorRT -RUN TRT_VERSION="10.8.0.43-1+cuda11.8" &&\ +RUN TRT_VERSION="10.9.0.34-1+cuda11.8" &&\ apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ apt-get update &&\ apt-get install -y \ diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 index a9dbefc6faee0..1d3575411a692 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 +++ b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 @@ -5,7 +5,7 @@ # Dockerfile to run ONNXRuntime with TensorRT integration # Build base image with required system packages -FROM nvidia/cuda:12.6.3-cudnn-devel-ubuntu22.04 AS base +FROM nvidia/cuda:12.8.0-cudnn-devel-ubuntu22.04 AS base # The local directory into which to build and install CMAKE ARG ONNXRUNTIME_LOCAL_CODE_DIR=/code @@ -31,7 +31,7 @@ RUN pip install --upgrade pip RUN pip install setuptools>=68.2.2 psutil # Install TensorRT -RUN TRT_VERSION="10.8.0.43-1+cuda12.8" &&\ +RUN TRT_VERSION="10.9.0.34-1+cuda12.8" &&\ apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ apt-get update &&\ apt-get install -y \ diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin index 7dd302a6b03da..03f14732b70f8 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin +++ b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin @@ -5,7 +5,7 @@ # Dockerfile to run ONNXRuntime with TensorRT installed from provided binaries # Build base image with required system packages -FROM nvidia/cuda:12.6.3-cudnn-devel-ubuntu22.04 AS base +FROM nvidia/cuda:12.8.0-cudnn-devel-ubuntu22.04 AS base # The local directory into which to build and install CMAKE ARG ONNXRUNTIME_LOCAL_CODE_DIR=/code diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile index 0c105daa38ac8..d1df74e2a4506 100644 --- a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile +++ b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile @@ -5,7 +5,7 @@ ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubi8 FROM $BASEIMAGE -ARG TRT_VERSION=10.8.0.43-1.cuda11.8 +ARG TRT_VERSION=10.9.0.34-1.cuda11.8 #Install TensorRT only if TRT_VERSION is not empty RUN if [ -n "${TRT_VERSION}" ]; then \ diff --git a/tools/ci_build/github/windows/setup_env_gpu.bat b/tools/ci_build/github/windows/setup_env_gpu.bat index fd9890fa12fb3..ecadab5d3f8a3 100644 --- a/tools/ci_build/github/windows/setup_env_gpu.bat +++ b/tools/ci_build/github/windows/setup_env_gpu.bat @@ -6,10 +6,10 @@ if exist PATH=%AGENT_TEMPDIRECTORY%\v12.2\ ( ) else ( set PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\extras\CUPTI\lib64;%PATH% ) -set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8\lib;%PATH% +set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.9.0.34.Windows10.x86_64.cuda-12.8\lib;%PATH% @REM The default version is still cuda v12.2, because set cuda v11.8 after it -set PATH=%PATH%;%AGENT_TEMPDIRECTORY%\TensorRT-10.8.0.43.Windows10.x86_64.cuda-11.8\lib +set PATH=%PATH%;%AGENT_TEMPDIRECTORY%\TensorRT-10.9.0.34.Windows10.x86_64.cuda-11.8\lib if exist PATH=%AGENT_TEMPDIRECTORY%\v11.8\ ( set PATH=%PATH%;%AGENT_TEMPDIRECTORY%\v11.8\bin;%AGENT_TEMPDIRECTORY%\v11.8\extras\CUPTI\lib64 ) else ( diff --git a/tools/ci_build/github/windows/setup_env_trt.bat b/tools/ci_build/github/windows/setup_env_trt.bat index f598d25353c4a..45e0d970fb541 100644 --- a/tools/ci_build/github/windows/setup_env_trt.bat +++ b/tools/ci_build/github/windows/setup_env_trt.bat @@ -6,6 +6,6 @@ if exist PATH=%AGENT_TEMPDIRECTORY%\v12.2\ ( ) else ( set PATH=%PATH%;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\extras\CUPTI\lib64 ) -set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8\lib;%PATH% +set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.9.0.34.Windows10.x86_64.cuda-12.8\lib;%PATH% set GRADLE_OPTS=-Dorg.gradle.daemon=false set CUDA_MODULE_LOADING=LAZY From 127c85035a590259a6a9d57feb86ed55f56b9995 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Fri, 21 Mar 2025 01:05:04 +0800 Subject: [PATCH 136/266] [webgpu] Apply dp4a for generation shader (#24064) This pr applies DP4A to generation shader. And also support any block_size % 32 = 0. --- .../webgpu/quantization/dp4a_matmul_nbits.cc | 185 +++++++++++++++--- .../webgpu/quantization/dp4a_matmul_nbits.h | 18 ++ .../webgpu/quantization/matmul_nbits.cc | 6 +- 3 files changed, 183 insertions(+), 26 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc index a25d8e68f11cd..6d2370db853ee 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc @@ -7,6 +7,39 @@ namespace onnxruntime { namespace contrib { namespace webgpu { +namespace { + +constexpr std::string_view commonFunctions = R"ADDNL_FN( + fn DequantizedFrom4BitsTo8Bits(in: vec2) -> vec4 + { + var out = vec4(0); + var value_lower = vec4(unpack4xU8(in[0] & 0x0F0F0F0Fu)) - vec4(8); + var value_upper = vec4(unpack4xU8((in[0] >> 4) & 0x0F0F0F0Fu)) - vec4(8); + out[0] = pack4xI8(vec4(value_lower[0], value_upper[0], value_lower[1], value_upper[1])); + out[1] = pack4xI8(vec4(value_lower[2], value_upper[2], value_lower[3], value_upper[3])); + value_lower = vec4(unpack4xU8(in[1] & 0x0F0F0F0Fu)) - vec4(8); + value_upper = vec4(unpack4xU8((in[1] >> 4) & 0x0F0F0F0Fu)) - vec4(8); + out[2] = pack4xI8(vec4(value_lower[0], value_upper[0], value_lower[1], value_upper[1])); + out[3] = pack4xI8(vec4(value_lower[2], value_upper[2], value_lower[3], value_upper[3])); + return out; + } + + // Scaled dot product of 8 packed unsigned integers. + fn SDP8AI(a1:vec4, b1:vec4, a2:vec4, b2:vec4, scale:output_element_t) -> output_element_t + { + var local_sum = dot4I8Packed(a1[0], b1[0]); + local_sum += dot4I8Packed(a1[1], b1[1]); + local_sum += dot4I8Packed(a1[2], b1[2]); + local_sum += dot4I8Packed(a1[3], b1[3]); + local_sum += dot4I8Packed(a2[0], b2[0]); + local_sum += dot4I8Packed(a2[1], b2[1]); + local_sum += dot4I8Packed(a2[2], b2[2]); + local_sum += dot4I8Packed(a2[3], b2[3]); + return output_element_t(local_sum) * scale; + } + )ADDNL_FN"; + +} // namespace Status DP4AMatMulQuantizeProgram::GenerateShaderCode(ShaderHelper& shader) const { shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); @@ -65,7 +98,8 @@ Status DP4AMatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { // this shader require A to be int8 quantized with block size 64. B is regular // matmulnbits input with block size 32. - shader.AdditionalImplementation() << " const block_size = " << block_size_ << ";"; + shader.AdditionalImplementation() << commonFunctions + << " const block_size = " << block_size_ << ";"; shader.AdditionalImplementation() << R"ADDNL_FN( const tile_size = 64; @@ -105,34 +139,13 @@ Status DP4AMatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { } let b_value = input_b[b_global*uniforms.K16+kidx_v+col]; - var b_value_lower = vec4(unpack4xU8(b_value[0] & 0x0F0F0F0Fu)) - vec4(8); - var b_value_upper = vec4(unpack4xU8((b_value[0] >> 4) & 0x0F0F0F0Fu)) - vec4(8); - tile_B[col][row][0] = pack4xI8(vec4(b_value_lower[0], b_value_upper[0], b_value_lower[1], b_value_upper[1])); - tile_B[col][row][1] = pack4xI8(vec4(b_value_lower[2], b_value_upper[2], b_value_lower[3], b_value_upper[3])); - b_value_lower = vec4(unpack4xU8(b_value[1] & 0x0F0F0F0Fu)) - vec4(8); - b_value_upper = vec4(unpack4xU8((b_value[1] >> 4) & 0x0F0F0F0Fu)) - vec4(8); - tile_B[col][row][2] = pack4xI8(vec4(b_value_lower[0], b_value_upper[0], b_value_lower[1], b_value_upper[1])); - tile_B[col][row][3] = pack4xI8(vec4(b_value_lower[2], b_value_upper[2], b_value_lower[3], b_value_upper[3])); + tile_B[col][row] = DequantizedFrom4BitsTo8Bits(b_value); if (col == 0) { // kidx_v - each kidx_v covers 16 values of k scale_B[row] = scales_b[b_global*(uniforms.K/block_size) + kidx_v/(block_size/16)]; } } - - // Scaled dot product of 8 packed unsigned integers. - fn SDP8AI(a1:vec4, b1:vec4, a2:vec4, b2:vec4, scale:output_element_t) -> output_element_t - { - var local_sum = dot4I8Packed(a1[0], b1[0]); - local_sum += dot4I8Packed(a1[1], b1[1]); - local_sum += dot4I8Packed(a1[2], b1[2]); - local_sum += dot4I8Packed(a1[3], b1[3]); - local_sum += dot4I8Packed(a2[0], b2[0]); - local_sum += dot4I8Packed(a2[1], b2[1]); - local_sum += dot4I8Packed(a2[2], b2[2]); - local_sum += dot4I8Packed(a2[3], b2[3]); - return output_element_t(local_sum) * scale; - } )ADDNL_FN"; shader.MainFunctionBody() << R"MAIN_FN( @@ -249,11 +262,122 @@ Status DP4AMatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { return Status::OK(); } +// scale_A components = 1, b components = 4, output components = 1 +Status DP4AMatMulNBitsSmallMProgram::GenerateShaderCode(ShaderHelper& shader) const { + shader.AddInput("input_a", ShaderUsage::UseUniform); + shader.AddInput("scales_a", ShaderUsage::UseUniform); + shader.AddInput("input_b", ShaderUsage::UseUniform); + shader.AddInput("scales_b", ShaderUsage::UseUniform); + shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseElementTypeAlias); + // This algorithm works to compute dot product of k parallelly, by processing k at each step amongst tile_size_k_vec threads, + // and utilizing the remaining threads in the workgroup to process additional rows of b in parallel (such that the values in shared memory for A can be reused). + // For each load of k, the tile_size_k_vec threads also reload B tile_size/num_concurrent_b_rows times to compute partial dot products of other B rows + // in order to complete all tile_size b rows in this workgroup and also reusing the loaded in register values of a. + + // 1. Each workgroup handles tile_size_k_vec (16) * k_vectorization_in_b (32) columns (total 512) and num_concurrent_b_rows of matrix B at a time, + // iterating over the columns to compute a partial dot product. + // 2. Uses vec4 vectorization where each K represents 32 elements of matrix B + constexpr uint32_t tile_size_k_vec = 16; + + // 1. Workgroup Responsibility: + // - Processes one row of matrix A + // - Handles tile_size rows of matrix B + // + // 2. Computation Process: + // - Reads [tile_size][tile_size_k_vec] block of B data at a time + // - Each thread within workgroup computes dot products of 32 A*B elements since each K represents 32 elements of matrix B + // - Stores intermediate results in shared memory (inter_results) + // - Iterates through columns accumulating results in inter_results + // - Performs final reduction sum in inter_results for output + shader.AdditionalImplementation() << "const tile_size = " << tile_size_ << "u;\n" + << "const tile_size_k_vec = " << tile_size_k_vec << "u;\n" + // sub_tile_size is the number of concurrent b rows processed by the workgroup. + << "const sub_tile_size = " << WorkgroupSizeX() / tile_size_k_vec << "u;\n"; + shader.AdditionalImplementation() << commonFunctions + << R"ADDNL_FN( + // Shared memory + // Need 2 * tile_size_k_vec (32) to store a tile_A since b is quantized as 4 bits and a is quantized as 8 bits. + var tile_A : array, 32>; + // Need 4 scales value since each tile_A includes 512 (4x4x32) scalars and the block_size is 128. + var scale_A : array; + var inter_results: array, tile_size>; + fn loadSHMA(a_global: u32, kidx_v: u32, col: u32) + { + let k_offset = kidx_v + col; + if (k_offset >= uniforms.K16) { + return; + } + + tile_A[col] = input_a[a_global*uniforms.K16+k_offset]; + if (col < 4) + { + // kidx_v - covers 16 values of k in input_a + scale_A[col] = scales_a[a_global*(uniforms.K/128) + kidx_v/8 + col]; + } + } + )ADDNL_FN"; + + shader.MainFunctionBody() << R"MAIN_FN( + let a_global = u32(workgroup_idx / uniforms.num_N_tile); + let b_global_base = (workgroup_idx % uniforms.num_N_tile) * tile_size; + // Handle each workgroup threads as a block of [sub_tile_size][tile_size_k_vec] + let local_col = local_idx % tile_size_k_vec; + let local_row = local_idx / tile_size_k_vec; + for (var kidx_v:u32 = 0; kidx_v < uniforms.K32; kidx_v += tile_size_k_vec) + { + // Load Phase: Populate shared memory for the workgroup. + if (local_idx < 32) + { + loadSHMA(a_global, kidx_v * 2, local_idx); + } + workgroupBarrier(); + var own_a: vec4 = tile_A[local_col * 2]; + var own_a1: vec4 = tile_A[local_col * 2 + 1]; + var own_scale_a = scale_A[local_col / 4]; + var own_b = vec4(0); + var own_b1 = vec4(0); + let k_offset = kidx_v + local_col; + // calculate intermediate results into inter_results. + for (var row_offset = 0u; row_offset < tile_size; row_offset += sub_tile_size) { + let b_global = b_global_base + row_offset + local_row; + if (b_global < uniforms.N && k_offset < uniforms.K32) + { + let b_offset = b_global * uniforms.K32 + k_offset; + let b_value = input_b[b_offset]; + own_b = DequantizedFrom4BitsTo8Bits(b_value.xy); + own_b1 = DequantizedFrom4BitsTo8Bits(b_value.zw); + + // k_offset - covers 32 values of k in input_b + let own_scale_b = scales_b[b_global * uniforms.K / uniforms.block_size + k_offset * 32 / uniforms.block_size]; + inter_results[row_offset + local_row][local_col] += SDP8AI(own_a, own_b, own_a1, own_b1, own_scale_a * own_scale_b); + } + } + workgroupBarrier(); + } + + if (local_idx < tile_size) { + // Do reduce sum to get final output. + var output_value = output_element_t(0); + for (var b = 0u; b < tile_size_k_vec; b++) { + output_value += inter_results[local_idx][b]; + } + let b_global = b_global_base + local_idx; + let output_idx = a_global * uniforms.N + b_global; + if (b_global < uniforms.N) { + output[output_idx] = output_value; + } + } + )MAIN_FN"; + + return Status::OK(); +} + Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor* scales, uint32_t M, uint32_t N, uint32_t K, uint32_t block_size, + uint32_t min_M_for_tile_optimization, onnxruntime::webgpu::ComputeContext& context, Tensor* y) { constexpr uint32_t kVec4Components = 4; @@ -273,6 +397,21 @@ Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor {&a_scale, ProgramTensorMetadataDependency::Rank, a_scale.Shape(), 1}}); ORT_RETURN_IF_ERROR(context.RunProgram(quantize_program)); + if (M < min_M_for_tile_optimization) { + constexpr uint32_t kTileSize = 32; + DP4AMatMulNBitsSmallMProgram mul_program{kTileSize}; + uint32_t num_N_tile = (N + kTileSize - 1) / kTileSize; + mul_program.SetWorkgroupSize(128); + mul_program.SetDispatchGroupSize(M * num_N_tile); + mul_program.AddInputs({{&a_quant, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec4Components)}, + {&a_scale, ProgramTensorMetadataDependency::TypeAndRank, 1}, + {b, ProgramTensorMetadataDependency::TypeAndRank, static_cast(kVec4Components * kU32Components)}, + {scales, ProgramTensorMetadataDependency::TypeAndRank, 1}}) + .AddUniformVariables({M, N, K, K / 16, K / 32, block_size, num_N_tile}) + .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, 1}); + return context.RunProgram(mul_program); + } + constexpr uint32_t kTileSize = 64; TensorShape reshaped_y_shape{1, M, N / kVec4Components}; uint32_t num_M_tile = (M + kTileSize - 1) / kTileSize; diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h index f0157ca3e8c97..67e2e7d66e83a 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.h @@ -34,11 +34,29 @@ class DP4AMatMulNBitsProgram final : public Program { uint32_t block_size_; }; +class DP4AMatMulNBitsSmallMProgram final : public Program { + public: + DP4AMatMulNBitsSmallMProgram(uint32_t tile_size) : Program{"DP4AMatMulNBitsSmallMProgram"}, tile_size_(tile_size) {} + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( + {"M", ProgramUniformVariableDataType::Uint32}, + {"N", ProgramUniformVariableDataType::Uint32}, + {"K", ProgramUniformVariableDataType::Uint32}, + {"K16", ProgramUniformVariableDataType::Uint32}, + {"K32", ProgramUniformVariableDataType::Uint32}, + {"block_size", ProgramUniformVariableDataType::Uint32}, + {"num_N_tile", ProgramUniformVariableDataType::Uint32}); + + private: + uint32_t tile_size_; +}; + Status ApplyDP4AMatrixMatMulNBits(const Tensor* a, const Tensor* b, const Tensor* scales, uint32_t M, uint32_t N, uint32_t K, uint32_t block_size, + uint32_t min_M_for_tile_optimization, onnxruntime::webgpu::ComputeContext& context, Tensor* y); diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index cce10a59fbd4b..b4e47b9186265 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -574,9 +574,9 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context return ApplySubgroupMatrixMatMulNBits(a, b, scales, M, N, K, context, y); } - if (M >= kMinMForTileOptimization && - CanApplyDP4AMatrixMatMulNBits(context, accuracy_level_, block_size, batch_count, N, K, components_a, has_zero_points)) { - return ApplyDP4AMatrixMatMulNBits(a, b, scales, M, N, K, block_size, context, y); + // On FP32 only GPUs, integer math is faster than FP32 therefore always use DP4A independent of length of M. + if ((M >= kMinMForTileOptimization || y->DataType() == DataTypeImpl::GetType()) && CanApplyDP4AMatrixMatMulNBits(context, accuracy_level_, block_size, batch_count, N, K, components_a, has_zero_points)) { + return ApplyDP4AMatrixMatMulNBits(a, b, scales, M, N, K, block_size, kMinMForTileOptimization, context, y); } // TODO: Support output_number > 1. Some cases are failed when output_number > 1. From db0c95c16c0a1fb3265bde2ea48f585db40ad52a Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Thu, 20 Mar 2025 10:14:09 -0700 Subject: [PATCH 137/266] [CUDA] Support slide window in cutlass fused attention (#24072) ### Description Add slide window support in cutlass fused attention ### Motivation and Context The change was previously created by Ye: https://github.com/microsoft/onnxruntime/pull/21926 I merged the change and resolved some conflictions. Also reversed some Ye's change in kernel_forward.h, so that our code is consistent with pytorch code. --- .../cpu/bert/attention_parameters.h | 6 +- .../contrib_ops/cpu/bert/gqa_attention_base.h | 3 +- .../contrib_ops/cuda/bert/attention_impl.cu | 2 +- .../bert/cutlass_fmha/fmha_launch_template.h | 3 + .../cuda/bert/cutlass_fmha/kernel_forward.h | 65 +- .../cutlass_fmha/memory_efficient_attention.h | 55 +- .../cuda/bert/group_query_attention.cc | 7 +- .../cuda/bert/group_query_attention_impl.cu | 1 + .../bert/packed_multihead_attention_impl.cu | 4 +- ...st_flash_attn_cuda.py => test_gqa_cuda.py} | 573 ++---------------- ...st_flash_attn_rocm.py => test_gqa_rocm.py} | 3 +- .../transformers/test_mha_flash_attn.py | 452 ++++++++++++++ 12 files changed, 615 insertions(+), 559 deletions(-) rename onnxruntime/test/python/transformers/{test_flash_attn_cuda.py => test_gqa_cuda.py} (79%) rename onnxruntime/test/python/transformers/{test_flash_attn_rocm.py => test_gqa_rocm.py} (98%) create mode 100644 onnxruntime/test/python/transformers/test_mha_flash_attn.py diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h b/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h index 417865bb166ec..c3d5128948c6f 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_parameters.h @@ -87,9 +87,9 @@ struct GroupQueryAttentionParameters : AttentionParameters { int seqlen_present_kv_cache; // sequence length of present kv tensor int kv_hidden_size; int kv_num_heads; - int num_splits; // number of splits for splitkv - int rotary_dim; // rotary embedding dimension - int local_window_size; + int num_splits; // number of splits for splitkv + int rotary_dim; // rotary embedding dimension + int local_window_size; // The window size excludes current token. It only includes tokens on the left side. bool kv_share_buffer; bool is_packed_qkv; bool is_subsequent_prompt; // indicates whether we have past context and seqlen > 1 diff --git a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h index c8c66c880852f..c79508cbae273 100644 --- a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h @@ -270,7 +270,8 @@ class GQAAttentionBase { for (size_t seq = 0; seq < sequence_length; seq++) { size_t seq_causal_length = past_seqlen + seq + 1; - const bool should_apply_local_window = local_window_size_ > 0 && + // local_window_size does not include the current query token, while window_size includes it. + const bool should_apply_local_window = local_window_size_ >= 0 && seq_causal_length > static_cast(local_window_size_) + 1; const size_t start_offset = should_apply_local_window ? seq_causal_length - local_window_size_ - 1 : 0; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index 0209183f46425..84a7cc19f1576 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -512,7 +512,7 @@ Status EfficientAttention( p.seqstart_q_ptr = nullptr; p.seqstart_k_ptr = nullptr; } else { - p.seqlen_k_ptr = const_cast(reinterpret_cast(data.mask_index)); + p.seqlen_k_ptr = reinterpret_cast(data.mask_index); p.seqstart_q_ptr = p.seqlen_k_ptr + parameters.batch_size; p.seqstart_k_ptr = p.seqlen_k_ptr + 2 * parameters.batch_size + 1; } diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h index 9b3ba73254d73..8d8f735e3ed34 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h @@ -222,6 +222,9 @@ void LaunchCutlassFmha(const MemoryEfficientAttentionParams& params) { } p.use_smooth_softmax = params.use_smooth_softmax; + + // local_windows_size in GQA does not include current query token, while windows_size in this kernel includes it. + p.window_size = params.local_window_size + 1; } auto kernel_fn = attention_kernel_batched_impl; diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/kernel_forward.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/kernel_forward.h index 8dff521da48d1..f35d6c2e6c8dc 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/kernel_forward.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/kernel_forward.h @@ -174,10 +174,9 @@ struct AttentionKernel { scalar_t* key_ptr = nullptr; // [num_keys, num_heads, head_dim] scalar_t* value_ptr = nullptr; // [num_keys, num_heads, head_dim_value] scalar_t* attn_bias_ptr = nullptr; // [num_heads, num_queries, num_keys] - int32_t* seqstart_q_ptr = nullptr; - int32_t* seqstart_k_ptr = nullptr; - - int32_t* seqlen_k_ptr = nullptr; + const int32_t* seqstart_q_ptr = nullptr; + const int32_t* seqstart_k_ptr = nullptr; + const int32_t* seqlen_k_ptr = nullptr; uint32_t causal_diagonal_offset = 0; // Output tensors @@ -187,6 +186,8 @@ struct AttentionKernel { // [num_heads, num_queries] - can be null lse_scalar_t* logsumexp_ptr = nullptr; + int32_t window_size = -1; + // Scale accum_t scale = 0.0; @@ -651,6 +652,12 @@ struct AttentionKernel { XFORMERS_CHECK( p.custom_mask_type < NumCustomMaskTypes, "invalid value for `custom_mask_type`"); + if (p.window_size > 0) { + XFORMERS_CHECK( + p.custom_mask_type == CausalFromTopLeft || + p.custom_mask_type == CausalFromBottomRight, + "invalid value for custom_mask_type"); + } return true; } @@ -726,6 +733,13 @@ struct AttentionKernel { // Iterate through keys for (int32_t iter_key_start = 0; iter_key_start < p.num_keys; iter_key_start += kKeysPerBlock) { + if (p.window_size > 0) { + // don't compute anything if below attention band + if (iter_key_start + kKeysPerBlock < + static_cast(query_start + p.causal_diagonal_offset) - p.window_size) { + continue; + } + } int32_t problem_size_0_m = cutlass::fast_min((int32_t)kQueriesPerBlock, p.num_queries); int32_t problem_size_0_n = cutlass::fast_min( @@ -894,6 +908,38 @@ struct AttentionKernel { }, [&](int accum_m) {}); } + + // Mask out lower left corner of block if window_size > 0 + // only required if current block intersects with the lower left corner + // block starts at x_lowerleft = iter_key_start // y = query_start + + // kQueriesPerBlock first non masked value at this y is : x_first = + // query_start + kQueriesPerBlock - window_size mask if x_fist > + // x_lowerleft + + if (p.window_size > 0 && + (query_start + p.causal_diagonal_offset + + cutlass::fast_min( + static_cast(kQueriesPerBlock), static_cast(p.num_queries)) - + p.window_size >= + iter_key_start)) { + auto query_start = blockIdx.x * kQueriesPerBlock; + auto lane_offset = MM0::AccumLambdaIterator::get_lane_offset( + my_lane_id, my_warp_id, iteratorC_tile_offset); + int32_t first_col; + const int32_t offset = query_start + p.causal_diagonal_offset - + p.window_size - iter_key_start; + MM0::AccumLambdaIterator::iterateRows( + lane_offset, + [&](int accum_m) { first_col = accum_m + offset; }, + [&](int accum_m, int accum_n, int idx) { + if (accum_n <= first_col) { + accum[idx] = + -cutlass::platform::numeric_limits::infinity(); + } + }, + [&](int accum_m) {}); + } + // Update `mi` from accum stored in registers // Also does accum[i] <- exp(accum[i] - mi) iterative_softmax( @@ -1036,9 +1082,18 @@ struct AttentionKernel { } if (!kKeepOutputInRF) { + int first_key = 0; + if (p.window_size > 0) { + first_key = (cutlass::fast_max( + static_cast(query_start + p.causal_diagonal_offset) - + p.window_size + 1, + 0) / + kKeysPerBlock) * + kKeysPerBlock; + } MM1::Mma::drain_cp_asyncs(); DISPATCH_BOOL( - iter_key_start == 0, kIsFirst, ([&] { + iter_key_start == first_key, kIsFirst, ([&] { DISPATCH_BOOL( (iter_key_start + kKeysPerBlock) >= p.num_keys, kIsLast, diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h index 9fe66c6fe992e..287413bf5acde 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h @@ -14,42 +14,39 @@ namespace cuda { constexpr int kEfficientAttentionMaxHeadSize = 1024; struct MemoryEfficientAttentionParams { - int32_t sm; - bool is_half; + int32_t sm = 50; + bool is_half = false; bool is_kv_bsnh = true; - int32_t batch_size; - int32_t num_heads; - int32_t sequence_length; - int32_t kv_sequence_length; - int32_t max_sequence_length; - int32_t qk_head_size; - int32_t v_head_size; - bool causal; - bool use_smooth_softmax; - - float scale; + int32_t batch_size = 0; + int32_t num_heads = 0; + int32_t sequence_length = 0; + int32_t kv_sequence_length = 0; + int32_t max_sequence_length = 0; + int32_t qk_head_size = 0; + int32_t v_head_size = 0; + int32_t local_window_size = -1; + bool causal = false; + bool use_smooth_softmax = false; + bool broadcast_attn_bias_dim_0 = false; + bool broadcast_attn_bias_dim_1 = false; + bool has_custom_right_padding = false; + float scale = 1.0f; float softcap = 0.0; - int32_t* seqstart_q_ptr; - int32_t* seqstart_k_ptr; - int32_t* seqlen_k_ptr; - - const void* query; // [B, S, N, H] - const void* key; // [B, L, N, H], where L is kv_sequence_length - const void* value; // [B, L, N, H_v] - const void* attn_bias; // [B or 1, N or 1, S, L] or null - bool broadcast_attn_bias_dim_0; - bool broadcast_attn_bias_dim_1; - - void* output; // [B, S, N, H_v] - void* workspace; // [B, S, N, H_v] when kNeedsOutputAccumulatorBuffer, nullptr otherwise - cudaStream_t stream; + cudaStream_t stream = nullptr; + const int32_t* seqstart_q_ptr = nullptr; // [B + 1], cumulated sequence lengths of queries + const int32_t* seqstart_k_ptr = nullptr; // [B + 1], cumulated sequence lengths of keys + const int32_t* seqlen_k_ptr = nullptr; // [B], sequence lengths of keys + const void* query = nullptr; // [B, S, N, H] + const void* key = nullptr; // [B, L, N, H], where L is kv_sequence_length + const void* value = nullptr; // [B, L, N, H_v] + const void* attn_bias = nullptr; // [B or 1, N or 1, S, L] or null + void* workspace = nullptr; // [B, S, N, H_v] when kNeedsOutputAccumulatorBuffer, nullptr otherwise + void* output = nullptr; // [B, S, N, H_v] static bool need_workspace(size_t v_head_size, bool is_float) { return (v_head_size > 128 && !is_float); } - - bool has_custom_right_padding = false; }; void run_memory_efficient_attention(const MemoryEfficientAttentionParams& params); diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc index 8b63b363d8863..9f1bc46ee297d 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc @@ -156,13 +156,8 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { bool use_memory_efficient_attention = !use_flash_attention && !disable_memory_efficient_attention_ && - local_window_size_ == -1 && - (sizeof(T) == 2 || parameters.sequence_length >= this->kernel_options_->MinSeqLenForEfficientAttentionFp32()) && has_memory_efficient_attention(sm, sizeof(T) == 2, parameters.head_size, parameters.head_size); - if (!use_flash_attention && !use_memory_efficient_attention && local_window_size_ != -1) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Local attention UNSUPPORTED for sm < 80 on CUDA."); - } + // allocate buffers size_t kv_buffer_bytes = 0; // need a buffer if we must ungroup kv diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu index dbbee87238d0c..2d1b49033003d 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu @@ -635,6 +635,7 @@ Status EfficientAttention( p.stream = stream; p.has_custom_right_padding = true; p.use_smooth_softmax = parameters.use_smooth_softmax; + p.local_window_size = parameters.local_window_size; run_memory_efficient_attention(p); DUMP_TENSOR("efficient attention output", data.output, batch_size, sequence_length, num_heads, head_size); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu index f3b9fd310f46f..846d2be7bf2e1 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu @@ -698,8 +698,8 @@ Status FusedAttentionCutlass( p.scale = parameters.scale == 0.0f ? 1.f / sqrt(static_cast(qk_head_size)) : parameters.scale; p.seqlen_k_ptr = nullptr; - p.seqstart_q_ptr = const_cast(data.cumulative_sequence_length); - p.seqstart_k_ptr = const_cast(data.cumulative_sequence_length); + p.seqstart_q_ptr = data.cumulative_sequence_length; + p.seqstart_k_ptr = data.cumulative_sequence_length; p.query = data.no_qkv_workspace ? data.query : data.workspace; p.key = data.no_qkv_workspace ? data.key : (data.workspace + elements_qk); p.value = data.no_qkv_workspace ? data.value : (data.workspace + elements_qk + elements_qk); diff --git a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py b/onnxruntime/test/python/transformers/test_gqa_cuda.py similarity index 79% rename from onnxruntime/test/python/transformers/test_flash_attn_cuda.py rename to onnxruntime/test/python/transformers/test_gqa_cuda.py index a74d5389e9047..3923b229a0bff 100644 --- a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py +++ b/onnxruntime/test/python/transformers/test_gqa_cuda.py @@ -17,7 +17,6 @@ import numpy import torch -from bert_padding import pad_input, unpad_input from einops import rearrange, repeat from onnx import TensorProto, helper from packaging import version @@ -39,20 +38,16 @@ class Formats: class Config: batch_size = 0 sequence_length = 0 - kv_sequence_length = 0 - past_sequence_length = 0 + kv_sequence_length = 0 # this is past sequence length when there is past state. num_heads = 0 kv_num_heads = 0 head_size = 0 ep = "CUDAExecutionProvider" - def __init__( - self, batch_size, sequence_length, kv_sequence_length, past_sequence_length, num_heads, kv_num_heads, head_size - ): + def __init__(self, batch_size, sequence_length, kv_sequence_length, num_heads, kv_num_heads, head_size): self.batch_size = batch_size self.sequence_length = sequence_length self.kv_sequence_length = kv_sequence_length - self.past_sequence_length = past_sequence_length self.num_heads = num_heads self.kv_num_heads = kv_num_heads self.head_size = head_size @@ -61,7 +56,7 @@ def __repr__(self): short_ep = self.ep[: -len("ExecutionProvider")].lower() return ( f"Config(batch_size={self.batch_size}, sequence_length={self.sequence_length}, " - f"kv_sequence_length={self.kv_sequence_length}, past_sequence_length={self.past_sequence_length}, " + f"kv_sequence_length={self.kv_sequence_length}, " f"num_heads={self.num_heads}, kv_num_heads={self.kv_num_heads}, head_size={self.head_size}, ep={short_ep})" ) @@ -103,118 +98,6 @@ def __repr__(self): ) -def create_packed_multihead_attention_graph(config): - nodes = [ - helper.make_node( - "PackedMultiHeadAttention", - [ - "query", - "", - "", - "", - "token_offset", - "cumulative_sequence_length", - ], - ["output"], - "PackedMultiHeadAttention_0", - num_heads=config.num_heads, - domain="com.microsoft", - ), - ] - - graph = helper.make_graph( - nodes, - "PackedMultiHeadAttention_Graph", - [ - helper.make_tensor_value_info( - "query", - TensorProto.FLOAT16, - [ - -1, - config.num_heads, - 3, - config.head_size, - ], - ), - helper.make_tensor_value_info( - "token_offset", TensorProto.INT32, [config.batch_size, config.sequence_length] - ), - helper.make_tensor_value_info("cumulative_sequence_length", TensorProto.INT32, [config.batch_size + 1]), - ], - [ - helper.make_tensor_value_info( - "output", - TensorProto.FLOAT16, - [-1, config.num_heads * config.head_size], - ), - ], - ) - - model = helper.make_model(graph) - return model.SerializeToString() - - -def create_multihead_attention_graph(config): - nodes = [ - helper.make_node( - "MultiHeadAttention", - [ - "query", - "key", - "value", - ], - ["output"], - "MultiHeadAttention_0", - num_heads=config.num_heads, - domain="com.microsoft", - ), - ] - - graph = helper.make_graph( - nodes, - "MultiHeadAttention_Graph", - [ - helper.make_tensor_value_info( - "query", - TensorProto.FLOAT16, - [ - config.batch_size, - config.sequence_length, - config.num_heads * config.head_size, - ], - ), - helper.make_tensor_value_info( - "key", - TensorProto.FLOAT16, - [ - config.batch_size, - config.kv_sequence_length, - config.num_heads * config.head_size, - ], - ), - helper.make_tensor_value_info( - "value", - TensorProto.FLOAT16, - [ - config.batch_size, - config.kv_sequence_length, - config.num_heads * config.head_size, - ], - ), - ], - [ - helper.make_tensor_value_info( - "output", - TensorProto.FLOAT16, - [config.batch_size, config.sequence_length, config.num_heads * config.head_size], - ), - ], - ) - - model = helper.make_model(graph) - return model.SerializeToString() - - def create_group_query_attention_graph_prompt( config, past_kv_format=Formats.BSNH, @@ -575,204 +458,6 @@ def create_group_query_attention_graph_past( return model.SerializeToString() -def generate_random_padding_mask(max_seqlen, batch_size, device, mode="random"): - assert mode in ["full", "random", "third"] - if mode == "full": - lengths = torch.full((batch_size, 1), max_seqlen, device=device, dtype=torch.int32) - elif mode == "random": - lengths = torch.randint(max(1, max_seqlen - 20), max_seqlen, (batch_size, 1), device=device) - else: - lengths = torch.randint(max_seqlen // 3, max_seqlen, (batch_size, 1), device=device) - padding_mask = repeat(torch.arange(max_seqlen, device=device), "s -> b s", b=batch_size) < lengths - return padding_mask - - -def generate_qkv(q, k, v, query_padding_mask=None, key_padding_mask=None, kvpacked=False, qkvpacked=False): - """ - Arguments: - q: (batch_size, seqlen_q, nheads, d) - k: (batch_size, seqlen_k, nheads_k, d) - v: (batch_size, seqlen_k, nheads_k, d) - query_padding_mask: (batch_size, seqlen), bool - key_padding_mask: (batch_size, seqlen), bool - """ - assert not (kvpacked and qkvpacked) - batch_size, seqlen_q, nheads, d = q.shape - _, seqlen_k, nheads_k, _ = k.shape - assert k.shape == (batch_size, seqlen_k, nheads_k, d) - assert v.shape == (batch_size, seqlen_k, nheads_k, d) - - if query_padding_mask is not None: - q_unpad, indices_q, cu_seqlens_q, max_seqlen_q = unpad_input(q, query_padding_mask) - - def output_pad_fn(output_unpad): - return pad_input(output_unpad, indices_q, batch_size, seqlen_q) - - else: - q_unpad = rearrange(q, "b s h d -> (b s) h d") - cu_seqlens_q = torch.arange( - 0, (batch_size + 1) * seqlen_q, step=seqlen_q, dtype=torch.int32, device=q_unpad.device - ) - max_seqlen_q = seqlen_q - - def output_pad_fn(output_unpad): - return rearrange(output_unpad, "(b s) h d -> b s h d", b=batch_size) - - if key_padding_mask is not None: - k_unpad, indices_k, cu_seqlens_k, max_seqlen_k = unpad_input(k, key_padding_mask) - v_unpad, _, _, _ = unpad_input(v, key_padding_mask) - else: - k_unpad = rearrange(k, "b s h d -> (b s) h d") - v_unpad = rearrange(v, "b s h d -> (b s) h d") - cu_seqlens_k = torch.arange( - 0, (batch_size + 1) * seqlen_k, step=seqlen_k, dtype=torch.int32, device=k_unpad.device - ) - max_seqlen_k = seqlen_k - - if qkvpacked: - assert (query_padding_mask == key_padding_mask).all() - assert nheads == nheads_k - qkv_unpad = torch.stack([q_unpad, k_unpad, v_unpad], dim=1) - qkv = torch.stack([q, k, v], dim=2) - if query_padding_mask is not None: - - def dqkv_pad_fn(dqkv_unpad): - return pad_input(dqkv_unpad, indices_q, batch_size, seqlen_q) - - else: - - def dqkv_pad_fn(dqkv_unpad): - return rearrange(dqkv_unpad, "(b s) t h d -> b s t h d", b=batch_size) - - return ( - qkv_unpad.detach().requires_grad_(), - cu_seqlens_q, - max_seqlen_q, - qkv.detach().requires_grad_(), - output_pad_fn, - dqkv_pad_fn, - ) - elif kvpacked: - kv_unpad = torch.stack([k_unpad, v_unpad], dim=1) - kv = torch.stack([k, v], dim=2) - dq_pad_fn = output_pad_fn - if key_padding_mask is not None: - - def dkv_pad_fn(dkv_unpad): - return pad_input(dkv_unpad, indices_k, batch_size, seqlen_k) - - else: - - def dkv_pad_fn(dkv_unpad): - return rearrange(dkv_unpad, "(b s) t h d -> b s t h d", b=batch_size) - - return ( - q_unpad.detach().requires_grad_(), - kv_unpad.detach().requires_grad_(), - cu_seqlens_q, - cu_seqlens_k, - max_seqlen_q, - max_seqlen_k, - q.detach().requires_grad_(), - kv.detach().requires_grad_(), - output_pad_fn, - dq_pad_fn, - dkv_pad_fn, - ) - else: - dq_pad_fn = output_pad_fn - if key_padding_mask is not None: - - def dk_pad_fn(dk_unpad): - return pad_input(dk_unpad, indices_k, batch_size, seqlen_k) - - else: - - def dk_pad_fn(dk_unpad): - return rearrange(dk_unpad, "(b s) h d -> b s h d", b=batch_size) - - return ( - q_unpad.detach().requires_grad_(), - k_unpad.detach().requires_grad_(), - v_unpad.detach().requires_grad_(), - cu_seqlens_q, - cu_seqlens_k, - max_seqlen_q, - max_seqlen_k, - q.detach().requires_grad_(), - k.detach().requires_grad_(), - v.detach().requires_grad_(), - output_pad_fn, - dq_pad_fn, - dk_pad_fn, - ) - - -def create_inputs(config: Config, kv_packed=False, qkv_packed=True): - qkv = torch.randn( - config.batch_size, - config.sequence_length, - 3, - config.num_heads, - config.head_size, - device="cuda", - dtype=torch.float16, - requires_grad=False, - ) - key_padding_mask = generate_random_padding_mask( - config.sequence_length, config.batch_size, device="cuda", mode="random" - ) - qkv_unpad, cu_seqlens, max_seqlen, qkv, output_pad_fn, dqkv_pad_fn = generate_qkv( - *qkv.unbind(dim=2), key_padding_mask, key_padding_mask, kv_packed, qkv_packed - ) - return qkv_unpad, cu_seqlens, max_seqlen, qkv, output_pad_fn, dqkv_pad_fn, key_padding_mask - - -def generate_token_offset(cu_seqlens, max_seqlen): - token_offset = [] - token_padset = [] # These are the indices that contain padding tokens - for i in range(1, len(cu_seqlens)): - start = i - 1 - pre_seqlen = cu_seqlens[i - 1] - seqlen = cu_seqlens[i] - token_offset += range(start * max_seqlen, (start * max_seqlen) + (seqlen - pre_seqlen)) - token_padset += range((start * max_seqlen) + (seqlen - pre_seqlen), i * max_seqlen) - return numpy.asarray(token_offset + token_padset, dtype=numpy.int32) - - -def flash_attn_varlen_qkvpacked_func(qkv_unpad, cu_seqlens, token_offset, config, causal=False): - onnx_model_str = create_packed_multihead_attention_graph(config) - qkv_unpad = torch.swapdims(qkv_unpad, 1, 2) - ort_inputs = { - "query": qkv_unpad.detach().cpu().numpy(), - "token_offset": token_offset, - "cumulative_sequence_length": cu_seqlens.cpu().numpy(), - } - sess_options = SessionOptions() - ort_session = InferenceSession(onnx_model_str, sess_options, providers=[config.ep]) - ort_output = ort_session.run(None, ort_inputs) - output = torch.tensor(ort_output) - return output - - -def mha_func(q, k, v, config): - onnx_model_str = create_multihead_attention_graph(config) - q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) - k = torch.reshape(k, (config.batch_size, config.kv_sequence_length, -1)) - v = torch.reshape(v, (config.batch_size, config.kv_sequence_length, -1)) - ort_inputs = { - "query": q.detach().cpu().numpy(), - "key": k.detach().cpu().numpy(), - "value": v.detach().cpu().numpy(), - } - sess_options = SessionOptions() - ort_session = InferenceSession(onnx_model_str, sess_options, providers=[config.ep]) - ort_output = ort_session.run(None, ort_inputs) - ort_output = numpy.array(ort_output) - output = torch.tensor(ort_output) - return output - - def rotary_options_for_current_os(): # Reference implementation of rotary uses triton, which is not available in Windows. # So we only test rotary in Linux right now. @@ -1009,14 +694,6 @@ def gqa_past_func( return output, present_k, present_v -def construct_causal_mask(seqlen_q, seqlen_k, query_padding_mask=None, key_padding_mask=None, device=None): - row_idx = rearrange(torch.arange(seqlen_q, device=device, dtype=torch.long), "s -> s 1") - col_idx = torch.arange(seqlen_k, device=device, dtype=torch.long) - sk = seqlen_k if key_padding_mask is None else rearrange(key_padding_mask.sum(-1), "b -> b 1 1 1") - sq = seqlen_q if query_padding_mask is None else rearrange(query_padding_mask.sum(-1), "b -> b 1 1 1") - return col_idx > row_idx + sk - sq - - def construct_local_mask( seqlen_q, seqlen_k, @@ -1127,93 +804,6 @@ def attention_ref( return output.to(dtype=dtype_og), attention.to(dtype=dtype_og) -def attention_qkvpacked_ref( - qkv, - key_padding_mask=None, - dropout_p=0.0, - dropout_mask=None, - causal=False, - upcast=True, - reorder_ops=False, - use_smooth_softmax=False, -): - return attention_ref( - qkv[:, :, 0], - qkv[:, :, 1], - qkv[:, :, 2], - key_padding_mask, - key_padding_mask, - dropout_p, - dropout_mask, - upcast=upcast, - causal=causal, - reorder_ops=reorder_ops, - use_smooth_softmax=use_smooth_softmax, - ) - - -def parity_check_mha( - config, - packed, - rtol=1e-3, - atol=1e-3, -): - if packed: - qkv_unpad, cu_seqlens, _, qkv, output_pad_fn, _, key_padding_mask = create_inputs(config) - token_offset = generate_token_offset(cu_seqlens, config.sequence_length).reshape( - (config.batch_size, config.sequence_length) - ) - # ORT Flash - out_unpad = flash_attn_varlen_qkvpacked_func(qkv_unpad, cu_seqlens, token_offset, config, causal=False) - out_unpad = torch.squeeze(out_unpad, 0) - out = torch.reshape( - output_pad_fn(out_unpad), (config.batch_size, config.sequence_length, config.num_heads, config.head_size) - ) - out = out.detach().cpu().numpy() - # Pytorch to compare - out_ref, _ = attention_qkvpacked_ref(qkv, key_padding_mask, 0.0, None, causal=False) - out_ref = out_ref.detach().cpu().numpy() - else: - q = torch.randn( - config.batch_size, - config.sequence_length, - config.num_heads, - config.head_size, - device="cuda", - dtype=torch.float16, - requires_grad=False, - ) - k = torch.randn( - config.batch_size, - config.kv_sequence_length, - config.kv_num_heads, - config.head_size, - device="cuda", - dtype=torch.float16, - requires_grad=False, - ) - v = torch.randn( - config.batch_size, - config.kv_sequence_length, - config.kv_num_heads, - config.head_size, - device="cuda", - dtype=torch.float16, - requires_grad=False, - ) - out = mha_func(q, k, v, config) - out = torch.squeeze(out, 0) - out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) - out = out.detach().cpu().numpy() - # Pytorch to compare - out_ref, _ = attention_ref(q, k, v, None, None, 0.0, None, causal=False) - out_ref = out_ref.detach().cpu().numpy() - - numpy.testing.assert_allclose( - out, out_ref, rtol=rtol, atol=atol, equal_nan=True, err_msg=f" with {config} packed={packed}" - ) - - def rotary_embedding(*args, **kwargs): # Use local import since triton is not available in Windows. from rotary_flash import apply_rotary_emb @@ -1222,7 +812,7 @@ def rotary_embedding(*args, **kwargs): def parity_check_gqa_prompt( - config, + config: PromptConfig, causal=True, local=False, past_format=Formats.BNSH, @@ -1420,7 +1010,7 @@ def parity_check_gqa_prompt( def parity_check_gqa_prompt_no_buff( - config, + config: PromptConfig, causal=True, local=False, past_format=Formats.BNSH, @@ -1595,7 +1185,7 @@ def parity_check_gqa_prompt_no_buff( def parity_check_gqa_past( - config, + config: Config, causal=True, local=False, past_format=Formats.BNSH, @@ -1788,7 +1378,7 @@ def parity_check_gqa_past( def parity_check_gqa_past_no_buff( - config, + config: Config, causal=True, local=False, past_format=Formats.BNSH, @@ -2019,67 +1609,6 @@ def has_memory_efficient(): return True -def packed_mha_test_cases(): - batches = [2] if pipeline_mode else [1, 5] - seqs = [1024, 1025] if pipeline_mode else [1024, 1025, 2048] - num_h = [1, 3] if pipeline_mode else [1, 6, 16] - h_sizes = [16, 256] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] - - for b in batches: - for s in seqs: - for n in num_h: - for h in h_sizes: - config = Config(b, s, s, 0, n, n, h) - yield str(config), config - - -def mha_test_cases(): - batches = [2] if pipeline_mode else [1, 5] - seqs = ( - [(1, 128), (113, 211), (2048, 2048)] - if pipeline_mode - else [ - (113, 203), - (128, 217), - (113, 211), - (108, 256), - (256, 512), - (512, 256), - (1024, 1024), - (1023, 1024), - (1024, 1023), - (2048, 2048), - ] - ) - num_h = [3] if pipeline_mode else [1, 6, 16] - h_sizes = [64] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] - - for b in batches: - for s, s2 in seqs: - for n in num_h: - for h in h_sizes: - config = Config(b, s, s2, 0, n, n, h) - yield str(config), config - - -class TestMHA(unittest.TestCase): - @parameterized.expand(packed_mha_test_cases()) - def test_packed_mha(self, _, config): - if not has_flash_attention(): - return - os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "0" - print("-------- TEST PACKED MHA ---------") - parity_check_mha(config, True) - - @parameterized.expand(mha_test_cases()) - def test_mha(self, _, config): - if not has_flash_attention(): - return - os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "0" - print("-------- TEST MHA ---------") - parity_check_mha(config, False) - - def gqa_no_past_memory_efficient_test_cases(): batches = [3] if pipeline_mode else [1, 3, 5] seqs = ( @@ -2103,18 +1632,22 @@ def gqa_no_past_memory_efficient_test_cases(): for sq, skv in seqs: for n, n2 in num_h: for h in h_sizes: - for rotary, rotary_interleaved in rotary_options_for_current_os(): - for packed in [False, True]: - for softcap in [0.0, 50.0]: - config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) - yield ( - str(config) + f"{rotary}_{rotary_interleaved}_{packed}", - config, - rotary, - rotary_interleaved, - packed, - softcap, - ) + for local in [False, True]: + for rotary, rotary_interleaved in rotary_options_for_current_os(): + for packed in [False, True]: + for softcap in [0.0, 50.0]: + config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) + if rotary and h % 16 > 0: + continue + yield ( + str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", + config, + local, + rotary, + rotary_interleaved, + packed, + softcap, + ) def gqa_no_past_flash_attention_test_cases(): @@ -2144,9 +1677,12 @@ def gqa_no_past_flash_attention_test_cases(): for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: for softcap in [0.0, 50.0]: + if rotary and h % 16 > 0: + continue + config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) yield ( - str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", + str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}_{softcap}", config, local, rotary, @@ -2183,19 +1719,22 @@ def gqa_past_memory_efficient_test_cases(): for s, s2 in seqs: for n, n2 in num_h: for h in h_sizes: - for rotary, rotary_interleaved in rotary_options_for_current_os(): - for packed in [False, True]: - for softcap in [0.0, 50.0]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) - yield ( - str(config) + f"{rotary}_{rotary_interleaved}_{packed}", - config, - rotary, - rotary_interleaved, - packed, - softcap, - ) + for local in [False, True]: + for rotary, rotary_interleaved in rotary_options_for_current_os(): + for packed in [False, True]: + for softcap in [0.0, 50.0]: + if rotary and h % 16 > 0: + continue + config = Config(b, s, s2, n, n2, h) + yield ( + str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}_{softcap}", + config, + local, + rotary, + rotary_interleaved, + packed, + softcap, + ) def gqa_past_flash_attention_test_cases(): @@ -2229,10 +1768,12 @@ def gqa_past_flash_attention_test_cases(): for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: for softcap in [0.0, 50.0]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) + if rotary and h % 16 > 0: + continue + + config = Config(b, s, s2, n, n2, h) yield ( - str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", + str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}_{softcap}", config, local, rotary, @@ -2272,7 +1813,10 @@ def gqa_interactive_one_batch_flash_attention_test_cases(): for local in [False, True]: for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: - config = Config(b, s, s2, -1, n, n2, h) + if rotary and h % 16 > 0: + continue + + config = Config(b, s, s2, n, n2, h) yield ( str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", config, @@ -2312,7 +1856,10 @@ def gqa_interactive_one_batch_memory_efficient_attention_test_cases(): for h in h_sizes: for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: - config = Config(b, s, s2, -1, n, n2, h) + if rotary and h % 16 > 0: + continue + + config = Config(b, s, s2, n, n2, h) yield ( str(config) + f"{rotary}_{rotary_interleaved}_{packed}", config, @@ -2410,12 +1957,13 @@ def test_gqa_interactive_one_batch_flash_attention(self, _, config, local, rotar @unittest.skipIf(not has_memory_efficient(), reason="Memory efficient FMHA is not available, skipping tests.") class TestMemoryEfficientGQA(unittest.TestCase): @parameterized.expand(gqa_no_past_memory_efficient_test_cases()) - def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleaved, packed, softcap): + def test_gqa_no_past_memory_efficient(self, _, config, local, rotary, rotary_interleaved, packed, softcap): os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "1" print("------- MEMORY EFFICIENT ATTENTION (PROMPT CASE) ---------") parity_check_gqa_prompt( config, + local=local, rtol=5e-3, atol=5e-3, past_format=Formats.BNSH, @@ -2427,6 +1975,7 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave ) parity_check_gqa_prompt_no_buff( config, + local=local, rtol=5e-3, atol=5e-3, past_format=Formats.BNSH, @@ -2438,12 +1987,13 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave ) @parameterized.expand(gqa_past_memory_efficient_test_cases()) - def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, packed, softcap): + def test_gqa_past_memory_efficient(self, _, config, local, rotary, rotary_interleaved, packed, softcap): os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "1" print("-------- MEMORY EFFICIENT (TOKEN GEN) --------") parity_check_gqa_past( config, + local=local, past_format=Formats.BNSH, rtol=1e-3, atol=1e-3, @@ -2455,6 +2005,7 @@ def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, ) parity_check_gqa_past_no_buff( config, + local=local, past_format=Formats.BNSH, rtol=1e-3, atol=1e-3, diff --git a/onnxruntime/test/python/transformers/test_flash_attn_rocm.py b/onnxruntime/test/python/transformers/test_gqa_rocm.py similarity index 98% rename from onnxruntime/test/python/transformers/test_flash_attn_rocm.py rename to onnxruntime/test/python/transformers/test_gqa_rocm.py index a5910c28c2975..29ae1b6e44a78 100644 --- a/onnxruntime/test/python/transformers/test_flash_attn_rocm.py +++ b/onnxruntime/test/python/transformers/test_gqa_rocm.py @@ -3,7 +3,7 @@ import torch from parameterized import parameterized -from test_flash_attn_cuda import ( +from test_gqa_cuda import ( Formats, gqa_no_past_flash_attention_test_cases, gqa_past_flash_attention_test_cases, @@ -38,6 +38,7 @@ def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_inte rtol=0.001, atol=0.005, ) + parity_check_gqa_prompt_no_buff( config, local=local, diff --git a/onnxruntime/test/python/transformers/test_mha_flash_attn.py b/onnxruntime/test/python/transformers/test_mha_flash_attn.py new file mode 100644 index 0000000000000..f87370e37d21a --- /dev/null +++ b/onnxruntime/test/python/transformers/test_mha_flash_attn.py @@ -0,0 +1,452 @@ +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# ------------------------------------------------------------------------- +import os +import unittest + +import numpy +import torch +from bert_padding import pad_input, unpad_input +from einops import rearrange, repeat +from onnx import TensorProto, helper +from parameterized import parameterized +from test_gqa_cuda import attention_ref, has_flash_attention + +from onnxruntime import InferenceSession, SessionOptions + +torch.manual_seed(0) + +pipeline_mode = True # Reduces number of tests so pipeline doesn't time out + + +class Formats: + BSNH = 0 + BNSH = 1 + + +class Config: + batch_size = 0 + sequence_length = 0 + kv_sequence_length = 0 # this is past sequence length when there is past state. + num_heads = 0 + kv_num_heads = 0 + head_size = 0 + ep = "CUDAExecutionProvider" + + def __init__(self, batch_size, sequence_length, kv_sequence_length, num_heads, kv_num_heads, head_size): + self.batch_size = batch_size + self.sequence_length = sequence_length + self.kv_sequence_length = kv_sequence_length + self.num_heads = num_heads + self.kv_num_heads = kv_num_heads + self.head_size = head_size + + def __repr__(self): + short_ep = self.ep[: -len("ExecutionProvider")].lower() + return ( + f"Config(batch_size={self.batch_size}, sequence_length={self.sequence_length}, " + f"kv_sequence_length={self.kv_sequence_length}, " + f"num_heads={self.num_heads}, kv_num_heads={self.kv_num_heads}, head_size={self.head_size}, ep={short_ep})" + ) + + +def create_packed_multihead_attention_graph(config: Config): + nodes = [ + helper.make_node( + "PackedMultiHeadAttention", + [ + "query", + "", + "", + "", + "token_offset", + "cumulative_sequence_length", + ], + ["output"], + "PackedMultiHeadAttention_0", + num_heads=config.num_heads, + domain="com.microsoft", + ), + ] + + graph = helper.make_graph( + nodes, + "PackedMultiHeadAttention_Graph", + [ + helper.make_tensor_value_info( + "query", + TensorProto.FLOAT16, + [ + -1, + config.num_heads, + 3, + config.head_size, + ], + ), + helper.make_tensor_value_info( + "token_offset", TensorProto.INT32, [config.batch_size, config.sequence_length] + ), + helper.make_tensor_value_info("cumulative_sequence_length", TensorProto.INT32, [config.batch_size + 1]), + ], + [ + helper.make_tensor_value_info( + "output", + TensorProto.FLOAT16, + [-1, config.num_heads * config.head_size], + ), + ], + ) + + model = helper.make_model(graph) + return model.SerializeToString() + + +def create_multihead_attention_graph(config: Config): + nodes = [ + helper.make_node( + "MultiHeadAttention", + [ + "query", + "key", + "value", + ], + ["output"], + "MultiHeadAttention_0", + num_heads=config.num_heads, + domain="com.microsoft", + ), + ] + + graph = helper.make_graph( + nodes, + "MultiHeadAttention_Graph", + [ + helper.make_tensor_value_info( + "query", + TensorProto.FLOAT16, + [ + config.batch_size, + config.sequence_length, + config.num_heads * config.head_size, + ], + ), + helper.make_tensor_value_info( + "key", + TensorProto.FLOAT16, + [ + config.batch_size, + config.kv_sequence_length, + config.num_heads * config.head_size, + ], + ), + helper.make_tensor_value_info( + "value", + TensorProto.FLOAT16, + [ + config.batch_size, + config.kv_sequence_length, + config.num_heads * config.head_size, + ], + ), + ], + [ + helper.make_tensor_value_info( + "output", + TensorProto.FLOAT16, + [config.batch_size, config.sequence_length, config.num_heads * config.head_size], + ), + ], + ) + + model = helper.make_model(graph) + return model.SerializeToString() + + +def generate_random_padding_mask(max_seqlen, batch_size, device, mode="random"): + assert mode in ["full", "random", "third"] + if mode == "full": + lengths = torch.full((batch_size, 1), max_seqlen, device=device, dtype=torch.int32) + elif mode == "random": + lengths = torch.randint(max(1, max_seqlen - 20), max_seqlen, (batch_size, 1), device=device) + else: + lengths = torch.randint(max_seqlen // 3, max_seqlen, (batch_size, 1), device=device) + padding_mask = repeat(torch.arange(max_seqlen, device=device), "s -> b s", b=batch_size) < lengths + return padding_mask + + +def generate_packed_qkv(q, k, v, query_padding_mask=None, key_padding_mask=None): + """ + Arguments: + q: (batch_size, seqlen_q, nheads, d) + k: (batch_size, seqlen_k, nheads_k, d) + v: (batch_size, seqlen_k, nheads_k, d) + query_padding_mask: (batch_size, seqlen), bool + key_padding_mask: (batch_size, seqlen), bool + """ + batch_size, seqlen_q, nheads, d = q.shape + _, seqlen_k, nheads_k, _ = k.shape + assert k.shape == (batch_size, seqlen_k, nheads_k, d) + assert v.shape == (batch_size, seqlen_k, nheads_k, d) + + if query_padding_mask is not None: + q_unpad, indices_q, cu_seqlens_q, max_seqlen_q = unpad_input(q, query_padding_mask) + + def output_pad_fn(output_unpad): + return pad_input(output_unpad, indices_q, batch_size, seqlen_q) + + else: + q_unpad = rearrange(q, "b s h d -> (b s) h d") + cu_seqlens_q = torch.arange( + 0, (batch_size + 1) * seqlen_q, step=seqlen_q, dtype=torch.int32, device=q_unpad.device + ) + max_seqlen_q = seqlen_q + + def output_pad_fn(output_unpad): + return rearrange(output_unpad, "(b s) h d -> b s h d", b=batch_size) + + if key_padding_mask is not None: + k_unpad, _, _, _ = unpad_input(k, key_padding_mask) + v_unpad, _, _, _ = unpad_input(v, key_padding_mask) + else: + k_unpad = rearrange(k, "b s h d -> (b s) h d") + v_unpad = rearrange(v, "b s h d -> (b s) h d") + + assert (query_padding_mask == key_padding_mask).all() + assert nheads == nheads_k + qkv_unpad = torch.stack([q_unpad, k_unpad, v_unpad], dim=1) + qkv = torch.stack([q, k, v], dim=2) + if query_padding_mask is not None: + + def dqkv_pad_fn(dqkv_unpad): + return pad_input(dqkv_unpad, indices_q, batch_size, seqlen_q) + + else: + + def dqkv_pad_fn(dqkv_unpad): + return rearrange(dqkv_unpad, "(b s) t h d -> b s t h d", b=batch_size) + + return ( + qkv_unpad.detach().requires_grad_(), + cu_seqlens_q, + max_seqlen_q, + qkv.detach().requires_grad_(), + output_pad_fn, + dqkv_pad_fn, + ) + + +def create_inputs(config: Config): + qkv = torch.randn( + config.batch_size, + config.sequence_length, + 3, + config.num_heads, + config.head_size, + device="cuda", + dtype=torch.float16, + requires_grad=False, + ) + padding_mask = generate_random_padding_mask(config.sequence_length, config.batch_size, device="cuda", mode="random") + qkv_unpad, cu_seqlens, max_seqlen, qkv, output_pad_fn, dqkv_pad_fn = generate_packed_qkv( + *qkv.unbind(dim=2), padding_mask, padding_mask + ) + return qkv_unpad, cu_seqlens, max_seqlen, qkv, output_pad_fn, dqkv_pad_fn, padding_mask + + +def generate_token_offset(cu_seqlens, max_seqlen): + token_offset = [] + token_padset = [] # These are the indices that contain padding tokens + for i in range(1, len(cu_seqlens)): + start = i - 1 + pre_seqlen = cu_seqlens[i - 1] + seqlen = cu_seqlens[i] + token_offset += range(start * max_seqlen, (start * max_seqlen) + (seqlen - pre_seqlen)) + token_padset += range((start * max_seqlen) + (seqlen - pre_seqlen), i * max_seqlen) + return numpy.asarray(token_offset + token_padset, dtype=numpy.int32) + + +def flash_attn_varlen_qkvpacked_func(qkv_unpad, cu_seqlens, token_offset, config): + onnx_model_str = create_packed_multihead_attention_graph(config) + qkv_unpad = torch.swapdims(qkv_unpad, 1, 2) + ort_inputs = { + "query": qkv_unpad.detach().cpu().numpy(), + "token_offset": token_offset, + "cumulative_sequence_length": cu_seqlens.cpu().numpy(), + } + sess_options = SessionOptions() + ort_session = InferenceSession(onnx_model_str, sess_options, providers=[config.ep]) + ort_output = ort_session.run(None, ort_inputs) + output = torch.tensor(ort_output) + return output + + +def mha_func(q, k, v, config): + onnx_model_str = create_multihead_attention_graph(config) + q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) + k = torch.reshape(k, (config.batch_size, config.kv_sequence_length, -1)) + v = torch.reshape(v, (config.batch_size, config.kv_sequence_length, -1)) + ort_inputs = { + "query": q.detach().cpu().numpy(), + "key": k.detach().cpu().numpy(), + "value": v.detach().cpu().numpy(), + } + sess_options = SessionOptions() + ort_session = InferenceSession(onnx_model_str, sess_options, providers=[config.ep]) + ort_output = ort_session.run(None, ort_inputs) + ort_output = numpy.array(ort_output) + output = torch.tensor(ort_output) + return output + + +def attention_qkvpacked_ref( + qkv, + key_padding_mask=None, + dropout_p=0.0, + dropout_mask=None, + causal=False, + upcast=True, + reorder_ops=False, + use_smooth_softmax=False, +): + return attention_ref( + qkv[:, :, 0], + qkv[:, :, 1], + qkv[:, :, 2], + key_padding_mask, + key_padding_mask, + dropout_p, + dropout_mask, + upcast=upcast, + causal=causal, + reorder_ops=reorder_ops, + use_smooth_softmax=use_smooth_softmax, + ) + + +def parity_check_mha( + config, + packed, + rtol=1e-3, + atol=1e-3, +): + if packed: + qkv_unpad, cu_seqlens, _, qkv, output_pad_fn, _, key_padding_mask = create_inputs(config) + token_offset = generate_token_offset(cu_seqlens, config.sequence_length).reshape( + (config.batch_size, config.sequence_length) + ) + # ORT Flash + out_unpad = flash_attn_varlen_qkvpacked_func(qkv_unpad, cu_seqlens, token_offset, config) + out_unpad = torch.squeeze(out_unpad, 0) + out = torch.reshape( + output_pad_fn(out_unpad), (config.batch_size, config.sequence_length, config.num_heads, config.head_size) + ) + out = out.detach().cpu().numpy() + # Pytorch to compare + out_ref, _ = attention_qkvpacked_ref(qkv, key_padding_mask, 0.0, None, causal=False) + out_ref = out_ref.detach().cpu().numpy() + else: + q = torch.randn( + config.batch_size, + config.sequence_length, + config.num_heads, + config.head_size, + device="cuda", + dtype=torch.float16, + requires_grad=False, + ) + k = torch.randn( + config.batch_size, + config.kv_sequence_length, + config.kv_num_heads, + config.head_size, + device="cuda", + dtype=torch.float16, + requires_grad=False, + ) + v = torch.randn( + config.batch_size, + config.kv_sequence_length, + config.kv_num_heads, + config.head_size, + device="cuda", + dtype=torch.float16, + requires_grad=False, + ) + out = mha_func(q, k, v, config) + out = torch.squeeze(out, 0) + out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) + out = out.detach().cpu().numpy() + # Pytorch to compare + out_ref, _ = attention_ref(q, k, v, None, None, 0.0, None, causal=False) + out_ref = out_ref.detach().cpu().numpy() + + numpy.testing.assert_allclose( + out, out_ref, rtol=rtol, atol=atol, equal_nan=True, err_msg=f" with {config} packed={packed}" + ) + + +def packed_mha_test_cases(): + batch_sizes = [2] if pipeline_mode else [1, 5] + sequence_lengths = [1024, 1025] if pipeline_mode else [1024, 1025, 2048] + num_heads = [1, 3] if pipeline_mode else [1, 6, 16] + head_sizes = [16, 256] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] + + for b in batch_sizes: + for s in sequence_lengths: + for n in num_heads: + for h in head_sizes: + config = Config(b, s, s, n, n, h) + yield str(config), config + + +def mha_test_cases(): + batch_sizes = [2] if pipeline_mode else [1, 5] + sequence_lengths = ( + [(1, 128), (113, 211), (2048, 2048)] + if pipeline_mode + else [ + (113, 203), + (128, 217), + (113, 211), + (108, 256), + (256, 512), + (512, 256), + (1024, 1024), + (1023, 1024), + (1024, 1023), + (2048, 2048), + ] + ) + num_heads = [3] if pipeline_mode else [1, 6, 16] + head_sizes = [64] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] + + for b in batch_sizes: + for s, kv_sequence_length in sequence_lengths: + for n in num_heads: + for h in head_sizes: + config = Config(b, s, kv_sequence_length, n, n, h) + yield str(config), config + + +class TestMHA(unittest.TestCase): + @parameterized.expand(packed_mha_test_cases()) + def test_packed_mha(self, _, config): + if not has_flash_attention(): + return + os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "0" + print("-------- TEST PACKED MHA ---------") + parity_check_mha(config, True) + + @parameterized.expand(mha_test_cases()) + def test_mha(self, _, config): + if not has_flash_attention(): + return + os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "0" + print("-------- TEST MHA ---------") + parity_check_mha(config, False) + + +if __name__ == "__main__": + unittest.main() From 16b0b323f67bda3903b9658fedf5c42591b49793 Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Thu, 20 Mar 2025 18:56:11 +0100 Subject: [PATCH 138/266] [MIGraphX EP] rename HIPPinnedAllocator to MIGraphXPinnedAllocator (#24103) ### Description Rename class HIPPinnedAllocator to MIGraphXPinnedAllocator ### Motivation and Context To align allocators' naming for the MIGraphX EP --- .../core/providers/migraphx/migraphx_allocator.cc | 4 ++-- .../core/providers/migraphx/migraphx_allocator.h | 11 +++++------ .../providers/migraphx/migraphx_provider_factory.cc | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/onnxruntime/core/providers/migraphx/migraphx_allocator.cc b/onnxruntime/core/providers/migraphx/migraphx_allocator.cc index 3d9ae2bf7e6ff..cf9f44f4cd8f0 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_allocator.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_allocator.cc @@ -68,7 +68,7 @@ void* MIGraphXExternalAllocator::Reserve(size_t size) { return p; } -void* HIPPinnedAllocator::Alloc(size_t size) { +void* MIGraphXPinnedAllocator::Alloc(size_t size) { void* p = nullptr; if (size > 0) { HIP_CALL_THROW(hipHostMalloc((void**)&p, size)); @@ -76,7 +76,7 @@ void* HIPPinnedAllocator::Alloc(size_t size) { return p; } -void HIPPinnedAllocator::Free(void* p) { +void MIGraphXPinnedAllocator::Free(void* p) { HIP_CALL_THROW(hipHostFree(p)); } diff --git a/onnxruntime/core/providers/migraphx/migraphx_allocator.h b/onnxruntime/core/providers/migraphx/migraphx_allocator.h index c8c935eba44ab..2a84445897391 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_allocator.h +++ b/onnxruntime/core/providers/migraphx/migraphx_allocator.h @@ -49,17 +49,16 @@ class MIGraphXExternalAllocator : public MIGraphXAllocator { std::unordered_set reserved_; }; -// TODO: add a default constructor -class HIPPinnedAllocator : public IAllocator { +class MIGraphXPinnedAllocator final : public IAllocator { public: - HIPPinnedAllocator(int device_id, const char* name) + MIGraphXPinnedAllocator(const int device_id, const char* name) : IAllocator( - OrtMemoryInfo(name, OrtAllocatorType::OrtDeviceAllocator, + OrtMemoryInfo(name, OrtDeviceAllocator, OrtDevice(OrtDevice::CPU, OrtDevice::MemType::HIP_PINNED, static_cast(device_id)), device_id, OrtMemTypeCPUOutput)) {} - virtual void* Alloc(size_t size) override; - virtual void Free(void* p) override; + void* Alloc(size_t size) override; + void Free(void* p) override; }; } // namespace onnxruntime diff --git a/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc b/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc index 7b192b657b7cc..2904c17bb4aa0 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc @@ -39,7 +39,7 @@ struct ProviderInfo_MIGraphX_Impl final : ProviderInfo_MIGraphX { } std::unique_ptr CreateMIGraphXPinnedAllocator(int16_t device_id, const char* name) override { - return std::make_unique(device_id, name); + return std::make_unique(device_id, name); } } g_info; From 9922d48014fcf433869ff03d783653ddd4a65d7e Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Thu, 20 Mar 2025 20:16:32 +0100 Subject: [PATCH 139/266] [MIGraphX EP] check POLICY CMP0144 availability before used (#24104) ### Description For a newer CMake, suppress warnings about incorrect letter cases in package names. ### Motivation and Context To avoid reporting for newer CMake that a package name contains capital letters when small letters are required. --- cmake/onnxruntime_providers_migraphx.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/onnxruntime_providers_migraphx.cmake b/cmake/onnxruntime_providers_migraphx.cmake index 685e77bc483bd..495ff093326ad 100644 --- a/cmake/onnxruntime_providers_migraphx.cmake +++ b/cmake/onnxruntime_providers_migraphx.cmake @@ -21,8 +21,10 @@ # Add search paths for default rocm installation list(APPEND CMAKE_PREFIX_PATH /opt/rocm/hcc /opt/rocm/hip /opt/rocm $ENV{HIP_PATH}) - # Suppress the warning about the small capitals of the package name - Enable when support to CMake 3.27.0 is used - # cmake_policy(SET CMP0144 NEW) + if(POLICY CMP0144) + # Suppress the warning about the small capitals of the package name + cmake_policy(SET CMP0144 NEW) + endif() if(WIN32 AND NOT HIP_PLATFORM) set(HIP_PLATFORM "amd") From 469fb7e3a1643e728352482c801b74314430d3cf Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Thu, 20 Mar 2025 16:13:43 -0700 Subject: [PATCH 140/266] [JSEP] handles edge case in gridsample operator (#24121) fix for https://github.com/microsoft/onnxruntime/issues/24070 --- js/web/lib/wasm/jsep/webgpu/ops/grid-sample.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/grid-sample.ts b/js/web/lib/wasm/jsep/webgpu/ops/grid-sample.ts index 50c71472434ad..16c3af871b4e6 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/grid-sample.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/grid-sample.ts @@ -126,6 +126,8 @@ const pixelAtGrid = (input: IndicesHelper, dataType: string, attributes: GridSam if (r >= 0 && r < H && c >=0 && c < W) { indices[${idxH}] = u32(r); indices[${idxW}] = u32(c); + } else { + return ${dataType}(0); } `; case 'border': From 49024a1eb138e0b681f190593ce71e72ab180242 Mon Sep 17 00:00:00 2001 From: sfatimar Date: Fri, 21 Mar 2025 05:25:26 +0530 Subject: [PATCH 141/266] [OpenVINO]Session Options Appended After AppendExecutionProvider (#23852) Description To honor SessionOption API Contract the ordering of AddConfigOption and AppendExecutionProvider_OpenVINO should not matter. This PR is fixing that issue Motivation and Context This PR fixes a regression happened during last PR in ordering of SessionOptions. --- .../core/providers/openvino/contexts.h | 1 + .../openvino/openvino_provider_factory.cc | 45 ++++++++++--------- .../core/session/provider_bridge_ort.cc | 12 +++-- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/onnxruntime/core/providers/openvino/contexts.h b/onnxruntime/core/providers/openvino/contexts.h index 216fc5b132696..a1a756a9baef7 100644 --- a/onnxruntime/core/providers/openvino/contexts.h +++ b/onnxruntime/core/providers/openvino/contexts.h @@ -101,6 +101,7 @@ struct ProviderInfo { bool so_context_embed_mode{false}; // ORT session option bool so_share_ep_contexts{false}; // ORT session option fs::path so_context_file_path{}; // ORT session option + const ConfigOptions* config_options{NULL}; }; // Holds context applicable to the entire EP instance. diff --git a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc index 95e039f8b6d5f..87a1dda9a5db1 100644 --- a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc +++ b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc @@ -14,12 +14,21 @@ namespace onnxruntime { namespace openvino_ep { -void ParseConfigOptions(ProviderInfo& pi, const ConfigOptions& config_options) { - pi.so_disable_cpu_ep_fallback = config_options.GetConfigOrDefault(kOrtSessionOptionsDisableCPUEPFallback, "0") == "1"; - pi.so_context_enable = config_options.GetConfigOrDefault(kOrtSessionOptionEpContextEnable, "0") == "1"; - pi.so_context_embed_mode = config_options.GetConfigOrDefault(kOrtSessionOptionEpContextEmbedMode, "0") == "1"; - pi.so_share_ep_contexts = config_options.GetConfigOrDefault(kOrtSessionOptionShareEpContexts, "0") == "1"; - pi.so_context_file_path = config_options.GetConfigOrDefault(kOrtSessionOptionEpContextFilePath, ""); +void ParseConfigOptions(ProviderInfo& pi) { + if (pi.config_options == nullptr) + return; + + pi.so_disable_cpu_ep_fallback = pi.config_options->GetConfigOrDefault(kOrtSessionOptionsDisableCPUEPFallback, "0") == "1"; + pi.so_context_enable = pi.config_options->GetConfigOrDefault(kOrtSessionOptionEpContextEnable, "0") == "1"; + pi.so_context_embed_mode = pi.config_options->GetConfigOrDefault(kOrtSessionOptionEpContextEmbedMode, "0") == "1"; + pi.so_share_ep_contexts = pi.config_options->GetConfigOrDefault(kOrtSessionOptionShareEpContexts, "0") == "1"; + pi.so_context_file_path = pi.config_options->GetConfigOrDefault(kOrtSessionOptionEpContextFilePath, ""); + + if (pi.so_share_ep_contexts) { + ov::AnyMap map; + map["NPU_COMPILATION_MODE_PARAMS"] = "enable-wd-blockarg-input=true compute-layers-with-higher-precision=Sqrt,Power,ReduceSum"; + pi.load_config["NPU"] = std::move(map); + } } void* ParseUint64(const ProviderOptions& provider_options, std::string option_name) { @@ -166,6 +175,7 @@ struct OpenVINOProviderFactory : IExecutionProviderFactory { ~OpenVINOProviderFactory() override {} std::unique_ptr CreateProvider() override { + ParseConfigOptions(provider_info_); return std::make_unique(provider_info_, shared_context_); } @@ -184,13 +194,17 @@ struct OpenVINO_Provider : Provider { void* GetInfo() override { return &info_; } std::shared_ptr CreateExecutionProviderFactory(const void* void_params) override { - // Extract the void_params into ProviderOptions and ConfigOptions - using ConfigBuffer = std::pair; - const ConfigBuffer* buffer = reinterpret_cast(void_params); - const auto& provider_options = *buffer->first; - const auto& config_options = buffer->second; + if (void_params == nullptr) { + LOGS_DEFAULT(ERROR) << "[OpenVINO EP] Passed NULL options to CreateExecutionProviderFactory()"; + return nullptr; + } + + std::array pointers_array = *reinterpret_cast*>(void_params); + const ProviderOptions provider_options = *reinterpret_cast(pointers_array[0]); + const ConfigOptions* config_options = reinterpret_cast(pointers_array[1]); ProviderInfo pi; + pi.config_options = config_options; std::string bool_flag = ""; @@ -326,20 +340,11 @@ struct OpenVINO_Provider : Provider { pi.disable_dynamic_shapes = ParseBooleanOption(provider_options, "disable_dynamic_shapes"); - ParseConfigOptions(pi, config_options); - // Always true for NPU plugin or when passed . if (pi.device_type.find("NPU") != std::string::npos) { pi.disable_dynamic_shapes = true; } - // Append values to config to support weight-as-inputs conversion for shared contexts - if (pi.so_share_ep_contexts) { - ov::AnyMap map; - map["NPU_COMPILATION_MODE_PARAMS"] = "enable-wd-blockarg-input=true compute-layers-with-higher-precision=Sqrt,Power,ReduceSum"; - pi.load_config["NPU"] = std::move(map); - } - return std::make_shared(pi, SharedContext::Get()); } diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 69dea34175155..e46236f4ca11c 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -2019,10 +2019,14 @@ std::shared_ptr QNNProviderFactoryCreator::Create(con std::shared_ptr OpenVINOProviderFactoryCreator::Create( const ProviderOptions* provider_options_map, const SessionOptions* session_options) { // Append session options applicable for EP to EP Provider options. - std::pair config_buffer = {provider_options_map, - session_options->config_options}; - const void* obj = reinterpret_cast(&config_buffer); - return s_library_openvino.Get().CreateExecutionProviderFactory(obj); + const ConfigOptions* config_options = nullptr; + if (session_options != nullptr) { + config_options = &session_options->config_options; + } + + std::array configs_array = {provider_options_map, config_options}; + const void* arg = reinterpret_cast(&configs_array); + return s_library_openvino.Get().CreateExecutionProviderFactory(arg); } std::shared_ptr DnnlProviderFactoryCreator::Create(const OrtDnnlProviderOptions* dnnl_options) { From 7a6514c812a109bacce757247043ce54a71537c8 Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Fri, 21 Mar 2025 08:42:15 +0800 Subject: [PATCH 142/266] [webgpu]Add MaxPool and AveragePool (#23714) This adds Max and Average pool operators for webgpu-native. Basically, this is a rewrite of the corresponding JSEP operators with some improvements: 1) 'dilations' support 2) Pooling with kernelShape.length > 2 for NHWC format 3) code cleanup However, there are still a few missing features: 1) ceil 'ceil_mode' 2) column major 'storage_order' 3) 'Indices' output for Max pools. --- onnxruntime/core/providers/webgpu/nn/pool.cc | 254 ++++++++++++++++++ onnxruntime/core/providers/webgpu/nn/pool.h | 53 ++++ .../webgpu/webgpu_execution_provider.cc | 46 ++-- .../test/providers/cpu/math/softmax_test.cc | 3 +- .../providers/cpu/nn/pool_fp16_op_test.cc | 12 +- .../test/providers/cpu/nn/pool_op_test.cc | 21 +- 6 files changed, 356 insertions(+), 33 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/nn/pool.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/pool.h diff --git a/onnxruntime/core/providers/webgpu/nn/pool.cc b/onnxruntime/core/providers/webgpu/nn/pool.cc new file mode 100644 index 0000000000000..79072a1dbaba8 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/pool.cc @@ -0,0 +1,254 @@ + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/string_macros.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/nn/pool.h" + +#include + +namespace onnxruntime { +namespace webgpu { + +namespace { + +std::vector NarrowToU32(const TensorShapeVector& shape) { + std::vector result; + result.reserve(shape.size()); + for (auto dim : shape) { + result.push_back(static_cast(dim)); + } + return result; +} + +} // namespace + +#define POOLING_KERNEL(op_name, domain, is_nhwc, pool_type, since_version) \ + ONNX_OPERATOR_KERNEL_EX(op_name, domain, since_version, kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), \ + Pool); + +#define POOLING_KERNEL_VERSIONED(op_name, domain, is_nhwc, pool_type, since_version, end_version) \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX(op_name, domain, since_version, end_version, kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), \ + Pool); + +#define POOLING_KERNEL_WITH_INDICES(op_name, domain, is_nhwc, pool_type, since_version) \ + ONNX_OPERATOR_KERNEL_EX(op_name, domain, since_version, kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T", WebGpuSupportedFloatTypes()) \ + .TypeConstraint("I", DataTypeImpl::GetTensorType()), \ + Pool); + +#define POOLING_KERNEL_VERSIONED_WITH_INDICES(op_name, domain, is_nhwc, pool_type, since_version, end_version) \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX(op_name, domain, since_version, end_version, kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T", WebGpuSupportedFloatTypes()) \ + .TypeConstraint("I", DataTypeImpl::GetTensorType()), \ + Pool); + +POOLING_KERNEL_VERSIONED(AveragePool, kOnnxDomain, false, AveragePool, 7, 9) +POOLING_KERNEL_VERSIONED(AveragePool, kMSInternalNHWCDomain, true, AveragePool, 7, 9) +POOLING_KERNEL_VERSIONED(AveragePool, kOnnxDomain, false, AveragePool, 10, 10) +POOLING_KERNEL_VERSIONED(AveragePool, kMSInternalNHWCDomain, true, AveragePool, 10, 10) +POOLING_KERNEL(AveragePool, kOnnxDomain, false, AveragePool, 11) +POOLING_KERNEL(AveragePool, kMSInternalNHWCDomain, true, AveragePool, 11) +POOLING_KERNEL(GlobalAveragePool, kOnnxDomain, false, AveragePool, 1) +POOLING_KERNEL(GlobalAveragePool, kMSInternalNHWCDomain, true, AveragePool, 1) + +POOLING_KERNEL_VERSIONED(MaxPool, kOnnxDomain, false, MaxPool<1>, 1, 7) +POOLING_KERNEL_VERSIONED(MaxPool, kMSInternalNHWCDomain, true, MaxPool<1>, 1, 7) +POOLING_KERNEL_VERSIONED_WITH_INDICES(MaxPool, kOnnxDomain, false, MaxPool<8>, 8, 9) +POOLING_KERNEL_VERSIONED_WITH_INDICES(MaxPool, kMSInternalNHWCDomain, true, MaxPool<8>, 8, 9) +POOLING_KERNEL_VERSIONED_WITH_INDICES(MaxPool, kOnnxDomain, false, MaxPool<8>, 10, 10) +POOLING_KERNEL_VERSIONED_WITH_INDICES(MaxPool, kMSInternalNHWCDomain, true, MaxPool<8>, 10, 10) +POOLING_KERNEL_VERSIONED_WITH_INDICES(MaxPool, kOnnxDomain, false, MaxPool<8>, 11, 11) +POOLING_KERNEL_VERSIONED_WITH_INDICES(MaxPool, kMSInternalNHWCDomain, true, MaxPool<8>, 11, 11) +POOLING_KERNEL_WITH_INDICES(MaxPool, kOnnxDomain, false, MaxPool<8>, 12) +POOLING_KERNEL_WITH_INDICES(MaxPool, kMSInternalNHWCDomain, true, MaxPool<8>, 12) +POOLING_KERNEL(GlobalMaxPool, kOnnxDomain, false, MaxPool<1>, 1) +POOLING_KERNEL(GlobalMaxPool, kMSInternalNHWCDomain, true, MaxPool<1>, 1) + +Status PoolProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& input = shader.AddInput("input", ShaderUsage::UseUniform); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform); + + // Declare and initialize the variables needed. + std::string var_decl_code; + // Process each element in the pooling window. + std::string sampling_code; + // Calculate the output value for each pooling window. + std::string downsampling_code; + + constexpr const size_t kStringInitialSize = 128; + if (is_max_pool_) { + std::string f16_min = "f16(-65504)"; + + SS(f32_min_ss, kStringInitialSize); + f32_min_ss << "f32(" << std::numeric_limits::lowest() << ")"; + std::string f32_min = SS_GET(f32_min_ss); + + SS(var_decl_ss, kStringInitialSize); + var_decl_ss << " var value = " << (is_float16_ ? f16_min : f32_min) << ";\n"; + var_decl_code = SS_GET(var_decl_ss); + + sampling_code = " value = max(value, x_val);\n"; + } else { + SS(var_decl_ss, kStringInitialSize); + var_decl_ss << " var value = " << (is_float16_ ? "f16(0)" : "f32(0)") << ";\n"; + if (!count_include_pad_) { + var_decl_ss << " var count = u32(0);\n"; + } else { + var_decl_ss << " var count = uniforms.kernel_size;\n"; + } + var_decl_code = SS_GET(var_decl_ss); + + SS(sampling_ss, kStringInitialSize); + sampling_ss << " value += x_val;\n"; + if (!count_include_pad_) { + sampling_ss << " count++;\n"; + } + sampling_code = SS_GET(sampling_ss); + + SS(downsampling_ss, kStringInitialSize); + downsampling_ss << " value /= " << (is_float16_ ? "f16" : "f32") << "(count);\n"; + downsampling_code = SS_GET(downsampling_ss); + } + + const auto kernel_rank = kernel_shape_.size(); + const auto pads_rank = kernel_shape_.size() * 2; + // The dimension index for H or D1 + const auto data_dim_begin = is_nhwc_ ? 1 : 2; + // The dimension index after W or Dn + auto data_dim_end = input.Rank(); + data_dim_end = is_nhwc_ ? data_dim_end - 1 : data_dim_end; + + auto& body = shader.MainFunctionBody(); + body << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << " let y_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << " var x_indices = y_indices;\n" + << " var k_indices: array;\n" + << var_decl_code + << " for (var i: u32 = 0; i < uniforms.kernel_size; i++) {\n" + << " var offset = i;\n" + // ---- Compute offset to indices in pooling window. + << " for (var j = 0; j < " << kernel_rank << "; j++) {\n" + << " k_indices[j] = offset / " << GetElementAt("uniforms.kernel_strides", "j", kernel_rank) << ";\n" + << " offset = offset % " << GetElementAt("uniforms.kernel_strides", "j", kernel_rank) << ";\n" + << " }\n" + // ---- Apply dilations in pooling window. + << " for (var j = 0; j < " << kernel_rank << "; j++) {\n" + << " k_indices[j] *= " << GetElementAt("uniforms.dilations", "j", kernel_rank) << ";\n" + << " }\n" + << " var is_pad = false;\n" + // ---- Compute x_indices in each data dimension + << " for (var j = " << data_dim_begin << "; j < " << data_dim_end << "; j++) {\n" + << " let d_idx = j - " << data_dim_begin << ";\n" + << " x_indices[j] = y_indices[j] * " << GetElementAt("uniforms.strides", "d_idx", kernel_rank) << ";\n" + << " x_indices[j] += k_indices[d_idx];\n" + << " x_indices[j] -= " << GetElementAt("uniforms.pads", "d_idx", pads_rank) << ";\n" + << " let j_dim_len = " << input.IndicesGet("uniforms.input_shape", "j") << ";\n" + // ------ Check if x_indices[j] is out of bounds to handle padding. + << " if (x_indices[j] < 0 || x_indices[j] >= j_dim_len) {\n" + << " is_pad = true;\n" + << " break;\n" + << " }\n" + << " }\n" + << " if (!is_pad) {\n" + << " let x_val = " << input.GetByIndices("x_indices") << ";\n" + << sampling_code + << " }\n" + << " }\n" + << downsampling_code + << " " << output.SetByOffset("global_idx", "value") << ";\n"; + + return Status::OK(); +} + +template +Status Pool::ComputeInternal(ComputeContext& context) const { + // TODO: support 'ceil' mode. + ORT_RETURN_IF_NOT(pool_attrs_.ceil_mode == 0, "Using ceil is not supported yet."); + // TODO: support 'column major' storage_order. + ORT_RETURN_IF_NOT(pool_attrs_.storage_order == 0, "Using column major storage_order is not supported yet."); + + // TODO: support 'Indices' output. + ORT_RETURN_IF_NOT(context.OutputCount() == 1, "The Indices output is not supported yet."); + + const auto* X = context.Input(0); + const TensorShape& x_shape = X->Shape(); + const auto input_shape = x_shape.AsShapeVector(); + ORT_RETURN_IF_NOT(input_shape.size() >= 3, "Input dimension cannot be less than 3."); + + auto kernel_shape = pool_attrs_.kernel_shape; + auto strides = pool_attrs_.strides; + auto pads = pool_attrs_.pads; + auto dilations = pool_attrs_.dilations; + // Global pooling is equivalent to having the kernel size equal to the spatial dimension of input tensor. + if (pool_attrs_.global_pooling) { + if (!is_nhwc) { + kernel_shape.assign(input_shape.begin() + 2, input_shape.end()); + } else { + kernel_shape.assign(input_shape.begin() + 1, input_shape.end() - 1); + } + // No padding. + pads.assign(2 * kernel_shape.size(), 0); + // Stride of 1. + strides.assign(kernel_shape.size(), 1); + // Dilation of 1. + dilations.assign(kernel_shape.size(), 1); + } + + // Calculate the output shape + const auto out_channel = x_shape[is_nhwc ? input_shape.size() - 1 : 1]; + const auto output_shape = pool_attrs_.SetOutputSize(x_shape, out_channel, &pads, is_nhwc); + Tensor* Y = context.Output(0, output_shape); + + std::vector kernel_strides(kernel_shape.size()); + ORT_ENFORCE(kernel_shape.size() > 0, "kernel_shape must have at least one element."); + // Calculate the kernel element strides for each dimension in reverse order. For example: + // kernel_shape = [3, 2], kernel_strides = [2, 1] + // kernel_shape = [2, 3, 2], kernel_strides = [6, 2, 1] + for (size_t i = kernel_shape.size(); i > 0; --i) { + if (i == kernel_shape.size()) { + kernel_strides[i - 1] = 1; + } else { + kernel_strides[i - 1] = kernel_strides[i] * gsl::narrow_cast(kernel_shape[i]); + } + } + + bool is_max_pool = false; + if constexpr (PoolType::type == onnxruntime::PoolType::kMaxPool) { + is_max_pool = true; + } else if constexpr (PoolType::type != onnxruntime::PoolType::kAveragePool) { + ORT_NOT_IMPLEMENTED("Unsupported PoolType."); + } + bool is_float16 = X->GetElementType() == ONNX_NAMESPACE::TensorProto_DataType_FLOAT16; + bool count_include_pad = pool_attrs_.count_include_pad; + PoolProgram program{is_max_pool, is_nhwc, kernel_shape, is_float16, count_include_pad}; + + // Number of elements + uint32_t output_size = gsl::narrow_cast(Y->Shape().Size()); + uint32_t kernel_size = gsl::narrow_cast(TensorShape{kernel_shape}.Size()); + + const auto pads_u32 = NarrowToU32(pads); + const auto strides_u32 = NarrowToU32(strides); + const auto dilations_u32 = NarrowToU32(dilations); + + program.CacheHint(kernel_shape.size(), is_max_pool, is_nhwc, is_float16, count_include_pad) + .AddInputs({{X, ProgramTensorMetadataDependency::TypeAndRank}}) + .AddOutputs({{Y}}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({output_size, kernel_size, + gsl::span(kernel_strides.data(), kernel_strides.size()), + gsl::span(pads_u32.data(), pads_u32.size()), + gsl::span(strides_u32.data(), strides_u32.size()), + gsl::span(dilations_u32.data(), dilations_u32.size())}); + + return context.RunProgram(program); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/pool.h b/onnxruntime/core/providers/webgpu/nn/pool.h new file mode 100644 index 0000000000000..c1716542e5549 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/pool.h @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/common.h" +#include "core/providers/cpu/nn/pool_base.h" + +namespace onnxruntime { +namespace webgpu { + +class PoolProgram final : public Program { + public: + PoolProgram(bool is_max_pool, bool is_nhwc, const TensorShapeVector& kernel_shape, bool is_float16, + bool count_include_pad) + : Program{"Pool"}, + is_max_pool_{is_max_pool}, + is_nhwc_{is_nhwc}, + kernel_shape_{kernel_shape}, + is_float16_{is_float16}, + count_include_pad_{count_include_pad} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, + {"kernel_size", ProgramUniformVariableDataType::Uint32}, + {"kernel_strides", ProgramUniformVariableDataType::Uint32}, + {"pads", ProgramUniformVariableDataType::Uint32}, + {"strides", ProgramUniformVariableDataType::Uint32}, + {"dilations", ProgramUniformVariableDataType::Uint32}); + + private: + // Whether it is max pool or average pool. + const bool is_max_pool_; + + const bool is_nhwc_; + const TensorShapeVector kernel_shape_; + const bool is_float16_; + const bool count_include_pad_; +}; + +template +class Pool : public WebGpuKernel, public PoolBase { + public: + explicit Pool(const OpKernelInfo& info) : WebGpuKernel(info), PoolBase(info) {} + + Status ComputeInternal(ComputeContext& context) const override; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index aacbcc5fb4f0a..874607988773b 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -593,29 +593,29 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, diff --git a/onnxruntime/test/providers/cpu/math/softmax_test.cc b/onnxruntime/test/providers/cpu/math/softmax_test.cc index 1c6375ebdb0b1..03f5fdaab2780 100644 --- a/onnxruntime/test/providers/cpu/math/softmax_test.cc +++ b/onnxruntime/test/providers/cpu/math/softmax_test.cc @@ -422,7 +422,8 @@ TEST(SoftmaxOperator, GH15949_regression_test) { {0.00032932f, 0.01798029f, 0.9816904f}); // disable TRT as it does not support axis=0 as used by the model - tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + // TODO: Fix the Softmax operator of WebGPU EP. + tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kWebGpuExecutionProvider}); } } // namespace test diff --git a/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc b/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc index c14fc1fb62ae5..24cdb818b9e32 100644 --- a/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/pool_fp16_op_test.cc @@ -3,7 +3,7 @@ #include "core/mlas/inc/mlas.h" -#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) || defined(USE_XNNPACK) +#if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) || defined(USE_COREML) || defined(USE_XNNPACK) || defined(USE_WEBGPU) #include "core/providers/cpu/nn/pool.h" #include "gtest/gtest.h" @@ -280,7 +280,10 @@ TEST(PoolFp16Test, MaxPool_Dilation_Ceil1_2d) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kAclExecutionProvider}); + + // TODO: Enable the case for WebGPU once ceil is supported. + test.Run(OpTester::ExpectResult::kExpectSuccess, "", + {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); } TEST(PoolTest, MaxPool_DilationPadding_3d) { @@ -484,7 +487,10 @@ TEST(PoolFp16Test, AveragePool_10_ceil1_2d) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kAclExecutionProvider}); + + // TODO: Enable the case for WebGPU once ceil is supported. + test.Run(OpTester::ExpectResult::kExpectSuccess, "", + {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); } TEST(PoolFp16Test, GlobalAveragePool) { diff --git a/onnxruntime/test/providers/cpu/nn/pool_op_test.cc b/onnxruntime/test/providers/cpu/nn/pool_op_test.cc index f1d612276174f..b6eb812e6a399 100644 --- a/onnxruntime/test/providers/cpu/nn/pool_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/pool_op_test.cc @@ -178,9 +178,10 @@ static void MaxPool_8_WithIndexTest(bool has_index, int64_t storage_order = 0) { storage_order == 0 ? test.AddOutput("Indices", expected_dims, expected_indices_row) : test.AddOutput("Indices", expected_dims, expected_indices_col); } + // TODO: Enable the case for WebGPU once WGSL can support int64. test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kDnnlExecutionProvider, kTensorrtExecutionProvider, - kAclExecutionProvider, kArmNNExecutionProvider, kOpenVINOExecutionProvider}); + {kDnnlExecutionProvider, kTensorrtExecutionProvider, kAclExecutionProvider, kArmNNExecutionProvider, + kOpenVINOExecutionProvider, kWebGpuExecutionProvider}); } TEST(PoolTest, MaxPool_8_With_Index) { @@ -268,8 +269,10 @@ static void MaxPool1D_8_WithIndexTest(int64_t storage_order) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); test.AddOutput("Indices", expected_dims, expected_indices); + + // TODO: Enable the case for WebGPU once WGSL can support int64. test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kTensorrtExecutionProvider, kAclExecutionProvider}); + {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); } TEST(PoolTest, MaxPool1D_8_With_Index) { @@ -641,8 +644,10 @@ TEST(PoolTest, MaxPool_10_Dilation_Ceil1_2d) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); + + // TODO: Enable the case for WebGPU once ceil is supported. test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kTensorrtExecutionProvider, kAclExecutionProvider}); + {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); } TEST(PoolTest, MaxPool_10_DilationPadding_3d) { @@ -1000,8 +1005,10 @@ TEST(PoolTest, AveragePool_10_ceil1_2d) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); + + // TODO: Enable the case for WebGPU once ceil is supported. test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kTensorrtExecutionProvider, kAclExecutionProvider}); + {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); } TEST(PoolTest, AveragePool_19_dilation_2d) { @@ -1817,8 +1824,10 @@ TEST(PoolTest, MaxPoolDimWithZeroForN) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); + + // TODO: Fix WebGPU Transpose error: "Invalid dispatch group size (0, 1, 1)". test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kTensorrtExecutionProvider, kQnnExecutionProvider}); + {kTensorrtExecutionProvider, kQnnExecutionProvider, kWebGpuExecutionProvider}); } } // namespace test From 9e53afabde11feda4fedf999e2ee75c540229132 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 20 Mar 2025 19:46:48 -0700 Subject: [PATCH 143/266] [webgpu EP] put GetMaxComponents and SumVector to one place. (#24122) ### Description put `GetMaxComponents` and `SumVector` to one place. fix a bug in `SumVector`: ```diff - return "(" + x + ".x + " + x + ".y + " + x + ".w + " + x + ".z" + ")"; + return "(" + x + ".x + " + x + ".y + " + x + ".z + " + x + ".w" + ")"; ``` --- .../contrib_ops/webgpu/bert/bias_add.cc | 10 +------- .../webgpu/bert/skip_layer_norm.cc | 23 +------------------ .../webgpu/quantization/matmul_nbits.cc | 12 +--------- .../core/providers/webgpu/math/softmax.cc | 23 +------------------ .../core/providers/webgpu/nn/layer_norm.cc | 23 +------------------ .../core/providers/webgpu/webgpu_utils.h | 17 ++++++++++++-- 6 files changed, 20 insertions(+), 88 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc index 65c14e8cb0bdd..e822f8764b63f 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_utils.h" #include "core/providers/webgpu/webgpu_supported_types.h" #include "contrib_ops/webgpu/bert/bias_add.h" #include "contrib_ops/webgpu/webgpu_contrib_kernels.h" @@ -34,15 +35,6 @@ Status BiasAddProgram::GenerateShaderCode(ShaderHelper& shader) const { return Status::OK(); } -static int64_t GetMaxComponents(int64_t size) { - if (size % 4 == 0) { - return 4; - } else if (size % 2 == 0) { - return 2; - } - return 1; -} - Status BiasAdd::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) const { const auto* input = context.Input(0); const auto* bias = context.Input(1); diff --git a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc index d5d4632c01e2a..61f701f7911a7 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_utils.h" #include "core/providers/webgpu/webgpu_supported_types.h" #include "contrib_ops/webgpu/webgpu_contrib_kernels.h" #include "contrib_ops/webgpu/bert/skip_layer_norm.h" @@ -10,28 +11,6 @@ namespace onnxruntime { namespace contrib { namespace webgpu { -static uint32_t GetMaxComponents(int size) { - if (size % 4 == 0) { - return 4; - } else if (size % 2 == 0) { - return 2; - } - return 1; -} - -static std::string SumVector(std::string x, int components) { - switch (components) { - case 1: - return x; - case 2: - return "(" + x + ".x + " + x + ".y" + ")"; - case 4: - return "(" + x + ".x + " + x + ".y + " + x + ".w + " + x + ".z" + ")"; - default: - ORT_THROW("Unsupported number of components: ", components); - } -} - Status SkipLayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); shader.AddInput("skip", ShaderUsage::UseUniform); diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index b4e47b9186265..be105a0fd4374 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -10,23 +10,13 @@ #include "core/providers/cpu/math/matmul_helper.h" #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_utils.h" namespace onnxruntime { namespace contrib { namespace webgpu { namespace { -// Put it to a common place? -uint32_t GetMaxComponents(uint32_t size) { - // we cannot use vec3 type since it has alignment of 16 bytes - if (size % 4 == 0) { - return 4; - } else if (size % 2 == 0) { - return 2; - } - - return 1; -} std::string QuantizedDataType(int components) { switch (components) { diff --git a/onnxruntime/core/providers/webgpu/math/softmax.cc b/onnxruntime/core/providers/webgpu/math/softmax.cc index d06fc5a57eb8c..6a6cfe154b91c 100644 --- a/onnxruntime/core/providers/webgpu/math/softmax.cc +++ b/onnxruntime/core/providers/webgpu/math/softmax.cc @@ -11,6 +11,7 @@ #include "core/providers/webgpu/shader_variable.h" #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_utils.h" namespace onnxruntime { namespace webgpu { @@ -56,28 +57,6 @@ static std::string MaxVector(const std::string& name, int components) { } } -static std::string SumVector(const std::string& x, int components) { - switch (components) { - case 1: - return x; - case 2: - return "(" + x + ".x + " + x + ".y" + ")"; - case 4: - return "(" + x + ".x + " + x + ".y + " + x + ".w + " + x + ".z" + ")"; - default: - ORT_THROW("Unsupported number of components: ", components); - } -} - -static int GetMaxComponents(int64_t size) { - if (size % 4 == 0) { - return 4; - } else if (size % 2 == 0) { - return 2; - } - return 1; -} - Status SoftmaxProgram::GenerateShaderCode(ShaderHelper& shader) const { // Add input and output variables const auto& input = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc index 28ad686909a47..cf2939555057a 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc @@ -4,20 +4,12 @@ #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_utils.h" #include "core/providers/webgpu/nn/layer_norm.h" namespace onnxruntime { namespace webgpu { -static int GetMaxComponents(int64_t size) { - if (size % 4 == 0) { - return 4; - } else if (size % 2 == 0) { - return 2; - } - return 1; -} - static size_t NormalizeAxis(int64_t axis, size_t tensor_rank) { int64_t rank = static_cast(tensor_rank); if (axis < -rank && axis >= rank) { @@ -26,19 +18,6 @@ static size_t NormalizeAxis(int64_t axis, size_t tensor_rank) { return onnxruntime::narrow(axis < 0 ? axis + rank : axis); } -static std::string SumVector(std::string x, int components) { - switch (components) { - case 1: - return x; - case 2: - return "(" + x + ".x + " + x + ".y" + ")"; - case 4: - return "(" + x + ".x + " + x + ".y + " + x + ".w + " + x + ".z" + ")"; - default: - ORT_THROW("Unsupported number of components: ", components); - } -} - Status LayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); shader.AddInput("scale", ShaderUsage::UseUniform); diff --git a/onnxruntime/core/providers/webgpu/webgpu_utils.h b/onnxruntime/core/providers/webgpu/webgpu_utils.h index 4f9018646905d..eb25a9bd5386e 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_utils.h +++ b/onnxruntime/core/providers/webgpu/webgpu_utils.h @@ -7,7 +7,7 @@ namespace onnxruntime { namespace webgpu { -inline int64_t GetMaxComponents(int64_t size) { +inline int GetMaxComponents(int64_t size) { if (size % 4 == 0) { return 4; } else if (size % 2 == 0) { @@ -16,5 +16,18 @@ inline int64_t GetMaxComponents(int64_t size) { return 1; } +inline std::string SumVector(std::string x, int components) { + switch (components) { + case 1: + return x; + case 2: + return "(" + x + ".x + " + x + ".y" + ")"; + case 4: + return "(" + x + ".x + " + x + ".y + " + x + ".z + " + x + ".w" + ")"; + default: + ORT_THROW("Unsupported number of components: ", components); + } +} + } // namespace webgpu -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime From dcc1f5ac59ca292267871517f6442648a7dbe120 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Fri, 21 Mar 2025 00:11:18 -0700 Subject: [PATCH 144/266] skip MOE python test when MPI is not installed (#24116) ### Description It is not common that dev machine have MPI installed. Skip the test if MPI is not installed. ### Motivation and Context Make it easy to run pytest in dev machine without the need to skip the test manually. --- .../sharded_moe/test_sharded_moe.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/onnxruntime/test/python/transformers/sharded_moe/test_sharded_moe.py b/onnxruntime/test/python/transformers/sharded_moe/test_sharded_moe.py index 42682d67e94ec..2d29135726839 100644 --- a/onnxruntime/test/python/transformers/sharded_moe/test_sharded_moe.py +++ b/onnxruntime/test/python/transformers/sharded_moe/test_sharded_moe.py @@ -6,22 +6,28 @@ import unittest import numpy as np -from mpi4py import MPI from onnx import TensorProto, helper import onnxruntime -np.random.seed(3) +try: + from mpi4py import MPI + + comm = MPI.COMM_WORLD +except (ImportError, RuntimeError): + comm = None -comm = MPI.COMM_WORLD +has_mpi = comm is not None + +np.random.seed(3) def get_rank(): - return comm.Get_rank() + return comm.Get_rank() if comm else 0 def get_size(): - return comm.Get_size() + return comm.Get_size() if comm else 0 def print_out(*args): @@ -254,7 +260,7 @@ def run_ort_with_parity_check( ) -def test_moe_with_tensor_parallelism( +def run_moe_with_tensor_parallelism( hidden_size, inter_size, num_experts, @@ -327,7 +333,7 @@ def get_fc2_tensor_shards(expert_weights): ) -def test_moe_with_expert_parallelism( +def run_moe_with_expert_parallelism( hidden_size, inter_size, num_experts, @@ -390,19 +396,22 @@ def test_moe_with_expert_parallelism( class TestMoE(unittest.TestCase): def test_moe_parallelism(self): + if not has_mpi: + self.skipTest("No MPI support") + for hidden_size in [128, 1024]: for inter_size in [512, 2048]: for num_experts in [64]: for num_rows in [1024]: print_out("EP") - test_moe_with_expert_parallelism( + run_moe_with_expert_parallelism( hidden_size, inter_size, num_experts, num_rows, ) print_out("TP") - test_moe_with_tensor_parallelism( + run_moe_with_tensor_parallelism( hidden_size, inter_size, num_experts, From 90c5ffb585dd37a888ef33ae459d1b73b9a4c533 Mon Sep 17 00:00:00 2001 From: Michael Tyler <67695629+MichaelTylerArm@users.noreply.github.com> Date: Fri, 21 Mar 2025 20:32:09 +0000 Subject: [PATCH 145/266] Integrate KleidiAI for MatMulNBits via MlasQNBitGemm (#23627) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description This PR integrates Arm® KleidiAI™ to provide optimized assembly kernels for matrix multiplication with 4-bit quantized weights. These changes target the MlasQNBitGemm functions, and can be utilized via the MatMulNBits operator. --- ThirdPartyNotices.txt | 74 ++++++++++ cmake/CMakeLists.txt | 15 ++ cmake/deps.txt | 2 +- cmake/onnxruntime_common.cmake | 4 +- cmake/onnxruntime_mlas.cmake | 25 ++++ .../cpu/quantization/matmul_nbits.cc | 45 ++++-- onnxruntime/core/mlas/inc/mlas_qnbit.h | 26 +++- .../core/mlas/lib/kai_ukernel_interface.cpp | 81 +++++++++++ .../core/mlas/lib/kai_ukernel_interface.h | 12 ++ onnxruntime/core/mlas/lib/qnbitgemm.cpp | 71 +++++++-- onnxruntime/core/mlas/lib/qnbitgemm.h | 77 +++++++++- .../core/mlas/lib/qnbitgemm_kernel_neon.cpp | 136 ++++++++++++++++-- .../core/mlas/lib/qnbitgemm_kernel_neon.h | 36 +++++ .../core/mlas/lib/sqnbitgemm_kernel_avx2.cpp | 7 +- .../mlas/lib/sqnbitgemm_kernel_avx512.cpp | 7 +- .../mlas/lib/sqnbitgemm_kernel_avx512vnni.cpp | 7 +- .../mlas/lib/sqnbitgemm_kernel_avx_common.h | 14 +- .../mlas/lib/sqnbitgemm_kernel_neon_int8.cpp | 85 ++++++++++- .../test/mlas/bench/bench_qnbitgemm.cpp | 4 +- .../test/mlas/unittest/test_sqnbitgemm.cpp | 4 +- tools/ci_build/build.py | 3 + 21 files changed, 675 insertions(+), 60 deletions(-) create mode 100644 onnxruntime/core/mlas/lib/kai_ukernel_interface.cpp create mode 100644 onnxruntime/core/mlas/lib/kai_ukernel_interface.h diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index a449e42f6bf19..7b2bbdd2094d1 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -6080,3 +6080,77 @@ https://dawn.googlesource.com/dawn CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +KleidiAI + +https://gitlab.arm.com/kleidi/kleidiai + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright 2024-2025 Arm Limited and/or its affiliates + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index d520f4ac9212a..560d1cd423083 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -87,6 +87,7 @@ option(onnxruntime_USE_SNPE "Build with SNPE support" OFF) option(onnxruntime_USE_RKNPU "Build with RKNPU support" OFF) option(onnxruntime_USE_DNNL "Build with DNNL support" OFF) option(onnxruntime_USE_JSEP "Build with JavaScript implemented kernels support" OFF) +option(onnxruntime_USE_KLEIDIAI "Build with KleidiAI integration in MLAS" OFF) option(onnxruntime_BUILD_UNIT_TESTS "Build ONNXRuntime unit tests" ON) option(onnxruntime_BUILD_CSHARP "Build C# library" OFF) option(onnxruntime_BUILD_OBJC "Build Objective-C library" OFF) @@ -831,6 +832,20 @@ else() endif() endif() +if (onnxruntime_USE_KLEIDIAI AND NOT MSVC AND ( + (onnxruntime_target_platform STREQUAL "aarch64") OR + (onnxruntime_target_platform STREQUAL "ARM64") OR + (APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64"))) + check_cxx_compiler_flag(-march=armv8.2-a+dotprod HAS_ARM64_DOTPROD) + check_cxx_compiler_flag(-march=armv8.2-a+i8mm HAS_ARM64_I8MM) + if (NOT HAS_ARM64_DOTPROD) + message(FATAL_ERROR "The compiler doesn't support dotprod") + endif() + if (NOT HAS_ARM64_I8MM) + message(FATAL_ERROR "The compiler doesn't support i8mm") + endif() +endif() + #names in this var must match the directory names under onnxruntime/core/providers #ONNXRUNTIME_PROVIDER_NAMES is the list of providers that needs to export additional symbols in the global namespace. #For example CUDA EP exports "OrtSessionOptionsAppendExecutionProvider_CUDA", which is a global function. diff --git a/cmake/deps.txt b/cmake/deps.txt index 82b4128e4cf8d..060dd72d655d3 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -58,4 +58,4 @@ composable_kernel;https://github.com/ROCmSoftwarePlatform/composable_kernel/arch directx_headers;https://github.com/microsoft/DirectX-Headers/archive/refs/tags/v1.613.1.zip;47653509a3371eabb156360f42faf582f314bf2e cudnn_frontend;https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.7.0.zip;d0753d8d5b39947ca0729d7773cb84653a129eb1 dawn;https://github.com/google/dawn/archive/40a9fa79f76e6c76cca9e2fa69ea07f202f1d2e6.zip;e224563d5ab4a8e53a517b06f721242533bce722 -kleidiai;https://gitlab.arm.com/kleidi/kleidiai/-/archive/d15722976120710080ca098fe8ddabf4556cb40f/kleidiai-d15722976120710080ca098fe8ddabf4556cb40f.zip;d6c840d00c3b05aedf06e957ddaece1013d1f40b +kleidiai;https://github.com/ARM-software/kleidiai/archive/refs/tags/v1.4.0.tar.gz;22d3b57b54a61c194ab256ff11b0353a3b220244 diff --git a/cmake/onnxruntime_common.cmake b/cmake/onnxruntime_common.cmake index e599e4f04ad91..3c526cd61418a 100644 --- a/cmake/onnxruntime_common.cmake +++ b/cmake/onnxruntime_common.cmake @@ -67,13 +67,13 @@ if(onnxruntime_target_platform STREQUAL "ARM64EC") link_directories("$ENV{VCINSTALLDIR}/Tools/MSVC/$ENV{VCToolsVersion}/lib/ARM64EC") link_directories("$ENV{VCINSTALLDIR}/Tools/MSVC/$ENV{VCToolsVersion}/ATLMFC/lib/ARM64EC") link_libraries(softintrin.lib) - add_compile_options("/bigobj") + add_compile_options("$<$>:/bigobj>") endif() endif() if(onnxruntime_target_platform STREQUAL "ARM64") if (MSVC) - add_compile_options("/bigobj") + add_compile_options("$<$>:/bigobj>") endif() endif() diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index 87387d4f281ed..9b468da44928e 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -128,6 +128,10 @@ function(setup_mlas_source_for_windows) ${MLAS_SRC_DIR}/arm64/SymQgemmS8KernelSDot.asm ${MLAS_SRC_DIR}/arm64/SymQgemmS8KernelSDotLd64.asm ) + + if (onnxruntime_USE_KLEIDIAI) + setup_kleidiai() + endif() else() target_sources(onnxruntime_mlas PRIVATE ${MLAS_SRC_DIR}/qgemm_kernel_neon.cpp @@ -256,6 +260,24 @@ function(setup_mlas_source_for_windows) endif() endfunction() +function(setup_kleidiai) + target_compile_definitions(onnxruntime_mlas PRIVATE USE_KLEIDIAI) + + # Disable the KleidiAI tests + set(KLEIDIAI_BUILD_TESTS OFF) + + # Fetch KleidiAI sources: + if (NOT TARGET kleidiai) + onnxruntime_fetchcontent_declare(kleidiai URL ${DEP_URL_kleidiai} URL_HASH SHA1=${DEP_SHA1_kleidiai} EXCLUDE_FROM_ALL) + endif() + onnxruntime_fetchcontent_makeavailable(kleidiai) + + target_sources(onnxruntime_mlas PRIVATE + ${MLAS_SRC_DIR}/kai_ukernel_interface.cpp + ) + target_link_libraries(onnxruntime_mlas PRIVATE kleidiai) +endfunction() + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") if (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) file(GLOB_RECURSE mlas_platform_srcs @@ -395,6 +417,9 @@ else() ${MLAS_SRC_DIR}/eltwise_kernel_neon.h ${MLAS_SRC_DIR}/eltwise_kernel_neon.cpp ) + if (onnxruntime_USE_KLEIDIAI) + setup_kleidiai() + endif() set_source_files_properties(${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+dotprod") if (NOT APPLE) diff --git a/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc index c3e43f897c509..d5a6a1ae699d9 100644 --- a/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc @@ -133,6 +133,7 @@ class MatMulNBits final : public OpKernel { const size_t nbits_; const bool has_g_idx_; const bool has_bias_; + bool scales_are_packed_{false}; const MLAS_QNBIT_GEMM_COMPUTE_TYPE compute_type_; bool has_unquantized_zero_point_{false}; const bool column_wise_quant_{true}; @@ -181,13 +182,18 @@ Status MatMulNBits::PrePack(const Tensor& tensor, int input_idx, /*out*/ All return Status::OK(); } if (input_idx == InputIndex::B) { - packed_b_size_ = MlasQNBitGemmPackQuantBDataSize(N_, K_, nbits_, block_size_, compute_type_); + const Tensor* scales = nullptr; + OpKernel::Info().TryGetConstantInput(InputIndex::scales, &scales); + + packed_b_size_ = MlasQNBitGemmPackQuantBDataSize(N_, K_, nbits_, block_size_, has_zp_input_, compute_type_); if (packed_b_size_ == 0) { return Status::OK(); } auto qptr = tensor.DataRaw(); + auto scale_ptr = scales ? scales->DataRaw() : nullptr; packed_b_ = IAllocator::MakeUniquePtr(alloc, packed_b_size_, true); - MlasQNBitGemmPackQuantBData(N_, K_, nbits_, block_size_, compute_type_, qptr, packed_b_.get(), nullptr, has_zp_input_, nullptr, nullptr); + MlasQNBitGemmPackQuantBData(N_, K_, nbits_, block_size_, compute_type_, qptr, packed_b_.get(), scale_ptr, + has_zp_input_, nullptr, nullptr); is_packed = true; } else if (compute_type_ == SQNBIT_CompInt8) { #ifdef MLAS_TARGET_AMD64_IX86 @@ -198,10 +204,17 @@ Status MatMulNBits::PrePack(const Tensor& tensor, int input_idx, /*out*/ All is_packed = false; } else if (input_idx == InputIndex::zero_points && packed_b_ != nullptr) { auto zptr = tensor.Data(); - MlasQNBitGemmPackQuantBData(N_, K_, nbits_, block_size_, compute_type_, nullptr, packed_b_.get(), nullptr, has_zp_input_, zptr, nullptr); + MlasQNBitGemmPackQuantBData(N_, K_, nbits_, block_size_, compute_type_, nullptr, packed_b_.get(), nullptr, + has_zp_input_, zptr, nullptr); is_packed = false; } -#endif // MLAS_TARGET_AMD64_IX86 +#elif defined(MLAS_TARGET_ARM64) + if (input_idx == InputIndex::scales && packed_b_ != nullptr && + MlasQNBitGemmScalesPacked(K_, nbits_, block_size_, compute_type_, has_zp_input_)) { + scales_are_packed_ = true; + is_packed = true; + } +#endif // MLAS_TARGET_ARM64 } return Status::OK(); @@ -236,14 +249,24 @@ Status MatMulNBits::PrePack(const Tensor& tensor, int input_idx, /*ou return Status::OK(); } if (input_idx == InputIndex::B) { - packed_b_size_ = MlasQNBitGemmPackQuantBDataSize(N_, K_, nbits_, block_size_, compute_type_); + const Tensor* scales = nullptr; + OpKernel::Info().TryGetConstantInput(InputIndex::scales, &scales); + if (scales && MlasQNBitGemmScalesPacked(K_, nbits_, block_size_, compute_type_, has_zp_input_)) { + auto sptr = scales->Data(); + auto tensor_size = static_cast(tensor.Shape().Size()); + auto ptr = IAllocator::MakeUniquePtr(alloc, tensor_size, true); + MlasConvertHalfToFloatBuffer(sptr, ptr.get(), tensor_size); + scales_fp32_ = std::move(ptr); + } + + packed_b_size_ = MlasQNBitGemmPackQuantBDataSize(N_, K_, nbits_, block_size_, has_zp_input_, compute_type_); if (packed_b_size_ == 0) { return Status::OK(); } auto qptr = tensor.DataRaw(); packed_b_ = IAllocator::MakeUniquePtr(alloc, packed_b_size_, true); MlasQNBitGemmPackQuantBData(N_, K_, nbits_, block_size_, compute_type_, qptr, packed_b_.get(), - nullptr, has_zp_input_, nullptr, nullptr); + scales_fp32_.get(), has_zp_input_, nullptr, nullptr); is_packed = true; } else if (compute_type_ == SQNBIT_CompInt8) { #ifdef MLAS_TARGET_AMD64_IX86 @@ -287,7 +310,7 @@ Status MatMulNBits::ComputeBPacked(const Tensor* a, concurrency::ThreadPool* thread_pool, const MatMulComputeHelper& helper) const { const auto* a_data = a->Data(); - const auto* scales_data = scales->Data(); + const auto* scales_data = scales == nullptr ? nullptr : scales->Data(); const auto* zero_points_data = zero_points == nullptr ? nullptr : zero_points->DataRaw(); const auto* bias_data = bias == nullptr ? nullptr : bias->Data(); auto* y_data = y->MutableData(); @@ -300,7 +323,7 @@ Status MatMulNBits::ComputeBPacked(const Tensor* a, IAllocatorUniquePtr workspace{}; const size_t workspace_size = MlasQNBitGemmBatchWorkspaceSize( - M, N, K, batch_count, nbits_, block_size_, compute_type_); + M, N, K, batch_count, nbits_, block_size_, zero_points, compute_type_); if (workspace_size > 0) { // Use reserve since no caching is needed workspace = IAllocator::MakeUniquePtr(allocator, workspace_size, true); @@ -310,11 +333,9 @@ Status MatMulNBits::ComputeBPacked(const Tensor* a, for (size_t i = 0; i < batch_count; ++i) { data[i].A = a_data + helper.LeftOffsets()[i]; data[i].lda = lda; -#ifdef MLAS_TARGET_AMD64_IX86 if (compute_type_ == SQNBIT_CompInt8) { data[i].QuantBDataWorkspace = packed_b_.get(); } -#endif data[i].PackedQuantBData = static_cast(packed_b_.get()); data[i].QuantBScale = scales_data; data[i].QuantBZeroPoint = zero_points_data; @@ -351,7 +372,7 @@ Status MatMulNBits::ComputeBPacked(const Tensor* a, IAllocatorUniquePtr workspace{}; const size_t workspace_size = MlasQNBitGemmBatchWorkspaceSize( - M, N, K, batch_count, nbits_, block_size_, compute_type_); + M, N, K, batch_count, nbits_, block_size_, zero_points, compute_type_); if (workspace_size > 0) { // Use reserve since no caching is needed workspace = IAllocator::MakeUniquePtr(allocator, workspace_size, true); @@ -653,7 +674,7 @@ template Status MatMulNBits::Compute(OpKernelContext* ctx) const { concurrency::ThreadPool* thread_pool = ctx->GetOperatorThreadPool(); const Tensor* a = ctx->Input(InputIndex::A); - const Tensor* scales = ctx->Input(InputIndex::scales); + const Tensor* scales = scales_are_packed_ ? nullptr : ctx->Input(InputIndex::scales); const Tensor* zero_points = ctx->Input(InputIndex::zero_points); const Tensor* reorder_idx = ctx->Input(InputIndex::g_idx); const Tensor* bias = ctx->Input(InputIndex::bias); diff --git a/onnxruntime/core/mlas/inc/mlas_qnbit.h b/onnxruntime/core/mlas/inc/mlas_qnbit.h index 9608644a22523..3627989609737 100644 --- a/onnxruntime/core/mlas/inc/mlas_qnbit.h +++ b/onnxruntime/core/mlas/inc/mlas_qnbit.h @@ -123,6 +123,7 @@ MlasIsQNBitGemmAvailable( * @param[in] BatchN number of batches * @param[in] BlkBitWidth quantized value bit width (e.g., 4 means 4 bit ints) * @param[in] BlkLen number of quantized values per block + * @param[in] HasZeroPoint whether zero points are provided * @param[in] ComputeType GEMM compute type (e.g., multiplying float or int8 values) */ size_t MLASCALL @@ -133,6 +134,7 @@ MlasQNBitGemmBatchWorkspaceSize( size_t BatchN, size_t BlkBitWidth, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ); @@ -147,6 +149,7 @@ MlasQNBitGemmBatchWorkspaceSize( * @param[in] K column size of matrix A and row size of matrix B * @param[in] BlkBitWidth quantized value bit width (e.g., 4 means 4 bit ints) * @param[in] BlkLen number of quantized values per block + * @param[in] HasZeroPoint whether zero points are provided * @param[in] ComputeType GEMM compute type (e.g., multiplying float or int8 values) */ size_t MLASCALL @@ -155,6 +158,7 @@ MlasQNBitGemmPackQuantBDataSize( size_t K, size_t BlkBitWidth, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ); @@ -181,7 +185,7 @@ MlasQNBitGemmPackQuantBDataSize( * @param[in] QuantBData quantized B data * @param[in] PackedQuantBDataAndOrBlkSum buffer to store packed quantized B data and/or BlkSum * @param[in] QuantBScale quantized B scale - * @param[in] has_zp_input whether QuantBZeroPoint is provided + * @param[in] HasZeroPoint whether QuantBZeroPoint is provided * @param[in] QuantBZeroPoint quantized B zero point * @param[in] ThreadPool thread pool to use (no parallel if nullptr) */ @@ -195,7 +199,25 @@ MlasQNBitGemmPackQuantBData( const void* QuantBData, void* PackedQuantBDataAndOrBlkSum, const void* QuantBScale, - bool has_zp_input, + bool HasZeroPoint, const void* QuantBZeroPoint, MLAS_THREADPOOL* ThreadPool ); + +/** + * @brief Returns true if scales are packed when calling MlasQNBitGemmPackQuantBData the first time. + * + * @param[in] K column size of matrix A and row size of matrix B + * @param[in] BlkBitWidth quantized value bit width (e.g., 4 means 4 bit ints) + * @param[in] BlkLen number of quantized values per block + * @param[in] ComputeType GEMM compute type (e.g., multiplying float or int8 values) + * @param[in] HasZeroPoint whether QuantBZeroPoint is provided + */ +bool MLASCALL +MlasQNBitGemmScalesPacked( + size_t K, + size_t BlkBitWidth, + size_t BlkLen, + MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, + bool HasZeroPoint +); diff --git a/onnxruntime/core/mlas/lib/kai_ukernel_interface.cpp b/onnxruntime/core/mlas/lib/kai_ukernel_interface.cpp new file mode 100644 index 0000000000000..fdada83cc6582 --- /dev/null +++ b/onnxruntime/core/mlas/lib/kai_ukernel_interface.cpp @@ -0,0 +1,81 @@ +// +// SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or its affiliates +// +// SPDX-License-Identifier: MIT +// + +#include "kai_ukernel_interface.h" +#include "mlasi.h" + +#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4c32p/kai_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod.h" +#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4c32p/kai_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod.h" +#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4c32p/kai_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod.h" +#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4c32p/kai_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm.h" + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel kai_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod = + {kai_get_m_step_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_n_step_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_mr_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_nr_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_kr_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_sr_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_lhs_packed_offset_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_rhs_packed_offset_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_dst_offset_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_get_dst_size_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod, + kai_run_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod}; + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel kai_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod = + {kai_get_m_step_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_n_step_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_mr_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_nr_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_kr_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_sr_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_lhs_packed_offset_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_rhs_packed_offset_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_dst_offset_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_get_dst_size_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod, + kai_run_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod}; + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel kai_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod = + {kai_get_m_step_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_n_step_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_mr_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_nr_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_kr_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_sr_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_lhs_packed_offset_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_rhs_packed_offset_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_dst_offset_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_get_dst_size_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod, + kai_run_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod}; + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel kai_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm = + {kai_get_m_step_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_n_step_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_mr_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_nr_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_kr_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_sr_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_lhs_packed_offset_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_rhs_packed_offset_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_dst_offset_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_get_dst_size_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm, + kai_run_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm}; + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& GetKleidiAIGemmUKernel() { + if (MLAS_CPUIDINFO::GetCPUIDInfo().HasArmNeon_I8MM()) { + return kai_matmul_clamp_f32_qai8dxp4x8_qsi4c32p4x8_16x4x32_neon_i8mm; + } else { + return kai_matmul_clamp_f32_qai8dxp4x4_qsi4c32p4x4_16x4_neon_dotprod; + } +} + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& GetKleidiAIGemvUKernel() { + if (MLAS_CPUIDINFO::GetCPUIDInfo().HasArmNeon_I8MM()) { + return kai_matmul_clamp_f32_qai8dxp1x8_qsi4c32p4x8_1x4x32_neon_dotprod; + } else { + return kai_matmul_clamp_f32_qai8dxp1x4_qsi4c32p4x4_1x4_neon_dotprod; + } +} diff --git a/onnxruntime/core/mlas/lib/kai_ukernel_interface.h b/onnxruntime/core/mlas/lib/kai_ukernel_interface.h new file mode 100644 index 0000000000000..1a6f111d1c794 --- /dev/null +++ b/onnxruntime/core/mlas/lib/kai_ukernel_interface.h @@ -0,0 +1,12 @@ +// +// SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or its affiliates +// +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4c32p/kai_matmul_clamp_f32_qai8dxp_qsi4c32p_interface.h" + +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& GetKleidiAIGemmUKernel(); +const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& GetKleidiAIGemvUKernel(); diff --git a/onnxruntime/core/mlas/lib/qnbitgemm.cpp b/onnxruntime/core/mlas/lib/qnbitgemm.cpp index f064a8e1d6a78..eafe91575c528 100644 --- a/onnxruntime/core/mlas/lib/qnbitgemm.cpp +++ b/onnxruntime/core/mlas/lib/qnbitgemm.cpp @@ -91,6 +91,7 @@ MlasIsQNBitGemmAvailable( } case SQNBitGemmVariant_BitWidth4_CompInt8: { // SQ4BitGemmKernel_BlkSum_CompInt8 return + (Dispatch->SQ4BitGemmKernel_Packed_CompInt8 != nullptr && Dispatch->QuantizeA_Packed_CompInt8 != nullptr) || (Dispatch->SQ4BitGemmKernel_CompInt8 != nullptr && Dispatch->QuantizeARow_CompInt8 != nullptr) || (Dispatch->SQ4BitGemmKernel_BlkSum_CompInt8 != nullptr && Dispatch->QuantizeARowComputeBlkSum_CompInt8 != nullptr); } @@ -110,6 +111,7 @@ QNBitGemmPerGemmWorkspaceSize( size_t K, size_t BlkBitWidth, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { @@ -119,7 +121,7 @@ QNBitGemmPerGemmWorkspaceSize( } if (BlkBitWidth == 4 && Dispatch->Q4BitGemmPerGemmWorkspaceSize != nullptr) { - return Dispatch->Q4BitGemmPerGemmWorkspaceSize(M, N, K, BlkLen, ComputeType); + return Dispatch->Q4BitGemmPerGemmWorkspaceSize(M, N, K, BlkLen, HasZeroPoint, ComputeType); } return 0; @@ -151,10 +153,11 @@ QNBitGemmPerGemmWorkspaceStride( size_t K, size_t BlkBitWidth, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { - const auto Size = QNBitGemmPerGemmWorkspaceSize(M, N, K, BlkBitWidth, BlkLen, ComputeType); + const auto Size = QNBitGemmPerGemmWorkspaceSize(M, N, K, BlkBitWidth, BlkLen, HasZeroPoint, ComputeType); const auto Alignment = QNBitGemmPerGemmWorkspaceAlignment(BlkBitWidth, BlkLen, ComputeType); return MlasDivRoundup(Size, Alignment) * Alignment; } @@ -169,10 +172,12 @@ MlasQNBitGemmBatchWorkspaceSize( size_t BatchN, size_t BlkBitWidth, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { - const size_t PerGemmWorkspaceStride = QNBitGemmPerGemmWorkspaceStride(M, N, K, BlkBitWidth, BlkLen, ComputeType); + const size_t PerGemmWorkspaceStride = + QNBitGemmPerGemmWorkspaceStride(M, N, K, BlkBitWidth, BlkLen, HasZeroPoint, ComputeType); if (PerGemmWorkspaceStride == 0) { return 0; } @@ -190,6 +195,7 @@ MlasQNBitGemmPackQuantBDataSize( size_t K, size_t BlkBitWidth, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { @@ -200,7 +206,7 @@ MlasQNBitGemmPackQuantBDataSize( if (BlkBitWidth == 4 && Dispatch->Q4BitGemmPackQuantBDataSize != nullptr) { return Dispatch->Q4BitGemmPackQuantBDataSize( - N, K, BlkLen, ComputeType + N, K, BlkLen, HasZeroPoint, ComputeType ); } @@ -232,7 +238,7 @@ MlasQNBitGemmPackQuantBData( const void* QuantBData, void* PackedQuantBDataAndOrBlkSumWorkspace, const void* QuantBScale, - bool has_zp_input, + bool HasZeroPoint, const void* QuantBZeroPoint, MLAS_THREADPOOL* ThreadPool ) @@ -253,7 +259,7 @@ MlasQNBitGemmPackQuantBData( ComputeType, static_cast(QuantBData), static_cast(QuantBScale), - has_zp_input, + HasZeroPoint, static_cast(QuantBZeroPoint), packed_quant_b, ThreadPool @@ -286,6 +292,29 @@ MlasQNBitGemmPackQuantBData( } } +bool MLASCALL +MlasQNBitGemmScalesPacked( + size_t K, + size_t BlkBitWidth, + size_t BlkLen, + MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, + bool HasZeroPoint +) { +#ifdef MLAS_TARGET_ARM64 + if (BlkBitWidth == 4 && ComputeType == SQNBIT_CompInt8) { + const auto UsePacked = GetMlasPlatform().QNBitGemmDispatch->UsePacked_CompInt8; + return UsePacked && UsePacked(K, BlkLen, HasZeroPoint); + } +#else + MLAS_UNREFERENCED_PARAMETER(K); + MLAS_UNREFERENCED_PARAMETER(BlkBitWidth); + MLAS_UNREFERENCED_PARAMETER(BlkLen); + MLAS_UNREFERENCED_PARAMETER(ComputeType); + MLAS_UNREFERENCED_PARAMETER(HasZeroPoint); +#endif // MLAS_TARGET_ARM64 + return false; +} + namespace { @@ -519,6 +548,16 @@ SQ4BitGemm_CompInt8( const size_t RangeCountN ) { + const auto UsePacked = GetMlasPlatform().QNBitGemmDispatch->UsePacked_CompInt8; + const auto SQ4BitGemm = GetMlasPlatform().QNBitGemmDispatch->SQ4BitGemmKernel_Packed_CompInt8; + if (UsePacked && SQ4BitGemm && UsePacked(K, BlkLen, DataParams->QuantBZeroPoint)) { + const std::byte* QuantA = static_cast(PerGemmWorkspace); + SQ4BitGemm(BlkLen, QuantA, DataParams->PackedQuantBData, + DataParams->C, RangeStartM, RangeCountM, RangeStartN, RangeCountN, K, + DataParams->ldc, DataParams->Bias); + return; + } + #ifdef MLAS_TARGET_AMD64_IX86 PerGemmQuantAWorkspace* const per_gemm_quant_a_workspace = static_cast(PerGemmWorkspace); constexpr size_t BlkBitWidth = 4; @@ -666,6 +705,8 @@ InitializeWorkspace_CompInt8( { MLAS_UNREFERENCED_PARAMETER(N); + const auto UsePacked = GetMlasPlatform().QNBitGemmDispatch->UsePacked_CompInt8; + const auto QuantizeA_Packed = GetMlasPlatform().QNBitGemmDispatch->QuantizeA_Packed_CompInt8; const auto QuantizeARow = GetMlasPlatform().QNBitGemmDispatch->QuantizeARow_CompInt8; const auto QuantizeARow2 = GetMlasPlatform().QNBitGemmDispatch->QuantizeARowComputeBlkSum_CompInt8; @@ -673,7 +714,15 @@ InitializeWorkspace_CompInt8( const size_t QuantAStride = BlockCountK * Q8BlkSize(BlkLen); // TODO: try parallel on BatchN * M threads because BatchN is usually 1. - if (QuantizeARow) { + if (UsePacked && QuantizeA_Packed && UsePacked(K, BlkLen, DataParams->QuantBZeroPoint)) { + MlasTrySimpleParallel(ThreadPool, BatchN, [&](ptrdiff_t gemm_idx) { + const auto& data = DataParams[gemm_idx]; + + const float* ARowPtr = data.A; + std::byte* QuantARowPtr = static_cast(Workspace) + gemm_idx * PerGemmWorkspaceStride; + QuantizeA_Packed(BlkLen, ARowPtr, M, K, QuantARowPtr); + }); + } else if (QuantizeARow) { MlasTrySimpleParallel(ThreadPool, BatchN, [&](ptrdiff_t gemm_idx) { const auto& data = DataParams[gemm_idx]; @@ -844,7 +893,9 @@ MlasQNBitGemmBatch( ); } - const size_t PerGemmWorkspaceStride = QNBitGemmPerGemmWorkspaceStride(M, N, K, BlkBitWidth, BlkLen, ComputeType); + const bool has_zp_input = DataParams->QuantBZeroPoint; + const size_t PerGemmWorkspaceStride = + QNBitGemmPerGemmWorkspaceStride(M, N, K, BlkBitWidth, BlkLen, has_zp_input, ComputeType); if (const auto InitializeWorkspaceOperation = GetInitializeWorkspace(Variant); InitializeWorkspaceOperation != nullptr) { @@ -862,7 +913,7 @@ MlasQNBitGemmBatch( const auto* Data = &DataParams[gemm_i]; void* PerGemmWorkspace = reinterpret_cast(Workspace) + gemm_i * PerGemmWorkspaceStride; - if (ComputeType == SQNBIT_CompInt8 && GetMlasPlatform().QNBitGemmDispatch->SQ4BitGemmPackQuantBDataAndBlkSum != nullptr) { + if (ComputeType == SQNBIT_CompInt8 && GetMlasPlatform().QNBitGemmDispatch->SQ4BitGemmKernel_BlkSum_CompInt8 != nullptr) { PackedQuantBDataStruct packed_quant_b(const_cast(Data->QuantBDataWorkspace), N, BlockCountK, BlkLen); const_cast*>(Data)->PackedQuantBData = packed_quant_b.PackedQuantBData; const_cast*>(Data)->QuantBBlkSum = packed_quant_b.QuantBBlkSum; @@ -933,7 +984,7 @@ MlasQNBitGemmBatch( void* PerGemmWorkspace = reinterpret_cast(Workspace) + gemm_i * PerGemmWorkspaceStride; - if (ComputeType == SQNBIT_CompInt8 && GetMlasPlatform().QNBitGemmDispatch->SQ4BitGemmPackQuantBDataAndBlkSum != nullptr) { + if (ComputeType == SQNBIT_CompInt8 && GetMlasPlatform().QNBitGemmDispatch->SQ4BitGemmKernel_BlkSum_CompInt8 != nullptr) { PackedQuantBDataStruct packed_quant_b(const_cast(Data->QuantBDataWorkspace), N, BlockCountK, BlkLen); const_cast*>(Data)->PackedQuantBData = packed_quant_b.PackedQuantBData; const_cast*>(Data)->QuantBBlkSum = packed_quant_b.QuantBBlkSum; diff --git a/onnxruntime/core/mlas/lib/qnbitgemm.h b/onnxruntime/core/mlas/lib/qnbitgemm.h index eb3d0b44ae3de..e25455cbfa217 100644 --- a/onnxruntime/core/mlas/lib/qnbitgemm.h +++ b/onnxruntime/core/mlas/lib/qnbitgemm.h @@ -55,9 +55,12 @@ struct PackedQuantBDataStruct { constexpr size_t BlkBitWidth = 4; const size_t PackedQuantBDataSize = N * BlockCountK * MlasQNBitBlkDataSizeInBytes(BlkBitWidth, BlkLen); size_t BlkSumSize = MlasDivRoundup(N, 16) * BlockCountK * 16 * sizeof(T); - +#if defined(MLAS_TARGET_AMD64_IX86) // _mm256_load_si256 requires alignment on a 32-byte boundary PackedQuantBData = (std::byte*)MlasAlignAddress(PackedQuantBWorkspace, 32); +#else + PackedQuantBData = (std::byte*)PackedQuantBWorkspace; +#endif QuantBBlkSum = (T*)(PackedQuantBData + PackedQuantBDataSize); QuantBBlkSum = (T*)MlasAlignAddress(QuantBBlkSum, MlasQNBitQuantBBlkSumAlignment()); PackedQuantBScale = (T*)((std::byte*)QuantBBlkSum + BlkSumSize); @@ -95,6 +98,7 @@ struct MLAS_QNBIT_GEMM_DISPATCH { size_t N, size_t K, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ); @@ -121,9 +125,9 @@ struct MLAS_QNBIT_GEMM_DISPATCH { MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, const std::byte* QuantBDataBegin, const float* QuantBScaleBegin, - bool has_zp_input, + bool HasZeroPoint, const std::byte* QuantBZPBegin, - PackedQuantBDataStruct& packed_quant_b, + PackedQuantBDataStruct& PackedQuantB, MLAS_THREADPOOL* ThreadPool ); @@ -141,6 +145,7 @@ struct MLAS_QNBIT_GEMM_DISPATCH { * @param[in] N column size of matrix B and C * @param[in] K column size of matrix A and row size of matrix B * @param[in] BlkLen number of quantized values per block + * @param[in] HasZeroPoint whether zero points are provided * @param[in] ComputeType GEMM compute type (e.g., multiplying float or int8 values) */ typedef size_t(Q4BitGemmPerGemmWorkspaceSize_Fn)( @@ -148,6 +153,7 @@ struct MLAS_QNBIT_GEMM_DISPATCH { size_t N, size_t K, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ); @@ -267,6 +273,39 @@ struct MLAS_QNBIT_GEMM_DISPATCH { // SQNBIT_CompInt8 kernel function prototypes. // + /** + * @brief Multiply quantized 8-bit integer matrix A with quantized 4-bit integer matrix B. + * A and B are block quantized and B is column major. + * A should be packed using QuantizeA_Packed_CompInt8. + * + * @param BlkLen Number of values in a block. + * @param QuantA Supplies the quantized A matrix. + Binary data containing block quantized int8 data and scale values. + * @param PackedQuantBData Supplies the packed quantized B matrix data. + * @param[out] C Supplies the output C matrix. + * @param RangeStartM Start of M range. + * @param RangeCountM Number of rows of A and C. + * @param RangeStartN Start of N range. + * @param RangeCountN Number of columns of B and C. + * @param CountK Number of columns of A and rows of B. + * @param ldc Number of elements between adjacent rows of C. + */ + typedef void(SQ4BitGemmKernel_Packed_CompInt8_Fn)( + size_t BlkLen, + const std::byte* QuantA, + const std::byte* PackedQuantBData, + float* C, + const size_t RangeStartM, + const size_t RangeCountM, + const size_t RangeStartN, + const size_t RangeCountN, + size_t CountK, + size_t ldc, + const float* Bias + ); + + SQ4BitGemmKernel_Packed_CompInt8_Fn* SQ4BitGemmKernel_Packed_CompInt8 = nullptr; + /** * @brief Multiply quantized 8-bit integer matrix A with quantized 4-bit integer matrix B. * A and B are block quantized and B is column major. @@ -343,6 +382,38 @@ struct MLAS_QNBIT_GEMM_DISPATCH { SQ4BitGemmKernel_CompInt8_Fn* SQ4BitGemmKernel_CompInt8 = nullptr; + /** + * @brief Whether to use SQ4BitGemmKernel_Packed_CompInt8 for this problem. + */ + typedef bool(UsePacked_CompInt8_Fn)( + size_t K, + size_t BlkLen, + bool HasZp + ); + + UsePacked_CompInt8_Fn* UsePacked_CompInt8 = nullptr; + + /** + * @brief Block quantize values from matrix A from floats to quantized 8-bit integers. + * Used in conjunction with SQ4BitGemmKernel_Packed_CompInt8. + * + * @param BlkLen Number of values in a block. + * @param A Supplies the A matrix. + * @param CountM Number of rows of A. + * @param CountK Number of columns of A. + * @param[out] QuantA Supplies the output quantized A matrix. + * Binary data containing block quantized int8 data and scale values. + */ + typedef void(QuantizeA_Packed_CompInt8_Fn)( + size_t BlkLen, + const float* A, + size_t CountM, + size_t CountK, + std::byte* QuantA + ); + + QuantizeA_Packed_CompInt8_Fn* QuantizeA_Packed_CompInt8 = nullptr; + /** * @brief Block quantize values from one row of matrix A from floats to quantized 8-bit integers. * diff --git a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp index 748ad8b9ba1a0..ab71492805e9c 100644 --- a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp +++ b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.cpp @@ -20,10 +20,18 @@ Module Name: #include #include +#include #include "qnbitgemm.h" #include "sqnbitgemm_q8_block.h" +#ifdef USE_KLEIDIAI +#include "kai/kai_common.h" +#include "kai/ukernels/matmul/pack/kai_rhs_pack_nxk_qsi4c32p_qsu4c32s1s0.h" +#include "kai/ukernels/matmul/pack/kai_lhs_quant_pack_qai8dxp_f32.h" +#include "kai_ukernel_interface.h" +#endif + namespace sqnbitgemm_neon { @@ -39,16 +47,31 @@ Q4BitGemmPackQuantBDataSize( size_t N, size_t K, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { +#ifndef USE_KLEIDIAI + MLAS_UNREFERENCED_PARAMETER(HasZeroPoint); MLAS_UNREFERENCED_PARAMETER(ComputeType); // same size regardless of ComputeType - - constexpr size_t BlkBitWidth = 4; - - const size_t BlockCountK = MlasDivRoundup(K, BlkLen); - const size_t PackedQuantBDataSize = N * BlockCountK * MlasQNBitBlkDataSizeInBytes(BlkBitWidth, BlkLen); - return PackedQuantBDataSize; +#endif + +#ifdef USE_KLEIDIAI + if (ComputeType == SQNBIT_CompInt8 && UseKleidiAI(K, BlkLen, HasZeroPoint)) { + const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& ukernel = GetKleidiAIGemmUKernel(); + const size_t nr = ukernel.get_nr(); + const size_t kr = ukernel.get_kr(); + const size_t sr = ukernel.get_sr(); + return kai_get_rhs_packed_size_rhs_pack_nxk_qsi4c32p_qsu4c32s1s0(N, K, nr, kr, sr, BlkLen, kai_dt_bf16); + } else +#endif + { + constexpr size_t BlkBitWidth = 4; + + const size_t BlockCountK = MlasDivRoundup(K, BlkLen); + const size_t PackedQuantBDataSize = N * BlockCountK * MlasQNBitBlkDataSizeInBytes(BlkBitWidth, BlkLen); + return PackedQuantBDataSize; + } } void @@ -122,6 +145,60 @@ SQ4BitGemmPackQuantBData( ); } +void +SQ4BitGemmPackQuantBDataAndBlkSum( + size_t N, + size_t K, + size_t BlkLen, + MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, + const std::byte* QuantBDataBegin, + const float* QuantBScaleBegin, + bool HasZeroPoint, + const std::byte*, + PackedQuantBDataStruct& PackedQuantB, + MLAS_THREADPOOL* ThreadPool +) +{ +#ifndef USE_KLEIDIAI + MLAS_UNREFERENCED_PARAMETER(QuantBScaleBegin); + MLAS_UNREFERENCED_PARAMETER(HasZeroPoint); +#endif + assert(BlkLen >= 16 && BlkLen % 16 == 0); + +#ifdef USE_KLEIDIAI + if (UseKleidiAI(K, BlkLen, HasZeroPoint)) { + const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& ukernel = GetKleidiAIGemmUKernel(); + std::byte* PackedQuantBDataBegin = PackedQuantB.PackedQuantBData; + + const size_t nr = ukernel.get_nr(); + const size_t kr = ukernel.get_kr(); + const size_t sr = ukernel.get_sr(); + + kai_rhs_pack_nxk_qsi4c32p_qsu4c32s1s0_params params; + params.lhs_zero_point = 1; + params.rhs_zero_point = 8; + params.scale_dt = kai_dt_bf16; + + const size_t BlockCountK = MlasDivRoundup(K, BlkLen); + const size_t scales_len = N * BlockCountK; + std::vector scales(scales_len); + for (size_t i = 0; i < scales_len; i++) { + const uint32_t* i32 = reinterpret_cast(&QuantBScaleBegin[i]); + scales[i] = *i32 >> 16; + } + + kai_run_rhs_pack_nxk_qsi4c32p_qsu4c32s1s0(1, N, K, nr, kr, sr, BlkLen, + reinterpret_cast(QuantBDataBegin), BlockCountK * BlkLen / 2, + nullptr, scales.data(), BlockCountK * sizeof(uint16_t), + PackedQuantBDataBegin, 0, ¶ms); + } else +#endif + { + std::byte* PackedQuantBDataBegin = reinterpret_cast(PackedQuantB.QuantBWorkspace_); + SQ4BitGemmPackQuantBData(N, K, BlkLen, ComputeType, QuantBDataBegin, PackedQuantBDataBegin, ThreadPool); + } +} + // // Workspace size calculation function implementation. // @@ -132,17 +209,34 @@ Q4BitGemmPerGemmWorkspaceSize( size_t N, size_t K, size_t BlkLen, + bool HasZeroPoint, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { MLAS_UNREFERENCED_PARAMETER(N); +#ifndef USE_KLEIDIAI + MLAS_UNREFERENCED_PARAMETER(HasZeroPoint); +#endif switch (ComputeType) { case SQNBIT_CompInt8: { // workspace buffer is used for block quantization of A to int8 - const size_t BlockCountK = MlasDivRoundup(K, BlkLen); - const size_t PerGemmWorkspaceSize = M * BlockCountK * Q8BlkSize(BlkLen); - return PerGemmWorkspaceSize; +#ifdef USE_KLEIDIAI + if (UseKleidiAI(K, BlkLen, HasZeroPoint)) { + const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& ukernel = + M == 1? GetKleidiAIGemvUKernel() : GetKleidiAIGemmUKernel(); + + const size_t mr = ukernel.get_mr(); + const size_t kr = ukernel.get_kr(); + const size_t sr = ukernel.get_sr(); + return kai_get_lhs_packed_size_lhs_quant_pack_qai8dxp_f32(M, K, mr, kr, sr); + } else +#endif + { + const size_t BlockCountK = MlasDivRoundup(K, BlkLen); + const size_t PerGemmWorkspaceSize = M * BlockCountK * Q8BlkSize(BlkLen); + return PerGemmWorkspaceSize; + } } default: { return 0; @@ -170,6 +264,20 @@ Q4BitGemmPerGemmWorkspaceAlignment( } // namespace +bool +UseKleidiAI(size_t K, size_t BlkLen, bool HasZp) +{ +#ifdef USE_KLEIDIAI + bool has_dotprod = MLAS_CPUIDINFO::GetCPUIDInfo().HasArmNeonDot(); + return (BlkLen % 32) == 0 && (K % BlkLen) == 0 && !HasZp && has_dotprod; +#else + MLAS_UNREFERENCED_PARAMETER(K); + MLAS_UNREFERENCED_PARAMETER(BlkLen); + MLAS_UNREFERENCED_PARAMETER(HasZp); + return false; +#endif +} + } // namespace sqnbitgemm_neon // @@ -189,16 +297,24 @@ GetMlasQNBitGemmDispatchNeon( d.Q4BitGemmPackQuantBDataSize = sqnbitgemm_neon::Q4BitGemmPackQuantBDataSize; d.SQ4BitGemmPackQuantBData = sqnbitgemm_neon::SQ4BitGemmPackQuantBData; + d.SQ4BitGemmPackQuantBDataAndBlkSum = sqnbitgemm_neon::SQ4BitGemmPackQuantBDataAndBlkSum; d.Q4BitGemmPerGemmWorkspaceSize = sqnbitgemm_neon::Q4BitGemmPerGemmWorkspaceSize; d.Q4BitGemmPerGemmWorkspaceAlignment = sqnbitgemm_neon::Q4BitGemmPerGemmWorkspaceAlignment; d.SQ4BitGemmM1Kernel_CompFp32 = sqnbitgemm_neon::SQ4BitGemmM1Kernel_CompFp32; d.SQ4BitBlkDequantBForSgemm_CompFp32 = sqnbitgemm_neon::SQ4BitBlkDequantBForSgemm_CompFp32; + if (InitializeWithDotSupport) { d.SQ4BitGemmKernel_CompInt8 = sqnbitgemm_neon::SQ4BitGemmKernel_CompInt8; + d.QuantizeARow_CompInt8 = sqnbitgemm_neon::QuantizeARow_CompInt8; + d.UsePacked_CompInt8 = sqnbitgemm_neon::UsePacked_CompInt8; + +#ifdef USE_KLEIDIAI + d.SQ4BitGemmKernel_Packed_CompInt8 = sqnbitgemm_neon::SQ4BitGemmKernel_Packed_CompInt8; + d.QuantizeA_Packed_CompInt8 = sqnbitgemm_neon::QuantizeA_Packed_CompInt8; +#endif } - d.QuantizeARow_CompInt8 = sqnbitgemm_neon::QuantizeARow_CompInt8; #if defined(MLAS_F16VEC_INTRINSICS_SUPPORTED) && defined(MLAS_TARGET_ARM64) d.HQ4BitGemmPackQuantBData = sqnbitgemm_neon::HQ4BitGemmPackQuantBData_CompFp16; diff --git a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h index ce9f0fe6d939d..a254ec9f92596 100644 --- a/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h +++ b/onnxruntime/core/mlas/lib/qnbitgemm_kernel_neon.h @@ -108,6 +108,13 @@ HQ4BitGemmKernel_CompFp16( // SQNBIT_CompInt8 declarations +bool +UsePacked_CompInt8( + size_t K, + size_t BlkLen, + bool HasZp +); + void QuantizeARow_CompInt8( size_t BlkLen, @@ -132,6 +139,35 @@ SQ4BitGemmKernel_CompInt8( const float* Bias ); +#ifdef USE_KLEIDIAI +void +QuantizeA_Packed_CompInt8( + size_t BlkLen, + const float* A, + size_t CountM, + size_t CountK, + std::byte* QuantA +); + +void +SQ4BitGemmKernel_Packed_CompInt8( + size_t BlkLen, + const std::byte* QuantA, + const std::byte* PackedQuantBData, + float* C, + const size_t RangeStartM, + const size_t RangeCountM, + const size_t RangeStartN, + const size_t RangeCountN, + size_t CountK, + size_t ldc, + const float *Bias +); +#endif + +bool +UseKleidiAI(size_t K, size_t BlkLen, bool HasZp); + // // General helpers. // diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx2.cpp b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx2.cpp index 81615da46aa2e..79893eea85eca 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx2.cpp +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx2.cpp @@ -1309,9 +1309,9 @@ SQ4BitGemmPackQuantBDataAndBlkSum( MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, const std::byte* QuantBDataBegin, const float* QuantBScaleBegin, - bool has_zp_input, + bool HasZeroPoint, const std::byte* QuantBZPBegin, - PackedQuantBDataStruct& packed_quant_b, + PackedQuantBDataStruct& PackedQuantB, MLAS_THREADPOOL* ThreadPool ) { @@ -1324,7 +1324,8 @@ SQ4BitGemmPackQuantBDataAndBlkSum( if (BlkLen == 32 && ComputeType == SQNBIT_CompInt8) { SubBlkLen = 64; } - PackQuantBDataAndBlkSum(N, BlockCountK, BlkLen, SubBlkLen, QuantBDataBegin, QuantBScaleBegin, has_zp_input, QuantBZPBegin, packed_quant_b, ThreadPool); + PackQuantBDataAndBlkSum(N, BlockCountK, BlkLen, SubBlkLen, QuantBDataBegin, QuantBScaleBegin, + HasZeroPoint, QuantBZPBegin, PackedQuantB, ThreadPool); } // diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512.cpp b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512.cpp index b4e25d4e4040a..ea06f954c854a 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512.cpp +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512.cpp @@ -335,9 +335,9 @@ SQ4BitGemmPackQuantBDataAndBlkSum512( MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, const std::byte* QuantBDataBegin, const float* QuantBScaleBegin, - bool has_zp_input, + bool HasZeroPoint, const std::byte* QuantBZPBegin, - PackedQuantBDataStruct& packed_quant_b, + PackedQuantBDataStruct& PackedQuantB, MLAS_THREADPOOL* ThreadPool ) { @@ -349,7 +349,8 @@ SQ4BitGemmPackQuantBDataAndBlkSum512( if (ComputeType == SQNBIT_CompInt8) { SubBlkLen = 128; } - PackQuantBDataAndBlkSum(N, BlockCountK, BlkLen, SubBlkLen, QuantBDataBegin, QuantBScaleBegin, has_zp_input, QuantBZPBegin, packed_quant_b, ThreadPool); + PackQuantBDataAndBlkSum(N, BlockCountK, BlkLen, SubBlkLen, QuantBDataBegin, QuantBScaleBegin, + HasZeroPoint, QuantBZPBegin, PackedQuantB, ThreadPool); } const MLAS_QNBIT_GEMM_DISPATCH MlasSQNBitGemmDispatchAvx512 = []() { diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512vnni.cpp b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512vnni.cpp index a4468bb906bbc..c2fcd92be2364 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512vnni.cpp +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512vnni.cpp @@ -317,9 +317,9 @@ SQ4BitGemmPackQuantBDataAndBlkSum512vnni( MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType, const std::byte* QuantBDataBegin, const float* QuantBScaleBegin, - bool has_zp_input, + bool HasZeroPoint, const std::byte* QuantBZPBegin, - PackedQuantBDataStruct& packed_quant_b, + PackedQuantBDataStruct& PackedQuantB, MLAS_THREADPOOL* ThreadPool ) { @@ -331,7 +331,8 @@ SQ4BitGemmPackQuantBDataAndBlkSum512vnni( if (ComputeType == SQNBIT_CompInt8) { SubBlkLen = 128; } - PackQuantBDataAndBlkSum(N, BlockCountK, BlkLen, SubBlkLen, QuantBDataBegin, QuantBScaleBegin, has_zp_input, QuantBZPBegin, packed_quant_b, ThreadPool); + PackQuantBDataAndBlkSum(N, BlockCountK, BlkLen, SubBlkLen, QuantBDataBegin, QuantBScaleBegin, + HasZeroPoint, QuantBZPBegin, PackedQuantB, ThreadPool); } // diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx_common.h b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx_common.h index b0367b7fb9a15..02429a0c64f8e 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx_common.h +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx_common.h @@ -11,6 +11,7 @@ Q4BitGemmPackQuantBDataSize( size_t N, size_t K, size_t BlkLen, + bool /* HasZeroPoint */, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { @@ -302,22 +303,22 @@ PackQuantBDataAndBlkSum( size_t SubBlkLen, const std::byte* QuantBDataBegin, const float* QuantBScaleBegin, - bool has_zp_input, + bool HasZeroPoint, const std::byte* QuantBZPBegin, - PackedQuantBDataStruct& packed_quant_b, + PackedQuantBDataStruct& PackedQuantB, MLAS_THREADPOOL* ThreadPool ) { if (QuantBDataBegin) { - PackQuantB(QuantBDataBegin, packed_quant_b.PackedQuantBData, ThreadPool, N, BlockCountK, BlkLen, SubBlkLen); + PackQuantB(QuantBDataBegin, PackedQuantB.PackedQuantBData, ThreadPool, N, BlockCountK, BlkLen, SubBlkLen); } if (QuantBScaleBegin) { - std::copy(QuantBScaleBegin, QuantBScaleBegin + N * BlockCountK, packed_quant_b.PackedQuantBScale); + std::copy(QuantBScaleBegin, QuantBScaleBegin + N * BlockCountK, PackedQuantB.PackedQuantBScale); } - if ((QuantBScaleBegin && !has_zp_input) || QuantBZPBegin) { - ComputePackBlkSum(BlkLen, SubBlkLen, N, packed_quant_b.PackedQuantBScale, QuantBZPBegin, packed_quant_b.QuantBBlkSum, ThreadPool, BlockCountK); + if ((QuantBScaleBegin && !HasZeroPoint) || QuantBZPBegin) { + ComputePackBlkSum(BlkLen, SubBlkLen, N, PackedQuantB.PackedQuantBScale, QuantBZPBegin, PackedQuantB.QuantBBlkSum, ThreadPool, BlockCountK); } } @@ -331,6 +332,7 @@ Q4BitGemmPerGemmWorkspaceSize( size_t N, size_t K, size_t BlkLen, + bool /* HasZeroPoint */, MLAS_QNBIT_GEMM_COMPUTE_TYPE ComputeType ) { diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_neon_int8.cpp b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_neon_int8.cpp index 73beb06a3cfad..8dbd339468930 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_neon_int8.cpp +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_neon_int8.cpp @@ -1,7 +1,6 @@ /*++ Copyright (c) Microsoft Corporation. All rights reserved. - Licensed under the MIT License. Module Name: @@ -20,11 +19,17 @@ Module Name: #include #include +#include #include "qnbitgemm.h" #include "qnbitgemm_kernel_neon.h" #include "sqnbitgemm_q8_block.h" +#ifdef USE_KLEIDIAI +#include "kai/ukernels/matmul/pack/kai_lhs_quant_pack_qai8dxp_f32.h" +#include "kai_ukernel_interface.h" +#endif + namespace sqnbitgemm_neon { @@ -126,6 +131,41 @@ QuantizeBlock( } // namespace +bool +UsePacked_CompInt8(size_t K, size_t BlkLen, bool HasZp) +{ + return UseKleidiAI(K, BlkLen, HasZp); +} + +#ifdef USE_KLEIDIAI +void +QuantizeA_Packed_CompInt8( + size_t, + const float* A, + size_t CountM, + size_t CountK, + std::byte* QuantA +) +{ + const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel& ukernel = + CountM == 1? GetKleidiAIGemvUKernel() : GetKleidiAIGemmUKernel(); + + const size_t mr = ukernel.get_mr(); + const size_t kr = ukernel.get_kr(); + const size_t sr = ukernel.get_sr(); + + const size_t src_stride = CountK * sizeof(float); + const size_t lhs_offset = kai_get_lhs_offset_lhs_quant_pack_qai8dxp_f32(0, src_stride); + const size_t lhs_packed_offset = kai_get_lhs_packed_offset_lhs_quant_pack_qai8dxp_f32( + 0, CountK, mr, kr, sr); + + const float* src_ptr = reinterpret_cast(reinterpret_cast(A) + lhs_offset); + void* dst_ptr = QuantA + lhs_packed_offset; + + kai_run_lhs_quant_pack_qai8dxp_f32(CountM, CountK, mr, kr, sr, 0, src_ptr, src_stride, dst_ptr); +} +#endif + void QuantizeARow_CompInt8( size_t BlkLen, @@ -1399,4 +1439,47 @@ SQ4BitGemmKernel_CompInt8( return CountM; } +#ifdef USE_KLEIDIAI +void +SQ4BitGemmKernel_Packed_CompInt8( + size_t BlkLen, + const std::byte* QuantA, + const std::byte* PackedQuantBData, + float* C, + const size_t RangeStartM, + const size_t RangeCountM, + const size_t RangeStartN, + const size_t RangeCountN, + size_t CountK, + size_t ldc, + const float* Bias +) +{ + const kai_matmul_clamp_f32_qai8dxp_qsi4c32p_ukernel ukernel = + RangeCountM == 1 && RangeStartM == 0? GetKleidiAIGemvUKernel() : GetKleidiAIGemmUKernel(); + + const size_t dst_stride = ldc * sizeof(float); + + const size_t lhs_packed_offset = ukernel.get_lhs_packed_offset(RangeStartM, CountK); + const size_t rhs_packed_offset = ukernel.get_rhs_packed_offset(RangeStartN, CountK, BlkLen); + const size_t dst_offset = ukernel.get_dst_offset(RangeStartM, RangeStartN, dst_stride); + + const void* lhs_ptr = QuantA + lhs_packed_offset; + const void* rhs_ptr = PackedQuantBData + rhs_packed_offset; + float* dst_ptr = reinterpret_cast(reinterpret_cast(C) + dst_offset); + + ukernel.run_matmul( + RangeCountM, RangeCountN, CountK, BlkLen, lhs_ptr, rhs_ptr, dst_ptr, dst_stride, sizeof(float), + -std::numeric_limits::max(), std::numeric_limits::max()); + + if (Bias != nullptr) { + for (size_t m = RangeStartM; m < RangeStartM + RangeCountM; m++) { + for (size_t n = RangeStartN; n < RangeStartN + RangeCountN; n++) { + C[m * ldc + n] += Bias[n]; + } + } + } +} +#endif + } // namespace sqnbitgemm_neon diff --git a/onnxruntime/test/mlas/bench/bench_qnbitgemm.cpp b/onnxruntime/test/mlas/bench/bench_qnbitgemm.cpp index 64d229889214b..88c036ac4854e 100644 --- a/onnxruntime/test/mlas/bench/bench_qnbitgemm.cpp +++ b/onnxruntime/test/mlas/bench/bench_qnbitgemm.cpp @@ -63,13 +63,13 @@ void RunQNBitGemmBenchmark(size_t BlkLen, tp.get()); std::unique_ptr Workspace; - if (const auto WorkspaceSize = MlasQNBitGemmBatchWorkspaceSize(M, N, K, 1, BlkBitWidth, BlkLen, ComputeType); + if (const auto WorkspaceSize = MlasQNBitGemmBatchWorkspaceSize(M, N, K, 1, BlkBitWidth, BlkLen, !Symmetric, ComputeType); WorkspaceSize > 0) { Workspace = std::make_unique(WorkspaceSize); } std::unique_ptr PackedQuantBData; - if (const auto PackedQuantBDataSize = MlasQNBitGemmPackQuantBDataSize(N, K, BlkBitWidth, BlkLen, ComputeType); + if (const auto PackedQuantBDataSize = MlasQNBitGemmPackQuantBDataSize(N, K, BlkBitWidth, BlkLen, !Symmetric, ComputeType); PackedQuantBDataSize > 0) { PackedQuantBData = std::make_unique(PackedQuantBDataSize); MlasQNBitGemmPackQuantBData(N, K, BlkBitWidth, BlkLen, ComputeType, QuantBData.data(), PackedQuantBData.get(), diff --git a/onnxruntime/test/mlas/unittest/test_sqnbitgemm.cpp b/onnxruntime/test/mlas/unittest/test_sqnbitgemm.cpp index e22018ae2877f..16af51cfaa12d 100644 --- a/onnxruntime/test/mlas/unittest/test_sqnbitgemm.cpp +++ b/onnxruntime/test/mlas/unittest/test_sqnbitgemm.cpp @@ -265,13 +265,13 @@ class MlasSQNBitGemmTest : public MlasTestBase { } void* Workspace = nullptr; - if (const auto WorkspaceSize = MlasQNBitGemmBatchWorkspaceSize(M, N, K, 1, BlkBitWidth, BlkLen, ComputeType); + if (const auto WorkspaceSize = MlasQNBitGemmBatchWorkspaceSize(M, N, K, 1, BlkBitWidth, BlkLen, !Symmetric, ComputeType); WorkspaceSize > 0) { Workspace = BufferWorkspace.GetBuffer(WorkspaceSize); } void* PackedQuantBDataWorkspace = nullptr; - if (const auto PackedQuantBDataSize = MlasQNBitGemmPackQuantBDataSize(N, K, BlkBitWidth, BlkLen, ComputeType); + if (const auto PackedQuantBDataSize = MlasQNBitGemmPackQuantBDataSize(N, K, BlkBitWidth, BlkLen, !Symmetric, ComputeType); PackedQuantBDataSize > 0) { PackedQuantBDataWorkspace = BufferPackedQuantBData.GetBuffer(PackedQuantBDataSize); bool has_zp_input = QuantBZeroPoint != nullptr; diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index d5903c9d1d211..2493887dfc347 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -704,6 +704,7 @@ def convert_arg_line_to_args(self, arg_line): parser.add_argument("--armnn_home", help="Path to ArmNN home dir") parser.add_argument("--armnn_libs", help="Path to ArmNN libraries") parser.add_argument("--build_micro_benchmarks", action="store_true", help="Build ONNXRuntime micro-benchmarks.") + parser.add_argument("--no_kleidiai", action="store_true", help="Disable KleidiAI integration on Arm platforms.") # options to reduce binary size parser.add_argument( @@ -1628,6 +1629,8 @@ def generate_build_tree( if args.use_snpe: cmake_args += ["-Donnxruntime_USE_SNPE=ON"] + cmake_args += ["-Donnxruntime_USE_KLEIDIAI=" + ("OFF" if args.no_kleidiai else "ON")] + if args.macos or args.ios or args.visionos or args.tvos: # Note: Xcode CMake generator doesn't have a good support for Mac Catalyst yet. if args.macos == "Catalyst" and args.cmake_generator == "Xcode": From 0a363d9e79161f4ac1e5867e12ee97f0b89076fb Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 21 Mar 2025 13:43:07 -0700 Subject: [PATCH 146/266] add test cases for webgpu ep in web (#24117) ### Description This PR enables web tests (NPM suite tests) for WebGPU EP. There are some test failures expected, so the specific job is marked as "continueOnError". ### Motivation and Context --- .../templates/linux-wasm-ci.yml | 38 ++++++++---- .../azure-pipelines/templates/web-ci.yml | 2 +- .../azure-pipelines/templates/win-web-ci.yml | 62 ++++++++++++++++--- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index dffcea9500393..d7850153698e1 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -125,11 +125,6 @@ jobs: WithCache: ${{ parameters.WithCache }} - ${{ if eq(parameters.BuildWebGPU, true) }}: - # This step only verifies whether the build is successful. - # currently, we uses EMSDK 3.1.59, which is not compatible with Dawn's changes in its Emscripten fork. Closure compiler will not work for WebGPU build. - # Only enables in DEBUG build. - # - # TODO: when upgrading to a newer Emscripten version, we should fix this step. - template: build-linux-wasm-step.yml parameters: Today: $(Today) @@ -138,31 +133,50 @@ jobs: ${{ else }}: AdditionalKey: wasm_inferencing_webgpu_exp | ${{ parameters.BuildConfig }} CacheDir: $(ORT_CACHE_DIR)/wasm_inferencing_webgpu - Arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)/wasm_inferencing_webgpu --use_webgpu --target onnxruntime_webassembly --skip_tests' + Arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)/wasm_inferencing_webgpu --use_webgpu --use_jsep --use_webnn --target onnxruntime_webassembly --skip_tests' DisplayName: 'Build (simd + threads + WebGPU experimental)' WithCache: ${{ parameters.WithCache }} - ${{ if eq(parameters.SkipPublish, false) }}: - script: | - cp $(Build.BinariesDirectory)/wasm_inferencing/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.wasm $(Build.ArtifactStagingDirectory) - cp $(Build.BinariesDirectory)/wasm_inferencing/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.mjs $(Build.ArtifactStagingDirectory) + mkdir -p $(Build.ArtifactStagingDirectory)/wasm/ + cp $(Build.BinariesDirectory)/wasm_inferencing/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.wasm $(Build.ArtifactStagingDirectory)/wasm/ + cp $(Build.BinariesDirectory)/wasm_inferencing/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.mjs $(Build.ArtifactStagingDirectory)/wasm/ if [ -d $(Build.BinariesDirectory)/wasm_inferencing_jsep ]; then - cp $(Build.BinariesDirectory)/wasm_inferencing_jsep/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.wasm $(Build.ArtifactStagingDirectory) - cp $(Build.BinariesDirectory)/wasm_inferencing_jsep/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.mjs $(Build.ArtifactStagingDirectory) + cp $(Build.BinariesDirectory)/wasm_inferencing_jsep/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.wasm $(Build.ArtifactStagingDirectory)/wasm/ + cp $(Build.BinariesDirectory)/wasm_inferencing_jsep/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.mjs $(Build.ArtifactStagingDirectory)/wasm/ fi displayName: 'Create Artifacts' + - ${{ if eq(parameters.BuildWebGPU, true) }}: + - script: | + mkdir -p $(Build.ArtifactStagingDirectory)/wasm_webgpu/ + cp $(Build.BinariesDirectory)/wasm_inferencing_webgpu/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.wasm $(Build.ArtifactStagingDirectory)/wasm_webgpu/ + cp $(Build.BinariesDirectory)/wasm_inferencing_webgpu/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.jsep.mjs $(Build.ArtifactStagingDirectory)/wasm_webgpu/ + displayName: 'Create Artifacts (WebGPU EP)' - ${{ if eq(parameters.is1ES, false) }}: - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact' inputs: artifactName: '${{ parameters.BuildConfig }}_wasm' - targetPath: '$(Build.ArtifactStagingDirectory)' + targetPath: '$(Build.ArtifactStagingDirectory)/wasm' + - ${{ if eq(parameters.BuildWebGPU, true) }}: + - task: PublishPipelineArtifact@1 + displayName: 'Publish Pipeline Artifact (WebGPU EP)' + inputs: + artifactName: '${{ parameters.BuildConfig }}_wasm_webgpu' + targetPath: '$(Build.ArtifactStagingDirectory)/wasm_webgpu' - ${{ if eq(parameters.is1ES, true) }}: - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact' inputs: artifactName: '${{ parameters.BuildConfig }}_wasm' - targetPath: '$(Build.ArtifactStagingDirectory)' + targetPath: '$(Build.ArtifactStagingDirectory)/wasm' + - ${{ if eq(parameters.BuildWebGPU, true) }}: + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline Artifact (WebGPU EP)' + inputs: + artifactName: '${{ parameters.BuildConfig }}_wasm_webgpu' + targetPath: '$(Build.ArtifactStagingDirectory)/wasm_webgpu' - task: PublishTestResults@2 displayName: 'Publish unit test results' inputs: diff --git a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml index 2e3589ee87c29..e6d86b8802148 100644 --- a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml @@ -147,7 +147,7 @@ stages: ExtraBuildArgs: '--target onnxruntime_webassembly --skip_tests --enable_wasm_api_exception_catching --disable_rtti ${{ parameters.ExtraBuildArgs }}' PoolName: ${{ parameters.PoolName }} BuildJsep: ${{ parameters.BuildJsep }} - BuildWebGPU: false + BuildWebGPU: ${{ parameters.BuildWebGPU }} WithCache: ${{ parameters.WithCache }} is1ES: ${{ parameters.is1ES }} diff --git a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml index 6868043f64d81..4ae7423803ddf 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml @@ -81,12 +81,12 @@ jobs: versionSpec: '20.x' - task: DownloadPipelineArtifact@2 inputs: - patterns: '${{ parameters.BuildConfig }}_*/**/*' - path: $(Pipeline.Workspace)\artifacts + patterns: '${{ parameters.BuildConfig }}_wasm/**/*' + path: $(Pipeline.Workspace)\artifacts_wasm displayName: 'Download WebAssembly artifacts' - task: CopyFiles@2 inputs: - sourceFolder: $(Pipeline.Workspace)\artifacts + sourceFolder: $(Pipeline.Workspace)\artifacts_wasm contents: | **\ort-*.wasm targetFolder: $(Build.SourcesDirectory)\js\web\dist @@ -94,7 +94,7 @@ jobs: displayName: 'Binplace dist files (.wasm)' - task: CopyFiles@2 inputs: - sourceFolder: $(Pipeline.Workspace)\artifacts + sourceFolder: $(Pipeline.Workspace)\artifacts_wasm contents: | **\ort-*.mjs targetFolder: $(Build.SourcesDirectory)\js\web\dist @@ -221,6 +221,47 @@ jobs: workingDirectory: '$(Build.SourcesDirectory)\js\web' displayName: 'Run ort-web tests - WebAssembly: proxy' condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) + + # === Start of experimental WebGPU EP tests === + + - ${{ if eq(parameters.RunWebGpuTests, true) }}: + - task: DownloadPipelineArtifact@2 + inputs: + patterns: '${{ parameters.BuildConfig }}_wasm_webgpu/**/*' + path: $(Pipeline.Workspace)\artifacts_wasm_webgpu + displayName: 'Download WebAssembly artifacts' + - task: CopyFiles@2 + inputs: + sourceFolder: $(Pipeline.Workspace)\artifacts_wasm_webgpu + contents: | + **\ort-*.wasm + targetFolder: $(Build.SourcesDirectory)\js\web\dist + flattenFolders: true + overWrite: true + displayName: 'Binplace dist files (.wasm)' + - task: CopyFiles@2 + inputs: + sourceFolder: $(Pipeline.Workspace)\artifacts_wasm_webgpu + contents: | + **\ort-*.mjs + targetFolder: $(Build.SourcesDirectory)\js\web\dist + flattenFolders: true + overWrite: true + displayName: 'Binplace dist files (.mjs)' + - script: | + powershell "Get-WmiObject Win32_Process -Filter \"name = 'chrome.exe'\" | Format-List CommandLine" + displayName: 'Check active Chrome processes (before test)' + condition: and(succeeded(), eq(variables['Agent.Diagnostic'], 'true')) + - script: | + mkdir $(Agent.TempDirectory)\web\test\07 + dir $(Agent.TempDirectory)\web\test\07 + npm test --webgpu-ep -- -b=webgpu -e=chrome $(webgpuCommandlineExtraFlags) --user-data-dir=$(Agent.TempDirectory)\web\test\07 --chromium-flags=--enable-logging --chromium-flags=--v=1 + workingDirectory: '$(Build.SourcesDirectory)\js\web' + displayName: 'Run ort-web tests - WebGPU EP' + continueOnError: true # we allow WebGPU EP tests to fail for now + + # === End of experimental WebGPU EP tests === + - script: | npm run test:e2e -- --browser=Chrome_default workingDirectory: '$(Build.SourcesDirectory)\js\web' @@ -256,12 +297,13 @@ jobs: displayName: 'Publish Pipeline Artifact' condition: and(succeeded(), eq('${{ parameters.BuildConfig }}', 'Release')) - script: | - if exist 01 (echo ------------------- BEGIN 01 -------------------&&type 01\chrome_debug.log&&echo ------------------- END 01 ------------------- ) - if exist 02 (echo ------------------- BEGIN 02 -------------------&&type 02\chrome_debug.log&&echo ------------------- END 02 ------------------- ) - if exist 03 (echo ------------------- BEGIN 03 -------------------&&type 03\chrome_debug.log&&echo ------------------- END 03 ------------------- ) - if exist 04 (echo ------------------- BEGIN 04 -------------------&&type 04\chrome_debug.log&&echo ------------------- END 04 ------------------- ) - if exist 05 (echo ------------------- BEGIN 05 -------------------&&type 05\chrome_debug.log&&echo ------------------- END 05 ------------------- ) - if exist 06 (echo ------------------- BEGIN 06 -------------------&&type 06\chrome_debug.log&&echo ------------------- END 06 ------------------- ) + for %%i in (01 02 03 04 05 06 07) do ( + if exist %%i ( + echo ------------------- BEGIN %%i ------------------- + type %%i\chrome_debug.log + echo ------------------- END %%i ------------------- + ) + ) displayName: 'Log Chrome processes (after test)' workingDirectory: '$(Agent.TempDirectory)\web\test' condition: always() From cd9406bf56ad6b7928cccdfa76393e8899855371 Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Fri, 21 Mar 2025 15:14:13 -0700 Subject: [PATCH 147/266] Refactor Webnn IsSupported*() to use constant initializers. (#24118) ### Description This PR continues the work started at https://github.com/microsoft/onnxruntime/pull/19401. ### Motivation and Context An overridable initializer should not have a fixed value included in an WebNN model as it could be changed at runtime. The current check doesn't include validating that the initializer is constant. --- .../core/providers/shared/utils/utils.cc | 11 ------ .../core/providers/shared/utils/utils.h | 6 ---- .../core/providers/webnn/builders/helper.cc | 6 ++-- .../core/providers/webnn/builders/helper.h | 7 ++-- .../builders/impl/argmax_min_op_builder.cc | 4 +-- .../webnn/builders/impl/base_op_builder.cc | 16 ++++----- .../webnn/builders/impl/base_op_builder.h | 8 ++--- .../webnn/builders/impl/binary_op_builder.cc | 4 +-- .../webnn/builders/impl/clip_op_builder.cc | 9 ++--- .../webnn/builders/impl/concat_op_builder.cc | 4 +-- .../webnn/builders/impl/conv_op_builder.cc | 8 ++--- .../webnn/builders/impl/cumsum_op_builder.cc | 7 ++-- .../webnn/builders/impl/dropout_op_builder.cc | 4 +-- .../webnn/builders/impl/einsum_op_builder.cc | 8 ++--- .../webnn/builders/impl/expand_op_builder.cc | 14 +++++--- .../impl/gatherElements_op_builder.cc | 4 +-- .../builders/impl/gatherND_op_builder.cc | 8 ++--- .../webnn/builders/impl/gather_op_builder.cc | 8 ++--- .../webnn/builders/impl/gemm_op_builder.cc | 8 ++--- .../webnn/builders/impl/gru_op_builder.cc | 13 +++---- .../webnn/builders/impl/logical_op_builder.cc | 8 ++--- .../webnn/builders/impl/lrn_op_builder.cc | 8 ++--- .../webnn/builders/impl/lstm_op_builder.cc | 13 +++---- .../webnn/builders/impl/max_min_op_builder.cc | 8 ++--- .../builders/impl/normalization_op_builder.cc | 8 ++--- .../webnn/builders/impl/pad_op_builder.cc | 6 ++-- .../webnn/builders/impl/pool_op_builder.cc | 4 +-- .../webnn/builders/impl/qdq_op_builder.cc | 8 ++--- .../builders/impl/reduction_op_builder.cc | 6 ++-- .../webnn/builders/impl/reshape_op_builder.cc | 9 ++--- .../webnn/builders/impl/resize_op_builder.cc | 35 ++++++++++--------- .../impl/rotaryEmbedding_op_builder.cc | 8 ++--- .../impl/scatterElements_op_builder.cc | 8 ++--- .../builders/impl/scatterND_op_builder.cc | 8 ++--- .../webnn/builders/impl/slice_op_builder.cc | 14 ++++---- .../webnn/builders/impl/softmax_op_builder.cc | 4 +-- .../webnn/builders/impl/split_op_builder.cc | 9 ++--- .../impl/squeeze_unsqueeze_op_builder.cc | 7 ++-- .../webnn/builders/impl/ternary_op_builder.cc | 4 +-- .../webnn/builders/impl/tile_op_builder.cc | 7 ++-- .../builders/impl/triangular_op_builder.cc | 7 ++-- .../providers/webnn/builders/op_builder.h | 2 +- 42 files changed, 173 insertions(+), 175 deletions(-) diff --git a/onnxruntime/core/providers/shared/utils/utils.cc b/onnxruntime/core/providers/shared/utils/utils.cc index 5b2f2c1fa1b2e..4281b5e53c5fd 100644 --- a/onnxruntime/core/providers/shared/utils/utils.cc +++ b/onnxruntime/core/providers/shared/utils/utils.cc @@ -100,17 +100,6 @@ bool GetClipMinMax(const GraphViewer& graph_viewer, const Node& node, float& min node, min, max, logger); } -// deprecated version that is not able to check if the initializer is constant -bool GetClipMinMax(const InitializedTensorSet& initializers, const Node& node, float& min, float& max, - const logging::Logger& logger) { - return GetClipMinMaxImpl( - [&initializers](const std::string& name) -> const ONNX_NAMESPACE::TensorProto* { - auto entry = initializers.find(name); - return entry == initializers.end() ? nullptr : entry->second; - }, - node, min, max, logger); -} - NodeAttrHelper::NodeAttrHelper(const onnxruntime::Node& node) : node_attributes_(node.GetAttributes()) {} diff --git a/onnxruntime/core/providers/shared/utils/utils.h b/onnxruntime/core/providers/shared/utils/utils.h index ddbae42534711..78da6c76047bd 100644 --- a/onnxruntime/core/providers/shared/utils/utils.h +++ b/onnxruntime/core/providers/shared/utils/utils.h @@ -27,12 +27,6 @@ class NodeUnit; bool GetClipMinMax(const GraphViewer& graph_viewer, const Node& node, float& min, float& max, const logging::Logger& logger); -/// GraphViewer GetConstantInitializer/IsConstantInitializer should be used to ensure the initializer is -/// constant. Low risk for Clip min/max but in general the infrastructure to check if an operator is supported needs -/// to be updated to not use InitializedTensorSet which may contain non-constant initializers. -bool GetClipMinMax(const InitializedTensorSet& initializers, const Node& node, - float& min, float& max, const logging::Logger& logger); - // Get the type of the given NodeArg // Will return false if the given NodeArg has no type bool GetType(const NodeArg& node_arg, int32_t& type, const logging::Logger& logger); diff --git a/onnxruntime/core/providers/webnn/builders/helper.cc b/onnxruntime/core/providers/webnn/builders/helper.cc index 47f65cd0b8e85..e0d82b26c2174 100644 --- a/onnxruntime/core/providers/webnn/builders/helper.cc +++ b/onnxruntime/core/providers/webnn/builders/helper.cc @@ -58,12 +58,12 @@ bool GetShape(const NodeArg& node_arg, std::vector& shape, const loggin return true; } -bool IsNodeSupported(const Node& node, const GraphViewer& graph_viewer, const WebnnDeviceType device_type, +bool IsNodeSupported(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType device_type, const emscripten::val& wnn_limits, const logging::Logger& logger) { const auto& op_builders = GetOpBuilders(); if (Contains(op_builders, node.OpType())) { const auto* op_builder = op_builders.at(node.OpType()); - return op_builder->IsOpSupported(graph_viewer.GetAllInitializedTensors(), node, device_type, wnn_limits, logger); + return op_builder->IsOpSupported(graph_viewer, node, device_type, wnn_limits, logger); } else { return false; } @@ -107,7 +107,7 @@ std::unordered_set GetSupportedNodes(const GraphViewer& graph_viewe std::unordered_set supported_nodes; for (const auto& node : graph_viewer.Nodes()) { - const bool supported = IsNodeSupported(node, graph_viewer, device_type, wnn_limits, logger); + const bool supported = IsNodeSupported(graph_viewer, node, device_type, wnn_limits, logger); LOGS(logger, VERBOSE) << "Operator type: [" << node.OpType() << "] index: [" << node.Index() << "] name: [" << node.Name() diff --git a/onnxruntime/core/providers/webnn/builders/helper.h b/onnxruntime/core/providers/webnn/builders/helper.h index 9a1566ccdc99a..95c4b79053a1f 100644 --- a/onnxruntime/core/providers/webnn/builders/helper.h +++ b/onnxruntime/core/providers/webnn/builders/helper.h @@ -171,12 +171,13 @@ inline bool ReadScalarTensorData(const onnx::TensorProto& tensor, emscripten::va return true; } -inline bool IsEmptyTensor(const InitializedTensorSet& initializers, const std::string& name) { - if (name.empty() || !Contains(initializers, name)) { +inline bool IsEmptyTensor(const GraphViewer& graph_viewer, const std::string& name) { + const auto* tensor_init = graph_viewer.GetConstantInitializer(name); + if (name.empty() || !tensor_init) { return true; } - const auto& tensor = *initializers.at(name); + const auto& tensor = *tensor_init; const auto dims = tensor.dims(); // An empty tensor contains a 0 in the dimensions list. return std::any_of(dims.begin(), dims.end(), [](auto d) { return d == 0; }); diff --git a/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc index 08580ab2861d7..fc630af8cf1e3 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/argmax_min_op_builder.cc @@ -20,7 +20,7 @@ class ArgMaxMinOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, WebnnDeviceType device_type, const logging::Logger& logger) const override; }; @@ -66,7 +66,7 @@ Status ArgMaxMinOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool ArgMaxMinOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool ArgMaxMinOpBuilder::IsOpSupportedImpl(const GraphViewer& /* initializers */, const Node& node, WebnnDeviceType device_type, const logging::Logger& logger) const { diff --git a/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.cc index 4504a54a379f3..d5683454c89b7 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.cc @@ -17,7 +17,7 @@ namespace webnn { Status BaseOpBuilder::AddToModelBuilder(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const { ORT_RETURN_IF_NOT( - IsOpSupported(model_builder.GetInitializerTensors(), node, model_builder.GetWebnnDeviceType(), + IsOpSupported(model_builder.GetGraphViewer(), node, model_builder.GetWebnnDeviceType(), model_builder.GetOpSupportLimits(), logger), "Unsupported operator ", node.OpType()); ORT_RETURN_IF_ERROR(AddToModelBuilderImpl(model_builder, node, logger)); @@ -26,10 +26,10 @@ Status BaseOpBuilder::AddToModelBuilder(ModelBuilder& model_builder, const Node& // Operator support related. -bool BaseOpBuilder::IsOpSupported(const InitializedTensorSet& initializers, const Node& node, +bool BaseOpBuilder::IsOpSupported(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType device_type, const emscripten::val& wnn_limits, const logging::Logger& logger) const { - if (!HasSupportedInputs(initializers, node, wnn_limits, logger)) + if (!HasSupportedInputs(graph_viewer, node, wnn_limits, logger)) return false; if (!HasSupportedOutputs(node, wnn_limits, logger)) @@ -38,11 +38,11 @@ bool BaseOpBuilder::IsOpSupported(const InitializedTensorSet& initializers, cons if (!HasSupportedOpSet(node, logger)) return false; - return IsOpSupportedImpl(initializers, node, device_type, logger); + return IsOpSupportedImpl(graph_viewer, node, device_type, logger); } -bool BaseOpBuilder::HasSupportedInputs(const InitializedTensorSet& initializers, const Node& node, const emscripten::val& wnn_limits, - const logging::Logger& logger) const { +bool BaseOpBuilder::HasSupportedInputs(const GraphViewer& graph_viewer, const Node& node, + const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto node_name = MakeString("Node [", node.Name(), "] type [", node.OpType(), "]"); for (const auto* input : node.InputDefs()) { if (!IsTensorShapeSupported(*input, node_name, logger, allow_empty_tensor_as_input_)) { @@ -50,10 +50,10 @@ bool BaseOpBuilder::HasSupportedInputs(const InitializedTensorSet& initializers, } } - return HasSupportedInputsImpl(initializers, node, wnn_limits, logger); + return HasSupportedInputsImpl(graph_viewer, node, wnn_limits, logger); } -bool BaseOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& initializers, const Node& node, +bool BaseOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { // We only check the type of input 0 by default, specific op builder can override this. diff --git a/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h b/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h index 0a4367a71add4..b794ff6a63a6c 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h +++ b/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h @@ -30,17 +30,17 @@ class BaseOpBuilder : public IOpBuilder { // Operator support related. public: - bool IsOpSupported(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupported(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType device_type, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; protected: - virtual bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& /* node */, + virtual bool IsOpSupportedImpl(const GraphViewer& /* graph_viewer */, const Node& /* node */, const WebnnDeviceType /* device_type */, const logging::Logger& /* logger */) const { return true; } - virtual bool HasSupportedInputsImpl(const InitializedTensorSet& initializers, const Node& node, const emscripten::val& wnn_limits, + virtual bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const; virtual bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const; @@ -56,7 +56,7 @@ class BaseOpBuilder : public IOpBuilder { private: bool HasSupportedOpSet(const Node& node, const logging::Logger& logger) const; - bool HasSupportedInputs(const InitializedTensorSet& initializers, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const; + bool HasSupportedInputs(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const; bool HasSupportedOutputs(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const; const bool allow_empty_tensor_as_input_; // Some operators can handle ignoring an empty tensor as input. diff --git a/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc index c17ad0c89bd9d..29d02690d17c8 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc @@ -20,7 +20,7 @@ class BinaryOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -57,7 +57,7 @@ Status BinaryOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const return Status::OK(); } -bool BinaryOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool BinaryOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc index a244efdd9b2eb..8e618285e29ba 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc @@ -23,7 +23,7 @@ class ClipOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType device_type, const logging::Logger& logger) const override; }; @@ -61,15 +61,12 @@ Status ClipOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool ClipOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool ClipOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType device_type, const logging::Logger& logger) const { - // TODO: Update IsOpSupportedImpl to pass GraphViewer instead of InitializedTensorSet so the implementations - // can ensure initializers are constant. See #19401 for details of how this update was made to the NNAPI EP. - // GetClipMinMax(graph_viewer, node, minValue, maxValue, logger) float min, max; - return GetClipMinMax(initializers, node, min, max, logger); + return GetClipMinMax(graph_viewer, node, min, max, logger); } void CreateClipOpBuilder(const std::string& op_type, OpBuilderRegistrations& op_registrations) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc index ee2512ddd8b5a..f5b78bf4bc16b 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/concat_op_builder.cc @@ -20,7 +20,7 @@ class ConcatOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -54,7 +54,7 @@ Status ConcatOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, return Status::OK(); } -bool ConcatOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool ConcatOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc index 4c393e8a9bdba..436324e087321 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc @@ -26,9 +26,9 @@ class ConvOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType device_type, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -344,7 +344,7 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N // Operator support related. -bool ConvOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool ConvOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType device_type, const logging::Logger& logger) const { @@ -381,7 +381,7 @@ bool ConvOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, return true; } -bool ConvOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool ConvOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc index 99be8f75771ad..14324415b3659 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/cumsum_op_builder.cc @@ -27,7 +27,7 @@ class CumSumOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -70,7 +70,7 @@ Status CumSumOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const } // Operator support related. -bool CumSumOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool CumSumOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -82,7 +82,8 @@ bool CumSumOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers const std::string axis_name = GetTensorName(input_defs, 1); // Inputs contain optional 'axis' input. - if (!Contains(initializers, axis_name)) { + const auto* init = graph_viewer.GetConstantInitializer(axis_name); + if (init == nullptr) { LOGS(logger, VERBOSE) << "The axis must be a constant initializer."; return false; } diff --git a/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc index 974e48bc57de9..c22dd9e97bb1a 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/dropout_op_builder.cc @@ -24,7 +24,7 @@ class DropoutOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -73,7 +73,7 @@ Status DropoutOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool DropoutOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool DropoutOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { diff --git a/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc index 6cee04bac3e2b..e5b4fcddc4221 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/einsum_op_builder.cc @@ -24,9 +24,9 @@ class EinsumOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -694,7 +694,7 @@ Status EinsumOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool EinsumOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool EinsumOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType device_type, const logging::Logger& logger) const { @@ -734,7 +734,7 @@ bool EinsumOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializ return true; } -bool EinsumOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool EinsumOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc index 3f813f08279e7..2c28786b788f9 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/expand_op_builder.cc @@ -27,7 +27,7 @@ class ExpandOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -63,23 +63,27 @@ Status ExpandOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool ExpandOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool ExpandOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const auto& shape_name = input_defs[1]->Name(); - if (!Contains(initializers, shape_name)) { + + // We need a constant which can not be overriden by input + const auto* shape_init = graph_viewer.GetConstantInitializer(shape_name); + if (!shape_init) { LOGS(logger, VERBOSE) << "The shape must be a constant initializer."; return false; } - std::vector new_shape; - const auto& shape_tensor = *initializers.at(shape_name); + const auto& shape_tensor = *shape_init; if (shape_tensor.data_type() != ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64) { LOGS(logger, VERBOSE) << "The type of tensor's element data must be INT64."; return false; } + + std::vector new_shape; if (!ReadIntArrayFrom1DTensor(shape_tensor, new_shape, logger)) { LOGS(logger, VERBOSE) << "Cannot get shape."; return false; diff --git a/onnxruntime/core/providers/webnn/builders/impl/gatherElements_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gatherElements_op_builder.cc index 1db0ec12b0dfb..06beb56415609 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gatherElements_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gatherElements_op_builder.cc @@ -20,7 +20,7 @@ class GatherElementsOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -49,7 +49,7 @@ Status GatherElementsOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builde // Operator support related. -bool GatherElementsOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool GatherElementsOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& data = *node.InputDefs()[0]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/gatherND_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gatherND_op_builder.cc index 279305c8ed3b4..9200c596c0e53 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gatherND_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gatherND_op_builder.cc @@ -20,9 +20,9 @@ class GatherNDOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -43,7 +43,7 @@ Status GatherNDOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, con // Operator support related. -bool GatherNDOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool GatherNDOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { NodeAttrHelper helper(node); @@ -55,7 +55,7 @@ bool GatherNDOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initial return true; } -bool GatherNDOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool GatherNDOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& data = *node.InputDefs()[0]; const auto& indices = *node.InputDefs()[1]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/gather_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gather_op_builder.cc index 4d983eeb799fd..d84c70032e1d1 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gather_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gather_op_builder.cc @@ -20,9 +20,9 @@ class GatherOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -51,7 +51,7 @@ Status GatherOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool GatherOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool GatherOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -69,7 +69,7 @@ bool GatherOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializ return true; } -bool GatherOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool GatherOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input = *node.InputDefs()[0]; const auto& indices = *node.InputDefs()[1]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc index 1f24124745a19..fbf3ac1df2bc2 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gemm_op_builder.cc @@ -22,9 +22,9 @@ class GemmOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -148,7 +148,7 @@ Status GemmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N // Operator support related. -bool GemmOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool GemmOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -212,7 +212,7 @@ bool GemmOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializer return true; } -bool GemmOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool GemmOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/gru_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/gru_op_builder.cc index 1180721105fb0..403bc8af8ac1f 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/gru_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/gru_op_builder.cc @@ -24,9 +24,9 @@ class GruOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /*device_type*/, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer& graph_viewer, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; @@ -119,7 +119,7 @@ Status GruOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const No return Status::OK(); } -bool GruOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, +bool GruOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /*device_type*/, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); if (input_defs.size() < 3) { @@ -135,12 +135,13 @@ bool GruOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, c int32_t steps = static_cast(input_shape[0]); if (TensorExists(input_defs, 4)) { - if (!Contains(initializers, input_defs[4]->Name())) { + const auto* seq_initializer = graph_viewer.GetConstantInitializer(input_defs[4]->Name()); + if (!seq_initializer) { LOGS(logger, ERROR) << "GRU: sequence_lens must be constant"; return false; } - const auto& sequence_lens_tensor = *initializers.at(input_defs[4]->Name()); + const auto& sequence_lens_tensor = *seq_initializer; std::vector sequence_lens; if (!ReadIntArrayFrom1DTensor(sequence_lens_tensor, sequence_lens, logger)) { LOGS(logger, ERROR) << "Cannot read sequence lens tensor"; @@ -187,7 +188,7 @@ bool GruOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, c return true; } -bool GruOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool GruOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/logical_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/logical_op_builder.cc index 86fc1bc01e18a..7c6de428d0934 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/logical_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/logical_op_builder.cc @@ -19,9 +19,9 @@ class LogicalOpBuilder : public BaseOpBuilder { Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -54,7 +54,7 @@ Status LogicalOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, cons return Status::OK(); } -bool LogicalOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool LogicalOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -72,7 +72,7 @@ bool LogicalOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initiali return true; } -bool LogicalOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool LogicalOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/lrn_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/lrn_op_builder.cc index 19c17f58bdb23..2e5d3d6b5228a 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/lrn_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/lrn_op_builder.cc @@ -21,9 +21,9 @@ class LRNOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; @@ -128,7 +128,7 @@ Status LRNOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool LRNOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool LRNOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -146,7 +146,7 @@ bool LRNOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, return true; } -bool LRNOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool LRNOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/lstm_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/lstm_op_builder.cc index b25037d439bf4..c49f360c11737 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/lstm_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/lstm_op_builder.cc @@ -23,9 +23,9 @@ class LstmOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /*device_type*/, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; @@ -125,7 +125,7 @@ Status LstmOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N return Status::OK(); } -bool LstmOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, +bool LstmOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /*device_type*/, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); if (input_defs.size() < 3) { @@ -141,12 +141,13 @@ bool LstmOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, int32_t steps = static_cast(input_shape[0]); if (TensorExists(input_defs, 4)) { - if (!Contains(initializers, input_defs[4]->Name())) { + const auto* sequence_lens_init = graph_viewer.GetConstantInitializer(input_defs[4]->Name()); + if (!sequence_lens_init) { LOGS(logger, ERROR) << "LSTM: sequence_lens must be constant"; return false; } - const auto& sequence_lens_tensor = *initializers.at(input_defs[4]->Name()); + const auto& sequence_lens_tensor = *sequence_lens_init; std::vector sequence_lens; if (!ReadIntArrayFrom1DTensor(sequence_lens_tensor, sequence_lens, logger)) { LOGS(logger, ERROR) << "Cannot read sequence lens tensor"; @@ -198,7 +199,7 @@ bool LstmOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, return true; } -bool LstmOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool LstmOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/max_min_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/max_min_op_builder.cc index a7bcbfeb4b13e..7ec4ff640132c 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/max_min_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/max_min_op_builder.cc @@ -20,9 +20,9 @@ class MaxMinOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -68,7 +68,7 @@ Status MaxMinOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool MaxMinOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool MaxMinOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -87,7 +87,7 @@ bool MaxMinOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializ return true; } -bool MaxMinOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool MaxMinOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc index 5b57df7f184e7..704c6a65624d8 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc @@ -22,9 +22,9 @@ class NormalizationOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; @@ -225,7 +225,7 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder // Operator support related. -bool NormalizationOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool NormalizationOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -270,7 +270,7 @@ bool NormalizationOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initi return true; } -bool NormalizationOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool NormalizationOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc index e8f26af928ab3..f17d87d41f9ae 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pad_op_builder.cc @@ -25,7 +25,7 @@ class PadOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -155,7 +155,7 @@ Status PadOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool PadOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool PadOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -183,7 +183,7 @@ bool PadOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, for (size_t i = 1; i < input_defs.size(); i++) { // Optional tensors (constant_value, axes) can be indicated by an empty name, just ignore it. const std::string input_name = GetTensorName(input_defs, i); - if (!input_name.empty() && !Contains(initializers, input_name)) { + if (!input_name.empty() && !graph_viewer.GetConstantInitializer(input_name)) { LOGS(logger, VERBOSE) << "Input [" << input_name << "] must be known as initializer"; return false; } diff --git a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc index 79ad3574e07e9..2d263c1ec1f9f 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc @@ -22,7 +22,7 @@ class PoolOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -111,7 +111,7 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool PoolOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool PoolOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { diff --git a/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc index ed62b2bd69618..dd25fb9bf9315 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/qdq_op_builder.cc @@ -21,9 +21,9 @@ class QDQOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -121,7 +121,7 @@ Status QDQOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool QDQOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool QDQOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -152,7 +152,7 @@ bool QDQOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers return true; } -bool QDQOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool QDQOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc index b23fbeba1ddc8..a3a0397eda4a3 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/reduction_op_builder.cc @@ -28,7 +28,7 @@ class ReductionOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -123,7 +123,7 @@ Status ReductionOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool ReductionOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool ReductionOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -136,7 +136,7 @@ bool ReductionOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializ const auto& op_type = node.OpType(); const std::string axes_name = GetTensorName(input_defs, 1); // If the optional input 'axes' is provided, it must be an initializer. - if (!axes_name.empty() && !Contains(initializers, axes_name)) { + if (!axes_name.empty() && !graph_viewer.GetConstantInitializer(axes_name)) { LOGS(logger, VERBOSE) << "Input axes of " << op_type << " must be a constant"; return false; } diff --git a/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc index 2fc47430a1c66..da5e034c38c8e 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/reshape_op_builder.cc @@ -27,7 +27,7 @@ class ReshapeOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -74,7 +74,7 @@ Status ReshapeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool ReshapeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool ReshapeOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -85,12 +85,13 @@ bool ReshapeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializer return false; const auto& perm_name = input_defs[1]->Name(); - if (!Contains(initializers, perm_name)) { + const auto* perm_init = graph_viewer.GetConstantInitializer(perm_name); + if (!perm_init) { LOGS(logger, VERBOSE) << "New shape of reshape must be a constant initializer"; return false; } - const auto& perm_tensor = *initializers.at(perm_name); + const auto& perm_tensor = *perm_init; std::vector unpacked_tensor; auto status = onnxruntime::utils::UnpackInitializerData(perm_tensor, unpacked_tensor); if (!status.IsOK()) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc index eec6911a686cf..f71ec2f98d112 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc @@ -30,7 +30,7 @@ class ResizeOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; // Resize opset 10- is very different than Resize opset 11+, with many key attributes missing. @@ -39,7 +39,7 @@ class ResizeOpBuilder : public BaseOpBuilder { }; // Helper functions -bool GetResizeScalesAndAxes(const InitializedTensorSet& initializers, +bool GetResizeScalesAndAxes(const GraphViewer& graph_viewer, const Node& node, std::vector& scales, std::vector& axes, const bool is_nhwc, const logging::Logger& logger) { @@ -48,13 +48,14 @@ bool GetResizeScalesAndAxes(const InitializedTensorSet& initializers, return false; const bool has_axes = !axes.empty(); - const auto& scales_tensor = *initializers.at(input_defs[2]->Name()); - if (scales_tensor.dims_size() != 1) { - LOGS(logger, ERROR) << "'scales' should be a 1D tensor."; + const auto* scales_init = graph_viewer.GetConstantInitializer(input_defs[2]->Name()); + if (!scales_init || scales_init->dims_size() != 1) { + LOGS(logger, ERROR) << "Expecting 'scales' as a 1D constant initialized tensor."; return false; } // Number of elements of 'scales' tensor. + const auto& scales_tensor = *scales_init; const auto num_of_scales = scales_tensor.dims()[0]; if (has_axes && num_of_scales != 2) { @@ -106,7 +107,7 @@ bool GetResizeScalesAndAxes(const InitializedTensorSet& initializers, return true; } -bool GetResizeSizesAndAxes(const InitializedTensorSet& initializers, +bool GetResizeSizesAndAxes(const GraphViewer& graph_viewer, const Node& node, std::vector& sizes, std::vector& axes, const bool is_nhwc, const gsl::span& input_shape, @@ -116,12 +117,13 @@ bool GetResizeSizesAndAxes(const InitializedTensorSet& initializers, return false; const bool has_axes = !axes.empty(); - const auto& sizes_tensor = *initializers.at(input_defs[3]->Name()); - if (sizes_tensor.dims_size() != 1) { - LOGS(logger, ERROR) << "'sizes' should be a 1D tensor."; + const auto* sizes_init = graph_viewer.GetConstantInitializer(input_defs[3]->Name()); + if (!sizes_init || sizes_init->dims_size() != 1) { + LOGS(logger, ERROR) << "'sizes' should be a 1D constant initializer tensor."; return false; } + const auto& sizes_tensor = *sizes_init; // Number of elements of sizes tensor. const auto num_of_sizes = sizes_tensor.dims()[0]; if (has_axes && num_of_sizes != 2) { @@ -222,12 +224,13 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // This handles Resize-11 where 'scales' was a required input but 'sizes' were used if provided. bool using_sizes = !sizes_name.empty() && Contains(initializers, sizes_name); if (using_sizes) { - ORT_RETURN_IF_NOT(GetResizeSizesAndAxes(initializers, node, sizes, axes, is_nhwc, input_shape, logger), + ORT_RETURN_IF_NOT(GetResizeSizesAndAxes(model_builder.GetGraphViewer(), node, sizes, axes, is_nhwc, + input_shape, logger), "Error getting Resize sizes"); webnn_sizes = GetNarrowedIntfromInt64(sizes); options.set("sizes", emscripten::val::array(webnn_sizes)); } else { - ORT_RETURN_IF_NOT(GetResizeScalesAndAxes(initializers, node, scales, axes, is_nhwc, logger), + ORT_RETURN_IF_NOT(GetResizeScalesAndAxes(model_builder.GetGraphViewer(), node, scales, axes, is_nhwc, logger), "Error getting Resize scales"); options.set("scales", emscripten::val::array(scales)); } @@ -243,7 +246,7 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool ResizeOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -304,8 +307,8 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers // Check for 'sizes' first. // This handles Resize-11 where 'scales' was a required input but 'sizes' were used if provided. // 'scales' or 'sizes' may be empty tensor. - bool using_sizes = !IsEmptyTensor(initializers, sizes_name); - bool using_scales = !using_sizes && !IsEmptyTensor(initializers, scales_name); + bool using_sizes = !IsEmptyTensor(graph_viewer, sizes_name); + bool using_scales = !using_sizes && !IsEmptyTensor(graph_viewer, scales_name); if (!using_scales && !using_sizes) { LOGS(logger, VERBOSE) << "Resize: only one of 'scales' and 'sizes' can be specified"; @@ -325,12 +328,12 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers const bool is_nhwc = node.Domain() == kMSInternalNHWCDomain; if (using_sizes) { // We are using 'sizes'. std::vector sizes; - if (!GetResizeSizesAndAxes(initializers, node, sizes, axes, is_nhwc, input_shape, logger)) { + if (!GetResizeSizesAndAxes(graph_viewer, node, sizes, axes, is_nhwc, input_shape, logger)) { return false; } } else { // We are using 'scales'. std::vector scales; - if (!GetResizeScalesAndAxes(initializers, node, scales, axes, is_nhwc, logger)) { + if (!GetResizeScalesAndAxes(graph_viewer, node, scales, axes, is_nhwc, logger)) { return false; } } diff --git a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc index 0a84835ee9fc0..bdd0c97b7b81c 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/rotaryEmbedding_op_builder.cc @@ -57,9 +57,9 @@ class RotaryEmbeddingOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer& graph_viewer, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; @@ -286,7 +286,7 @@ Status RotaryEmbeddingOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_build } // Operator support related. -bool RotaryEmbeddingOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, +bool RotaryEmbeddingOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); @@ -325,7 +325,7 @@ bool RotaryEmbeddingOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& ini return true; } -bool RotaryEmbeddingOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, +bool RotaryEmbeddingOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { diff --git a/onnxruntime/core/providers/webnn/builders/impl/scatterElements_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/scatterElements_op_builder.cc index 1a68f7862f1ab..f894e8bfbd517 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/scatterElements_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/scatterElements_op_builder.cc @@ -20,9 +20,9 @@ class ScatterElementsOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer& graph_viewer, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -53,7 +53,7 @@ Status ScatterElementsOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_build // Operator support related. -bool ScatterElementsOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool ScatterElementsOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { NodeAttrHelper helper(node); @@ -65,7 +65,7 @@ bool ScatterElementsOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* return true; } -bool ScatterElementsOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool ScatterElementsOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& data = *node.InputDefs()[0]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/scatterND_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/scatterND_op_builder.cc index 2b123dc2e9323..e61ac3dcc9617 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/scatterND_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/scatterND_op_builder.cc @@ -20,9 +20,9 @@ class ScatterNDOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer& graph_viewer, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -45,7 +45,7 @@ Status ScatterNDOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, co // Operator support related. -bool ScatterNDOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool ScatterNDOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { NodeAttrHelper helper(node); @@ -57,7 +57,7 @@ bool ScatterNDOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initia return true; } -bool ScatterNDOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool ScatterNDOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& data = *node.InputDefs()[0]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc index 468c0e24a3e88..6206ac23e4bd4 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/slice_op_builder.cc @@ -24,9 +24,9 @@ class SliceOpBuilder : public BaseOpBuilder { private: Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const override ORT_MUST_USE_RESULT; - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; - bool HasSupportedInputsImpl(const InitializedTensorSet& initializers, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer& graph_viewer, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; // TODO: Support Slice opset < 10, which uses attributes for starts and ends. int GetMinSupportedOpSet(const Node& /* node */) const override { return 10; } @@ -132,7 +132,7 @@ Status SliceOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const return Status::OK(); } -bool SliceOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, +bool SliceOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { const auto& name = node.Name(); const auto& op_type = node.OpType(); @@ -152,7 +152,8 @@ bool SliceOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, for (size_t i = 1; i < input_defs.size(); i++) { // Optional tensors (axes, steps) can be indicated by an empty name, just ignore it. const std::string input_name = GetTensorName(input_defs, i); - if (!input_name.empty() && !Contains(initializers, input_name)) { + const auto* init = graph_viewer.GetConstantInitializer(input_name); + if (!input_name.empty() && !init) { LOGS(logger, VERBOSE) << "Input [" << input_name << "] of " << op_type << " [" << name << "] must be known as initializer"; return false; @@ -162,7 +163,7 @@ bool SliceOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, return true; } -bool SliceOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& initializers, const Node& node, +bool SliceOpBuilder::HasSupportedInputsImpl(const GraphViewer& graph_viewer, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const auto& input = *input_defs[0]; @@ -174,7 +175,8 @@ bool SliceOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& initiali // If there is step < 0, check data type support of reverse. if (TensorExists(input_defs, 4)) { std::vector steps; - if (!ReadIntArrayFrom1DTensor(*initializers.at(input_defs[4]->Name()), steps, logger)) + const auto* init = graph_viewer.GetConstantInitializer(input_defs[4]->Name()); + if (!init || !ReadIntArrayFrom1DTensor(*init, steps, logger)) return false; if (std::any_of(steps.begin(), steps.end(), [](int64_t step) { return step < 0; })) { if (!IsDataTypeSupportedByWebNNOp(op_type, "reverse", input_type, wnn_limits, "input", "data", logger)) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc index 0e754b53e78d1..23e73bb8f1e74 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/softmax_op_builder.cc @@ -21,7 +21,7 @@ class SoftmaxOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -48,7 +48,7 @@ Status SoftmaxOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool SoftmaxOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, +bool SoftmaxOpBuilder::IsOpSupportedImpl(const GraphViewer&, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { diff --git a/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc index 21b44b1066694..8094d3024a321 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/split_op_builder.cc @@ -25,7 +25,7 @@ class SplitOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; bool HasSupportedOutputsImpl(const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; @@ -94,7 +94,7 @@ Status SplitOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool SplitOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool SplitOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -114,12 +114,13 @@ bool SplitOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, const std::string split_name = GetTensorName(input_defs, 1); // Inputs contain optional 'split' input. if (!split_name.empty()) { - if (!Contains(initializers, split_name)) { + const auto* split_init = graph_viewer.GetConstantInitializer(split_name); + if (!split_init) { LOGS(logger, VERBOSE) << "The split must be a constant initializer."; return false; } // Values should be >= 0. Sum of the values must be equal to the dim value at 'axis' specified. - const auto& split_tensor = *initializers.at(input_defs[1]->Name()); + const auto& split_tensor = *split_init; if (split_tensor.data_type() != ONNXTensorElementDataType::ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64) { LOGS(logger, VERBOSE) << "The type of tensor's element data must be INT64."; return false; diff --git a/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc index 5687b1133c628..1ba6df9febf14 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/squeeze_unsqueeze_op_builder.cc @@ -27,7 +27,7 @@ class SqueezeUnsqueezeOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -121,7 +121,7 @@ Status SqueezeUnsqueezeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_buil // Operator support related. -bool SqueezeUnsqueezeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool SqueezeUnsqueezeOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -140,7 +140,8 @@ bool SqueezeUnsqueezeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& in if (node.SinceVersion() >= 13) { const std::string axes_name = GetTensorName(input_defs, 1); if (!axes_name.empty()) { - if (!Contains(initializers, axes_name)) { + const auto* init = graph_viewer.GetConstantInitializer(axes_name); + if (!init) { LOGS(logger, ERROR) << "Input axes of " << op_type << " is not present and constant"; return false; } diff --git a/onnxruntime/core/providers/webnn/builders/impl/ternary_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/ternary_op_builder.cc index a233ba82ebbc6..f6c1744ca7a3e 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/ternary_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/ternary_op_builder.cc @@ -18,7 +18,7 @@ class TernaryOpBuilder : public BaseOpBuilder { private: Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const override ORT_MUST_USE_RESULT; - bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, + bool HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -46,7 +46,7 @@ Status TernaryOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, cons return Status::OK(); } -bool TernaryOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, +bool TernaryOpBuilder::HasSupportedInputsImpl(const GraphViewer&, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const std::string_view op_type = node.OpType(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc index 259bb0552b7c7..29b232026d7df 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/tile_op_builder.cc @@ -26,7 +26,7 @@ class TileOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -65,13 +65,14 @@ Status TileOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // Operator support related. -bool TileOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool TileOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); const auto& repetitions_name = input_defs[1]->Name(); - if (!Contains(initializers, repetitions_name)) { + const auto* init = graph_viewer.GetConstantInitializer(repetitions_name); + if (!init) { LOGS(logger, VERBOSE) << "Repetitions of tile must be a constant initializer"; return false; } diff --git a/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc index f2092d6163713..ca98d8264fdcd 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/triangular_op_builder.cc @@ -24,7 +24,7 @@ class TriangularOpBuilder : public BaseOpBuilder { // Operator support related. private: - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, + bool IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const override; }; @@ -69,7 +69,7 @@ Status TriangularOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, } // Operator support related. -bool TriangularOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, +bool TriangularOpBuilder::IsOpSupportedImpl(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType /* device_type */, const logging::Logger& logger) const { @@ -87,7 +87,8 @@ bool TriangularOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initiali const std::string diagonal_name = GetTensorName(input_defs, 1); // Inputs contain optional 'diagonal' input. if (!diagonal_name.empty()) { - if (!Contains(initializers, diagonal_name)) { + const auto* init = graph_viewer.GetConstantInitializer(diagonal_name); + if (!init) { LOGS(logger, VERBOSE) << "The diagonal must be a constant initializer."; return false; } diff --git a/onnxruntime/core/providers/webnn/builders/op_builder.h b/onnxruntime/core/providers/webnn/builders/op_builder.h index bb69a6a545597..636b1dc9f478a 100644 --- a/onnxruntime/core/providers/webnn/builders/op_builder.h +++ b/onnxruntime/core/providers/webnn/builders/op_builder.h @@ -28,7 +28,7 @@ class IOpBuilder { // Operator support related. public: // Check if an operator is supported. - virtual bool IsOpSupported(const InitializedTensorSet& initializers, const Node& node, + virtual bool IsOpSupported(const GraphViewer& graph_viewer, const Node& node, const WebnnDeviceType device_type, const emscripten::val& wnn_limits, const logging::Logger& logger) const = 0; }; From 4959468abf648c921dba5c1237809bcd411080b3 Mon Sep 17 00:00:00 2001 From: Andreas Hussing <93076125+CodingSeaotter@users.noreply.github.com> Date: Sat, 22 Mar 2025 01:09:01 +0100 Subject: [PATCH 148/266] Deleted the constant SKIP_CUDA_TEST_WITH_DML (#24113) ### Description Deleted the constant SKIP_CUDA_TEST_WITH_DML. It does not seem to be used anywhere. ### Motivation and Context The constant SKIP_CUDA_TEST_WITH_DML prohibits onnxruntime to be compiled when both of the flags -use_cuda and -use_dml are set. Co-authored-by: Andreas Hussing --- onnxruntime/test/contrib_ops/beam_search_test.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/onnxruntime/test/contrib_ops/beam_search_test.cc b/onnxruntime/test/contrib_ops/beam_search_test.cc index df670012f54c0..367553a28f166 100644 --- a/onnxruntime/test/contrib_ops/beam_search_test.cc +++ b/onnxruntime/test/contrib_ops/beam_search_test.cc @@ -403,9 +403,6 @@ TEST(BeamSearchTest, GptBeamSearchFp16_VocabPadded) { } TEST(BeamSearchTest, DummyT5) { -#if defined(USE_CUDA) && defined(USE_DML) - SKIP_CUDA_TEST_WITH_DML; -#endif // dummy_t5.onnx model generated using following command: // python onnxruntime/test/testdata/dummy_t5_generator.py --output-path dummy_t5.onnx ModelTester tester(CurrentTestName(), ORT_TSTR("testdata/dummy_t5.onnx")); @@ -419,9 +416,6 @@ TEST(BeamSearchTest, DummyT5) { } TEST(BeamSearchTest, DummyT5WithOuterScopeInitializers) { -#if defined(USE_CUDA) && defined(USE_DML) - SKIP_CUDA_TEST_WITH_DML; -#endif // dummy_t5_with_outer_scope_initializers.onnx model generated using following command: // python onnxruntime/test/testdata/dummy_t5_generator.py --output-path dummy_t5_with_outer_scope_initializers.onnx --move-initializers ModelTester tester(CurrentTestName(), ORT_TSTR("testdata/dummy_t5_with_outer_scope_initializers.onnx")); @@ -448,9 +442,6 @@ TEST(BeamSearchTest, DummyT5WithSequenceInputIds) { } TEST(BeamSearchTest, DummyT5PointerGenerator) { -#if defined(USE_CUDA) && defined(USE_DML) - SKIP_CUDA_TEST_WITH_DML; -#endif // dummy_t5_pointer_generator.onnx model generated using following command: // python onnxruntime/test/testdata/dummy_t5_generator.py --output-path dummy_t5_pointer_generator.onnx --decoder-needs-input-ids ModelTester tester(CurrentTestName(), ORT_TSTR("testdata/dummy_t5_pointer_generator.onnx")); From d84314cbcf1e683754bc5314cc271b97a5b0959d Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Sat, 22 Mar 2025 21:13:51 -0700 Subject: [PATCH 149/266] Update T5 Onnx Export and Optimization (#23949) Previously, the encoder onnx model adds extra initialization for decoder to generate kv cache from prompt. It is not necessary. Here we redesign onnx export for T5 model to output two separate models for encode and decoder. Move Linear that generates cross features based on encoder_hidden_states to encoder onnx model. In this way, the encoder does not need output encoder_hidden_states, and only need output the features for cross attention used in decoder. Major changes: -[x] update t5 onnx export script -[x] update convert_generation script -[x] update beam search to support changes of inputs and outputs (detail can be found below). -[x] add a tiny t5 model, and enable the generation test for T5 in Linux CI pipelines. Example change in inputs and outputs for one layer model: **Encoder Inputs**: - encoder_input_ids: int32 (B, encode_sequence_length) - encoder_attention_mask: int32 (B, encode_sequence_length) - ~~decoder_input_ids: int32 (B, 1)~~ **Encoder Outputs**: - ~~logits: (B, 1, vocab_size)~~ - ~~encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size)~~ - ~~present_key_self_0: (B, num_heads, 1, head_size)~~ - ~~present_value_self_0: (B, num_heads, 1, head_size)~~ - present_key_cross_0: (B, num_heads, encode_sequence_length, head_size) - present_value_cross_0: (B, num_heads, encode_sequence_length, head_size) **Decoder Inputs**: - input_ids: int32 (B, 1) - ~~encoder_input_ids: int32 (B, encode_sequence_length) (optional for old format; removed in new format)~~ - encoder_attention_mask: int32 (B, encode_sequence_length) - ~~encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) (optional for old format; removed in new format)~~ - past_key_self_0: (B, num_heads, past_decode_sequence_length, head_size) - past_value_self_0: (B, num_heads, past_decode_sequence_length, head_size) - past_key_cross_0: (B, num_heads, encode_sequence_length, head_size) - past_value_cross_0: (B, num_heads, encode_sequence_length, head_size) **Decoder Outputs**: - logits: (B, 1, vocab_size) - present_key_self_0: (B, num_heads, past_decode_sequence_length + 1, head_size) - present_value_self_0: (B, num_heads, past_decode_sequence_length + 1, head_size) Known issues: - Some postprocessing (like converting to use decoder masked MHA, past and present buffer sharing) is not done. Could be a future work item to integrate with onnxruntime-genai. ### Motivation and Context Make the encoder onnx model simpler and more efficient in inference (no need to output encoder_hidden_states). --- .../cpu/transformers/beam_search.cc | 16 +- .../cpu/transformers/beam_search_impl_t5.h | 71 +- .../cpu/transformers/subgraph_base.cc | 18 +- .../cpu/transformers/subgraph_t5_decoder.cc | 180 ++-- .../cpu/transformers/subgraph_t5_decoder.h | 5 +- .../cpu/transformers/subgraph_t5_encoder.cc | 117 ++- .../cpu/transformers/subgraph_t5_encoder.h | 13 +- .../tools/transformers/benchmark_helper.py | 91 +- .../tools/transformers/convert_generation.py | 309 ++++-- .../fusion_simplified_layernorm.py | 54 +- .../models/gpt2/convert_to_onnx.py | 3 - .../transformers/models/t5/convert_to_onnx.py | 104 +- .../transformers/models/t5/t5_encoder.py | 116 +-- .../models/t5/t5_encoder_decoder_init.py | 127 ++- .../tools/transformers/models/t5/t5_helper.py | 151 +-- .../python/tools/transformers/onnx_model.py | 14 +- .../tools/transformers/onnx_model_t5.py | 361 ++++--- .../python/transformers/test_generation.py | 261 +++-- .../transformers/tiny_t5/added_tokens.json | 102 ++ .../testdata/transformers/tiny_t5/config.json | 60 ++ .../tiny_t5/generation_config.json | 7 + .../transformers/tiny_t5/model.safetensors | Bin 0 -> 48888 bytes .../tiny_t5/special_tokens_map.json | 125 +++ .../transformers/tiny_t5/spiece.model | Bin 0 -> 252835 bytes .../testdata/transformers/tiny_t5/tiny_t5.py | 85 ++ .../tiny_t5/tokenizer_config.json | 940 ++++++++++++++++++ .../transformers-test/requirements.txt | 1 + 27 files changed, 2578 insertions(+), 753 deletions(-) create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/added_tokens.json create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/config.json create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/generation_config.json create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/model.safetensors create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/special_tokens_map.json create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/spiece.model create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/tiny_t5.py create mode 100644 onnxruntime/test/testdata/transformers/tiny_t5/tokenizer_config.json diff --git a/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc b/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc index 12fae5ccf0983..7962662ff6088 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc +++ b/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc @@ -139,13 +139,19 @@ Status BeamSearch::SetupSubgraphExecutionInfo(const SessionState& session_state, ORT_RETURN_IF_ERROR(t5_encoder_subgraph_->Setup(session_state, subgraph_session_state)); encoder_feeds_fetches_manager_ = t5_encoder_subgraph_->GetFeedsFetchesManager(); - if (parameters_->decoder_start_token_id < 0) { - ORT_RETURN_IF(t5_encoder_subgraph_->num_subgraph_inputs != 2, - "Encoder subgraph shall have 2 inputs when decoder_start_token_id attribute is empty"); + if (!t5_encoder_subgraph_->HasLogitsOutput()) { + // New format requires start token id. + ORT_ENFORCE(parameters_->decoder_start_token_id >= 0); } else { - ORT_RETURN_IF(t5_encoder_subgraph_->num_subgraph_inputs != 3, - "Encoder subgraph shall have 3 inputs when decoder_start_token_id attribute is available"); + if (parameters_->decoder_start_token_id < 0) { + ORT_RETURN_IF(t5_encoder_subgraph_->num_subgraph_inputs != 2, + "Encoder subgraph shall have 2 inputs when decoder_start_token_id attribute is empty"); + } else { + ORT_RETURN_IF(t5_encoder_subgraph_->num_subgraph_inputs != 3, + "Encoder subgraph shall have 3 inputs when decoder_start_token_id attribute is available"); + } } + } else if (attribute_name == "decoder") { ORT_ENFORCE(t5_decoder_subgraph_ == nullptr, "SetupSubgraphExecutionInfo should only be called once for each subgraph."); diff --git a/onnxruntime/contrib_ops/cpu/transformers/beam_search_impl_t5.h b/onnxruntime/contrib_ops/cpu/transformers/beam_search_impl_t5.h index b67d003eaceeb..c9646cf0fab2e 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/beam_search_impl_t5.h +++ b/onnxruntime/contrib_ops/cpu/transformers/beam_search_impl_t5.h @@ -51,7 +51,13 @@ class BeamSearchT5 : public BeamSearchBase { expand_buffer_int32_func_(expand_buffer_int32_func), expand_buffer_float_func_(expand_buffer_float_func), expand_buffer_float16_func_(expand_buffer_float16_func), - create_beam_scorer_func_(create_beam_scorer_func) {} + create_beam_scorer_func_(create_beam_scorer_func) { + // When decoder uses encoder_hidden_state, make sure the encoder outputs it. + if (decoder_subgraph_.UseEncoderHiddenState()) { + ORT_ENFORCE(encoder_subgraph_.subgraph_output_names[1] == "encoder_hidden_states"); + } + ORT_ENFORCE(encoder_subgraph_.num_layers == decoder_subgraph_.num_layers); + } #ifdef USE_CUDA Status InitializeCuda( @@ -160,7 +166,7 @@ Status BeamSearchT5::Execute(const FeedsFetchesManager& encoder_feeds_fetches this->create_encoder_inputs_func_, this->add_to_feeds_func_, buffer, - decoder_input_ids, + decoder_input_ids, // new format does not use decoder_input_ids in encoder, it is still initialized here when decoder_start_token_id >= 0. this->ort_stream_)); #ifdef DEBUG_NODE_INPUTS_OUTPUTS @@ -233,35 +239,47 @@ Status BeamSearchT5::Execute(const FeedsFetchesManager& encoder_feeds_fetches std::vector decoder_fetches; - if (current_length + 1 < parameters->max_length) { + // When encoder outputs logits (in old format), we need get the next token from logits. + if (current_length + 1 < parameters->max_length && encoder_subgraph_.HasLogitsOutput()) { ++iteration_counter; - ORT_RETURN_IF_ERROR(this->GenerateNextToken(encoder_fetches[0], + const OrtValue& logits = encoder_fetches[0]; + ORT_RETURN_IF_ERROR(this->GenerateNextToken(logits, beam_next_tokens, beam_state, cpu_state, iteration_counter)); ++current_length; // Increase sequence length after a new token is generated. + } - ORT_RETURN_IF_ERROR(decoder_subgraph_.CreateInitialFeeds(this->cpu_allocator_, - ReinterpretAsSpan(beam_next_tokens), - this->implicit_inputs_, - encoder_feeds, - encoder_fetches, - decoder_feeds, - this->device_copy_int32_func_, - this->expand_buffer_int32_func_, - this->expand_buffer_float_func_, - this->expand_buffer_float16_func_, - parameters->num_beams, - this->ort_stream_, - decoder_subgraph_.UseSequenceAsInputIds(), - current_length, - cpu_state.sequences, - parameters->max_length, - decoder_subgraph_.has_decoder_masked_attention_, - this->cuda_device_prop_ != nullptr)); + if (current_length < parameters->max_length) { + // when no logits, copy sequence (filled with start token IDs) to input_ids for decoder. + bool copy_sequence_to_input_ids = decoder_subgraph_.UseSequenceAsInputIds() || !encoder_subgraph_.HasLogitsOutput(); + if (copy_sequence_to_input_ids) { + ORT_ENFORCE(current_length == cpu_state.sequences.GetSequenceLength()); + } + + // Generate inputs for next decoder subgraph call. + ORT_RETURN_IF_ERROR(decoder_subgraph_.CreateInitialFeeds( + this->cpu_allocator_, + ReinterpretAsSpan(beam_next_tokens), + this->implicit_inputs_, + encoder_feeds, + encoder_fetches, + decoder_feeds, + this->device_copy_int32_func_, + this->expand_buffer_int32_func_, + this->expand_buffer_float_func_, + this->expand_buffer_float16_func_, + parameters->num_beams, + this->ort_stream_, + copy_sequence_to_input_ids, + cpu_state.sequences, + parameters->max_length, + decoder_subgraph_.has_decoder_masked_attention_, + this->cuda_device_prop_ != nullptr)); if (decoder_subgraph_.past_present_share_buffer_) { + // Configure buffer sharing of past and present kv cache. decoder_fetches.reserve(static_cast(decoder_subgraph_.GetFirstPresentOutputIndex()) + 2 * static_cast(decoder_subgraph_.num_layers)); decoder_fetches.resize(decoder_subgraph_.GetFirstPresentOutputIndex(), OrtValue()); @@ -299,14 +317,19 @@ Status BeamSearchT5::Execute(const FeedsFetchesManager& encoder_feeds_fetches while (current_length < parameters->max_length) { iteration_counter++; + #ifdef DEBUG_GENERATION - auto cur_len = std::to_string(current_length); - dumper->Print("***CurrentLength", cur_len, true); + dumper->Print(::onnxruntime::MakeString("Iteration=", iteration_counter, + ", CurrentLength=", current_length, + ", num_layers=", decoder_subgraph_.num_layers, + ", decoder_feeds=", decoder_feeds.size(), + ", start_token_id=", parameters->decoder_start_token_id)); for (int i = 0; i < decoder_subgraph_.GetFirstPastInputIndex(); i++) { dumper->Print("decoder_feeds", i, true); dumper->Print("", decoder_feeds[i]); } + for (int i = 0; i < decoder_subgraph_.num_layers; i++) { int self_key_idx = decoder_subgraph_.GetFirstPastInputIndex() + 2 * i; int self_value_idx = self_key_idx + 1; diff --git a/onnxruntime/contrib_ops/cpu/transformers/subgraph_base.cc b/onnxruntime/contrib_ops/cpu/transformers/subgraph_base.cc index 7757435990a65..537d066b264a1 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/subgraph_base.cc +++ b/onnxruntime/contrib_ops/cpu/transformers/subgraph_base.cc @@ -36,12 +36,9 @@ Subgraph::Subgraph( auto& subgraph_inputs = subgraph.GetInputs(); auto& subgraph_outputs = subgraph.GetOutputs(); - // inputs: input_ids, position_ids, attention_mask, past_0, past_1, ... - // outputs: logits, present_0, present_1, ... num_subgraph_inputs = static_cast(subgraph_inputs.size()); num_subgraph_outputs = static_cast(subgraph_outputs.size()); - // CheckSubgraph will verify inputs and outputs later. subgraph_input_names.reserve(num_subgraph_inputs); for (int i = 0; i < num_subgraph_inputs; ++i) { subgraph_input_names.push_back(subgraph_inputs[i]->Name()); @@ -68,10 +65,9 @@ Status Subgraph::Setup(const SessionState& session_state, InlinedVector feed_names; feed_names.reserve(static_cast(num_subgraph_inputs) + static_cast(num_implicit_inputs)); - // Use the first output (logits) to find device location. + // Use the first output to find device location. const OrtDevice& default_location = utils::FindDeviceForValue(subgraph_session_state, subgraph_output_names[0]); - // The position_ids, attention_mask, past_0, ... are created by this operator so the name doesn't matter. feed_names.insert(feed_names.end(), subgraph_input_names.begin(), subgraph_input_names.end()); const auto& subgraph_map = subgraph_session_state.GetOrtValueNameIdxMap(); @@ -174,13 +170,15 @@ Status Subgraph::GetParameters(const ONNX_NAMESPACE::TensorShapeProto* past_shap } // Logits shape is like (batch_size, seq_len, vocabulary_size) - ORT_RETURN_IF(logits_shape->dim_size() != 3, - "subgraph logits output is expected to have 3 dimension, got ", logits_shape->dim_size()); + if (logits_shape != nullptr) { + ORT_RETURN_IF(logits_shape->dim_size() != 3, + "subgraph logits output is expected to have 3 dimension, got ", logits_shape->dim_size()); - ORT_RETURN_IF(!logits_shape->dim(2).has_dim_value() || logits_shape->dim(2).dim_value() <= 0, - "subgraph past state dimension 2 shall have a positive value for vocabulary size"); + ORT_RETURN_IF(!logits_shape->dim(2).has_dim_value() || logits_shape->dim(2).dim_value() <= 0, + "subgraph past state dimension 2 shall have a positive value for vocabulary size"); - this->vocab_size = static_cast(logits_shape->dim(2).dim_value()); + this->vocab_size = static_cast(logits_shape->dim(2).dim_value()); + } return Status::OK(); } diff --git a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.cc b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.cc index 997beb198f450..09bce9828aa33 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.cc +++ b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.cc @@ -6,11 +6,12 @@ #include "core/framework/tensorprotoutils.h" #include "core/framework/utils.h" #include "core/providers/cpu/tensor/utils.h" -#include #include "contrib_ops/cpu/transformers/subgraph_t5_decoder.h" #include "contrib_ops/cpu/utils/dump_tensor.h" #include "contrib_ops/cpu/transformers/generation_device_helper.h" #include "contrib_ops/cpu/transformers/sequences.h" +#include +#include namespace onnxruntime { namespace contrib { @@ -20,9 +21,9 @@ namespace transformers { Inputs: input_ids: int32 (B, 1) - encoder_input_ids: int32 (B, encode_sequence_length) (optional) + encoder_input_ids: int32 (B, encode_sequence_length) (optional for old format; removed in new format) encoder_attention_mask: int32 (B, encode_sequence_length) - encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) (optional) + encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) (optional for old format; removed in new format) past_key_self_0: (B, num_heads, past_decode_sequence_length, head_size) past_value_self_0: (B, num_heads, past_decode_sequence_length, head_size) @@ -141,14 +142,23 @@ Status T5DecoderSubgraph::Validate(const std::vector& subgraph_i } // Create inputs for decoder from the following data sources: -// encoder feeds: encoder_input_ids, encoder_attention_mask, decoder_input_ids (with start tokens) -// encoder fetches: logits, -// encoder_hidden_states, -// present_key_self_0, present_value_self_0, ..., present_key_cross_0, present_value_cross_0, ... -// decoder_feeds: input_ids, -// encoder_attention_mask, -// encoder_hidden_states, -// present_key_self_0, present_value_self_0, ..., present_key_cross_0, present_value_cross_0, ... +// New format: +// encoder feeds: encoder_input_ids, encoder_attention_mask +// encoder fetches: present_key_cross_0, present_value_cross_0, ... +// decoder_feeds: input_ids, encoder_attention_mask, +// present_key_self_0, present_value_self_0, ..., +// present_key_cross_0, present_value_cross_0, ... +// past_seq_len (optional), num_beams (optional), cache_indirection (optional) +// +// Old format: +// encoder feeds: encoder_input_ids, encoder_attention_mask, decoder_input_ids (with start tokens) +// encoder fetches: logits, encoder_hidden_states, +// present_key_self_0, present_value_self_0, ..., +// present_key_cross_0, present_value_cross_0, ... +// decoder_feeds: input_ids, encoder_input_ids (optional), encoder_attention_mask, encoder_hidden_states (optional), +// present_key_self_0, present_value_self_0, ..., +// present_key_cross_0, present_value_cross_0, ... +// past_seq_len (optional), num_beams (optional), cache_indirection (optional) Status T5DecoderSubgraph::CreateInitialFeeds( AllocatorPtr cpu_allocator, gsl::span beam_next_tokens, @@ -162,8 +172,7 @@ Status T5DecoderSubgraph::CreateInitialFeeds( const GenerationDeviceHelper::ExpandBufferFunc& expand_buffer_float16_func, int num_beam, Stream* stream, - bool use_sequence_as_input_ids, - int cur_len, + bool copy_sequence_to_input_ids, transformers::Sequences& sequences, int past_present_share_buffer_max_seq_len, bool need_cache_indir, @@ -173,34 +182,30 @@ Status T5DecoderSubgraph::CreateInitialFeeds( // Allocate subgraph inputs from same device as inputs of encoder subgraph. AllocatorPtr allocator = session_state_->GetAllocator(encoder_feeds[0].Get().Location()); + int batch_beam_size = static_cast(encoder_fetches[0].Get().Shape()[0]) * num_beam; + // Copy beam next tokens in CPU to input_ids in provider device (CPU for CPU EP, or GPU for CUDA EP). - int batch_beam_size = static_cast(beam_next_tokens.size()); - int sequence_length = !use_sequence_as_input_ids ? 1 : cur_len; + int sequence_length = !copy_sequence_to_input_ids ? 1 : sequences.GetSequenceLength(); int64_t dims[] = {batch_beam_size, sequence_length}; TensorShape input_ids_shape(&dims[0], 2); OrtValue input_ids; Tensor::InitOrtValue(DataTypeImpl::GetType(), input_ids_shape, allocator, input_ids); - int32_t* input_ids_data = input_ids.GetMutable()->MutableData(); - AllocatorPtr buffer_allocator = std::make_shared(); - size_t total_size = static_cast(cur_len) * static_cast(batch_beam_size); - size_t total_size_bytes = total_size * sizeof(int); - auto seq_copy = IAllocator::MakeUniquePtr(buffer_allocator, total_size_bytes, false, stream); - int* seq_copy_ptr = seq_copy.get(); - - if (!use_sequence_as_input_ids_) { + + // Prepare data for input_ids. + if (!copy_sequence_to_input_ids) { // use next tokens for input_ids. ORT_RETURN_IF_ERROR(device_copy_int32_func( input_ids.GetMutable()->MutableDataAsSpan(), beam_next_tokens, stream, DeviceCopyDirection::hostToDevice)); - } else { + } else { // use whole sequences for input_ids. + int32_t* input_ids_data = input_ids.GetMutable()->MutableData(); if (use_cuda) { auto sequences_buffer = sequences.GetCurrentDeviceSequences(); for (int i = 0; i < batch_beam_size; i++) { - size_t batch_beam_stride = static_cast(i) * static_cast(sequences.GetMaxLength()); - int seq_size = sequences.GetSequenceLength(); - gsl::span sequence = sequences_buffer.subspan(batch_beam_stride, seq_size); - gsl::span temp_input(input_ids_data + static_cast(i) * seq_size, seq_size); + size_t offset = static_cast(i) * static_cast(sequences.GetMaxLength()); + gsl::span sequence = sequences_buffer.subspan(offset, sequence_length); + gsl::span temp_input(input_ids_data + static_cast(i) * sequence_length, sequence_length); ORT_RETURN_IF_ERROR(device_copy_int32_func( temp_input, sequence, @@ -208,12 +213,19 @@ Status T5DecoderSubgraph::CreateInitialFeeds( DeviceCopyDirection::deviceToDevice)); } } else { - const size_t cur_len_bytes = cur_len * sizeof(int); + size_t total_size = static_cast(sequence_length) * static_cast(batch_beam_size); + size_t total_size_bytes = total_size * sizeof(int); + AllocatorPtr buffer_allocator = std::make_shared(); + // TODO: not need extra buffer. Copy directly to input_ids_data instead like the user_cuda above. + auto seq_copy = IAllocator::MakeUniquePtr(buffer_allocator, total_size_bytes, false, stream); + int* seq_copy_ptr = seq_copy.get(); + + const size_t sequence_bytes = sequence_length * sizeof(int); for (int i = 0; i < batch_beam_size; i++) { gsl::span sequence = sequences.GetSequence(i); const int32_t* sequence_data = sequence.data(); - ptrdiff_t seq_index = static_cast(i) * cur_len; - memcpy(seq_copy_ptr + seq_index, sequence_data, cur_len_bytes); + ptrdiff_t seq_index = static_cast(i) * sequence_length; + memcpy(seq_copy_ptr + seq_index, sequence_data, sequence_bytes); } gsl::span temp_input(input_ids_data, total_size); gsl::span temp_sequence(seq_copy_ptr, total_size); @@ -227,9 +239,11 @@ Status T5DecoderSubgraph::CreateInitialFeeds( // The ordering is the same as used in Setup. decoder_feeds.reserve(static_cast(num_subgraph_inputs) + static_cast(num_implicit_inputs)); + + // input 0: input_ids decoder_feeds.push_back(input_ids); - if (has_encoder_input_ids_) { + if (has_encoder_input_ids_) { // encoder_input_ids is optional // The encoder_input_ids is copied from the first input of encoder. OrtValue expanded_encoder_input_ids; ORT_RETURN_IF_ERROR(expand_buffer_int32_func(stream, @@ -251,70 +265,66 @@ Status T5DecoderSubgraph::CreateInitialFeeds( expanded_decoder_attention_masks, false, 0 /*max_sequence_length*/)); - decoder_feeds.push_back(expanded_decoder_attention_masks); if (!past_present_share_buffer_) { past_present_share_buffer_max_seq_len = 0; } - // When first_past_input_index_ == 3, the encoder_hidden_states and past states are copied from the second output - // of encoder. - // When first_past_input_index_ == 2, the past states are copied from the second output of encoder. - // TODO - probably more robust to introduce a encoder_out/decoder_in mapping instead of relying on positions. - // What happens if encoder_hidden_states is present in the encoder_fetches but not in the decoder_feeds? - for (size_t j = static_cast(2) - has_hidden_state_; j < encoder_fetches.size(); j++) { - if (j == 1) { - ORT_RETURN_IF(has_hidden_state_ == false, "Invalid hidden_states expension: has_hidden_state_ == false"); - OrtValue expanded_hidden_states; - if (is_output_float16_) { - ORT_RETURN_IF_ERROR(expand_buffer_float16_func(stream, - encoder_fetches[j], - num_beam, - allocator, - expanded_hidden_states, - false, - 0 /*max_sequence_length*/)); - } else { - ORT_RETURN_IF_ERROR(expand_buffer_float_func(stream, - encoder_fetches[j], - num_beam, - allocator, - expanded_hidden_states, - false, - 0 /*max_sequence_length*/)); - } - decoder_feeds.push_back(expanded_hidden_states); - } else { +// macro to expand encoder outputs and append to decoder feeds. +#define ADD_DECODER_FEED(encoder_output, is_dynamic_kv_cache) \ + OrtValue expanded; \ + if (is_output_float16_) { \ + ORT_RETURN_IF_ERROR(expand_buffer_float16_func(stream, encoder_output, num_beam, allocator, expanded, false, \ + is_dynamic_kv_cache ? past_present_share_buffer_max_seq_len : 0)); \ + } else { \ + ORT_RETURN_IF_ERROR(expand_buffer_float_func(stream, encoder_output, num_beam, allocator, expanded, false, \ + is_dynamic_kv_cache ? past_present_share_buffer_max_seq_len : 0)); \ + } \ + decoder_feeds.push_back(expanded); + + // The encoder_hidden_states is copied from the second output of encoder. + if (has_hidden_state_) { + ADD_DECODER_FEED(encoder_fetches[1], false); + } + + // New format of encoder has only cross outputs. + bool is_new_format = (static_cast(encoder_fetches.size()) == 2 * num_layers); + if (is_new_format) { + for (int i = 0; i < 2 * num_layers; i++) { + // cross shape is (batch_size, num_heads, encode_sequence_length, head_size) + const TensorShape& cross_shape = encoder_fetches[0].Get().Shape(); + ORT_ENFORCE(cross_shape.NumDimensions() == 4); + + // Shape for kv cache: (batch_size * num_beam, num_heads, max_seq_len, head_size) + int64_t cache_dims[4] = {0}; + cross_shape.CopyDims(cache_dims, cross_shape.NumDimensions()); + cache_dims[0] *= num_beam; + cache_dims[2] = past_present_share_buffer_max_seq_len; + TensorShape expanded_shape(&cache_dims[0], cross_shape.NumDimensions()); + + MLDataType element_type = encoder_fetches[0].Get().DataType(); + OrtValue past; + Tensor::InitOrtValue(element_type, expanded_shape, allocator, past); + decoder_feeds.push_back(past); + } + + // Add cross inputs from encoder output. + for (size_t j = 0; j < encoder_fetches.size(); j++) { + ADD_DECODER_FEED(encoder_fetches[j], false); + } + } else { + // present_* output of encoder are added as decoder inputs. + for (size_t j = 2; j < encoder_fetches.size(); j++) { // past key/value for cross attention does not need to be initialized with max_seq_len since they are static. - bool use_max_seq_len = (j - first_past_input_index_) < 2 * static_cast(num_layers); - - OrtValue expanded_cache; - if (is_output_float16_) { - ORT_RETURN_IF_ERROR(expand_buffer_float16_func(stream, - encoder_fetches[j], - num_beam, - allocator, - expanded_cache, - false, - use_max_seq_len ? past_present_share_buffer_max_seq_len : 0)); - } else { - ORT_RETURN_IF_ERROR(expand_buffer_float_func(stream, - encoder_fetches[j], - num_beam, - allocator, - expanded_cache, - false, - use_max_seq_len ? past_present_share_buffer_max_seq_len : 0)); - } - decoder_feeds.push_back(expanded_cache); + bool is_dynamic_kv_cache = (j - first_past_input_index_) < 2 * static_cast(num_layers); + ADD_DECODER_FEED(encoder_fetches[j], is_dynamic_kv_cache); } } - // TODO: This part shares the similar logic with CreateInitialFeeds() in subgraph_gpt.cc. We should refactor it. if (past_present_share_buffer_) { - // Past sequence length feed - ORT_RETURN_IF_ERROR(AppendPastSequenceLength(decoder_feeds, cpu_allocator, 1)); + // Past sequence length set to 0 + ORT_RETURN_IF_ERROR(AppendPastSequenceLength(decoder_feeds, cpu_allocator, is_new_format ? 0 : 1)); // Add beam search specific inputs if (need_cache_indir) { const int64_t batch_size = static_cast(batch_beam_size / num_beam); diff --git a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.h b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.h index b5d727b67924c..87782d47cdbe1 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.h +++ b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_decoder.h @@ -45,7 +45,6 @@ class T5DecoderSubgraph : public Subgraph { int num_beam, Stream* stream, bool use_sequence_as_input_ids, - int cur_len, transformers::Sequences& sequences, int past_present_share_buffer_max_seq_len = -1, bool need_cache_indir = false, @@ -72,6 +71,10 @@ class T5DecoderSubgraph : public Subgraph { return use_sequence_as_input_ids_; } + inline bool UseEncoderHiddenState() const { + return has_hidden_state_; + } + protected: int first_past_input_index_; int first_present_output_index_; diff --git a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.cc b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.cc index d59db4afac2c2..a54c0d960980c 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.cc +++ b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.cc @@ -15,70 +15,97 @@ namespace transformers { /* T5 Encoder Subgraph (It also contains decoder initialization where decoder_input_ids are filled with start token ID). - Inputs: + New format: + Inputs: encoder_input_ids: int32 (B, encode_sequence_length) encoder_attention_mask: int32 (B, encode_sequence_length) - decoder_input_ids: int32 (B, 1) Outputs: - logits: (B, 1, vocab_size) - encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) - - present_key_self_0: (B, num_heads, 1, head_size) - present_value_self_0: (B, num_heads, 1, head_size) - ... (for each self attention layer) - present_key_cross_0: (B, num_heads, encode_sequence_length, head_size) present_value_cross_0: (B, num_heads, encode_sequence_length, head_size) ... (for each cross attention layer) - Note: - Here, B = batch_size * num_beams since we expand the inputs. - Ideally, we could use B=batch_size and expand the outputs with a factor of num_beams. - Data type of input or output is float or float16 if not specified. + Old format: + Inputs: + encoder_input_ids: int32 (B, encode_sequence_length) + encoder_attention_mask: int32 (B, encode_sequence_length) + decoder_input_ids: int32 (B, 1) + + Outputs: + logits: (B, 1, vocab_size) + encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) + + present_key_self_0: (B, num_heads, 1, head_size) + present_value_self_0: (B, num_heads, 1, head_size) + ... (for each self attention layer) + + present_key_cross_0: (B, num_heads, encode_sequence_length, head_size) + present_value_cross_0: (B, num_heads, encode_sequence_length, head_size) + ... (for each cross attention layer) + + Note: + Here, B = batch_size * num_beams since we expand the inputs. + Ideally, we could use B=batch_size and expand the outputs with a factor of num_beams. + Data type of input or output is float or float16 if not specified. */ Status T5EncoderSubgraph::Validate(const std::vector& subgraph_inputs, const std::vector& subgraph_outputs) { - ORT_RETURN_IF(num_subgraph_inputs != 3, "expect 3 inputs, got:", num_subgraph_inputs); - - ORT_RETURN_IF(num_subgraph_outputs < 6, "expect >=6 outputs, got:", num_subgraph_outputs); - ORT_RETURN_IF((static_cast(subgraph_outputs.size()) - first_present_output_index_) % 4 != 0, - "number of outputs expected to be 2 + 4 * layers, got:", num_subgraph_outputs); + constexpr auto int32_type = ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT32; + constexpr auto float32_type = ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_FLOAT; + constexpr auto float16_type = ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_FLOAT16; + ORT_RETURN_IF(num_subgraph_inputs != 2 && num_subgraph_inputs != 3, "expect 2 or 3 inputs, got:", num_subgraph_inputs); ORT_RETURN_IF(subgraph_inputs[0]->Name() != "encoder_input_ids", "encoder subgraph input 0 shall be named as encoder_input_ids, got: ", subgraph_inputs[0]->Name()); ORT_RETURN_IF(subgraph_inputs[1]->Name() != "encoder_attention_mask", "encoder subgraph input 1 shall be named as encoder_attention_mask, got: ", subgraph_inputs[1]->Name()); - ORT_RETURN_IF(subgraph_inputs[2]->Name() != "decoder_input_ids", - "encoder subgraph input 2 shall be named as decoder_input_ids, got: ", subgraph_inputs[2]->Name()); - - ORT_RETURN_IF(subgraph_outputs[0]->Name() != "logits", - "encoder subgraph output 0 shall be named as logits, got: ", subgraph_outputs[0]->Name()); - ORT_RETURN_IF(subgraph_outputs[1]->Name() != "encoder_hidden_states", - "encoder subgraph output 1 shall be named encoder_hidden_states, got: ", subgraph_outputs[1]->Name()); - ORT_RETURN_IF(subgraph_outputs[2]->Name() != "present_key_self_0", - "encoder subgraph output 2 shall be named as present_key_self_0, got: ", subgraph_outputs[2]->Name()); - ORT_RETURN_IF(subgraph_outputs[3]->Name() != "present_value_self_0", - "encoder subgraph output 3 shall be named as present_value_self_0, got: ", subgraph_outputs[3]->Name()); - - const ONNX_NAMESPACE::TensorShapeProto* past_shape = subgraph_outputs[2]->Shape(); - const ONNX_NAMESPACE::TensorShapeProto* logits_shape = subgraph_outputs[0]->Shape(); - - // Save parameters related to the subgraph. - ORT_RETURN_IF_ERROR(GetParameters(past_shape, logits_shape, false)); - num_layers = (static_cast(subgraph_outputs.size()) - first_present_output_index_) / 4; - - constexpr auto int32_type = ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT32; - constexpr auto float32_type = ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_FLOAT; - constexpr auto float16_type = ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_FLOAT16; ORT_RETURN_IF(subgraph_inputs[0]->TypeAsProto()->tensor_type().elem_type() != int32_type, "encoder subgraph input 0 (encoder_input_ids) shall have int32 type"); ORT_RETURN_IF(subgraph_inputs[1]->TypeAsProto()->tensor_type().elem_type() != int32_type, "encoder subgraph input 1 (encoder_attention_mask) shall have int32 type"); - ORT_RETURN_IF(subgraph_inputs[2]->TypeAsProto()->tensor_type().elem_type() != int32_type, - "encoder subgraph input 2 (decoder_input_ids) shall have int32 type"); + + if (num_subgraph_inputs == 2) { + ORT_RETURN_IF(num_subgraph_outputs < 2 || num_subgraph_outputs % 2 != 0, + "number of outputs expected to be 2 * layers, got:", num_subgraph_outputs); + + ORT_RETURN_IF(subgraph_outputs[0]->Name() != "present_key_cross_0", + "encoder subgraph output 0 shall be named as present_key_cross_0, got: ", subgraph_outputs[0]->Name()); + ORT_RETURN_IF(subgraph_outputs[1]->Name() != "present_value_cross_0", + "encoder subgraph output 1 shall be named as present_value_cross_0, got: ", subgraph_outputs[1]->Name()); + + // Deduce num_heads and head_size parameters from shape of graph outputs + const ONNX_NAMESPACE::TensorShapeProto* past_shape = subgraph_outputs[0]->Shape(); + const ONNX_NAMESPACE::TensorShapeProto* logits_shape = nullptr; + ORT_RETURN_IF_ERROR(GetParameters(past_shape, logits_shape, false)); + + num_layers = num_subgraph_outputs / 2; + } else { + ORT_RETURN_IF(num_subgraph_outputs < 6 || (num_subgraph_outputs - first_present_output_index_) % 4 != 0, + "number of outputs expected to be 2 + 4 * layers, got:", num_subgraph_outputs); + + ORT_RETURN_IF(subgraph_inputs[2]->Name() != "decoder_input_ids", + "encoder subgraph input 2 shall be named as decoder_input_ids, got: ", subgraph_inputs[2]->Name()); + ORT_RETURN_IF(subgraph_inputs[2]->TypeAsProto()->tensor_type().elem_type() != int32_type, + "encoder subgraph input 2 (decoder_input_ids) shall have int32 type"); + + ORT_RETURN_IF(subgraph_outputs[0]->Name() != "logits", + "encoder subgraph output 0 shall be named as logits, got: ", subgraph_outputs[0]->Name()); + ORT_RETURN_IF(subgraph_outputs[1]->Name() != "encoder_hidden_states", + "encoder subgraph output 1 shall be named encoder_hidden_states, got: ", subgraph_outputs[1]->Name()); + ORT_RETURN_IF(subgraph_outputs[2]->Name() != "present_key_self_0", + "encoder subgraph output 2 shall be named as present_key_self_0, got: ", subgraph_outputs[2]->Name()); + ORT_RETURN_IF(subgraph_outputs[3]->Name() != "present_value_self_0", + "encoder subgraph output 3 shall be named as present_value_self_0, got: ", subgraph_outputs[3]->Name()); + + // Deduce num_heads, head_size and vocab_size from shape of graph outputs + const ONNX_NAMESPACE::TensorShapeProto* past_shape = subgraph_outputs[2]->Shape(); + const ONNX_NAMESPACE::TensorShapeProto* logits_shape = subgraph_outputs[0]->Shape(); + ORT_RETURN_IF_ERROR(GetParameters(past_shape, logits_shape, false)); + + num_layers = (num_subgraph_outputs - first_present_output_index_) / 4; + } auto output_type = subgraph_outputs[0]->TypeAsProto()->tensor_type().elem_type(); ORT_RETURN_IF(output_type != float32_type && output_type != float16_type, @@ -86,7 +113,7 @@ Status T5EncoderSubgraph::Validate(const std::vector& subgraph_i for (int i = 1; i < num_subgraph_outputs; i++) { ORT_RETURN_IF(subgraph_outputs[i]->TypeAsProto()->tensor_type().elem_type() != output_type, - "encoder subgraph outputs 1, 2, ... shall have same data type"); + "encoder subgraph outputs shall have same data type"); } is_output_float16_ = (output_type == float16_type); @@ -120,7 +147,6 @@ Status T5EncoderSubgraph::CreateInitialFeeds( } ORT_RETURN_IF(cpu_allocator == nullptr, "cpu_allocator shouldn't be nullptr"); - // TODO(tianleiwu): expand the outputs instead of inputs to save computation. OrtValue encoder_input_ids; OrtValue encoder_attention_mask; ORT_RETURN_IF_ERROR(create_encoder_inputs_func(&original_encoder_input_ids, @@ -136,9 +162,10 @@ Status T5EncoderSubgraph::CreateInitialFeeds( AllocatorPtr default_allocator = session_state_->GetAllocator(provider->GetOrtDeviceByMemType(OrtMemTypeDefault)); AllocatorPtr pinned_allocator = session_state_->GetAllocator(provider->GetOrtDeviceByMemType(OrtMemTypeCPU)); const OrtMemoryInfo& location = default_allocator->Info(); + ORT_RETURN_IF_ERROR(add_to_feeds_func( ort_stream, - {encoder_input_ids, encoder_attention_mask, decoder_input_ids}, + num_subgraph_inputs == 2 ? std::initializer_list{encoder_input_ids, encoder_attention_mask} : std::initializer_list{encoder_input_ids, encoder_attention_mask, decoder_input_ids}, feeds, buffer, default_allocator, diff --git a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.h b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.h index a79f677f5a043..33fd522bdfd82 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.h +++ b/onnxruntime/contrib_ops/cpu/transformers/subgraph_t5_encoder.h @@ -16,7 +16,11 @@ class T5EncoderSubgraph : public Subgraph { const onnxruntime::Node& node_in, const std::string& attribute_name, const GraphViewer& subgraph_in) : Subgraph(node_in, attribute_name, subgraph_in) { - first_present_output_index_ = 2; + has_logits_output_ = num_subgraph_outputs > 0 && subgraph_output_names[0] == "logits"; + + // Old format: The first output is logits, the second one is encoder_hidden_states. + // New format: No logits and encoder_hidden_states. All outputs are cross. + first_present_output_index_ = HasLogitsOutput() ? 2 : 0; } // Create inputs for first inference of subgraph. @@ -36,11 +40,18 @@ class T5EncoderSubgraph : public Subgraph { Status Validate(const std::vector& subgraph_inputs, const std::vector& subgraph_outputs) override; +#ifdef DEBUG_GENERATION int GetFirstPresentOutputIndex() const { return first_present_output_index_; } +#endif + + bool HasLogitsOutput() const { + return has_logits_output_; + } protected: + bool has_logits_output_; int first_present_output_index_; }; diff --git a/onnxruntime/python/tools/transformers/benchmark_helper.py b/onnxruntime/python/tools/transformers/benchmark_helper.py index 2a210729112d7..3dd2c2ef945ec 100644 --- a/onnxruntime/python/tools/transformers/benchmark_helper.py +++ b/onnxruntime/python/tools/transformers/benchmark_helper.py @@ -88,61 +88,62 @@ def create_onnxruntime_session( enable_mlas_gemm_fastmath_arm64_bfloat16=False, provider_options={}, # map execution provider name to its option # noqa: B006 ): - session = None - try: - sess_options = onnxruntime.SessionOptions() + sess_options = onnxruntime.SessionOptions() - if enable_all_optimization: - sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_ALL - else: - sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_BASIC + if enable_all_optimization: + sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_ALL + else: + sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_BASIC - if enable_profiling: - sess_options.enable_profiling = True + if enable_profiling: + sess_options.enable_profiling = True - if num_threads > 0: - sess_options.intra_op_num_threads = num_threads - logger.debug(f"Session option: intra_op_num_threads={sess_options.intra_op_num_threads}") + if num_threads > 0: + sess_options.intra_op_num_threads = num_threads + logger.debug(f"Session option: intra_op_num_threads={sess_options.intra_op_num_threads}") - if verbose: - sess_options.log_severity_level = 0 - else: - sess_options.log_severity_level = 4 - - logger.debug(f"Create session for onnx model: {onnx_model_path}") - if use_gpu: - if provider == "dml": - providers = ["DmlExecutionProvider", "CPUExecutionProvider"] - elif provider == "rocm": - providers = ["ROCMExecutionProvider", "CPUExecutionProvider"] - elif provider == "migraphx": - providers = [ - "MIGraphXExecutionProvider", - "ROCMExecutionProvider", - "CPUExecutionProvider", - ] - elif provider == "cuda": - providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] - elif provider == "tensorrt": - providers = [ - "TensorrtExecutionProvider", - "CUDAExecutionProvider", - "CPUExecutionProvider", - ] - else: - providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] + if verbose: + sess_options.log_severity_level = 0 + else: + sess_options.log_severity_level = 4 + + if provider in onnxruntime.get_available_providers(): + providers = [provider] + elif use_gpu: + if provider == "dml": + providers = ["DmlExecutionProvider", "CPUExecutionProvider"] + elif provider == "rocm": + providers = ["ROCMExecutionProvider", "CPUExecutionProvider"] + elif provider == "migraphx": + providers = [ + "MIGraphXExecutionProvider", + "ROCMExecutionProvider", + "CPUExecutionProvider", + ] + elif provider == "cuda" or provider is None: + providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] + elif provider == "tensorrt": + providers = [ + "TensorrtExecutionProvider", + "CUDAExecutionProvider", + "CPUExecutionProvider", + ] else: - providers = ["CPUExecutionProvider"] + raise RuntimeError(f"The execution provider is not supported: {provider}") + else: + providers = ["CPUExecutionProvider"] - if provider_options: - providers = [(name, provider_options[name]) if name in provider_options else name for name in providers] + if provider_options: + providers = [(name, provider_options[name]) if name in provider_options else name for name in providers] - if enable_mlas_gemm_fastmath_arm64_bfloat16: - sess_options.add_session_config_entry("mlas.enable_gemm_fastmath_arm64_bfloat16", "1") + if enable_mlas_gemm_fastmath_arm64_bfloat16: + sess_options.add_session_config_entry("mlas.enable_gemm_fastmath_arm64_bfloat16", "1") + session = None + try: session = onnxruntime.InferenceSession(onnx_model_path, sess_options, providers=providers) except Exception: - logger.error("Exception", exc_info=True) # noqa: G201 + logger.exception(f"Failed to create session for {onnx_model_path} with providers={providers}") return session diff --git a/onnxruntime/python/tools/transformers/convert_generation.py b/onnxruntime/python/tools/transformers/convert_generation.py index 045910ea20828..8eb2afb3db896 100644 --- a/onnxruntime/python/tools/transformers/convert_generation.py +++ b/onnxruntime/python/tools/transformers/convert_generation.py @@ -16,19 +16,17 @@ python convert_generation.py -m gpt2 --output gpt2_beam_search.onnx --use_gpu -p fp16 --use_sln_strict_mode Example 4: convert T5 model with beam search in two steps: - cd ./models/t5 - python convert_to_onnx.py -m t5-small - cd ../.. - python convert_generation.py -m t5-small --model_type t5 \ - --decoder_onnx ./models/t5/onnx_models/t5-small_decoder.onnx \ - --encoder_decoder_init_onnx ./models/t5/onnx_models/t5-small_encoder_decoder_init.onnx \ - --output ./models/t5/onnx_models/t5_small_beam_search.onnx + python -m models.t5.convert_to_onnx -m t5-small + python convert_generation.py -m t5-small --model_type t5 \ + --decoder_onnx ./onnx_models/t5-small_decoder.onnx \ + --encoder_decoder_init_onnx ./onnx_models/t5-small_encoder.onnx \ + --output ./onnx_models/t5_small_beam_search.onnx Example 5: convert T5 model with beam search. All in one step: - python convert_generation.py -m t5-small --model_type t5 --output ./models/t5/onnx_models/t5_small_beam_search.onnx + python convert_generation.py -m t5-small --model_type t5 --output t5_small_beam_search.onnx Example 6: convert T5 model with beam search containing specific cuda optimizations. All in one step: - python convert_generation.py -m t5-small --model_type t5 --output ./models/t5/onnx_models/t5_small_beam_search.onnx \ + python convert_generation.py -m t5-small --model_type t5 --output t5_small_beam_search.onnx \ --use_gpu --past_present_share_buffer --use_decoder_masked_attention Example 7: convert MT5 model with external data file like mt5-base-beamsearch.onnx.data in below example. @@ -68,11 +66,23 @@ T5Tokenizer, ) -from onnxruntime import GraphOptimizationLevel, InferenceSession, SessionOptions, get_available_providers -from onnxruntime.transformers.models.gpt2.convert_to_onnx import main as convert_gpt2_to_onnx +from onnxruntime import ( + GraphOptimizationLevel, + InferenceSession, + SessionOptions, + get_available_providers, +) +from onnxruntime.transformers.models.gpt2.convert_to_onnx import ( + main as convert_gpt2_to_onnx, +) from onnxruntime.transformers.models.gpt2.gpt2_helper import PRETRAINED_GPT2_MODELS -from onnxruntime.transformers.models.t5.convert_to_onnx import export_onnx_models as export_t5_onnx_models -from onnxruntime.transformers.models.t5.t5_helper import PRETRAINED_MT5_MODELS, PRETRAINED_T5_MODELS +from onnxruntime.transformers.models.t5.convert_to_onnx import ( + export_onnx_models as export_t5_onnx_models, +) +from onnxruntime.transformers.models.t5.t5_helper import ( + PRETRAINED_MT5_MODELS, + PRETRAINED_T5_MODELS, +) logger = logging.getLogger("") @@ -162,9 +172,9 @@ def parse_arguments(argv: list[str] | None = None) -> argparse.Namespace: "-p", "--precision", required=False, - type=Precision, - default=Precision.FLOAT32, - choices=[Precision.FLOAT32, Precision.FLOAT16], + type=str, + default=Precision.FLOAT32.value, + choices=[Precision.FLOAT32.value, Precision.FLOAT16.value], help="Precision of model to run. fp32 for full precision, fp16 for half or mixed precision", ) @@ -189,7 +199,11 @@ def parse_arguments(argv: list[str] | None = None) -> argparse.Namespace: output_group.set_defaults(use_external_data_format=False) output_group.add_argument( - "-s", "--run_shape_inference", required=False, action="store_true", help="run shape inference" + "-s", + "--run_shape_inference", + required=False, + action="store_true", + help="run shape inference", ) output_group.set_defaults(run_shape_inference=False) @@ -223,6 +237,14 @@ def parse_arguments(argv: list[str] | None = None) -> argparse.Namespace: ) output_group.set_defaults(disable_shared_initializers=False) + output_group.add_argument( + "--encoder_decoder_init", + required=False, + action="store_true", + help="Add decoder initialization to encoder for T5 model. This is legacy format that will be deprecated.", + ) + output_group.set_defaults(encoder_decoder_init=False) + model_group = parser.add_argument_group("Beam search parameters that stored in the output model") model_group.add_argument( @@ -426,7 +448,10 @@ def parse_arguments(argv: list[str] | None = None) -> argparse.Namespace: test_group.set_defaults(use_sln_strict_mode=False) test_group.add_argument( - "--use_gpu", required=False, action="store_true", help="use GPU for inference. Required for fp16." + "--use_gpu", + required=False, + action="store_true", + help="use GPU for inference. Required for fp16.", ) test_group.set_defaults(use_gpu=False) @@ -490,7 +515,7 @@ def gpt2_to_onnx(args: argparse.Namespace): args.decoder_onnx, "--optimize_onnx", "--precision", - "fp32" if args.precision == Precision.FLOAT32 else "fp16", + args.precision, "--test_runs", "1", "--test_cases", @@ -508,7 +533,7 @@ def gpt2_to_onnx(args: argparse.Namespace): arguments.extend(["--op_block_list"]) arguments.extend(args.op_block_list) - if args.precision == Precision.FLOAT16: + if args.precision == Precision.FLOAT16.value: assert args.use_gpu, "fp16 or mixed precision model cannot run in CPU. Please add --use_gpu" # TODO(tianleiwu): Use auto mixed precision for fp16 conversion: arguments.append('--auto_mixed_precision') # Need change cuda kernel to support a combination of fp32 logits and fp16 past state. @@ -527,20 +552,21 @@ def t5_to_onnx(args: argparse.Namespace): args (argparse.Namespace): arguments parsed from command line """ paths = export_t5_onnx_models( - args.model_name_or_path, - args.cache_dir, - Path(args.output).parent, + model_name_or_path=args.model_name_or_path, + cache_dir=args.cache_dir, + output_dir=Path(args.output).parent, use_gpu=args.use_gpu, use_external_data_format=args.use_external_data_format, - optimize_onnx=(args.precision != Precision.FLOAT16), + optimize_onnx=(args.precision != Precision.FLOAT16.value), precision=args.precision, verbose=False, use_decoder_start_token=False, - merge_encoder_and_decoder_init=True, overwrite=True, disable_auto_mixed_precision=False, use_int32_inputs=True, model_type=args.model_type, + encoder_decoder_init=args.encoder_decoder_init, + force_fp16_io=(args.precision == Precision.FLOAT16.value), # required by BeamSearch op implementation. ) logger.debug(f"onnx model for encoder: {paths[0]}") @@ -693,7 +719,7 @@ def verify_gpt2_subgraph(graph: onnx.GraphProto, precision: Precision): ValueError: Output name is not expected. ValueError: Output data type is not expected. """ - is_float16 = precision == Precision.FLOAT16 + is_float16 = precision == Precision.FLOAT16.value input_count = len(graph.input) layer_count = input_count - 3 @@ -749,7 +775,7 @@ def verify_t5_decoder_subgraph(graph: onnx.GraphProto, precision: Precision): ValueError: Output name is not expected. ValueError: Output data type is not expected. """ - is_float16 = precision == Precision.FLOAT16 + is_float16 = precision == Precision.FLOAT16.value float_type = TensorProto.FLOAT16 if is_float16 else TensorProto.FLOAT input_count = len(graph.input) @@ -825,15 +851,20 @@ def verify_t5_encoder_decoder_init_subgraph(graph: onnx.GraphProto, precision: P ValueError: Output name is not expected. ValueError: Output data type is not expected. """ - is_float16 = precision == Precision.FLOAT16 - layer_count = (len(graph.output) - 2) // 4 - assert layer_count >= 1 + is_float16 = precision == Precision.FLOAT16.value + new_format = "cross" in graph.output[0].name # Expect 3 inputs: # encoder_input_ids: int32 (B, encode_sequence_length) # encoder_attention_mask: int32 (B, encode_sequence_length) # decoder_input_ids: int32 (B, 1) - expected_inputs = ["encoder_input_ids", "encoder_attention_mask", "decoder_input_ids"] + expected_inputs = [ + "encoder_input_ids", + "encoder_attention_mask", + "decoder_input_ids", + ] + if new_format: + expected_inputs = expected_inputs[:2] if len(graph.input) != len(expected_inputs): raise ValueError(f"Number of inputs expected to be {len(expected_inputs)}. Got {len(graph.input)}") @@ -846,22 +877,41 @@ def verify_t5_encoder_decoder_init_subgraph(graph: onnx.GraphProto, precision: P if input_type != expected_type: raise ValueError(f"Input {i} is expected to have onnx data type {expected_type}. Got {input_type}") - # Expected outputs: - # logits: (B, 1, vocab_size) - # encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) - # present_key_self_0: (B, num_heads, 1, head_size) - # present_value_self_0: (B, num_heads, 1, head_size) - # ... (for each self attention layer) - # present_key_cross_0: (B, num_heads, encode_sequence_length, head_size) - # present_value_cross_0: (B, num_heads, encode_sequence_length, head_size) - # ... (for each cross attention layer) - expected_outputs = ["logits", "encoder_hidden_states"] - for i in range(layer_count): - expected_outputs.append(f"present_key_self_{i}") - expected_outputs.append(f"present_value_self_{i}") - for i in range(layer_count): - expected_outputs.append(f"present_key_cross_{i}") - expected_outputs.append(f"present_value_cross_{i}") + if new_format: + assert len(graph.output) % 2 == 0 + layer_count = len(graph.output) // 2 + assert layer_count >= 1 + + # Expected outputs: + # present_key_cross_0: (B, num_heads, encode_sequence_length, head_size) + # present_value_cross_0: (B, num_heads, encode_sequence_length, head_size) + # ... (for each cross attention layer) + expected_outputs = [] + for i in range(layer_count): + expected_outputs.append(f"present_key_cross_{i}") + expected_outputs.append(f"present_value_cross_{i}") + else: + logger.warning("This format is deprecated. Please export T5 encoder in new format with only cross outputs.") + assert (len(graph.output) - 2) % 4 == 0 + layer_count = (len(graph.output) - 2) // 4 + assert layer_count >= 1 + + # Expected outputs: + # logits: (B, 1, vocab_size) + # encoder_hidden_states: (B, encode_sequence_length, encoder_hidden_size) + # present_key_self_0: (B, num_heads, 1, head_size) + # present_value_self_0: (B, num_heads, 1, head_size) + # ... (for each self attention layer) + # present_key_cross_0: (B, num_heads, encode_sequence_length, head_size) + # present_value_cross_0: (B, num_heads, encode_sequence_length, head_size) + # ... (for each cross attention layer) + expected_outputs = ["logits", "encoder_hidden_states"] + for i in range(layer_count): + expected_outputs.append(f"present_key_self_{i}") + expected_outputs.append(f"present_value_self_{i}") + for i in range(layer_count): + expected_outputs.append(f"present_key_cross_{i}") + expected_outputs.append(f"present_value_cross_{i}") if len(graph.output) != len(expected_outputs): raise ValueError(f"Number of outputs expected to be {len(expected_outputs)}. Got {len(graph.output)}") @@ -1116,6 +1166,7 @@ def update_decoder_subgraph_past_present_share_buffer(subg: GraphProto): new_nodes = [] for node in subg.node: + new_node = node if node.op_type == "Attention": kwargs = kwargs_of(node) kwargs.update({"past_present_share_buffer": 1}) @@ -1125,8 +1176,8 @@ def update_decoder_subgraph_past_present_share_buffer(subg: GraphProto): nis.extend([""]) if len(nis) < 7: nis.extend(["past_sequence_length"]) - node = onnx.helper.make_node("Attention", nis, node.output, name=node.name, **kwargs) # noqa: PLW2901 - new_nodes.extend([node]) + new_node = onnx.helper.make_node("Attention", nis, node.output, name=node.name, **kwargs) + new_nodes.extend([new_node]) subg.ClearField("node") subg.node.extend(new_nodes) return subg @@ -1152,7 +1203,9 @@ def update_decoder_subgraph_use_decoder_masked_attention( new_inputs.extend( [ onnx.helper.make_tensor_value_info( - "cache_indirection", onnx.TensorProto.INT32, shape=["batch_size", "beam_width", "max_seq_len"] + "cache_indirection", + onnx.TensorProto.INT32, + shape=["batch_size", "beam_width", "max_seq_len"], ) ] ) @@ -1203,7 +1256,11 @@ def update_decoder_subgraph_use_decoder_masked_attention( nis.extend(["cache_indirection"]) node = onnx.helper.make_node( # noqa: PLW2901 - "DecoderMaskedSelfAttention", nis, node.output, name=node.name, **kwargs + "DecoderMaskedSelfAttention", + nis, + node.output, + name=node.name, + **kwargs, ) new_nodes.extend([node]) subg.ClearField("node") @@ -1573,7 +1630,11 @@ def replace_mha_with_dmmha(model: OnnxModel, past_seq_len_name: str): def replace_mha_with_gqa( - model: OnnxModel, attn_mask: str, kv_num_heads: int = 0, world_size: int = 1, window_size: int = -1 + model: OnnxModel, + attn_mask: str, + kv_num_heads: int = 0, + world_size: int = 1, + window_size: int = -1, ): # Insert attention_mask subgraph to calculate shared inputs for all GroupQueryAttention nodes # @@ -1635,7 +1696,14 @@ def replace_mha_with_gqa( to=TensorProto.INT32, ) model.model.graph.node.extend( - [reduce_sum_node, sub_node, seqlen_k_cast_node, shape_node, gather_node, total_seqlen_cast_node] + [ + reduce_sum_node, + sub_node, + seqlen_k_cast_node, + shape_node, + gather_node, + total_seqlen_cast_node, + ] ) # Replace MultiHeadAttention with GroupQueryAttention @@ -1776,14 +1844,14 @@ def replace_mha_with_gqa( node.input[7], # past_value seqlen_k_cast_node.output[0], # seqlens_k (for attention mask) total_seqlen_cast_node.output[0], # total_seq_len (for attention mask) - q_rotary.input[2] if q_rotary is not None else "", # cos_cache (for rotary embeddings) - q_rotary.input[3] if q_rotary is not None else "", # sin_cache (for rotary embeddings) + (q_rotary.input[2] if q_rotary is not None else ""), # cos_cache (for rotary embeddings) + (q_rotary.input[3] if q_rotary is not None else ""), # sin_cache (for rotary embeddings) ], outputs=node.output, name=node.name.replace("MultiHeadAttention", "GroupQueryAttention"), domain="com.microsoft", num_heads=num_heads // world_size, - kv_num_heads=num_heads // world_size if kv_num_heads == 0 else kv_num_heads // world_size, + kv_num_heads=(num_heads // world_size if kv_num_heads == 0 else kv_num_heads // world_size), local_window_size=window_size, do_rotary=int(q_rotary is not None and k_rotary is not None), rotary_interleaved=interleaved, @@ -1831,7 +1899,9 @@ def update_decoder_subgraph_output_cross_attention(subg: GraphProto): node.attribute.extend([onnx.helper.make_attribute("output_qk", 1)]) cross_attention = onnx.helper.make_tensor_value_info( - cross_attention_out_name, TensorProto.FLOAT, [batch_size_dim, num_heads_dim, 1, cross_seq_len_dim] + cross_attention_out_name, + TensorProto.FLOAT, + [batch_size_dim, num_heads_dim, 1, cross_seq_len_dim], ) subg.output.extend([cross_attention]) if num_layer_output_qk != num_layers: @@ -1935,7 +2005,11 @@ def update_decoder_subgraph_share_buffer_and_use_decoder_masked_mha(subg: ModelP kwargs["past_present_share_buffer"] = 1 node = onnx.helper.make_node( # noqa: PLW2901 - "DecoderMaskedMultiHeadAttention", nis, node.output, name=node.name, **kwargs + "DecoderMaskedMultiHeadAttention", + nis, + node.output, + name=node.name, + **kwargs, ) if node not in nodes_to_remove: @@ -1968,7 +2042,9 @@ def update_decoder_subgraph_share_buffer_and_use_decoder_masked_mha(subg: ModelP new_inputs.extend( [ onnx.helper.make_tensor_value_info( - "cache_indirection", onnx.TensorProto.INT32, shape=["batch_size", "beam_width", "max_seq_len"] + "cache_indirection", + onnx.TensorProto.INT32, + shape=["batch_size", "beam_width", "max_seq_len"], ) ] ) @@ -2020,7 +2096,7 @@ def pack_qkv_for_decoder_masked_mha(model_proto: ModelProto): matmul_node_name = onnx_model.create_node_name("MatMul", name_prefix="MatMul_QKV") weight = onnx.helper.make_tensor( name=matmul_node_name + "_weight", - data_type=TensorProto.FLOAT if q_weight.data_type == 1 else TensorProto.FLOAT16, + data_type=(TensorProto.FLOAT if q_weight.data_type == 1 else TensorProto.FLOAT16), dims=[qkv_weight.shape[0], qkv_weight.shape[1]], vals=qkv_weight.flatten().tolist(), ) @@ -2074,12 +2150,18 @@ def update_input_shapes_for_gpt2_decoder_model(decoder_onnx_path: str, use_exter # Update dim_value to be 1 shape_dim_proto.dim_value = 1 - OnnxModel.save(decoder_model_proto, decoder_onnx_path, save_as_external_data=use_external_data_format) + OnnxModel.save( + decoder_model_proto, + decoder_onnx_path, + save_as_external_data=use_external_data_format, + ) return True def generate_gpt2_init_decoder( - decoder_onnx_path: str, init_decoder_onnx_path: str, use_external_data_format: bool = True + decoder_onnx_path: str, + init_decoder_onnx_path: str, + use_external_data_format: bool = True, ) -> bool: """Generates the initial decoder GPT2 subgraph and saves it for downstream use. The initial decoder model will be saved to init_decoder_onnx_path. @@ -2152,7 +2234,16 @@ def generate_gpt2_init_decoder( # Normalization Node is : LayerNormalization logits_matmul_to_residual_add_path = gpt2_init_decoder_model.match_parent_path( logits_matmul_node, - ["LayerNormalization", "Add", "Add", "MatMul", "FastGelu", "MatMul", "LayerNormalization", "Add"], + [ + "LayerNormalization", + "Add", + "Add", + "MatMul", + "FastGelu", + "MatMul", + "LayerNormalization", + "Add", + ], [0, 0, 1, 0, 0, 0, 0, 0], ) @@ -2183,7 +2274,9 @@ def generate_gpt2_init_decoder( if not is_skiplayernorm_path: residual_add_to_attention_parent_index = 0 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["Add", "Cast", "MatMul", "Attention"], [residual_add_to_attention_parent_index, 0, 0, 0] + residual_add_node, + ["Add", "Cast", "MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0, 0, 0], ) # Try other parent index of the residual Add node @@ -2199,42 +2292,54 @@ def generate_gpt2_init_decoder( if residual_add_to_attention_path is None: residual_add_to_attention_parent_index = 0 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["Add", "MatMul", "Attention"], [residual_add_to_attention_parent_index, 0, 0] + residual_add_node, + ["Add", "MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0, 0], ) # Try without the Casts before and after the MatMuls and other parent index of the residual Add node if residual_add_to_attention_path is None: residual_add_to_attention_parent_index = 1 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["Add", "MatMul", "Attention"], [residual_add_to_attention_parent_index, 0, 0] + residual_add_node, + ["Add", "MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0, 0], ) # SkipLayerNormalization path else: residual_add_to_attention_parent_index = 0 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["Cast", "MatMul", "Attention"], [residual_add_to_attention_parent_index, 0, 0] + residual_add_node, + ["Cast", "MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0, 0], ) # Try other parent index of the residual Add node if residual_add_to_attention_path is None: residual_add_to_attention_parent_index = 1 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["Cast", "MatMul", "Attention"], [residual_add_to_attention_parent_index, 0, 0] + residual_add_node, + ["Cast", "MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0, 0], ) # Try without the Casts before and after the MatMuls if residual_add_to_attention_path is None: residual_add_to_attention_parent_index = 0 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["MatMul", "Attention"], [residual_add_to_attention_parent_index, 0] + residual_add_node, + ["MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0], ) # Try without the Casts before and after the MatMuls and other parent index of the residual Add node if residual_add_to_attention_path is None: residual_add_to_attention_parent_index = 1 residual_add_to_attention_path = gpt2_init_decoder_model.match_parent_path( - residual_add_node, ["MatMul", "Attention"], [residual_add_to_attention_parent_index, 0] + residual_add_node, + ["MatMul", "Attention"], + [residual_add_to_attention_parent_index, 0], ) # TODO(hasesh): Are there more permutations to try before returning ? @@ -2252,7 +2357,9 @@ def generate_gpt2_init_decoder( # SkipLayerNormalization path else: add_before_residual_add = gpt2_init_decoder_model.match_parent( - residual_add_node, "SkipLayerNormalization", residual_add_to_add_parent_index + residual_add_node, + "SkipLayerNormalization", + residual_add_to_add_parent_index, ) if add_before_residual_add is None: @@ -2342,7 +2449,11 @@ def generate_gpt2_init_decoder( gpt2_init_decoder_model.topological_sort() # Save the init decoder model - OnnxModel.save(init_decoder_model_proto, init_decoder_onnx_path, save_as_external_data=use_external_data_format) + OnnxModel.save( + init_decoder_model_proto, + init_decoder_onnx_path, + save_as_external_data=use_external_data_format, + ) return True @@ -2383,7 +2494,10 @@ def make_dim_proto_numeric_t5(model, config): dim_proto.dim_value = dim_value -def convert_generation_model(args: argparse.Namespace, generation_type: GenerationType = GenerationType.BEAMSEARCH): +def convert_generation_model( + args: argparse.Namespace, + generation_type: GenerationType = GenerationType.BEAMSEARCH, +): """Convert model according to command line arguments. Args: @@ -2397,8 +2511,13 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati logger.info(f"**** past_present_share_buffer={past_present_share_buffer}") if len(args.op_block_list) == 1 and args.op_block_list[0] == "auto": - if is_gpt2 and args.precision == Precision.FLOAT16: - args.op_block_list = ["Add", "LayerNormalization", "SkipLayerNormalization", "FastGelu"] + if is_gpt2 and args.precision == Precision.FLOAT16.value: + args.op_block_list = [ + "Add", + "LayerNormalization", + "SkipLayerNormalization", + "FastGelu", + ] logger.info(f"**** Setting op_block_list to {args.op_block_list}") logger.info("**** use --op_block_list if you want to override the block operator list.") else: @@ -2434,9 +2553,7 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati logger.info(f"skip convert_to_onnx since path existed: {args.decoder_onnx}") else: if not args.decoder_onnx: - onnx_filename = "{}_past_{}.onnx".format( - args.model_name_or_path, "fp16" if args.precision == Precision.FLOAT16 else "fp32" - ) + onnx_filename = f"{args.model_name_or_path}_past_{args.precision}.onnx" args.decoder_onnx = Path(Path(args.output).parent, onnx_filename).as_posix() logger.info(f"Convert GPT model {args.model_name_or_path} to onnx {args.decoder_onnx} ...") @@ -2458,7 +2575,7 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati logits_matmul_weight_padded = False if ( not args.disable_pad_vocab_size - and args.precision == Precision.FLOAT16 + and args.precision == Precision.FLOAT16.value and is_gpt2 and (is_beamsearch or is_greedysearch or is_sampling) ): @@ -2481,14 +2598,14 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati ): logger.info(f"Creating an initial run GPT2 decoder from {args.decoder_onnx}. ") - gpt2_init_decoder_onnx_filename = "gpt2_init_past_{}.onnx".format( - "fp16" if args.precision == Precision.FLOAT16 else "fp32" - ) + gpt2_init_decoder_onnx_filename = f"gpt2_init_past_{args.precision}.onnx" gpt2_init_decoder_onnx_path = Path(Path(args.output).parent, gpt2_init_decoder_onnx_filename).as_posix() gpt2_init_decoder_generated = generate_gpt2_init_decoder( - args.decoder_onnx, gpt2_init_decoder_onnx_path, args.use_external_data_format + args.decoder_onnx, + gpt2_init_decoder_onnx_path, + args.use_external_data_format, ) if not gpt2_init_decoder_generated: @@ -2672,7 +2789,8 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati logger.info(f"Symbolic shape inference on {args.encoder_decoder_init_onnx}. The file will be overwritten.") shape_inference(args.encoder_decoder_init_onnx, args.use_external_data_format) encoder_model = onnx.load_model(args.encoder_decoder_init_onnx, load_external_data=True) - encoder_model.graph.name = f"{args.model_type} encoder and decoder init" + suffix = "encoder" if len(encoder_model.graph.input) == 2 else "encoder and decoder init" + encoder_model.graph.name = f"{args.model_type} {suffix}" verify_t5_encoder_decoder_init_subgraph(encoder_model.graph, args.precision) make_dim_proto_numeric_t5(encoder_model, config) @@ -2711,14 +2829,13 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati # ) # initializers.extend(moved_initializers) + assert config.decoder_start_token_id >= 0, "decoder_start_token_id should be >= 0" + node.attribute.extend( [ onnx.helper.make_attribute("encoder", encoder_model.graph), onnx.helper.make_attribute("decoder", decoder_model.graph), - onnx.helper.make_attribute( - "decoder_start_token_id", - config.decoder_start_token_id if len(encoder_model.graph.input) == 3 else -1, - ), + onnx.helper.make_attribute("decoder_start_token_id", config.decoder_start_token_id), ] ) else: @@ -2838,7 +2955,9 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati if args.output_sequences_scores: sequences_scores = onnx.helper.make_tensor_value_info( - "sequences_scores", TensorProto.FLOAT, ["batch_size", "num_return_sequences"] + "sequences_scores", + TensorProto.FLOAT, + ["batch_size", "num_return_sequences"], ) graph_outputs.append(sequences_scores) @@ -2852,7 +2971,7 @@ def convert_generation_model(args: argparse.Namespace, generation_type: Generati new_graph = onnx.helper.make_graph( [node], - f"{args.model_type} beam search" if not is_greedysearch else f"{args.model_type} greedy search", + (f"{args.model_type} beam search" if not is_greedysearch else f"{args.model_type} greedy search"), graph_inputs, graph_outputs, initializers, @@ -2912,7 +3031,7 @@ def test_torch_performance( if args.use_gpu and not torch.cuda.is_available(): raise RuntimeError("Please install PyTorch with Cuda for testing gpu performance.") - if args.precision == Precision.FLOAT16: + if args.precision == Precision.FLOAT16.value: model.half() device = torch.device("cuda:0" if args.use_gpu else "cpu") @@ -2961,7 +3080,11 @@ def create_attention_mask(input_ids, pad_token_id): return attention_mask -def test_gpt_model(args: argparse.Namespace, sentences: list[str] | None = None, is_greedy: bool = False): +def test_gpt_model( + args: argparse.Namespace, + sentences: list[str] | None = None, + is_greedy: bool = False, +): """Test GPT-2 model Args: @@ -3152,7 +3275,7 @@ def test_gpt_model(args: argparse.Namespace, sentences: list[str] | None = None, print("-" * 50) # Compare the generated text instead of word IDs since ORT pads to max sequence length but Torch not. is_same = torch_decoded_sequences == ort_decoded_sequences - print("Torch and ORT result is ", "same" if is_same else "different") + print("Torch and ORT result is", "same" if is_same else "different") output["parity"] = is_same if args.torch_performance: diff --git a/onnxruntime/python/tools/transformers/fusion_simplified_layernorm.py b/onnxruntime/python/tools/transformers/fusion_simplified_layernorm.py index a0eff081675fe..5ce089712ccb1 100644 --- a/onnxruntime/python/tools/transformers/fusion_simplified_layernorm.py +++ b/onnxruntime/python/tools/transformers/fusion_simplified_layernorm.py @@ -51,6 +51,7 @@ def fuse(self, node, input_name_to_nodes: dict, output_name_to_node: dict): mul_node, div_node, _sqrt_node, add_node, reduce_mean_node = sim_ln_nodes if not self.model.has_constant_input(div_node, 1.0): return + node_parent = mul_node else: # Div(1, RMS) can also be represented as Reciprocal(RMS) like # @@ -66,6 +67,7 @@ def fuse(self, node, input_name_to_nodes: dict, output_name_to_node: dict): # Mul --> ReduceMean --> Add ---> Sqrt --> Reciprocal --> Mul --> Mul (node) # (B=2) (A/B=eps) (A/B=scale) # + return_indice = [] sim_ln_nodes = self.model.match_parent_path( node, ["Mul", "Reciprocal", "Sqrt", "Add", "ReduceMean"], @@ -73,24 +75,50 @@ def fuse(self, node, input_name_to_nodes: dict, output_name_to_node: dict): output_name_to_node=output_name_to_node, return_indice=return_indice, ) - if sim_ln_nodes is None: - return - mul_node, _reciprocal_node, _sqrt_node, add_node, reduce_mean_node = sim_ln_nodes - - pow_or_mul_node = self.model.get_parent(reduce_mean_node, 0, output_name_to_node) - if pow_or_mul_node is None or pow_or_mul_node.op_type not in ["Pow", "Mul"]: + if sim_ln_nodes is not None: + mul_node, _reciprocal_node, _sqrt_node, add_node, reduce_mean_node = sim_ln_nodes + node_parent = mul_node + else: + # (root_input) --------------------------------+ + # | | + # v v + # Pow --> ReduceMean --> Add ---> Sqrt --> Div --> Mul (node) + # (B=2) (A/B=eps) (A/B=scale) + # + # (root_input) --------------------------------+ + # | | | + # v v v + # Mul --> ReduceMean --> Add ---> Sqrt --> Div --> Mul (node) + # (B=2) (A/B=eps) (A/B=scale) + # + return_indice = [] + sim_ln_nodes = self.model.match_parent_path( + node, + ["Div", "Sqrt", "Add", "ReduceMean"], + [None, 1, 0, None], + output_name_to_node=output_name_to_node, + return_indice=return_indice, + ) + if sim_ln_nodes is not None: + div_node, _sqrt_node, add_node, reduce_mean_node = sim_ln_nodes + node_parent = div_node + else: + return + + reduce_mean_parent = self.model.get_parent(reduce_mean_node, 0, output_name_to_node) + if reduce_mean_parent is None or reduce_mean_parent.op_type not in ["Pow", "Mul"]: return - if pow_or_mul_node.op_type == "Pow": - if self.model.find_constant_input(pow_or_mul_node, 2.0) != 1: + if reduce_mean_parent.op_type == "Pow": + if self.model.find_constant_input(reduce_mean_parent, 2.0) != 1: return else: - assert pow_or_mul_node.op_type == "Mul" - if pow_or_mul_node[0] != pow_or_mul_node[1]: + assert reduce_mean_parent.op_type == "Mul" + if reduce_mean_parent[0] != reduce_mean_parent[1]: return - root_input = pow_or_mul_node.input[0] - if root_input != mul_node.input[0]: + root_input = reduce_mean_parent.input[0] + if root_input not in node_parent.input: return _i, epsilon = self.model.get_constant_input(add_node) @@ -113,7 +141,7 @@ def fuse(self, node, input_name_to_nodes: dict, output_name_to_node: dict): return self.nodes_to_remove.extend(sim_ln_nodes) - self.nodes_to_remove.append(pow_or_mul_node) + self.nodes_to_remove.append(reduce_mean_parent) self.nodes_to_remove.append(node) normalize_node = helper.make_node( diff --git a/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py b/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py index 75887cc744081..f8b7dd80710ae 100644 --- a/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py +++ b/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py @@ -371,9 +371,6 @@ def main(argv=None, experiment_name: str = "", run_id: str = "0", csv_filename: model_size_in_MB = int(get_onnx_model_size(output_path, args.use_external_data_format) / 1024 / 1024) # noqa: N806 provider = args.provider - if args.provider == "migraphx": - provider = "MIGraphXExecutionProvider" - session = create_onnxruntime_session( output_path, args.use_gpu, provider, enable_all_optimization=True, verbose=args.verbose ) diff --git a/onnxruntime/python/tools/transformers/models/t5/convert_to_onnx.py b/onnxruntime/python/tools/transformers/models/t5/convert_to_onnx.py index adf5206be8353..dd519e36cfa88 100755 --- a/onnxruntime/python/tools/transformers/models/t5/convert_to_onnx.py +++ b/onnxruntime/python/tools/transformers/models/t5/convert_to_onnx.py @@ -10,8 +10,15 @@ import os import torch -from benchmark_helper import Precision, create_onnxruntime_session, prepare_environment, setup_logger +from benchmark_helper import ( + Precision, + create_onnxruntime_session, + prepare_environment, + setup_logger, +) +from onnx.shape_inference import infer_shapes_path from t5_helper import PRETRAINED_MT5_MODELS, PRETRAINED_T5_MODELS, T5Helper +from transformers import MT5Config, T5Config logger = logging.getLogger("") @@ -70,9 +77,9 @@ def parse_arguments(): "-p", "--precision", required=False, - type=Precision, - default=Precision.FLOAT32, - choices=[Precision.FLOAT32, Precision.FLOAT16], + type=str, + default=Precision.FLOAT32.value, + choices=[Precision.FLOAT32.value, Precision.FLOAT16.value], help="Precision of model to run. fp32 for full precision, fp16 for half precision", ) @@ -104,17 +111,17 @@ def parse_arguments(): "--disable_auto_mixed_precision", required=False, action="store_true", - help="use pure fp16 instead of mixed precision", + help="do not use auto mixed precision conversion", ) parser.set_defaults(disable_auto_mixed_precision=False) parser.add_argument( - "--separate_encoder_and_decoder_init", + "--force_fp16_io", required=False, action="store_true", - help="Do not merge encode and decoder init. Output 3 instead of 2 onnx models.", + help="Force to convert all float inputs and outputs to fp16 when precision is fp16.", ) - parser.set_defaults(separate_encoder_and_decoder_init=False) + parser.set_defaults(force_fp16_io=False) parser.add_argument( "--use_int64_inputs", @@ -131,34 +138,52 @@ def parse_arguments(): help="filepath to load pre-trained model with custom state dictionary (e.g. pytorch_model.bin)", ) + parser.add_argument( + "--encoder_decoder_init", + required=False, + action="store_true", + help="Combine encoder and decoder kv cache initialization into one model. It is legacy format that will be deprecated.", + ) + parser.set_defaults(encoder_decoder_init=False) + args = parser.parse_args() return args def export_onnx_models( - model_name_or_path, - cache_dir, - output_dir, - use_gpu, - use_external_data_format, - optimize_onnx, - precision, - verbose, + model_name_or_path: str, + cache_dir: str, + output_dir: str, + use_gpu: bool = False, + use_external_data_format: bool = False, + optimize_onnx: bool = False, + precision: str = Precision.FLOAT32.value, + verbose: bool = False, use_decoder_start_token: bool = False, - merge_encoder_and_decoder_init: bool = True, overwrite: bool = False, disable_auto_mixed_precision: bool = False, use_int32_inputs: bool = True, model_type: str = "t5", state_dict_path: str = "", + encoder_decoder_init: bool = False, + force_fp16_io: bool = False, + shape_infer_before_optimization: bool = False, ): + assert precision in [Precision.FLOAT32.value, Precision.FLOAT16.value], ( + f"Invalid precision: {precision}. Use 'fp32' or 'fp16'." + ) device = torch.device("cuda:0" if use_gpu else "cpu") models = T5Helper.load_model( - model_name_or_path, cache_dir, device, merge_encoder_and_decoder_init, model_type, state_dict_path + model_name_or_path, + cache_dir, + device, + model_type, + state_dict_path, + encoder_decoder_init=encoder_decoder_init, ) - config = models["decoder"].config + config: T5Config | MT5Config = models["decoder"].config if (not use_external_data_format) and (config.num_layers > 24): logger.info("Try use_external_data_format when model size > 2GB") @@ -191,8 +216,20 @@ def export_onnx_models( else: logger.info(f"Skip exporting: existed ONNX model {onnx_path}") - # Optimize ONNX graph. Note that we have not implemented graph optimization for T5 yet. - if optimize_onnx or precision != Precision.FLOAT32: + # Optimize ONNX graph. + # The precision shall be compared with string value. It is because the Precision enum loaded from local file + # (like by transformers test in CI pipeline) are not same as Precision enum from package. + if optimize_onnx or precision != Precision.FLOAT32.value: + onnx_shape_path = None + if shape_infer_before_optimization: + onnx_shape_path = T5Helper.get_onnx_path( + output_dir, + model_name_or_path, + suffix=filename_suffix + "_shape", + new_folder=False, + ) + infer_shapes_path(onnx_path, onnx_shape_path) + output_path = T5Helper.get_onnx_path( output_dir, model_name_or_path, @@ -203,30 +240,35 @@ def export_onnx_models( if overwrite or not os.path.exists(output_path): logger.info(f"Optimizing model to {output_path}") T5Helper.optimize_onnx( - onnx_path, + onnx_shape_path or onnx_path, output_path, - precision == Precision.FLOAT16, + precision == Precision.FLOAT16.value, config.num_heads, config.hidden_size, use_external_data_format, auto_mixed_precision=not disable_auto_mixed_precision, use_gpu=use_gpu, + force_fp16_io=force_fp16_io, ) else: - logger.info(f"Skip optimizing: existed ONNX model {onnx_path}") + logger.info(f"Skip optimizing: existed ONNX model {output_path}") else: output_path = onnx_path ort_session = create_onnxruntime_session( output_path, use_gpu=use_gpu, - provider=["CUDAExecutionProvider", "CPUExecutionProvider"] if use_gpu else ["CPUExecutionProvider"], + verbose=verbose, ) + if ort_session is None: + break with torch.no_grad(): max_diff = T5Helper.verify_onnx(model, ort_session, device, use_int32_inputs) logger.info(f"PyTorch and OnnxRuntime results max difference = {max_diff}") - if max_diff > 1e-4: + + # The threshold cannot apply to fp16 model, which need a larger threshold. + if precision == Precision.FLOAT32.value and max_diff > 1e-4: logger.warning("PyTorch and OnnxRuntime results are NOT close") output_paths.append(output_path) @@ -245,15 +287,12 @@ def main(): output_dir = args.output if not args.output.endswith(".onnx") else os.path.dirname(args.output) prepare_environment(cache_dir, output_dir, args.use_gpu) - if args.precision != Precision.FLOAT32: + if args.precision != Precision.FLOAT32.value: assert args.optimize_onnx, "fp16/int8 requires --optimize_onnx" - if args.precision == Precision.FLOAT16: + if args.precision == Precision.FLOAT16.value: assert args.use_gpu, "fp16 requires --use_gpu" - if args.optimize_onnx: - logger.warning("Graph optimization for T5 is not implemented yet.") - output_paths = export_onnx_models( args.model_name_or_path, cache_dir, @@ -264,11 +303,12 @@ def main(): args.precision, args.verbose, args.use_decoder_start_token, - not args.separate_encoder_and_decoder_init, args.overwrite, args.disable_auto_mixed_precision, not args.use_int64_inputs, args.model_type, + encoder_decoder_init=args.encoder_decoder_init, + force_fp16_io=args.force_fp16_io, ) logger.info(f"Done! Outputs: {output_paths}") diff --git a/onnxruntime/python/tools/transformers/models/t5/t5_encoder.py b/onnxruntime/python/tools/transformers/models/t5/t5_encoder.py index c6b0f7ee3adc2..df3a416f2947c 100644 --- a/onnxruntime/python/tools/transformers/models/t5/t5_encoder.py +++ b/onnxruntime/python/tools/transformers/models/t5/t5_encoder.py @@ -1,24 +1,14 @@ # ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# ------------------------------------------------------------------------- import logging -import os import random -import tempfile -from pathlib import Path -import numpy -import onnx import torch -from onnx_model import OnnxModel -from torch_onnx_export_helper import torch_onnx_export from transformers import MT5Config, T5Config -from onnxruntime import InferenceSession - logger = logging.getLogger(__name__) @@ -41,7 +31,11 @@ def __init__(self, input_ids, attention_mask): @staticmethod def create_dummy( - batch_size: int, sequence_length: int, vocab_size: int, device: torch.device, use_int32_inputs: bool = False + batch_size: int, + sequence_length: int, + vocab_size: int, + device: torch.device, + use_int32_inputs: bool = False, ): # -> T5EncoderInputs """Create dummy inputs for T5 encoder. @@ -74,97 +68,3 @@ def create_dummy( def to_list(self) -> list: input_list = [v for v in [self.input_ids, self.attention_mask] if v is not None] return input_list - - -class T5EncoderHelper: - @staticmethod - def export_onnx( - encoder: T5Encoder, - device: torch.device, - onnx_model_path: str, - verbose: bool = True, - use_external_data_format: bool = False, - use_int32_inputs: bool = False, - ): - """Export encoder to ONNX - - Args: - encoder (T5Encoder): encoder object - device (torch.device): device of encoder object - onnx_model_path (str): onnx path - verbose (bool, optional): print verbose information. Defaults to True. - use_external_data_format (bool, optional): use external data format or not. Defaults to False. - """ - config = encoder.config - encoder_inputs = T5EncoderInputs.create_dummy( - batch_size=2, - sequence_length=4, - vocab_size=config.vocab_size, - device=device, - use_int32_inputs=use_int32_inputs, - ) - - Path(onnx_model_path).parent.mkdir(parents=True, exist_ok=True) - - with tempfile.TemporaryDirectory() as tmp_dir_name: - temp_onnx_model_path = os.path.join(tmp_dir_name, "encoder.onnx") - Path(temp_onnx_model_path).parent.mkdir(parents=True, exist_ok=True) - torch_onnx_export( - encoder, - args=tuple(encoder_inputs.to_list()), - f=temp_onnx_model_path if use_external_data_format else onnx_model_path, - export_params=True, - input_names=["input_ids", "attention_mask"], - output_names=["hidden_states"], - dynamic_axes={ - "input_ids": {0: "batch_size", 1: "sequence_length"}, - "attention_mask": {0: "batch_size", 1: "sequence_length"}, - "hidden_states": {0: "batch_size", 1: "sequence_length"}, - }, - opset_version=12, - do_constant_folding=True, - use_external_data_format=use_external_data_format, - verbose=verbose, - ) - - if use_external_data_format: - model = onnx.load_model(temp_onnx_model_path, load_external_data=True) - OnnxModel.save( - model, - onnx_model_path, - save_as_external_data=True, - all_tensors_to_one_file=True, - ) - - @staticmethod - def onnxruntime_inference(ort_session, inputs: T5EncoderInputs): - """Run inference of ONNX model.""" - ort_inputs = { - "input_ids": numpy.ascontiguousarray(inputs.input_ids.cpu().numpy()), - "attention_mask": numpy.ascontiguousarray(inputs.attention_mask.cpu().numpy()), - } - - return ort_session.run(None, ort_inputs) - - @staticmethod - def verify_onnx( - model: T5Encoder, ort_session: InferenceSession, device: torch.device, use_int32_inputs: bool = False - ): - """Compare the result from PyTorch and OnnxRuntime to verify the ONNX model is good.""" - inputs = T5EncoderInputs.create_dummy( - batch_size=4, - sequence_length=11, - vocab_size=model.config.vocab_size, - device=device, - use_int32_inputs=use_int32_inputs, - ) - input_list = inputs.to_list() - torch_outputs = model(*input_list) - - ort_outputs = T5EncoderHelper.onnxruntime_inference(ort_session, inputs) - - max_diff = numpy.amax(numpy.abs(torch_outputs.cpu().numpy() - ort_outputs[0])) - - logger.info(f"max_diff={max_diff}") - - return max_diff diff --git a/onnxruntime/python/tools/transformers/models/t5/t5_encoder_decoder_init.py b/onnxruntime/python/tools/transformers/models/t5/t5_encoder_decoder_init.py index c76d7aabdf11a..98df18eab6064 100644 --- a/onnxruntime/python/tools/transformers/models/t5/t5_encoder_decoder_init.py +++ b/onnxruntime/python/tools/transformers/models/t5/t5_encoder_decoder_init.py @@ -1,8 +1,7 @@ # ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# ------------------------------------------------------------------------- import logging import os @@ -31,33 +30,40 @@ def __init__( self, encoder: torch.nn.Module, decoder: torch.nn.Module, - lm_head: torch.nn.Module, + lm_head: torch.nn.Linear, config: T5Config | MT5Config, decoder_start_token_id: int | None = None, + output_cross_only: bool = False, ): super().__init__() - self.config = config + self.config: T5Config | MT5Config = config self.t5_encoder = T5Encoder(encoder, config) self.t5_decoder_init = T5DecoderInit(decoder, lm_head, config, decoder_start_token_id) + self.output_cross_only = output_cross_only def forward( self, encoder_input_ids: torch.Tensor, encoder_attention_mask: torch.Tensor, - decoder_input_ids: torch.Tensor = None, + decoder_input_ids: torch.Tensor | None = None, ): encoder_hidden_states: torch.FloatTensor = self.t5_encoder(encoder_input_ids, encoder_attention_mask) + lm_logits, past_self, past_cross = self.t5_decoder_init( decoder_input_ids, encoder_attention_mask, encoder_hidden_states ) - return lm_logits, encoder_hidden_states, past_self, past_cross + + if self.output_cross_only: + return past_cross + else: + return lm_logits, encoder_hidden_states, past_self, past_cross class T5EncoderDecoderInitInputs: def __init__(self, encoder_input_ids, encoder_attention_mask, decoder_input_ids=None): self.encoder_input_ids: torch.LongTensor = encoder_input_ids self.encoder_attention_mask: torch.LongTensor = encoder_attention_mask - self.decoder_input_ids: torch.LongTensor = decoder_input_ids + self.decoder_input_ids: torch.LongTensor | None = decoder_input_ids @staticmethod def create_dummy( @@ -108,9 +114,14 @@ def export_onnx( onnx_model_path (str): onnx path verbose (bool, optional): print verbose information. Defaults to True. use_external_data_format (bool, optional): use external data format or not. Defaults to False. + use_int32_inputs (bool, optional): use int32 instead of int64 for integer inputs. Defaults to False. """ assert isinstance(model, T5EncoderDecoderInit) + # Do not exclude decoder in torch onnx export so that cross can show up. + output_cross_only = model.output_cross_only + model.output_cross_only = False + inputs = T5EncoderDecoderInitInputs.create_dummy( model.config, batch_size=2, @@ -139,7 +150,7 @@ def export_onnx( input_names = ["encoder_input_ids", "encoder_attention_mask"] - # ONNX exporter might mark dimension like 'Transposepresent_value_self_1_dim_2' in shape inference. + # ONNX exporter might mark dimension like 'present_value_self_1_dim_2' in shape inference. # We use a workaround here: first use dim_param "1" for sequence_length, and later change to dim_value. sequence_length = "1" num_heads = str(model.config.num_heads) @@ -201,9 +212,12 @@ def export_onnx( verbose=verbose, ) + # Restore output_cross_only setting. + model.output_cross_only = output_cross_only + # Workaround as mentioned earlier: change numeric dim_param to dim_value - model = onnx.load(temp_onnx_model_path) - for tensor in model.graph.output: + exported_model: onnx.ModelProto = onnx.load(temp_onnx_model_path) + for tensor in exported_model.graph.output: for dim_proto in tensor.type.tensor_type.shape.dim: if dim_proto.HasField("dim_param") and dim_proto.dim_param in [ sequence_length, @@ -215,8 +229,50 @@ def export_onnx( dim_proto.Clear() dim_proto.dim_value = dim_value + if output_cross_only: + # Rewrite onnx graph to only keep present_[key|value]_cross_* outputs. + onnx_model = OnnxModel(exported_model) + output_name_to_node = onnx_model.output_name_to_node() + + for output in exported_model.graph.output: + if "cross" in output.name: + assert output.name in output_name_to_node + + transpose_node = output_name_to_node[output.name] + assert transpose_node and transpose_node.op_type == "Transpose" + + permutation = OnnxModel.get_node_attribute(transpose_node, "perm") + assert isinstance(permutation, list) + assert permutation == [0, 2, 1, 3] + + matched_nodes = onnx_model.match_parent_path( + transpose_node, + ["Reshape", "MatMul"], + [0, 0], + output_name_to_node, + ) + assert matched_nodes is not None + + reshape_node, matmul_node = matched_nodes + assert "encoder_hidden_states" in matmul_node.input + + if not onnx_model.get_initializer("cross_reshape_shape"): + shape_tensor = onnx.helper.make_tensor( + name="cross_reshape_shape", + data_type=onnx.TensorProto.INT64, + dims=[4], + vals=[0, 0, int(num_heads), int(head_size)], + raw=False, + ) + onnx_model.add_initializer(shape_tensor) + + reshape_node.input[1] = "cross_reshape_shape" + + cross_outputs = [output.name for output in exported_model.graph.output if "cross" in output.name] + onnx_model.prune_graph(cross_outputs, allow_remove_graph_inputs=True) + OnnxModel.save( - model, + exported_model, onnx_model_path, save_as_external_data=use_external_data_format, all_tensors_to_one_file=True, @@ -269,27 +325,34 @@ def verify_onnx( num_decoder_layers = model.config.num_decoder_layers - assert torch_outputs[0].cpu().numpy().shape == ort_outputs[0].shape - max_diff = numpy.amax(numpy.abs(torch_outputs[0].cpu().numpy() - ort_outputs[0])) - logger.debug(f"logits max_diff={max_diff}") - max_diff_all = max_diff - - assert torch_outputs[1].cpu().numpy().shape == ort_outputs[1].shape - max_diff = numpy.amax(numpy.abs(torch_outputs[1].cpu().numpy() - ort_outputs[1])) - logger.debug(f"encoder_hidden_states max_diff={max_diff}") - max_diff_all = max(max_diff_all, max_diff) - - for i in range(2 * num_decoder_layers): - max_diff = numpy.amax(numpy.abs(torch_outputs[2][i].cpu().numpy() - ort_outputs[2 + i])) - logger.debug(f"self attention past state {i} max_diff={max_diff}") - - for i in range(2 * num_decoder_layers): - max_diff = numpy.amax( - numpy.abs(torch_outputs[3][i].cpu().numpy() - ort_outputs[2 + 2 * num_decoder_layers + i]) - ) - logger.debug(f"cross attention past state {i} max_diff={max_diff}") + if not model.output_cross_only: + assert torch_outputs[0].cpu().numpy().shape == ort_outputs[0].shape + max_diff = numpy.amax(numpy.abs(torch_outputs[0].cpu().numpy() - ort_outputs[0])) + logger.debug(f"logits max_diff={max_diff}") + max_diff_all = max_diff + + assert torch_outputs[1].cpu().numpy().shape == ort_outputs[1].shape + max_diff = numpy.amax(numpy.abs(torch_outputs[1].cpu().numpy() - ort_outputs[1])) + logger.debug(f"encoder_hidden_states max_diff={max_diff}") max_diff_all = max(max_diff_all, max_diff) + for i in range(2 * num_decoder_layers): + max_diff = numpy.amax(numpy.abs(torch_outputs[2][i].cpu().numpy() - ort_outputs[2 + i])) + logger.debug(f"self attention past state {i} max_diff={max_diff}") + + for i in range(2 * num_decoder_layers): + max_diff = numpy.amax( + numpy.abs(torch_outputs[3][i].cpu().numpy() - ort_outputs[2 + 2 * num_decoder_layers + i]) + ) + logger.debug(f"cross attention past state {i} max_diff={max_diff}") + max_diff_all = max(max_diff_all, max_diff) + else: + max_diff_all = -float("inf") + for i in range(2 * num_decoder_layers): + max_diff = numpy.amax(numpy.abs(torch_outputs[i].cpu().numpy() - ort_outputs[i])) + logger.debug(f"cross attention past state {i} max_diff={max_diff}") + max_diff_all = max(max_diff_all, max_diff) + test_cases_max_diff.append(max_diff_all) logger.info( f"batch_size={batch_size} encode_sequence_length={encode_sequence_length}, max_diff={max_diff_all}" diff --git a/onnxruntime/python/tools/transformers/models/t5/t5_helper.py b/onnxruntime/python/tools/transformers/models/t5/t5_helper.py index d3f25e979887d..7552008f920e0 100755 --- a/onnxruntime/python/tools/transformers/models/t5/t5_helper.py +++ b/onnxruntime/python/tools/transformers/models/t5/t5_helper.py @@ -1,8 +1,7 @@ # ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# ------------------------------------------------------------------------- import logging import os @@ -12,8 +11,7 @@ from float16 import float_to_float16_max_diff from onnx_model import OnnxModel from optimizer import optimize_model -from t5_decoder import T5Decoder, T5DecoderHelper, T5DecoderInit -from t5_encoder import T5Encoder, T5EncoderHelper +from t5_decoder import T5Decoder, T5DecoderHelper from t5_encoder_decoder_init import T5EncoderDecoderInit, T5EncoderDecoderInitHelper from transformers import MT5ForConditionalGeneration, T5ForConditionalGeneration @@ -22,7 +20,13 @@ logger = logging.getLogger(__name__) PRETRAINED_T5_MODELS = ["t5-small", "t5-base", "t5-large", "t5-3b", "t5-11b"] -PRETRAINED_MT5_MODELS = ["google/mt5-small", "google/mt5-base", "google/mt5-large", "google/mt5-xl", "google/mt5-xxl"] +PRETRAINED_MT5_MODELS = [ + "google/mt5-small", + "google/mt5-base", + "google/mt5-large", + "google/mt5-xl", + "google/mt5-xxl", +] class T5Helper: @@ -60,18 +64,19 @@ def load_model( model_name_or_path: str, cache_dir: str, device: torch.device, - merge_encoder_and_decoder_init: bool = True, model_type: str = "t5", state_dict_path: str = "", - ) -> dict[str, torch.nn.Module]: + encoder_decoder_init: bool = False, + ) -> dict[str, T5EncoderDecoderInit | T5Decoder]: """Load model given a pretrained name or path, then build models for ONNX conversion. Args: model_name_or_path (str): pretrained model name or path cache_dir (str): cache directory device (torch.device): device to run the model - merge_encoder_and_decoder_init (bool, optional): Whether merge encoder and decoder initialization into one ONNX model. Defaults to True. - is_mt5 (bool, optional): whether the model is MT5 instead of T5 + model_type (str, optional): model type "t5" or "mt5" + state_dict_path(str, optional): state dictionary path + encoder_decoder_init (bool, optional): combine encoder and decoder kv cache initialization into one model. Returns: Dict[str, torch.nn.Module]: mapping from name to modules for ONNX conversion. """ @@ -88,29 +93,21 @@ def load_model( decoder = T5Decoder(model.decoder, model.lm_head, model.config) decoder.eval().to(device) - if merge_encoder_and_decoder_init: - encoder_decoder_init = T5EncoderDecoderInit( - model.encoder, - model.decoder, - model.lm_head, - model.config, - decoder_start_token_id=None, - ) - return {"encoder_decoder_init": encoder_decoder_init, "decoder": decoder} - else: - encoder = T5Encoder(model.encoder, model.config) - encoder.eval().to(device) - decoder_init = T5DecoderInit(model.decoder, model.lm_head, model.config) - decoder_init.eval().to(device) - return { - "encoder": encoder, - "decoder": decoder, - "decoder_init": decoder_init, - } + encoder = T5EncoderDecoderInit( + model.encoder, + model.decoder, + model.lm_head, + model.config, + decoder_start_token_id=None, + output_cross_only=not encoder_decoder_init, + ) + + encoder_name = "encoder_decoder_init" if encoder_decoder_init else "encoder" + return {encoder_name: encoder, "decoder": decoder} @staticmethod def export_onnx( - model: T5Encoder | T5Decoder | T5DecoderInit | T5EncoderDecoderInit, + model: T5Decoder | T5EncoderDecoderInit, device: torch.device, onnx_model_path: str, verbose: bool = True, @@ -118,16 +115,7 @@ def export_onnx( use_decoder_input_ids: bool = True, use_int32_inputs: bool = False, ): - if isinstance(model, T5Encoder): - T5EncoderHelper.export_onnx( - model, - device, - onnx_model_path, - verbose, - use_external_data_format, - use_int32_inputs, - ) - elif isinstance(model, T5EncoderDecoderInit): + if isinstance(model, T5EncoderDecoderInit): T5EncoderDecoderInitHelper.export_onnx( model, device, @@ -150,21 +138,28 @@ def export_onnx( @staticmethod def auto_mixed_precision( onnx_model: OnnxModel, - op_block_list: list[str] = [ # noqa: B006 - "SimplifiedLayerNormalization", - "SkipSimplifiedLayerNormalization", - "Relu", - "Add", - ], + op_block_list: list[str] | None = None, + force_fp16_logits: bool = False, + use_symbolic_shape_infer: bool = True, ): """Convert model to mixed precision. It detects whether original model has fp16 precision weights, and set parameters for float16 conversion automatically. Args: onnx_model (OnnxModel): optimized ONNX model - op_block_list (List[str], optional): . Defaults to ["SimplifiedLayerNormalization", "SkipSimplifiedLayerNormalization", "Relu", "Add"] + op_block_list (List[str], optional): operators need to run in fp32. + force_fp16_logits (bool, optional): force logits and last MatMul node to be in float16. Defaults to False. + use_symbolic_shape_infer (bool, optional): use symbolic shape inference to convert float to float16. Defaults to True. Returns: parameters(dict): a dictionary of parameters used in float16 conversion """ + if op_block_list is None: + op_block_list = [ + "SimplifiedLayerNormalization", + "SkipSimplifiedLayerNormalization", + "Relu", + "Add", + ] + op_full_set = {node.op_type for node in onnx_model.nodes()} fp32_op_set = set(op_block_list) fp16_op_set = op_full_set.difference(fp32_op_set) @@ -198,11 +193,38 @@ def auto_mixed_precision( keep_io_types = [] node_block_list = [] - if (not is_weight_fp16_precision) and (last_matmul_node is not None): + if (not is_weight_fp16_precision) and (last_matmul_node is not None) and not force_fp16_logits: # When original weight is float32 precision, keep logits and last MatMul in float32 could get better precision. keep_io_types = [logits_output_name] node_block_list = [last_matmul_node.name] + if "Add" not in op_block_list: + input_name_to_nodes = onnx_model.input_name_to_nodes() + fp32_add = 0 + changed = True + add_nodes = onnx_model.get_nodes_by_op_type("Add") + while changed: + changed = False + for node in add_nodes: + if node.name not in node_block_list: + parents = onnx_model.get_parents(node, output_name_to_node) + children = onnx_model.get_children(node, input_name_to_nodes) + blocked_children = [ + child for child in children if child.op_type in op_block_list or child in node_block_list + ] + blocked_parents = [ + parent for parent in parents if parent.op_type in op_block_list or parent in node_block_list + ] + # If any child or parent is in fp32, we place the Add node to fp32. + if (len(blocked_children) + len(blocked_parents)) > 0: + node_block_list.append(node.name) + fp32_add += 1 + changed = True + fp16_add = len(add_nodes) - fp32_add + logger.info(f"node counter of Add operator: fp32={fp32_add} fp16={fp16_add}") + + logger.info(f"node_block_list: {node_block_list}") + parameters = { "keep_io_types": keep_io_types, "op_block_list": op_block_list, @@ -211,7 +233,18 @@ def auto_mixed_precision( } logger.info(f"auto_mixed_precision parameters: {parameters}") - onnx_model.convert_float_to_float16(use_symbolic_shape_infer=True, **parameters) + if use_symbolic_shape_infer: + onnx_model.convert_float_to_float16(use_symbolic_shape_infer=True, **parameters) + else: + # Workaround when symbolic shape inference fails. + # Need enable shape_infer_before_optimization in convert_to_onnx.py as well. + from float16 import convert_float_to_float16 + + convert_float_to_float16( + onnx_model.model, + disable_shape_infer=True, + **parameters, + ) return parameters @@ -225,6 +258,7 @@ def optimize_onnx( use_external_data_format: bool = False, auto_mixed_precision: bool = True, use_gpu: bool = False, + force_fp16_io: bool = False, ): """Optimize ONNX model with an option to convert it to use mixed precision.""" @@ -233,38 +267,35 @@ def optimize_onnx( optimization_options = None if is_float16: optimization_options = FusionOptions("t5") - optimization_options.enable_skip_layer_norm = False + # SkipLayerNormalization is faster but might bring accuracy drop since it uses fp16 accumulation. + optimization_options.enable_skip_layer_norm = not auto_mixed_precision m = optimize_model( onnx_model_path, model_type="t5", num_heads=num_attention_heads, hidden_size=hidden_size, - opt_level=2 if not use_external_data_format else 0, + opt_level=0, optimization_options=optimization_options, - use_gpu=False, - only_onnxruntime=not use_gpu, + use_gpu=use_gpu, ) if is_float16: if auto_mixed_precision: - T5Helper.auto_mixed_precision(m) + T5Helper.auto_mixed_precision(m, force_fp16_logits=force_fp16_io) else: - m.convert_model_float32_to_float16(cast_input_output=False) + m.convert_model_float32_to_float16(cast_input_output=force_fp16_io) m.save_model_to_file(optimized_model_path, use_external_data_format, all_tensors_to_one_file=True) @staticmethod def verify_onnx( - model: T5Encoder | T5Decoder | T5DecoderInit | T5EncoderDecoderInit, + model: T5Decoder | T5EncoderDecoderInit, ort_session: InferenceSession, device: torch.device, use_int32_inputs: bool, ): """Compare the result from PyTorch and OnnxRuntime to verify the ONNX model is good.""" - if isinstance(model, T5Encoder): - return T5EncoderHelper.verify_onnx(model, ort_session, device, use_int32_inputs) - if isinstance(model, T5EncoderDecoderInit): return T5EncoderDecoderInitHelper.verify_onnx(model, ort_session, device, use_int32_inputs) diff --git a/onnxruntime/python/tools/transformers/onnx_model.py b/onnxruntime/python/tools/transformers/onnx_model.py index c0310b3e8c663..8add38b5a7d07 100644 --- a/onnxruntime/python/tools/transformers/onnx_model.py +++ b/onnxruntime/python/tools/transformers/onnx_model.py @@ -1183,11 +1183,21 @@ def graph_topological_sort(graph, is_deterministic=False): graph.ClearField("node") graph.node.extend(sorted_nodes) - def topological_sort(self, is_deterministic=False): + def topological_sort(self, is_deterministic=False, dump_model_on_failure=False): # TODO: support graph_topological_sort() in subgraphs # for graph in self.graphs(): # self.graph_topological_sort(graph) - OnnxModel.graph_topological_sort(self.model.graph, is_deterministic) + try: + OnnxModel.graph_topological_sort(self.model.graph, is_deterministic) + except RuntimeError as e: + if dump_model_on_failure: + logger.info( + "Failed to sort graph in topological order. Dumping model to _topo_sort_failed.onnx for debugging." + ) + OnnxModel.save( + self.model, "_topo_sort_failed.onnx", save_as_external_data=True, all_tensors_to_one_file=True + ) + raise e @staticmethod def save( diff --git a/onnxruntime/python/tools/transformers/onnx_model_t5.py b/onnxruntime/python/tools/transformers/onnx_model_t5.py index 33dcc7795a465..de299a970ffd3 100644 --- a/onnxruntime/python/tools/transformers/onnx_model_t5.py +++ b/onnxruntime/python/tools/transformers/onnx_model_t5.py @@ -34,13 +34,13 @@ def __init__( num_heads, attention_mask, use_multi_head_attention=False, - search_op_types=["SkipSimplifiedLayerNormalization", "Add"], + search_op_types=["Softmax"], ) self.static_kv = 1 - def create_attention_node( + def make_attention_node( self, - mask_index: str, + mask_index: str | None, q_matmul: NodeProto, k_matmul: NodeProto, v_matmul: NodeProto, @@ -48,8 +48,8 @@ def create_attention_node( hidden_size: int, input: str, output: str, - add_qk_str: str, - scale: float | None = None, + attn_bias: str | None, + scale: float, ) -> NodeProto | None: """Create an Attention node. Args: @@ -122,14 +122,17 @@ def create_attention_node( attention_node_name + "_qkv_weight", "", ] - if mask_index is not None: + if mask_index: attention_inputs.append(mask_index) else: attention_inputs.append("") - if add_qk_str is not None: + if attn_bias: attention_inputs.append("") # no past - attention_inputs.append(add_qk_str) + attention_inputs.append(attn_bias) + + while attention_inputs and attention_inputs[-1] == "": + attention_inputs.pop() attention_node = helper.make_node( "Attention", @@ -153,50 +156,55 @@ def create_mha_node( query: str, key: str, value: str, - mask_index: str, - res_pos_bias: str, - past_key: str, - past_value: str, + mask_index: str | None, + attn_bias: str | None, + past_key: str | None, + past_value: str | None, output: str, - present_key: str, - present_value: str, + present_key: str | None, + present_value: str | None, num_heads: int, hidden_size: int, ) -> NodeProto | None: - assert num_heads > 0 + assert num_heads > 0 and hidden_size > 0 and query and key and value - if hidden_size > 0 and (hidden_size % num_heads) != 0: + if (hidden_size % num_heads) != 0: logger.debug(f"input hidden size {hidden_size} is not a multiple of num of heads {num_heads}") return None attention_node_name = self.model.create_node_name("MultiHeadAttention") attention_inputs = [ query, - "" if key is None else key, # key - "" if value is None else value, # value + key, + value, "", # bias ] - if mask_index is not None: + + if mask_index: attention_inputs.append(mask_index) else: attention_inputs.append("") - if res_pos_bias is not None: - attention_inputs.append(res_pos_bias) + if attn_bias: + attention_inputs.append(attn_bias) else: attention_inputs.append("") - if past_key is not None: - assert past_value is not None + if past_key: + assert past_value attention_inputs.append(past_key) attention_inputs.append(past_value) + while attention_inputs and attention_inputs[-1] == "": + attention_inputs.pop() + attention_outputs = [output] - if present_key is not None: - assert present_value is not None + if present_key: + assert present_value attention_outputs.append(present_key) attention_outputs.append(present_value) + print(f"{attention_inputs=}, {attention_outputs=}, {attention_node_name=}") attention_node = helper.make_node( "MultiHeadAttention", inputs=attention_inputs, @@ -213,21 +221,23 @@ def create_mha_node( self.increase_counter("MultiHeadAttention") return attention_node - def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): - self.fuse_t5_encoder(normalize_node, input_name_to_nodes, output_name_to_node) - self.fuse_t5_decoder(normalize_node, input_name_to_nodes, output_name_to_node) - - def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_node): - if normalize_node.op_type != "SkipSimplifiedLayerNormalization" and normalize_node.op_type != "Add": + def fuse(self, node, input_name_to_nodes, output_name_to_node): + if self.fuse_t5_encoder(node, input_name_to_nodes, output_name_to_node): return - qkv_nodes = self.model.match_parent_path( - normalize_node, ["MatMul", "Reshape", "Transpose", "MatMul"], [1, 0, 0, 0], output_name_to_node + self.fuse_t5_decoder(node, input_name_to_nodes, output_name_to_node) + + def fuse_t5_encoder(self, softmax_node, input_name_to_nodes, output_name_to_node): + assert softmax_node.op_type == "Softmax" + qkv_nodes = self.model.match_child_path( + softmax_node, + ["MatMul", "Transpose", "Reshape"], + edges=[(0, 0), (0, 0), (0, 0)], + input_name_to_nodes=input_name_to_nodes, ) if qkv_nodes is None: - return - - _, reshape_qkv, transpose_qkv, matmul_qkv = qkv_nodes + return False + matmul_qkv, _, reshape_qkv = qkv_nodes qkv_shape_nodes = self.model.match_parent_path( reshape_qkv, @@ -236,7 +246,7 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no output_name_to_node, ) if qkv_shape_nodes is None: - return + return False input_shape_node = qkv_shape_nodes[-1] v_nodes = self.model.match_parent_path( @@ -246,7 +256,7 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no output_name_to_node, ) if v_nodes is None: - return + return False _, reshape_v, matmul_v = v_nodes # todo: check reshape_v parent nodes @@ -257,7 +267,7 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no output_name_to_node, ) if qk_nodes is None: - return + return False _, add_qk, matmul_qk = qk_nodes mask_nodes = self.model.match_parent_path( @@ -268,7 +278,9 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no ) is_pattern_for_one_graph_input = mask_nodes is None - if mask_nodes is None: + if mask_nodes is not None: + mul_node = mask_nodes[1] + else: # Pattern for SD3 and Flux. mask_nodes = self.model.match_parent_path( add_qk, @@ -276,15 +288,22 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no [1, 1, 0, 0, 1, 0], output_name_to_node, ) + + # If the model is not optimized by ORT, there might be an additional Cast node. if mask_nodes is None: - return + mask_nodes = self.model.match_parent_path( + add_qk, + ["Add", "Slice", "Mul", "Sub", "Cast", "Unsqueeze", "Unsqueeze"], + [1, 1, 0, 0, 1, 0, 0], + output_name_to_node, + ) + if mask_nodes is None: + return False mul_node = mask_nodes[2] - else: - mul_node = mask_nodes[1] _, mul_val = self.model.get_constant_input(mul_node) if mul_val is None: - return + return False if mul_val != -10000: self.mask_filter_value = float(mul_val) @@ -327,7 +346,7 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no [1, 0, 0], ) if rpb_nodes is None: - return + return False res_pos_bias = rpb_nodes[-1].output[0] @@ -337,8 +356,8 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no [1, 0, 0], ) if k_nodes is None: - return - _, reshape_k, matmul_k = k_nodes + return False + _, _, matmul_k = k_nodes # todo: check reshape_k parent nodes q_nodes = self.model.match_parent_path( @@ -347,50 +366,50 @@ def fuse_t5_encoder(self, normalize_node, input_name_to_nodes, output_name_to_no [0, 0, 0], ) if q_nodes is None: - return + return False - transpose_q, reshape_q, matmul_q = q_nodes + _, reshape_q, matmul_q = q_nodes # todo: check reshape_q parent nodes if matmul_q.input[0] != input_shape_node.input[0]: - return + return False q_num_heads, q_hidden_size = self.get_num_heads_and_hidden_size(reshape_q) - new_node = self.create_attention_node( + new_node = self.make_attention_node( mask_index, matmul_q, matmul_k, matmul_v, - q_num_heads, - q_hidden_size, - input_shape_node.input[0], - reshape_qkv.output[0], - res_pos_bias, - 1.0, + num_heads=q_num_heads, + hidden_size=q_hidden_size, + input=input_shape_node.input[0], + output=reshape_qkv.output[0], + attn_bias=res_pos_bias, + scale=1.0, ) if new_node is None: - return + return False self.nodes_to_add.append(new_node) self.node_name_to_graph_name[new_node.name] = self.this_graph_name self.nodes_to_remove.append(reshape_qkv) self.prune_graph = True + return True - def fuse_t5_decoder(self, normalize_node, input_name_to_nodes, output_name_to_node): - if normalize_node.op_type != "SkipSimplifiedLayerNormalization" and normalize_node.op_type != "Add": - return + def fuse_t5_decoder(self, softmax_node, input_name_to_nodes, output_name_to_node): + assert softmax_node.op_type == "Softmax" - qkv_nodes = self.model.match_parent_path( - normalize_node, - ["MatMul", "Reshape", "Transpose", "MatMul"], - [1, 0, 0, 0], + qkv_nodes = self.model.match_child_path( + softmax_node, + ["MatMul", "Transpose", "Reshape"], + edges=[(0, 0), (0, 0), (0, 0)], + input_name_to_nodes=input_name_to_nodes, ) if qkv_nodes is None: return - - _, reshape_qkv, transpose_qkv, matmul_qkv = qkv_nodes + matmul_qkv, _transpose_qkv, reshape_qkv = qkv_nodes qkv_shape_nodes = self.model.match_parent_path( reshape_qkv, @@ -462,11 +481,17 @@ def fuse_t5_decoder(self, normalize_node, input_name_to_nodes, output_name_to_no ["Add", "Mul", "Sub", "Cast", "Unsqueeze", "Unsqueeze"], [1, 1, 0, 1, 0, 0], ) - if mask_nodes is None: - return - mul_node = mask_nodes[1] - if mask_nodes[1].op_type != "Mul": - return + if mask_nodes is not None: + mul_node = mask_nodes[1] + else: + mask_nodes = self.model.match_parent_path( + add_qk, + ["Add", "Slice", "Mul", "Sub", "Cast", "Unsqueeze", "Unsqueeze"], + [1, 1, 0, 0, 1, 0, 0], + ) + if mask_nodes is None: + return + mul_node = mask_nodes[2] _, mul_val = self.model.get_constant_input(mul_node) if mul_val != -10000: @@ -474,22 +499,19 @@ def fuse_t5_decoder(self, normalize_node, input_name_to_nodes, output_name_to_no mask_index = self.attention_mask.process_mask(mask_nodes[-1].input[0]) else: - rpb_nodes = self.model.match_parent_path( + matched_path_index, _, _ = self.model.match_parent_paths( add_qk, - ["Add", "Slice"], - [1, 0], + [ + (["Add", "Slice"], [1, 0]), + (["Add", "RelativePositionBias"], [1, 0]), + ], + output_name_to_node, ) - if rpb_nodes is not None: - res_pos_bias = add_qk.input[1] - else: - rpb_nodes = self.model.match_parent_path( - add_qk, - ["Add", "RelativePositionBias"], - [1, 0], - ) - if rpb_nodes is None: - return - res_pos_bias = add_qk.input[1] + if matched_path_index < 0: + logger.debug("Skip MultiHeadAttention fusion since attention bias pattern not matched") + return + + res_pos_bias = add_qk.input[1] key = None past_key = None @@ -608,56 +630,73 @@ def fuse_t5_decoder(self, normalize_node, input_name_to_nodes, output_name_to_no past_key = None past_value = None + if not (key and value and q_num_heads > 0 and q_hidden_size > 0): + return + new_node = self.create_mha_node( - matmul_q.output[0], - key, - value, - mask_index, - res_pos_bias, - past_key, - past_value, - reshape_qkv.output[0], - present_key, - present_value, - q_num_heads, - q_hidden_size, + query=matmul_q.output[0], + key=key, + value=value, + mask_index=mask_index, + attn_bias=res_pos_bias, + past_key=past_key, + past_value=past_value, + output=reshape_qkv.output[0], + present_key=present_key, + present_value=present_value, + num_heads=q_num_heads, + hidden_size=q_hidden_size, ) - if new_node is None: - return - self.nodes_to_add.append(new_node) - self.node_name_to_graph_name[new_node.name] = self.this_graph_name + if new_node: + self.nodes_to_add.append(new_node) + self.node_name_to_graph_name[new_node.name] = self.this_graph_name - self.nodes_to_remove.append(reshape_qkv) + # Since present_* is graph output, we need update the graph to avoid circular. + if present_key or present_value: + for graph_output in [present_key, present_value]: + if not (graph_output and self.model.find_graph_output(graph_output)): + print(f"{graph_output=} does not exist in graph output") + return + assert graph_output in output_name_to_node + output_name_to_node[graph_output].output[0] = graph_output + "_copy" + self.model.replace_input_of_all_nodes(graph_output, graph_output + "_copy") - self.prune_graph = True + self.nodes_to_remove.append(reshape_qkv) + self.prune_graph = False class FusionRelativePositionBiasBlock(Fusion): - def __init__(self, model: OnnxModel, max_distance: int): - super().__init__(model, "RelativePositionBias", ["Add", "Slice"]) - self.max_distance = max_distance - self.is_bidirectional = False + def __init__(self, model: OnnxModel): + super().__init__(model, "RelativePositionBias", ["Softmax"]) def fuse(self, node, input_name_to_nodes, output_name_to_node): - # TODO: Optimization opportunity: only last dimension of relative_position_bias is used in decoder. - # Cuda kernel can be optimized to only compute last dimension. - if node.op_type != "Add" and node.op_type != "Slice": - return - compute_bias_nodes = self.model.match_parent_path( - node, ["Unsqueeze", "Transpose", "Gather", "Where"], [0, 0, 0, 1], output_name_to_node + node, + ["Add", "Add", "Slice", "Unsqueeze", "Transpose", "Gather", "Where"], + [0, 1, 0, 0, 0, 0, 1], + output_name_to_node, ) + if compute_bias_nodes is None: compute_bias_nodes = self.model.match_parent_path( - node, ["Unsqueeze", "Transpose", "Gather", "Add", "Where"], [0, 0, 0, 1, 1], output_name_to_node + node, + ["Add", "Add", "Slice", "Unsqueeze", "Transpose", "Gather", "Add", "Where"], + [0, 1, 0, 0, 0, 0, 1, 1], + output_name_to_node, ) if compute_bias_nodes is None: return - gather = compute_bias_nodes[2] + gather = compute_bias_nodes[5] where = compute_bias_nodes[-1] - unsqueeze = compute_bias_nodes[0] + slice = compute_bias_nodes[2] + unsqueeze = compute_bias_nodes[3] + + # Current fusion will not remove the node until the graph is processed. + # This avoids to fuse it again when it is shared by multiple layers. + if unsqueeze in self.nodes_to_remove: + return compute_buckets_nodes = self.model.match_parent_path( where, @@ -668,12 +707,8 @@ def fuse(self, node, input_name_to_nodes, output_name_to_node): if compute_buckets_nodes is None: return - # It is possible to deduce max_distance from a Div node: - # The value of self.model.get_constant_value(compute_buckets_nodes[-3].input[1]) is close to - # math.log(max_distance / (relative_attention_num_buckets // (4 if is_bidirectional else 2))) - # See https://github.com/huggingface/transformers/blob/608e163b527eaee41e650ffb9eb4c422d2679902/src/transformers/models/t5/modeling_t5.py#L397. - # Most t5 models use max_distance=128, so we hardcode it unitl we see a model with different value. - # TODO: maybe add a sanity check here. + # This value is to used to compute max_distance later. + log_max = self.model.get_constant_value(compute_buckets_nodes[-3].input[1]) div = compute_buckets_nodes[-1] @@ -683,21 +718,33 @@ def fuse(self, node, input_name_to_nodes, output_name_to_node): [0, 0, 0, 1, 0, 0, 0, 0], output_name_to_node, ) + + is_bidirectional = False if range_nodes is None: range_nodes = self.model.match_parent_path( div, ["Cast", "Abs", "Sub", "Unsqueeze", "Range"], [0, 0, 0, 0, 0], output_name_to_node ) - self.is_bidirectional = True + is_bidirectional = True if range_nodes is None: return - range_node = range_nodes[-1] - self.nodes_to_remove.append(unsqueeze) - self.prune_graph = True + # Double check that the constant relative to max_distance and relative_attention_num_buckets. + # Most t5 models use max_distance=128, so we hardcode it unitl we see a model with different value. + + # The log_max is the value of the following formula: + # math.log(max_distance / (relative_attention_num_buckets // (4 if is_bidirectional else 2))) + # See https://github.com/huggingface/transformers/blob/608e163b527eaee41e650ffb9eb4c422d2679902/src/transformers/models/t5/modeling_t5.py#L397. + # Here is the value based on max_distance=128 and relative_attention_num_buckets=32: + max_distance = int(np.round(np.exp(log_max) * (32 // (4 if is_bidirectional else 2)))) + if max_distance != 128: + logger.warning( + f"max_distance is {max_distance}, which is different from the default value 128. " + "Please double check the model configuration." + ) node_name = self.model.create_node_name( - "RelativePositionBias", name_prefix="RelPosBias_" + ("encoder" if self.is_bidirectional else "decoder") + "RelativePositionBias", name_prefix="RelPosBias_" + ("encoder" if is_bidirectional else "decoder") ) table_weight_i = self.model.get_initializer(gather.input[0]) @@ -712,22 +759,64 @@ def fuse(self, node, input_name_to_nodes, output_name_to_node): vals=table_weight_t.tobytes(), raw=True, ) - self.model.add_initializer(bias_table, self.this_graph_name) + + # Relative position is like the following in encoder: + # seq_len + # | + # Range(0, *) + # / \ + # Unsqueeze(axes=0) Unsqueeze(axes=1) + # \ / + # Sub + # | + # Abs + # + # Relative position is like the following in decoder: + # past_seq_len seq_len + # \ / + # Add + # / \ + # Range(0, *) Range(0, *) + # \ / + # Sub + # Note that the graph will slice the attention bias to get last seq_len rows. + # + # In new version of transformers, the pattern of decoder is changed like the following + # + # total_seq_len Range(start=past_seq_len, end=total_seq_len) + # | | + # Range(0, *) Unsqueeze(axes=1) + # | | + # Unsqueeze(axes=0) Cast(to=int64) + # \ / + # Sub + # Currently, there is still Slice to get last seq_len rows so end result is same. + # But need to be careful that the shape of bias tensor is changed before Slice. + # + # RelativePositionBias operator requires query_length == key_length so we shall pass in total_seq_len. + # Here we get the end value of the Range node as length to pass to the RelativePositionBias node. + + # TODO: Optimization opportunity: change RelativePositionBias op to support query_length != key_length. + # only compute seq_len rows, then we can remove the Slice after the RelativePositionBias node. inputs = [bias_table.name, range_node.input[1], range_node.input[1]] - outputs = [unsqueeze.output[0]] + + # Use a new tensor name since the shape might be different as mentioned above. + bias_output = node_name + "_rel_pos_bias" + slice.input[0] = bias_output + rpb_node = helper.make_node( "RelativePositionBias", inputs=inputs, - outputs=outputs, + outputs=[bias_output], name=node_name, ) rpb_node.domain = "com.microsoft" - rpb_node.attribute.extend([helper.make_attribute("max_distance", self.max_distance)]) - rpb_node.attribute.extend([helper.make_attribute("is_bidirectional", self.is_bidirectional)]) - - self.nodes_to_add.append(rpb_node) + rpb_node.attribute.extend([helper.make_attribute("max_distance", max_distance)]) + rpb_node.attribute.extend([helper.make_attribute("is_bidirectional", is_bidirectional)]) self.node_name_to_graph_name[rpb_node.name] = self.this_graph_name + self.nodes_to_add.append(rpb_node) + self.prune_graph = True class T5OnnxModel(BertOnnxModel): @@ -744,7 +833,7 @@ def __init__(self, model, num_heads: int = 0, hidden_size: int = 0): self.attention_fusion = FusionT5Attention(self, self.hidden_size, self.num_heads, self.attention_mask) self.layer_norm_fusion = FusionSimplifiedLayerNormalization(self) self.skip_layer_norm_fusion = FusionSkipSimplifiedLayerNormalization(self) - self.rpb_fusion = FusionRelativePositionBiasBlock(self, 128) + self.rpb_fusion = FusionRelativePositionBiasBlock(self) def fuse_attention(self): self.attention_fusion.apply() diff --git a/onnxruntime/test/python/transformers/test_generation.py b/onnxruntime/test/python/transformers/test_generation.py index 7a94519c92bc8..c5cf8a07f557d 100644 --- a/onnxruntime/test/python/transformers/test_generation.py +++ b/onnxruntime/test/python/transformers/test_generation.py @@ -28,6 +28,10 @@ from onnxruntime.transformers.models.whisper.convert_to_onnx import main as run_whisper +def has_cuda_environment(): + return torch.cuda.is_available() and "CUDAExecutionProvider" in get_available_providers() + + class TestBeamSearchGpt(unittest.TestCase): """Test BeamSearch for GPT-2 model""" @@ -49,7 +53,7 @@ def setUp(self): # "The selloff in tech shares deepened", # "Abortion rights take center stage", ] - self.enable_cuda = torch.cuda.is_available() and "CUDAExecutionProvider" in get_available_providers() + self.enable_cuda = has_cuda_environment() self.remove_onnx_files() def tearDown(self): @@ -176,112 +180,253 @@ def test_external_data(self): ) -class TestBeamSearchT5(unittest.TestCase): - """Test BeamSearch for T5 model""" +def get_tiny_t5_model_dir(): + """Get the path to the tiny T5 model directory.""" + # This function is used to get the path to the tiny T5 model directory. + # It is used in the TestBeamSearchT5 and TestBeamSearchT5Fp16 classes. - def setUp(self): - self.model_name = "t5-small" - self.decoder_onnx_path = os.path.join(".", "onnx_models", "t5-small_decoder.onnx") - self.encoder_onnx_path = os.path.join(".", "onnx_models", "t5-small_encoder_decoder_init.onnx") - self.beam_search_onnx_path = os.path.join(".", "onnx_models", "t5_small_beam_search.onnx") - self.default_arguments = [ - f"-m {self.model_name}", + # Path relative to the build\Release directory, where transformers test is launched in pipeline. + tiny_model_dir = os.path.join( + "testdata", + "transformers", + "tiny_t5", + ) + if os.path.exists(tiny_model_dir): + return os.path.normpath(tiny_model_dir) + + # The path is relative to the current file's directory. + tiny_model_dir = os.path.join( + os.path.dirname(__file__), + "..", + "..", + "testdata", + "transformers", + "tiny_t5", + ) + return os.path.normpath(tiny_model_dir) + + +use_tiny_model = True + + +class TestBeamSearchT5(unittest.TestCase): + """Test BeamSearch for T5 model with fp32 in CPU""" + + @classmethod + def setUpClass(cls): + tiny_model_dir = get_tiny_t5_model_dir() + model_name = "tiny_t5" if use_tiny_model and os.path.exists(tiny_model_dir) else "t5-small" + cls.model_name = tiny_model_dir if model_name == "tiny_t5" else "t5-small" + cls.decoder_onnx_path = os.path.join(".", "t5_onnx_models", f"{model_name}_decoder.onnx") + cls.encoder_onnx_path = os.path.join(".", "t5_onnx_models", f"{model_name}_encoder.onnx") + cls.beam_search_onnx_path = os.path.join(".", "t5_onnx_models", f"{model_name}_beam_search.onnx") + cls.default_arguments = [ + f"-m {cls.model_name}", "--model_type t5", - f"--decoder_onnx {self.decoder_onnx_path}", - f"--encoder_decoder_init_onnx {self.encoder_onnx_path}", - f"--output {self.beam_search_onnx_path}", + f"--decoder_onnx {cls.decoder_onnx_path}", + f"--encoder_decoder_init_onnx {cls.encoder_onnx_path}", + f"--output {cls.beam_search_onnx_path}", "--output_sequences_score", "--repetition_penalty 2.0", ] - self.enable_cuda = torch.cuda.is_available() and "CUDAExecutionProvider" in get_available_providers() + # Remove onnx files if existed for any reason. + cls.remove_onnx_files() - export_t5_onnx_models( - self.model_name, + # This is in class setup so that we only export t5 model once. + paths = export_t5_onnx_models( + cls.model_name, os.path.join(".", "cache_models"), - os.path.join(".", "onnx_models"), + os.path.join(".", "t5_onnx_models"), use_gpu=False, use_external_data_format=False, optimize_onnx=False, - precision=Precision.FLOAT32, + precision=Precision.FLOAT32.value, verbose=False, use_decoder_start_token=False, - merge_encoder_and_decoder_init=True, overwrite=True, disable_auto_mixed_precision=False, use_int32_inputs=True, ) + assert len(paths) == 2 - self.sentences = [ + cls.sentences = [ "translate English to French: The product is released", "summarize: research continues to show that pets bring real health benefits to their owners. Having a dog around can lead to lower levels of stress for both adults and kids.", ] - if os.path.exists(self.beam_search_onnx_path): - os.remove(self.beam_search_onnx_path) + @classmethod + def remove_onnx_files(cls, beam_search_onnx_only: bool = False): + if os.path.exists(cls.beam_search_onnx_path): + os.remove(cls.beam_search_onnx_path) + if os.path.exists(cls.beam_search_onnx_path + ".data"): + os.remove(cls.beam_search_onnx_path + ".data") - def tearDown(self): - self.remove_onnx_files() + if not beam_search_onnx_only: + if os.path.exists(cls.encoder_onnx_path): + os.remove(cls.encoder_onnx_path) + if os.path.exists(cls.decoder_onnx_path): + os.remove(cls.decoder_onnx_path) - def remove_onnx_files(self): - if os.path.exists(self.beam_search_onnx_path): - os.remove(self.beam_search_onnx_path) + @classmethod + def tearDownClass(cls): + # cls.remove_onnx_files() + pass - if os.path.exists(self.decoder_onnx_path): - os.remove(self.decoder_onnx_path) + def setUp(self): + pass - if os.path.exists(self.encoder_onnx_path): - os.remove(self.encoder_onnx_path) + def tearDown(self): + # self.remove_onnx_files(beam_search_onnx_only=True) + pass - def run_beam_search(self, extra_arguments: str, sentences=None, append_arguments=True): - if append_arguments: - arguments = " ".join([*self.default_arguments, extra_arguments]).split() - else: - arguments = extra_arguments.split() + def run_beam_search(self, extra_arguments: str): + arguments = " ".join([*self.default_arguments, extra_arguments]).split() # Test CPU - result = run(arguments, sentences=self.sentences if sentences is None else sentences) + result = run(arguments) self.assertTrue(result["parity"], f"ORT and PyTorch result is different on CPU for arguments {arguments}") - # Test GPU - if self.enable_cuda: - if "--use_gpu" not in arguments: - arguments.append("--use_gpu") - result = run(arguments, sentences=self.sentences if sentences is None else sentences) - self.assertTrue(result["parity"], f"ORT and PyTorch result is different on GPU for arguments {arguments}") - - os.remove(self.beam_search_onnx_path) - - @pytest.mark.slow def test_return_sequences(self): for return_sequences in [1, 2]: self.run_beam_search(f"--num_return_sequences {return_sequences}") - @pytest.mark.slow def test_early_stopping(self): self.run_beam_search("--early_stopping") - @pytest.mark.slow def test_length_penalty(self): for length_penalty in [0.5, 2.0]: self.run_beam_search(f"--length_penalty {length_penalty}") - @pytest.mark.slow def test_no_repeat_ngram(self): for ngram_size in [1, 2]: self.run_beam_search(f"--no_repeat_ngram_size {ngram_size}") - @pytest.mark.slow def test_custom_attention_mask(self): self.run_beam_search("--custom_attention_mask") - @pytest.mark.slow def test_external_data(self): - self.run_beam_search( - f"-m t5-small --model_type t5 -e --output {self.beam_search_onnx_path}", - sentences=None, - append_arguments=False, - ) + self.run_beam_search("-e") + + +@unittest.skipUnless( + has_cuda_environment(), + "skip since there is no cuda environment.", +) +class TestBeamSearchT5Fp16(unittest.TestCase): + """Test BeamSearch for T5 model with fp16 in GPU""" + + @classmethod + def setUpClass(cls): + tiny_model_dir = get_tiny_t5_model_dir() + tiny_model_dir = os.path.normpath(tiny_model_dir) + cls.model_name = "tiny_t5" if use_tiny_model and os.path.exists(tiny_model_dir) else "t5-small" + cls.model_id = tiny_model_dir if cls.model_name == "tiny_t5" else "t5-small" + cls.beam_search_onnx_path = os.path.join(".", "onnx_models", f"{cls.model_name}_beam_search_fp16.onnx") + cls.default_arguments = [ + f"-m {cls.model_id}", + "--model_type t5", + f"--output {cls.beam_search_onnx_path}", + "--min_length 2", + "--max_length 16", + "--use_gpu", + "-p fp16", + ] + + cls.sentences = [ + "translate English to French: The product is released", + "summarize: research continues to show that pets bring real health benefits to their owners. Having a dog around can lead to lower levels of stress for both adults and kids.", + ] + + cls.remove_onnx_files() + + @classmethod + def remove_onnx_files(cls): + model_name = cls.model_name + for file in [ + f"{model_name}_beam_search_fp16.onnx", + f"{model_name}_encoder.onnx", + f"{model_name}_encoder_fp16.onnx", + f"{model_name}_decoder.onnx", + f"{model_name}_decoder_fp16.onnx", + ]: + if os.path.exists(os.path.join(".", "onnx_models", file)): + os.remove(os.path.join(".", "onnx_models", file)) + if os.path.exists(os.path.join(".", "onnx_models", file + ".data")): + os.remove(os.path.join(".", "onnx_models", file + ".data")) + + def setUp(self): + pass + + def tearDown(self): + self.remove_onnx_files() + + def check_encoder_fusion(self): + model_name = self.model_name + onnx_path = os.path.join(".", "onnx_models", f"{model_name}_encoder_fp16.onnx") + + model = onnx.load_model(onnx_path, format=None, load_external_data=True) + from onnxruntime.transformers.onnx_model import OnnxModel + + onnx_model = OnnxModel(model) + op_counters = onnx_model.get_operator_statistics() + print("encoder ops", op_counters) + + expected_node_count = { + "RelativePositionBias": 1, + "SimplifiedLayerNormalization": 5 if use_tiny_model else 13, + "Attention": 2 if use_tiny_model else 6, + } + for key, value in expected_node_count.items(): + self.assertIn(key, op_counters, f"Expected {key} to be in op_counters") + self.assertEqual(op_counters[key], value, f"Expected {key} to be {value}, but got {op_counters[key]}") + + def check_decoder_fusion(self): + model_name = self.model_name + onnx_path = os.path.join(".", "onnx_models", f"{model_name}_decoder_fp16.onnx") + + model = onnx.load_model(onnx_path, format=None, load_external_data=True) + from onnxruntime.transformers.onnx_model import OnnxModel + + onnx_model = OnnxModel(model) + op_counters = onnx_model.get_operator_statistics() + print("decoder ops", op_counters) + + expected_node_count = { + "RelativePositionBias": 1, + "SimplifiedLayerNormalization": 7 if use_tiny_model else 19, + "MultiHeadAttention": 4 if use_tiny_model else 12, + } + for key, value in expected_node_count.items(): + self.assertIn(key, op_counters, f"Expected {key} to be in op_counters") + self.assertEqual(op_counters[key], value, f"Expected {key} to be {value}, but got {op_counters[key]}") + + def run_beam_search(self, extra_arguments: str): + arguments = " ".join([*self.default_arguments, extra_arguments]).split() + result = run(arguments) + self.assertTrue(result["parity"], f"ORT and PyTorch result is different on GPU for arguments {arguments}") + + def test_return_sequences(self): + for return_sequences in [1, 2]: + self.run_beam_search(f"--num_return_sequences {return_sequences}") + + def test_early_stopping(self): + self.run_beam_search("--early_stopping") + + def test_length_penalty(self): + for length_penalty in [0.5, 2.0]: + self.run_beam_search(f"--length_penalty {length_penalty}") + + def test_no_repeat_ngram(self): + for ngram_size in [1, 2]: + self.run_beam_search(f"--no_repeat_ngram_size {ngram_size}") + + def test_external_data(self): + self.run_beam_search("-e") + + # Ensure fusion is done correctly. + self.check_encoder_fusion() + self.check_decoder_fusion() class TestBeamSearchWhisper(unittest.TestCase): @@ -294,7 +439,7 @@ def setUp(self): self.decoder_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_decoder.onnx") self.encoder_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_encoder.onnx") self.beam_search_onnx_path = os.path.join(".", self.onnx_folder, "whisper-tiny_beamsearch.onnx") - self.enable_cuda = torch.cuda.is_available() and "CUDAExecutionProvider" in get_available_providers() + self.enable_cuda = has_cuda_environment() self.base_arguments = [ "-m", diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/added_tokens.json b/onnxruntime/test/testdata/transformers/tiny_t5/added_tokens.json new file mode 100644 index 0000000000000..3f5132007c4fc --- /dev/null +++ b/onnxruntime/test/testdata/transformers/tiny_t5/added_tokens.json @@ -0,0 +1,102 @@ +{ + "": 32099, + "": 32089, + "": 32088, + "": 32087, + "": 32086, + "": 32085, + "": 32084, + "": 32083, + "": 32082, + "": 32081, + "": 32080, + "": 32098, + "": 32079, + "": 32078, + "": 32077, + "": 32076, + "": 32075, + "": 32074, + "": 32073, + "": 32072, + "": 32071, + "": 32070, + "": 32097, + "": 32069, + "": 32068, + "": 32067, + "": 32066, + "": 32065, + "": 32064, + "": 32063, + "": 32062, + "": 32061, + "": 32060, + "": 32096, + "": 32059, + "": 32058, + "": 32057, + "": 32056, + "": 32055, + "": 32054, + "": 32053, + "": 32052, + "": 32051, + "": 32050, + "": 32095, + "": 32049, + "": 32048, + "": 32047, + "": 32046, + "": 32045, + "": 32044, + "": 32043, + "": 32042, + "": 32041, + "": 32040, + "": 32094, + "": 32039, + "": 32038, + "": 32037, + "": 32036, + "": 32035, + "": 32034, + "": 32033, + "": 32032, + "": 32031, + "": 32030, + "": 32093, + "": 32029, + "": 32028, + "": 32027, + "": 32026, + "": 32025, + "": 32024, + "": 32023, + "": 32022, + "": 32021, + "": 32020, + "": 32092, + "": 32019, + "": 32018, + "": 32017, + "": 32016, + "": 32015, + "": 32014, + "": 32013, + "": 32012, + "": 32011, + "": 32010, + "": 32091, + "": 32009, + "": 32008, + "": 32007, + "": 32006, + "": 32005, + "": 32004, + "": 32003, + "": 32002, + "": 32001, + "": 32000, + "": 32090 +} diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/config.json b/onnxruntime/test/testdata/transformers/tiny_t5/config.json new file mode 100644 index 0000000000000..d649732da246f --- /dev/null +++ b/onnxruntime/test/testdata/transformers/tiny_t5/config.json @@ -0,0 +1,60 @@ +{ + "architectures": [ + "T5ForConditionalGeneration" + ], + "classifier_dropout": 0.0, + "d_ff": 16, + "d_kv": 4, + "d_model": 8, + "decoder_start_token_id": 0, + "dense_act_fn": "relu", + "dropout_rate": 0.1, + "eos_token_id": 1, + "feed_forward_proj": "relu", + "initializer_factor": 1.0, + "is_encoder_decoder": true, + "is_gated_act": false, + "layer_norm_epsilon": 1e-06, + "model_type": "t5", + "n_positions": 512, + "num_decoder_layers": 2, + "num_heads": 2, + "num_layers": 2, + "output_past": true, + "pad_token_id": 0, + "relative_attention_max_distance": 128, + "relative_attention_num_buckets": 32, + "task_specific_params": { + "summarization": { + "early_stopping": true, + "length_penalty": 2.0, + "max_length": 200, + "min_length": 30, + "no_repeat_ngram_size": 3, + "num_beams": 4, + "prefix": "summarize: " + }, + "translation_en_to_de": { + "early_stopping": true, + "max_length": 300, + "num_beams": 4, + "prefix": "translate English to German: " + }, + "translation_en_to_fr": { + "early_stopping": true, + "max_length": 300, + "num_beams": 4, + "prefix": "translate English to French: " + }, + "translation_en_to_ro": { + "early_stopping": true, + "max_length": 300, + "num_beams": 4, + "prefix": "translate English to Romanian: " + } + }, + "torch_dtype": "float32", + "transformers_version": "4.42.4", + "use_cache": true, + "vocab_size": 1024 +} diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/generation_config.json b/onnxruntime/test/testdata/transformers/tiny_t5/generation_config.json new file mode 100644 index 0000000000000..6f2a63c77c1b9 --- /dev/null +++ b/onnxruntime/test/testdata/transformers/tiny_t5/generation_config.json @@ -0,0 +1,7 @@ +{ + "_from_model_config": true, + "decoder_start_token_id": 0, + "eos_token_id": 1, + "pad_token_id": 0, + "transformers_version": "4.42.4" +} diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/model.safetensors b/onnxruntime/test/testdata/transformers/tiny_t5/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..1b90602ed07099cfa29684722ca8b22d95c30af2 GIT binary patch literal 48888 zcmcG#2{hN+_y2E}sUqDZnTjTvr}94gNSdWVlT*4R>?&9y_?5sV0i?*ka-&z-c?eW^a{@THM+U_21KJFfV`mSC+Zfo=n^}SpIdtVvq zJ9v0`PVo2l@b+KjsPw`dgWxPXSuZ3 z+AoZcr{{VP|Mk6pG}JRTGhh0bDL#LX(#y~@Gcx|`oOOSX)63AaFt_~c96t{)7ynfo zJ)B+sXCR$jSGlbJk8~4bJ>%aGW-nUL$k5pIuk$zlN75g9?H5GP$k@{G&q)8!iL-aF znEo^5_s{anx}K5ApE=D)f0DPGt%uuxEy7Gco-m-Tlii z|5qXX7eudj^!^|?{5#TL8Mi-39={-ZCgc7{bN`O?H)ql>h@Pp@A35mXk^bg9`UTN5 zH8uT%B=Y}}{=3ln%X%;3&m8pou<$qY`!9^1sl}hU==ZF@DTiMeJ=1Z2=A_@V{-z*) zVf4(5|IAIlXZ=k{{KDv&nHl~;UjH9S{Ojl64z0he_agqxO}~$Je>b%L;^>(h{@K|5 z9`;u>@kgQc7e~+B%=}NH(SI9Se_8KE{BPZPuJU&Aa{lio>Mxsm=H~y5*&g2iKQ6<6 zLG;Z3mF@l->908C4`TK&h@OSfKb7{^NPlyR{(|UP{41&cHPZj_a{O1ywJ`su&i~p6 z_?r>p7evou+&?44za#y3TKr|b7x8C)Gx|SUeEs6+S^g^t{_*qt9`;uR`9~4r7e~)> z+&?44zk~gEgZImNFXEpO;(sIlCxZVU?Wcc1^v3-wFa0&rUm3SQn8?2%dgK0;mHry( zZ%*W25WR60f8?NlH+p|_9{qy!?w}2OWzt)c_;(NW-)Z3==6^x{C@%cZ^ZZ`je>d6w z1JsNAR|fp!XZk(vuZZH0CeuGadPYWu7XR4G{5#x#IfTE=_d<;Rcfk9oSn0DHpP#zPsRF^lE6lCrA5@uVn>yH?qhq4gT9VRVsh> zsnGmqIn-D0hIF4C;m)=D!Q!zp-1xGEp6hvlcW+DLl6XrPHu4y;IU>nRc9~LJVgsLz zmXWs4cBpCohTMr=hDW~1QMdEMNmA!{rq}I@x&zeck$xWpuX0w9GZ&U(rGqrxoRWxB zA1s7+l|%61$aUafmJm5L0ad+Fe&((808kaPMakVepym91un`u)CAFlALC3D(^9iY_ z9P$IC)}_EC89#htzZo>nWWno<2G~%t5@p23fZBu#u#<8D6ZtWM^W&QF(UfDj*v*hh z*tvmEni4&2;zT@hFTjM^oh-FI5A5$qakoK+Jn67J)qS@VKbHQ$Y^AGsLNXC#F&maY zU5EiwjoF0kFQ_fC9o)z75Q>jKO&;&RkKc;3@JXs1)0yao5s@|6lYbZ51`Yw0(--j> z%@BOg@xVSgjN_MMr+A)iT5;#zWWYcM69rQE=+1 z2?>p80Vy*b7+;iBv1+I~?tCzh1pF3H7HJIz@+3i6q%TTzTLfUax`hoBy+d5;^5DDR zExDp0gUiY~m{a^mw%mRcHq94-vUB@b*7Du3$nPu8e6(L+x*-Ep)dJwDSWCr#wpFaC zsgdYu^}`-}b!ztDE_rG{9W~c2AUZV?bW2@X#qzP{q>pVOnRGG~#Ye{p>)%_Wm%$UO zgdh9hZ1Ya0pJzNiwzHK?UMvct(zoH>xPdg!b^(kE>W7Ve??QdSa*Wa+2jsI3D3)Ji ze%+C5;?&b*r<)Spcr6JO?x_pUhc=Gv3tSmkV<7N-1 zuUzI4ol|X)oK^@2_1fU(jwWV$)s^Jj0C1nzMFQ4F;DYW!JbiyBX*!q=ai8ItN1hlZ{wr!+7)p@dV&O( zx+;cK&c=h(stH&r>|sl$ZGubvR-?Q3S(d$}1V0bzfy8^sBw5daUpsLS!pnq^y|ojS z9;@)zuUp}Mv>n8sng|P5r{I(~7C6LrA|{M!gNE&)WYH!kynkJXK3H4Aa%UFehXD@+ z73Gnz)UyvS=^q32uSU@q#bZEzT`D7$3D#j3F~2CAIJ;a0w*i~*q~}r` zd!iYF+Q;!b86j|AOa;r{XtB(4OQs>Q2Sr3e=%0OG^f83rGH=5tqkPn!R1A;LpT;k8 z;l%fL6tI}#G-H7t5xyCS!G#lXPMXcE71mP>LA$fj< zJ?eWC=SCy$>OfSxsYoOy&w(UaJ!pULh(YRVbeX{quuzy!U&cSd*IVj^u_OBk)6Nz^ zlJ-)Jtr&}%r&6G5>0!1ct%SUF)uYF6JjGcSC)vmI4KQYaGmdQ91}~#yVNj3-KfdBL z;`;&ghxmIqpMQnL-+e&pXUqeO+7Jxx9}cbM**G}ef)0-Kz;~i9Y|a=>+}QUvEc7}K z^A|_p{ypR-CWy6ezuY_{$Z>`$HhSGIownLZ3KJYgh zLd8|vpw;y#MnM=^u2@SZ{D>z%q=xZT`{jwt_b?JD8H&cSig+@59G&rI0XnHJhpy%2 zFk-F(3pry&tv$2LBjoG|CpVzZN|HAp_eGrv?YLsx9QG)z8J>-C1hT%6ynPkLQzWE?%YjghCRxV3j2MlY42!-{5+ltdwsco&S)*Jk4QeiCGIT|W9v@nOE= z0bs8w&Xwhh;IvZ=@?Z(78TJ7$oSz8IvxIov{3A(Nsn0t%jK;|_7eJHD>xQ9|1Ux3%3t13kv%a^6>b)Qy1Y4@yvNTO$b{Bf^wUD$!X^TcKfZ3&c?$ zjP5GHh}P9$eKY_XENpp|cRIQL>NvREoe$RwE7;n$EX92{INV08V?74*R>X zrvPZ8h$J;O)xp}1L8L7+o)x(pVaU)_VdklO=rrpd&K`FcR;O#SKZ^~&{@3594=tZ1 z17(vexZ}}zbm`BNWY&ZVv@ZHV?tMwa+$3K-b9*ObPZ&twTuFwm+nQ+G`3l0P_M=Nr z=3wT-Au#a6M0j2ii_NP;VYu!mws7Sf-g9;_S5$lg;$zz5jeY6 z9nJ|Gg`*PX__goG5V&6gdnTQLr@OzPO>io^yCf1%TsOmqTOVV!%}}a5?m1?B8;(_r z`m--NCop`1GT(prHlBP}Dil3kzyt|n*_RD(*xa8-VNcFe;p*+_tk2{Ktb7`d_iVp1 zEAeNzEUX8kJ;sxPZlv-RQ*FyXXhM=ULF&|>}ooQAW@op`3YBwPiWCQ0=QwKea z88?-SUza64q37XV`Y1THU^w28H54k@oPmPF+ElagJ@g;ZjAYDGUSsPj{B2$j93G<2 z2bEXg0*NuaXw-1Jpt)68rkDY_H6@^FT!q7fmxE7&1G(=cN7pa`uIiq|Pf7Uw~W;Ep@j%ywX*Ds4=dUFHmwqA>)*OY)pS0r2RPzaw6oxz7AXOS^c z&nr?TGs=hTZU)0n4b=J4pFL2u$J6oEM7=ExC%q5AVfR;pyW(J0mayEa!)G6p5SHSB z9S`8j4!q}HbW;fhmtBX@aLQFu zemfJM+o|C$t18rIg~Y(m07fn4hkE!r{VS|2(@}y_nZkSl%f~Ma$ zVtBbM<}6BOqILRkCPM>L`%EVr$LSNpaU)^0s2sJ~q=c_CaxqbCsG!u_1h!m0fQN4f z!^7wx7M|9RWt8uN)Y%7xZb#l>pZQLxr>BRd*FUjxnG!s*=PB{1)Ff^f%0PCEIO3To zE0yKS?7;48>|T`!{HOQ;k6l@(zzx_$%;sVxiO9BprssSHsk41uTtX?MGX$Utz2|5Q>D!7`0;`<~6B-{2PD<4fl!wgXCfE>=%4}qM; zQ<#cNAD$5~m+cyrVWnx43G6~7_MIKdpTI^&%@;vVQZZJK$S0u=NyN2$5^1*G37Ux$ zpl1JQ+9;pPH`;2jB{3r0O5Kz?Z_s9ICs6dA=7-(yrsL+tmO%ZAn6;S~=C5tH;tm$r zGTKgP+^P=!6-KawqB`K8(|~WMiNO7)u~^xD0z5@#gNeBbZXYucJywUaYauVl^%E0e z))+CAs~(7r4Hklz?*_8FTeC@1@>$D03D;Oq#SFa3-Uw=%Q^|C}QILDwjjX>wsoB&&qX~zQ)D{SYUCfRM0Nf!8*uQ<1O3;n3+?-14S?y*MPp+2EDrk$NL^oqm8i>LY}+a%8xX(L$(M zoCP~Ir|>W57sLG`L)`qJ89}v+sgF>^@^zss$aM!keQeD=7wzd?ixlImN!J0r7Vzli zL1ga6P?(}2i?Y?1$uX;e6vX0SXU+rm-1yXg++VD$QDW@eBiJn%jWX8~g-0`_`BI;B z%+GiZHmkI_mY)cp&L*Q@&diFh4sbXWnl9q!C7AQdHsYy!JQ+p%1AGCJHVCF|}Kv#KCD{;FXW?_L*&CfT0_ zb7evxL**u^OiaTS;+JqzfdjmJkx8yo1z6(TL-N&}SxetX%rSQe7Z&T#Q4T+`(Xs)S zW_2;Kpb+$3QHGCScnKw;6OL-UWnG;yWbcP!a$tuhb$Vk+V=tY-IYJq7Zb~Cl@w$Rt zuCw6L=jSBlQ4nh{4aB_q44fFa9&TQq2Vyfiu(2+lDLCwe;h`aDv6Iq~_^53^8yOykn_k4jfOmGNbzTA0$}{1^v+-nhv;Bq~P=EH^eF;S(xRy5cKM;Sc*V;;=>^+45lYjw%94s~2ox&sDa| zHJ0@`l)_kAC3&%N4H)MSf@O8hc(vgiJU%WBZqX_@*!hR>uE%f^9J~l*b~`g~+Z}A| z1tn-2xdt_^Tac}WlAtMNfx+LUv9cwJJTqO%`ptX9?ENcYqeKqtGfWDVOm36h1L0WK zjx1fyi#@rzf=x?rB`?1lpm9YL?wzDA{5a+fn^Jxlix=fWqb;!awUfYnoi+p)dRZmC zPr-9VE~s?JIS4!9Lle_ zbAM>La#$R&>$#v)xtK3|ag|h9xuSvd09?9Qh8oOW41pmB;EZZ5Jj>O`@j_FkTq*$r z{1q^h_UGrn$HV>A)1lMb6r&%j(RTkl(pE7B##jl23(gv1=e-SBJlUvMlR;3sQjHpn zNBP{|0M)WYnABApIyzGvGAs4?pbAOq@!S`UY>J^p#_~^V55LwHmPL;I zQ{Mr^eU}x8IkgJkWSk_e;>D!2>=|*neh?a3ACN|4Lk`D<7`gfsEVVF$b35nLhO-n5 zEfE(?Y!VFfDM#Vr3+$V3KAKxgfZMDqV65oKYhUG~?wvw%^zv|CgWGY<^wi#Z#BMk= zv<$7qGAoG4KGu4*FWG1F4Yk6PahJ?O{B~58*i3Q)cN4`q zreLsnG}$<1zo1E;(92C)SbnBhpg$)ccU1PHb#Y&yAn_EOP_p3hK}SLLq#E6m^Af|` z^C8tb3$GMBAcZD_>AB?!xHu`7?AM=+-~mt#PTK6f1T7PsZf@t)epDBmoH{-*Ni@Od@NiMs+n)b_*A zm#5*RYqZc{kT}0qH;9LhPGO~|_F&AnZ`g2V1v;g8f_v*-@^+>n1`d|vtTrA?WE07S zYAdKaos7S=?}QGoebA?LD0N781oPAcyj5t=3UL;XT@nH7?2E}7|Nhu{QWr1fJcId? z)v)2w6kMHD%J{2&EIhNBS&Cd08eH8DCBvta1#yT~-^S5deYN4{h&=S)S_!L5wn7IK zVdN%Gbk9yl);bau58uJ$7n7`7-=^ZwC;1?A;{*yvSEGu{P;k#w6)dD(Rv~IRcyY!E z96Y!WKG-}~@M&f`yc0YiN|mcIYk-STuD7&<(>CBvzuSV^GMPt#NAjo3=!wh7ti%XMtk9w$uD7|N1PXwg;LA@Kc~ z4jXkLj?9%>NzQ)O&k+cMBKLL3hXUB#+zajHy zs__|)>J>xu#dwET7!eK|1vw${M`<61&z@1z#48A$uO_VP`=g zeiOOGyvjCN9kCbXqF#qFS79Jdx)uwyL7A+>a3Z=j@5SP}^*G|ecAP!44$p0`VENZL zyF=~a=h-OKc+kprm8<>7^}~PKf242aC}PlqEAAO0+|k1Tp(-94rUwhNGV$4&0I-Xc zDIdU^K<>^YzGht`{unTv-@9UlgZFx%lEDj1S@nUbIcng-fkv=k)d5yvmM@Y zF?8E8Q#6q~K~h$RQMm8UHf@O{hQ|V#!qzrCY##;1IRsmivT<{iA|G|}2o{flLO+AFT96yAIxELjr}npTAy0fs&kF2vxt^n12dbb$6dx>K&`B6kb3T> z;M4VyuzTJK{A%ce57gQrn-AokUs5rxyBYHz>_GWf4~3eJABbqbheD(DO6)uO0mQx3 z#P_;FmKAso+;^Ns*dzz)uhz1R+q+OFaU@%Mss}zadBEITr{TzaDH_;45HA1p<8;Ig z@bO)Rlc#sVH;E`*?B~;4vuCzJlh>Ql-@4d52F4aB&bcC zKRQ%OD*V?H`wRfHX)-LlDV+7&coAin6yT`n7B=|Z3S#xj24i;_c$l7B+*_!D=EN1&I=KJa>aj9$;=01DCI_BSIliPIBGgW{Q1^SrSSdBpy7tnIp zc&mZ^{IRV%9Mj^yvwP!|*pY*UtW)I@iHRG8TWhwnF<%}DzAC8U(?@q%O^q)~zq`!F zO8dcT@htedw2Unns|fF3A0=DFPs78RV&fH+nn;hk7v5;?X7l9}%yHJpfbf{&R4xx`gvsFJGy zeVGxkw%;ji&N#@-MedQ>-NV66xtv67ZehCbZb0{79eQg|JQVEphhZ<*;sl3IHquHQ z)Q{Q<2l!rO4^pkkK%ODewaB{#k;hD^u7e4~#s=&GvG8)jPAHR1_Q zxzL9j)v5EE6{_^j%_I2A{fWTWVLZL-{}vV2oFo#SF*qtzhwT}wM8iApV$htcf4*xL~Z3fG$6dJ7$ca_Sc>g?c1VIx=z5)N595G2Yun#@xG{<8jBJw z{piT792mX!5|CJBbo7q?kMZ;V%n%f`FTlF9%W&W-TX?rp6z90QVtGp!aUWU;dG$jH z;TMI6uU}^dAMeAWJ~@I#hf5f!J{8t`m6AbABXIf0iL6PZ5a;dOfQGi|P|4d-6H;Kg zbtfpDapinp1zQ#&i`wCXd57A3Ha|~*XK4d!D@&0|Mg@H(?7*p~m^6Hl#kNv;`ZMws zF&Os+-VZdV4S8O8+gXAxbuD0H^qNV(GaF#{kCW`jDKiMor*K>*7EXvYF#o4d;hm)n z*2rZdson{OQS(Wjv;hozwGnE*{a{nxzk?n3kAtVHD9nrWBfggh(y=YZY|Qo?yeTe; z6n<)?y!dsO)KFW(?SM3$$x?Sl6Yt@+_8-h9_OM_i-3h}PN* zAZ+(HLB!!gq#>njvbm$McIgfF?m`DSxmJhXUObQNYwU-EwMXL5q*fekcn7v=hNJJ4 zmlzd2AIk<_gXf-#q?(+Cl1mJGDxBcZ)?LJEf+4CLJp~68H-OrwaColUh!ca?pxoSG zGT^v4UD-N@UsdqMEoWfIKy=_^>D|E};J2RhsGQ$OJcAJR1ud|8Net*Y$byrB9PHL!LtZ-$#q)}Z z!nMzm;PiocxL79`rwum6O_LLuMT8-4OI`{eEt814-}dn;+j7axWN|p=7lFaO^;*S8 zJ~-Z6p5Ohh1lC#)(b%d-u-Nky$w(Q1bzSxNL*@Y8{GF{obW@iI_ z661mrSNyqnl<_K&Ruab4s zcEYT#0r;j;2&aEjz}qLsQ3moj@J$3B<`n0?uVp?@t+?CZFOd0pD$E;F&90a9hx^ZS zp?LKkc=h2N%s(`qSWKOdc}7jbS5saJmIiUy@+KR)wEB~F(UIiD@cYc`-gPkgyc7J% zbzGS{f+deQ0)0A^!0r4HB6t-8l5bbT_oM{0nyCdX!p{)m`<+z#oQ4-lXP{`wI`(~- zDPV#+&UMHmJ*zF@^R{^yD-wqFgBtK^{4$t%v;IHUZwDCN!MRB_?0C#Vc)I5y%dTZU>tkkKy3NJZ$r~0rRmlz__4Nps2kM_b?&M zAG?80wlgPXMu+j!a%=2Rt%KH$Dfs@q7Tz(9#=`!kaLRfZP6r1TkbRwWedx#C`41?G z$pvD0kBFFrk%3bsAVE`v$O}zD?r{}4pH$d8r@G+o_bS17v30`mVhI#GDFMRbTQK|b zLu|kM75tS`ktp`o&5L6p)v+3QUcS|WOQ+B^WTe%}g5El;moC+LeG0~?KEzhPDXiYG z4vpNO5|jQt__^&U8#dO1yhs$IK~9slD%8M&G7e&Lhn ziE!x9NwDv&A@;ppM0n~D+!WHn?Ar}1Y|WEl+j2wFQn&^xI>gZF)@X=2_@YAE=O{Cm z*g@hG3fZc8X(Xht0u0nVAzT}KhZH?Lj2HUr64$YQ&^;#+#Mg%r5%sIWhmMkLMA;b< z7&8W9OttX#)=y-Ti5f}-^!A{HTw{C3427?4`=P(yI&>5HBs>@Th)6UXBQpxlpxoel z8CycULsrwag%?eU3uMbTJ|n zdg0HqT5vgi8Ba^^#*D_+iqR8d=-#(?$+>$)!U-Gm0qt}^O)wPRC6^(7QKKzpX-uT0 z8g4#UV%k;h~Dhu3Cir;R} zhFPbYapIso74L+D$#0ovG}_6JX&v4{pd$f1o==Ab&riWtj~M>s)KrR_i{WbZl>bF4(pRhf~IM3yGe3fZPWs|*gX>2m)^R~)ff^`^^&~|dyWTJ&J$)Fs>Ppb3Xr?- zi7;K{H#Fs%{F&_;LEiJ;>D@7ccs9L*`JKjm(VcRXEy;uHJ$E5>#{%xE9LuWaEP>|a zo9OdoGPGW|fLpp-!2XyR-B36PlQxVdE3Uht*?1+4O*F%<<^B0<^FDOs0U4Yg5Q(GY zGy#SjB;UOnVb7A&=rCK3PadpB3d9WLA?~KBAiME1+#cP5ZG&Z~xluHGEwrKME(kH~qHRUS6-PXL)(n%J zZ?mBGMEqcNi%rhC2ZOio0~^shc)PF_kKNOtL2oi)%aQRoczFtT+8l+-%yitTXas%k zX`@_lIOfjGW%V}|_=xGsnBGSnl`hAEc37vNAnO3?;ZYo@F$7;UA0#=APNZasANZVh z1E8b-#EF+Wz~o~tgxM4=)tKRl31RNq4$E6(>XY6sDPavbff03ZAgL+uGu z<`7YiYxYT^n|vOcgu9a!zxA;65O-$Ldw$~*BV@UQZ<2b$dKUfR8hKlEl^q>=ll0_` zrJH$weqZdQu=_$AsaV~`YJIHm%Y9LPWw|E5xxgF6Y>vU!vMRFgyFVLy`I=zN4%BxRE`X@k}`D@}t&9L;`2(&PY z!OO-5@bYsbGnI-(zdmP#`h{D-f5Jr~UepcQ<0;k;U4+x>y|FkUj2Nw5)?4R#&m>LthLYt%Us05R`p-5=M%b61^jb;Xu1@ zJJah)%gd(%$=R1!vR5?uem0Rv^dAn2`Oys3FEH~#C*aKY1|sD;jNQ*)M|=WI;j=&r zpFfoarDwy*-1ZBk_iUduwJv6Jrg*^Q!*%d3MT1|Ox}W_zmwGyNC{6DU6GUc3;}Gdm zVO#AQ(sX+s6n(ov%Jo+>_cRlnFaME9Zs{b`*FQqd3+AxoOJs%4?s!OkDFPpb2Iw_5 z6o|SSZ)r}&J{w*NS1zynkNqM4sXim|$pBriIMS?Ry6^;(xXQwln5^p0_sB@lA-j~R z*qnEK&(JGyY@Qh%xuc#QU))YJ4xB}WiFy!j`v7NcvE}D8_RzFp$>b-mVQFtJ(se#v zLfa=};PTa-+(g!zI-XYL{Vyt1PK?ar!6Q}pq$GR3X21$+<~qvyL#H@D-egBj4yW^d za`))Mj`jRQ(-eA6^eKt+EaJ0U;%KCJ8=LcC2d%j}gbKqH`DA8B%a1D20n!JsFfWs{ z+5I7ZbR-?2R7g&>twvcrHF{u)BYhgK3@7f(QnjWf@Il@gYMK|oq}pHh0#0ljdbdmZeV4%xXsp;sCS`|U%WAqI`3XZ{kJ&Mt-a%v z(tFN3M_P{30u8*a8$i7SSMX8NE!=KFHT`~j6{{*1k`VtFwERmowJ)fkHpe!zj=jD8 zBy*GLdfofzCfh)z*2K|ZiIM!OWfi{})WVKJ;LzVCwWdoEd+US4AlCy@l`a)o;1H z{iZT!3uD-bOE=;Bq97U*pTQpw+Q1fjhC=C+Q2)5&eAskj>jyz@ zyzhow{4rrY$~TD-;|xTgux9rqcK1iXdmHEDx5>!K6K0`D+)8|i@x1(O6MTD)<)ARn{d8MEDGD^jG|je3d)Y(OD>OGz!j!uLzBA; zv-gprf~|{am%>Q8qP3o?rFYWR56$>^6?N;-)obaC@v3xTS1srLkMR+nWAJRdsI{St z2z@o)kb8=R@Q^rVoLaRDLsPRMq%xG$g;~<*xEC;gPB9KXAIC-IdV2!u!f3en3_dEp z0}30{`He>%kecMfs~zvb<5sE44;P>F_k1dbT;D~D?e?>+^TYVqW+PfRdu4CWbqH+t zt>P1u=Tg!4Hi9k_J3O=J8eAUXPD_7k@xzLfdUZ8~`kJ5MC2A@3gkUdMsgb1Tdyid1 z_LbuekAZyUqLqA_mmczm(tO&Aaoi&3Ecdz>%M-R9#78MZ`Th+d5Orn&9p;)q)f=|6 zj3PBUFv|fNhHRiUn>?x3D+b<%YB1sGVLqrxo0hv>=J`4Isd-Ir@A}(NK5Nc&ertj* zpFC(e?pf)JE2?K(H@N!p`sy#Nr-j2q8+$%<<~@2<|1_BwnNE{`OGCAG3m&DB0D&L& zaJ_=9^x|=UIuoO*p7?JxMyic&J68`gz8%8hS@OJddnJq+mLya$2Rg}6y7E@(e7^3+ zah@J6N;mJ9gEgs>`4-!3uAP2`rrF-0W-VK(`NuW%`P3_1D)9(CVJ{7HK0m^nDod$X z_ezk~AI~!vh0!OMPjT;CU&$rYLfXAas?y(hE~*$U_f_(Tyt(U>_ERQEjKWy)Wa_HV)_e=Io-PJ(f%}>@ z3Qf09rqN$t(6?Pvxv#1m*L${%`|34Oqu-Kn!>&jC%Wtb`dT1$^m7mNnC&<%c`yu>u zfGE8mdljZk?nV`_U2I0MLD3?9uD68Fjhg!-KzkV`1B(_>{AI@#}I8+Vv)qDtJ`$9*;E` zamt(@xvop!nij(b;}}>!DuvvYi{ibfo_tKJC4U??j9Z%LbCV^CJfxtFgiU^e?)P2r zxOzH@X10-@PyK04TpZtCUreP}q~cM{Od6RiN$t2qrO%TlNX{xjg{%^ov{9F?-s(x6 z@-EW33!A`OGly=QI@CJ%QzDnEXyD1yMpRA_^`jEr=~U8l7jJGAvCehR=Esa*kdend zVe*TGymML_mt5@0wc6!)M5Qc^(_BC|_?V%?d{KHM*rM{o%*EW)X(yPtO7k^Z#jyRo z4PSBKIFHXa13%`Au0 zX)7G~hp=h%QG5VzJampncyHu;EL!lq>Q^G^K9Rp@(&w?dclfP-6*R4)omMv1!x`lV zm|+)6=h^`w^98;d^L7l(_Yy#)lv~P=!x9 zc?eGj$5Ic+PQFV?1P4c-p&Mh%@m=mIK5BC&1{JQLU+Scp)397peLbE#3|4@XV&BQA z&3624zcu{LhF$#24F|k`Vh+x~Jh0MAaFiF7htcfueKEKvg}ZHy5{m38d>Q< zvn2b`kVobGHC;rXR0Pwfc86fun@~`AWyiRDx=Y>}Dt)NDACZAyo z90$;;Dj$ho;}@*={=mF%TF`?wW>j{IJe1y5xBl)w9rVk3;Dkp7jw~(V15*}3P3A7x z!ed9$fb5bDJX*`MvEI zx!$8>!G`nMv>?WUW~C_b1cPblFyRSwS53qQ^HLtRW-m8?aF9!CFXJy0Ho&OaW2n=< z5ROaC1+VQ1JU5!cWjzPOyput+T1S&Ed+rEYg({Vy)#jDzwH~OwA&r0Dlqx*1EtY1R zJf$o-9~|2SmAh(tbFfVr+*$6x=SIE-m8HparF$sNa+ZaleWf5~ejJy2ZJ-zG57L2( zmgxMojbD2l$jW0RY5VgttaRogI`ll@gSIc`R+)patwol0SY^>J&m3<2J(C~*{0vf- zkKi}kR6ssB7OdY4uue@ zio*G5&$D!R+K5W+o(o{0o5rVY@#S~JR&uv2J5+ev0XaH#LWAmNJX%`AlN0*VooRPy zsQmyw>O~nfY?=U4wzYh1VkckOlnF84w}SD0W!k^KmY)8iLIuOpY5M*%I9_x$-xd={ zi)1%(cdf;EBqERZBzMDFRiK|6%1~Y@ho^4*iS`$x>8%SL{O24^>)Ad9M7mE5pQ=2Q z-W<7)=_DTIrL$M^_p|J&ZABcPJB6cfcrvwG62iq7YgFz??o(;#5YHp_XM)PdXnH{} ziXK_m-#Xpu9@ADzrpCGF@LomleSn}h(EO$bi+}d1yfUW*^cTC(9I@$CeO5K@db=OL zZAs^zqe>u3BZKyh5fFXd{d}9tM+}iuph+ncd9AmUb#Qwt>*_rg)Hznh8{1R)-HJqB zVrM}EZm#6tH@_r4QTnh#2cJ$=wVq$72^TV|= zm$WYC^(7Z+>=7mUa&K=fzH*GfSf?+4vgZAlt?wY_H_e_P#^X?ar}-!LScuSgE%6*u<_w+CheMEJpxcY`<`Ys=@m zSb*ug7VaoNk}mX%dSyMgrbRTXQG{8qN4@f91Rx}R>6U&8j|<__98b|dw@^N|mAZiMZY5nR?zjIKIXfT>3L{C@jV z?$z6y7@Zvpt!b$^?r|FA^nT95;VFE-VJh!YY+wqjG~24 zq9L$!In<7C<~jzSss6aDbf2zjB~}Rd3y~5kvCf_rq&z`|tBri({vz7lT8mXPb_#`G z@6$E*)->x4_I7!B(H#R%a-$hK!Y3Q#`QE8Q&K8(ZJB>O%a(g6YA zB|3PPAr1dw%3p2?<3~NzaH4fKALE%pwvA1s$C#|OMqxbPB<;on7H#C0MtY)UnJo{p zJwe@D_VXQ)OX=H3j_iQVMEtJMyU$VNykSKdukYKJzbaFpZ8QkS)N>{Ywdg&)4MsRd z@gWXV;Dh-W+yZ=H>56W7*fVUmFsmdL4?p{giQO@@kHu&% zSDr&VW{OsxTw}|}U!2B$??+N~k7r=y;RB<3&QREYnA%E+R9bvUgZg)Vy?s)Job>k4 zh|Zl%Hck`cCwI?;;GcKU-f1v@JJXrh9a%`iTbEZp|c;KRY z5fp1C(o+Uq5Pg1~AYi#He>lyOi=EA(MB0qMf23&r&3rn&mfepV4cFiS=hV2{5-XZ( zHkBtNhoYHR1vTAhRhc|xIiF;|n$O~ibpO(PWNWy-wg)>hPoPe8p-{=LKV22)!;ALr1J&OBiC9tuSdW_yO|QjhjQSJiJauyK z9mQkxVEiRiKXVeL+paL3cponM-2w;I6!ORE%X!7T-g~fF2k1%@1FCm>JCBpTK<#i7 z>@^hd+TObjA2fn6eeY1N{o4`x)Ha&H;;HoF%w|Y++QK*a$MVvR&7>j7kvbnLV>4^w z=&7yA^lRo+?sTV*^{BHAe0BCx?k#J;Efvs@A7`Y-#EwQZdA61D)D87Onh3`Tckc z>&PDmuyLj&7acjO_wLFOx^9L8J=U}rQ-i0$@yc~HeAg;^H{}#pzaz~L`!$06EpaYd zS^#3l-MKmXK+&RCaJ;!srOknKc3b#`nr1Gg6NT6KPLIjf^YyO5vFaAcIDd-%T)h;R zUOhWnvHsIKSnBV>`3C(HnYf;`?tw7_nllsb01CJ#d!6sn-F)h zSNjVqVfO3};R5J}Yd2TZPR}Noq!mM-&&#EO zkf&Cs>5TU$xWj!%uJ!2xx4bSxN3`GPOAfz+tU5RPC}KA4GgXr-e=?;zMfTCHLocIB zoqXkkPhPZU{uF+tM1{JD7qKPF?}N5gCzzC3{y&P&!=J174dYfNiBO6ZT2w|6NzQYB z%7{ubDzc@eg{Df`Gs(zE$PA%mkMrE0RHR`fMeCcEP*G8#@;kr(;GEa%jQhT>_jNtk znlg>|rTYa5)|g2Hw##riBS`KNgm=7d zR*}o(SLyq~N%g~wRD&$=PIZ!Ax&)NB){x>WDp<7n1*utZn9dvbgR4!8$jj8^I(GLr zvOGxvM2gPW@P(FwUym~UwUHw?ZHsW>3~O+_sELdJtwueEOPJ$&nawQv0HvJY{Jqg1 zEQM{ceIywaBzJ?e^=uLlSVnlJw_sTCG>!!PCZSt&P?}@-BTFXWBOft1dfFLO^A?d6 zXB2ovv;+^RTeDB@$bM9FPGNm^YXq&CPh|IW=Oo+Y>N?ZF?U z#&st=nX&=d!w2v}loc-WUIA@$_u|(h`@#FY0Gji-oOts&CSjrt{ukgt!pA?8=xT51 z*cp!-pL`+9)VHuU=Bo707ZD;NK1ODhXyCkZhE9cBMux}P(J2;i#Uzb{ zt2VQJ*PerM{ViH5?2Tr7iax)O(ca0MS*&Oa@us45wrv7EQj(1gTg_p=&J!}FXEIMBY%-`h z%;2fW1kwFU<)maa5Bv4};ia@L=<>Grtuehd9LEeBn=9j~Q(6At$M z0mpfBabWKOSo$pnte^ih_#5|*j$1DU7nK2~`Q!`I<1<_bN3tPkz>S$)R0-Pu3dw|1 z)$C;MS*%Png>!!@alL&oRQSh3y>$a7=@-!C?e}p1Z&{dXxu3Mn^n)JZmEd*09H^Ke zG=BaB_upP3Zwx3-Sw9y(Z@5o4%lMNSi;8K-@MpSr!5C4J+yIt|(P;Qa6jP?w0PLJd zE)OjxzG1Ury2c#*QZj+}>+}bb`8yfDy4=RVL);vb)QMU*Obxs*Jzz>7IFhoDGVt}P zB8ctIp{^-!(dffV5HwDvkd{T4{5JwQ$AsXgWgDuN1(OENFu1TLhUEV)BY8`1kdWa` zIMs&B;GXRyYc&p$#}cW`o{J2wx)K88-p!0fs~KkJchO67wIo)0B7eW<0~|S3f=+{t z;8xN~OZAlD&7l{#zdDZW@{-{%l=#WccJ?Ph>#Jcf*aO{us1i>m%3vhoGI`r1g@^0+ zVEV;jD&`_dfB9B%-(X{Czx9+H6&B_Fz7&s62lcVC(*e9b%%Nh>qzn{1uD~T>G2XsK z*O|4&**IZaB`GuZqhss=SbugU<_XxrS8oaaB-OvjJ2?L<^@F zaeLm2mHb{|Q~F;=0JG%9Wz>+I4Ez3O!Ej76`lsk)@YHo|-S1;?Y;6oRNt?+2kjlb4 z(}U@bN?|mp`+z~$pOV&?o46u|Pj$9DAVG!#cq?EEtq=3X(mpj*3^_xmer~|c3;gNS zykf$W%+`NDdXok&PJvgyH!@Qq`E|)A*|?_2m2R3(pyh=KJiZ4s+&7ESwu_~8Qy$eF z()|Op^-Wz))CAtdJahK=gBE(sGysdNi!o8(2eYs8>9@?E%;W^5H&q6yRqk5IlzWAi z6IHP5fH*ApxC}geEQzhgA4X^SO0sC;HL_8tkBxs`jqLW125Ys=@NV85JS%$yw_Ui& zCiV1_TQgU{L+4bYcYF_+omRtTEdgB4kA)Lg523>SFLG$;`w(5`w%>s@uT3v7ge8D>T-V@a;F1V}Dr|E+c(ZPhmQK^5^`Yaz)sGu7JJ! z;t^?iTLorMGRe)!m&hTXqjcMcD@6OMKJKZxPR+L^klgk$sQP_^PWUxOmj3sJjIIAh zU0%Ipp58Vhg(KAl(fnXc7>FRu(Pm=k>y9r!PGtJt?j&y01M%~KGv<~*gI^cp0i|2; z`(k-wQaViU{SZV+;b!M;?{9+y?+gIX3oP&b){6Kd@=Q#J{<@zjC^@7gkr1mp)BDLR$jFN zi>*0ynYK3lZ}Ub{6&p)e*<_MLVO`SIR*L^@Uox(wpI(o@OioWe8(b@)pQOq@5tz^AM5F76$6O6+EX z4h=)S>lWHO;R4PPy@g90HsOM8bKqPRAF`fTz{52r>~42k=#)AM#9#yx#^1t{-H&lW z=q&uHk_WnsFqod*1T!=rz=o44IGNKaE;pZmQ1v^sVde|+bK4ZYdBQ8Q$8I4!TyPua zIJQ8lu^$FWc%x3u0kYBI0@ZGE1^*H!svIH5m-3j%>$AVWl-V!Gb+f0#q>g-6Hw5uw z$v^B?p9C9=&4y%g#nLGDQS}L7?icaGz^$L+K|b`eN@e#+LI*@EIW59oWxN|;riNO$(6 z5(EBEk|UCi^#ya#dqWg`zs(Q61n}ukEmu;_gkk0j1NwYlC|cSi;^nUl{nGG*ysj7G zP5RFYttGCI&e8_jyTc#G53%Spau^5H`(WwU49FREz_U#(J+Y|~I=9sU8(Bb}-0i|K z+cZYKlFP(Khq4l_S0K{PhJ1T<1g7jN!L_>oqw7hcG=Zk@)j3Esr9OA#=l^oJU4@+Svmli}*2CA$P(nQK1)$l&1U$Jyfqz>#3pS~& z#0iyJFn0Y0G@NcFv)*+Q=fO>++bWcH&eVjuthFGwQx!LyJq#x8qtv8gKKPGw-mlVc zs>W=>?){GpCOJ=l-S>Y3v+@q6Kc7Z@tof*DnFGtBE|IW=m#9?!fGtV#!NvvCFzn6* z{wZ&LM&-0PT@(0@jHaB2B}=(kOYStA^w$}sY6D>7k-c~**%g)f8vI=gu2IwDFCc0> z3@(mKq56tFr2l&Y-1Xl>0w!O8M9$xGyY++0B-&DT=3(>~m_|Jur|=GaGoo7ScH_-M z#rS2-LHsHtP3uQqk-2u_5LBDY%waAup9O``C+PyzOu7$WYpqDzv@keqql*t$q{D)V z4;TfP`y{K#8fBZl)A-;cY^+ZN%zT{)Ha1mc(TYaa#$uG5t7~TsO)V-}d9udEDfIl$>FgSt zdb+w#n)hu$5__{^Nq)j&cy&C6guS{3)ur*|S4TL^_!+j{6b5sC%LdsAFu2|w8u2Fmy8Z`we@zq=;(oG^T^8Zk$7i@l z@CmFv^b~ZY_A|wWtElL3EZz5=!Faj_~3wS(wdARDhAXs+6U1ZQO;Ry0*CyGb)5WT*4z?>_^ z?VA@+Ma^2$l_1I=5>3Fq_;g%&|1-`1w-9X(=0I(T6~ylqf_CkA#$|sWs2==Bd`;Ei zhf4*$KWqp#5(-4|jR{=c6oaDDCh*TMaP{m#BYf1i1q|C_F}6Dp3!0CT_R)DHtzH%@ z_sj6i8inYKpI`Cn;1Fv4QsPZdJx2qF4dC$X)!^}ADLlxR=F|QE@MJ(KzN)&2p5-~z z$0G=9Dw0V9LOB~8V(j#vG_(Wj`N($(PL*i+1ANrDD+R^d^dG+>QgKhI(Fc{ zql@s@^Gn1b@-cf>;XO-ddce9wcQF0S?FOaQT%JyluR5WU%=le^tyzuC$BcaT+HP$u zK2nNW4+@#BaMED@dCnUgEMu0q$ajVE7U5Tt8MM8CHHR(kcTpdX+t2#v`lKk z=WjfD%ghsTsr5w?DJ25xaqFd-?!t?{yKtwy6eHDd>f%PQH5yXmd|uW3?t8VBV@&0!@z+Gc7Ba0y)T`D z8hj6Q9*%__$%b@NnKUHKsbXD9SiC&^4pT+{B6c4pF80>&MQJimWL^u5G+gAexprLM zLJUhA#z@%b`TVfsDiF9h9%gE0qWNPA3D$S&l=4y`&om!G2LmAd&N;knwwczqSt?lR)f{J4S3 zw#P6@Cp95z%|&oe4#O(VI%d3J9T?oVh7WRo!1(89xRyBq21X(o$z>DZL(dIt#tU?e z7e{QbYC(I=Z}K>#8nZ55pxay;;YQmW6b-DSzU%E#aPSm57W|<;Z3+0$^g1m0d4b7( z9taP8E69wT9I{{R0W6!cib-6v0KeUiAqJ}VNO4s(^JbtQ99t~mPlo{A_+AnADVD;o zgbpfiZ$_h3OW;+o4R#1T2Zvc5)OPk<_@wouwsV&foD4dL0d0@K#N`^*74k)s%p~S5 zWRpLEFPL=>W2pKyn<&aT(|rT)DZH=3@y#aiFhZI)<-%kX^Y&vo`yXGMOEagFt`m3N z7nti(2r@TCd43&QFvBMkU0Z>rIx{$GFRB~TOXUb{Mj?rFE~%m1fCD(6U|@O;Mq?@JY`V{U0&7r zo6|1Veb1vSbN!&vau$yn@r7rJ3!o*Z45l}Q;jWXBRMF!VvFMor&$jWIp(8=4d1My9 zCPxRH{W<{VM-$mqaK|tLzPu7czi(MsQCo$*r3%iLJdihcqryH?<-4U(8N?E>9Rldy5WGB)OF@idn> zLY8y`o*78Qv#VS2Z(|S~<9zNst5VS5od=btU(r8s8S5B11AYI-fy{0m*Mpf2`ilf{ zcHm}of5pu)WzJN7Lo)pkpH0I1m7wd<6F9wl9{uuqHLOkEO?H~};0tjNJakb2jCvbM z{@o0Eu;MTcSw0`tjygc=<{Ic{cHaNX%Bp~F8Q z)yWkr@`U+X6H;LAaUNl|sYB8B4Uq9n5N^y&V;T)ZnV;U@h)YcptqyF0HBY`n%eFfJ z%vqBB`6`q6Cy9xcio^cdQ%Rp>5Ho%8c1CtM)!>tB3w6;fBFo%c(Cpq3n9*v9Cx|S& zC@LIB3s;cw`+Gr5y&MFKDcM>Y%U<9u#OPH@-2If%OHqsPB&T5w{qSP2X)8!?f66Z3 zPO*M-GNfyKrjKR_!#af>P}*dU3D14)26rDrSVK` zEaY>3!5=9-_?qiQS{|(?<|!iJ7AXs5h4aA1ZqtlcS# z!i%oK#hGt0EcYb|R=kI=`G;ZWi(-1^;5^oK1E2>hqVZh`?`!;$WX@32PfO=uF4u zC>AycFWpUs5xvEj;QW_fYpMdZgiGW~(p*T`1p<=0!Ok~^bi3|?_;>Dvc%1^{4bynBs$1CJtk2l~d?u=;Z$<;_4kp_(0maVT zprR9GSP|dvb;m?PNy&W!+>w_BTg11+VD|-jw=9#s5>X`ibs1E9#RUH5DYN*E&VE?m zaTTLq__G0p)}-pX9jIxq#Q1euWO!l}Y8)`fix%IZi+2m=Fslu$4k`0u7apavHtYez z&|J3i`bVZzP>C-y+Y?N6Oduro1nlP+D);B>aK5Ak`H=SnVw*(pZg(JAv}+Bfjz`ly z_V=Ny{**!Mq()qJej?VWeuv^EmytJbDaZ_a!<|+6*nVjagymM!Nugb2Y{yjI5@roZ zJ3pi)3*>NVa3_ZBJ+;d@tRg)HA`Y*26ZFw29AUu;uY?=ZpD}~4+7bA9;@e{iLn;!N# zF2b#kW6{OsJ(;g*i*3BA807hbOsS{`Ml1#Vl0~qva@&yiZks+2G;JvLxk% zFuzyt8Z%92JBHm4VMF^HNv7=-?3=93j@wa2=a>`}PE~@hwgoV8xifa2?ZZV0Z|jsq z&fp(c`MPCJbzJs01eE+W(72qBOMV;U+}3d1tu+f(cR#0o8S(Um?s+J>&7y5}5_~9> z<@8@2lsRY)XLlsg>^b3(Xy1W>FT2PYnhYCv4=@cibHR6%;-ZV+(1PA3yv+^dPT_1` zHTP|)T_FdLqA!8tl~R&3S(`BFcNvLkYB*)VE4X^k8&Cdq$E4^v@N8rc*jO~d!_>u4 zdEzacYKw$Wqe>$D62(8$>0>gF0vEkDc-dau- zxVku%*i2Nw`4cYGNoo9px?LaH#s%Mr;mJ4<`s;~|Z6-0ZX#jgZr>}eJqq@Uu2(Y?{ zSD9GSVqpeHR*usc^;z^?!VyX(DyYW4OJFh54f+3`&`WL2)V+8B))XWXm7aX|=!98> z{o+XPnLYq_v77KmS{Yxiz6SrWlQf$~)6){4;K`3tlKNpD>T2w!YL*7z%}+$HuY&xV zsjZN;xP-an8cCwHJg{!{7P_JJ9mG{lMUA<3w5{?6l-o~7$uowSbzch8j^6>{s~7Q? zl{jxsivUFV>XO+VinuAx3ci=k00)WxXqmbk#_I{gof;?FY*c;~VbZ<|>&d-umO(plQ!5M91H1`;$VeKvnC zMk}VHX>dMym9IoAj2*B^=m#qF6w$ z{QY-ySUafphR!hgv2Q)D!Ix=zV zGN{*=9F+DujwvOwP&{W1JoUAt-r_TO-T@YLL9scsHom3OD#64y{Wkt+2t_%a&3uiG zei$z}1%0Mz!(78Cm~&nZV`pYVjE^ZzS@4(civ7YcLkID9w>#XhK7`RbZs2R}$b}x(-;A_PYW2!l{@&_sI<=KHLJwy_M)xnLwPC-9gJMd|cgDGmSsDr;~oQ z&tue|I^%Ya<*@UbA2j`RgvS*IP&_&X&U_GrR}L>|6622tzKVl4r@f`EiYBPPj)~*E znQLn-@J1tIUGa00om~Q7MH0yE30H_;)jE=MSds6UkcKNR$Kx%(0Guy=72w4%S$wV) zmUi^v`UQTdIe3a}b$d!o8lIrPO)QN_OQU1?-LT_6pWaVjfub8Wf^YpM=ov_*VkYW% zsVN5S^_ByBMTX2j_y!cG&V=6Gg6N8M%!k}!IJg=>;@cPqd_4yN17duI+9=YpXbLa# zlJx4!Jh=S`>#l8P9gF|0zOisVZhUYIt9!d( z;GH`@-La4PFhdr)+?4rKT~fI`&jt`S6~b-hE%@`dC(W(N#Ol4iSQWmC+^wB~ZbrK? z`p{hzD)NI@oj0+T4I_VgzLU_-bd;RLrw{7GY2)Sn@KNs`aWuOQJBAWa#cC}^j$EW6 z(>Igi)rJuFeiH6ksE0$3v;iDz!E<0LO{y%SUb*(*qw0?yIlq|`>)SxmNEh=eLLe!s z9}OfTG5KXSx&+$5lg;a)#5x>L>6v1pnkY}Io04yT7Qr1yQE0Zj4gXnhVQca@Ry4^5 zPY0X_<9#(m{^_gQZ88(dXX_#ACZ0w5E~@gnPNbvI>3?*(T>whfykYiyzCt<*2H9@S zy#|}CZ z`W2o(TLAe<3rT;DFWK#gb^A4C@jsagGAdif?up-pUA$`sX>!5TKx+lY1V|I?zd<$k zOT+v7FF~SjF?fn-V``uV9x_qDx#!d{XPyEtX;UuVZtuZ!0@rcI_I6zS`W$^?TnKKD z#^`0uG#KbAW(P0ip(ZbS~(#7l|Pk*+^u@tQp0Z%zK0>=Shk@08xX3tFC zk4YWW=7c?}+%|wZ&5N)^CbH(fn>9v3FiL*E2me<1fpD}Vejl5}KAg+3Pkq8*_|O&( zN#3J%OC!K|*LnEd?#|5d9--1sDr|!JQX;xg8kz;Y=}2%HooDg|D->>m0N)zed(T*3 z1ra=^uL-Z*3uwRr8I19n0KC^0sP2}Bm%dB!Vmbfhwx2vdwO@x!HEzc_(TP;xT_cLl zm_fHDXu|o*snD5y8h_7tNBx?%(<+V)JN8BgTQ2l75sT#E!+(}E`G+LYnc{|dkMB{* zZ~erwtDkIDO2VBn!Wbg85>#w1QvKCh8A3B+zwnQG++s)(V z2VZ=2xPcy7?nP(K6#-i(fa*gMu=(H#I6oo^FT3q}r))AY@e9`j z-wB`g-G!3OJ!eioRXxJiZ;{!#g1TM&9I%sW2C6izrvVVz5#!5@xaS$Nr>ycrcF z#&tJgOnf6TGyH`QSTiW^UkU4H4bs=sBzU;T2dC`2ioKi^EoEiN(XQEG=9>)rH2|lb zK8T*3f#_%dj&5{ckB57WN!;>PsNedT-1=$_3&IB3^Vv5Top0U->L&T<>|6vQHLuv6 zBofXHA0RxXrFbv;FwvX76s|9d#7xr%xF~od8vU#R_umYgIen1qJ^unh{v4H`l231@ zL=b`39HYDC1^kdy!%uAyTqnIXZpyhzHw>6l>$!25H#34<*waKPDy`U-TUr_eL|f+5hk5YAo@V+NMq1@Ti1#HLokG0i&cX}G}ZX554?d5Sn_x*x6_ zSOnkWvN3np5fHlF4*FN@VD7tlq)e}fhDrEh_StvvJ$)$^bFU<(zuM5tC6KiLC%rm! z?JCfhJqNk_baCe@3Czg8!UR8cuhY2_0JC->0Betr?cT7He(k6HZ{{#HISx$(7o*Jd zQk;B$lLU9A^)2hJZ?*$D`#~aZa9eb=5dIW7=E%55dcO1=- zroP?w?861W=^NMEglh_dw7-3ja+9Od(w;JBOgSx5un=QyU*amm$*k?IKyvQ7v&re?6d}}@X z-;@YgtL%v3krMFa62%KvvS5+11o{H6QF#Y%WSZIx<}O@G9{#B(zjdX-z1fDD@LCDJ zpA>_FB|(t!l{*7qbS=7my#w|0s!08CC^E8B*<%MsNpg}J4)x6ECk1Ljk8&_;I!^(L z=O&XlqY=oSbcf_d`oR2~*Qhh^7TqE5g;LQ{_*%mh)R*bg>xWZl%J)UDIQFfm`-6+LB zD{GDwTSa*lk2E=U{x&@@qZ)g;nQ3{lJZ6{lk;jj@EKcAo{>pp3wTD$^gL-8g3Z8Po z7?)u-zk4HAHcp`0eG~bCBBkWmz%a29`$krL`$VU;nS+sVE}0-23L}%>lZNZX9kNjAdR%aA=nt}E<6~J^{Acb3`L9crRtY)_1ujB}> zCtei9d$`>^+6(r~m`?WRg<{OvY_@OlauVkxL(Efekh3p+F?7BUD#flwhr$||s@+1j z{W^nz=L&Gn?%Akp^qH(H-H0+=2Wo(ICYZ&$v3vKaf^+UxT3sj08_te~ErR!%k$ub2 z`gJ&}HD?f?kMkf@L!C~W*F-(zn(GP=3-ZKza%k47LF{>O7))mmQeD^I2AySg&@Lg1 zdRtn_#*@CdqqU2!*_BEwB750^g6kxIJ?H0$ZHA|)K#M(2)2A`Z@iZx;Pt7kdlw@{4k)9!S8?xj&hIj>FVFOaTqujL64&H3*z{l$os@%m~fapbl1T zG|Jcrv_@-4uX7*zN{eD+`3$nJ?@HZk@3~~+!H4wUpJ0f7uL4a?oHpnahAY+uaM=T{ zw6NqJ5!>hrl?Tql5&QK}?7j+0(k=0DR2Q8UEdYDwcie$g%_Nwe!Y67&xuE$i8HHX{;UVpvb;)Z|nb7!|Jp1PcC^Ka< zxGkQ^=)LsACrkkx@5-V%e*C&~+JPu+<4QKFe?xb#+3bYfhnb&u49Iq~DX?N4pG3@Y zqARza!&MKqf!aeeZpRgelG1;S(8)94GiHF-%GYu_mp+~0`Uhspbss+1QJ0YtSpU-z1$sPtmgg9ucQFd#v4BjnzrH8^nV zC~RFLhcO#AV0c9egexPQam@qM&SKK8vxB~qRmPKvC#Xg94PqpeLpMuo!l!QzfV%tv9(?lP!->kk82qHw?0grT{kr2T6YI?rxK$GA8=qkJAJ zody_X^TjY=Q-rDyK4Hws0QxYXm@xgjs73T$XkGn>bbZ%@as3Y1RsRC4<}QHd(pO+6 zZHze=C|;bmoL^@6flPRLoTbIzsbkX|h`2U^mvDY6e_W^-l?o5Ro^3{09uW@Gg5AuA zQ&aewf)a4{*afgl+6ULm!%@*?GyBtPIUbVmhNy23a9eB=X1Irg?R;re-*EyK*W6^@ z_-JA0%Kc!oEd%%STw&vM|2nPYUo`hX8?pLTfVQI?23f)NczO2F3nfSKjlT$#NBoA! zdGa`^^fk2|(u0EPAUtaogk8sH)V&(MgW@os&b^R8>@36CiswokEoF(pA_1^#+9Zq( zt6+@}WKdC|Alx{+gv#x;uAA4&B8+yBBYzs9Cx0gI`;Q3R*fdV_HjR?8pqpTPU@xeb z6qD_jIUnxWay+_WCd_bJ04J5?!0qrI_Sxo8gMaQ-AQ9Y07c@HJ5;sq@j&P~+G#uJYBBIZdMWoIB2PJqXjdchyd?m!%E|@vTQZX|s32Y3l@d0lST9dRs2j8?_HS zxO~)nQ(@dCUI!&(CNOQ~3U(H5AZ}wpRISkz>?c>#kZr24=J|BEXB5S;z4Ew~356@8 z{SchOuQNMZ2sP4maPtwMz=o#~<`PRkG1u9s+P^T?UIt%ghBJj(zHpuiN5dt)pFxr>Pg<$|1Vosk3f#Q`|+PXILfyr+d*itt~<6u$1@B=YIbI=bW2YGjXd z*@44N#B$4Q+B*GItq#u>mz>C@i=@o>$20suQq=%fypiC!s^&61k-_-=@Im^$^gUj< zdmki~LSe6X0D8U;Cu~+Hjm|m%%iF}M?_mpgSf~JF-1lQ|;!|{#UIwiT+dvNjsAO3V zj^9pUAGZSh;LnB%J4L7;dPq*3xKAf@T>{#Uw{fLz33~l}K(@38!)M_uusmoddWBx3 z3KyS|;6+bqH{T4JdIJn%`&00>93RFq#>q~N2>gFX+L~o8WHg!Jd+`{0QJ{d_RGrAv z;9F9M{5nScydXdDkvSxocjCH_ZXjHLl((&SC2`%Eh~ER9;ECZ>H09ectyLZ<_jNl7 zYdKA_G)+-bZ7;XSIDotM4X{pF4(FUxsl0?eI{x{K)j3CSRZ9vy{1SsdWF+{pcjvP@ z50~-`PK+3AT$)S{%2>eJCF-!7^Dz8w2=ap-rvg36vALO_ar3{O=GnAAaW9VEIt4GV6;D;y(1tIOIQisxGB0K-KW1G9-sRpAtB$wC zVNnLepGhG$RSB?9M+XP&UZ5VEg?jD-z$Q$fQ8RWkn&Xu69&&fNt43&k+@zh>I= zS)9M+@CYqCpGx~G1EHbi31QSt5$ErREtTQW-W6+bnHOIxE8I;Yu4mE5-!7rK`5n5; z!4~JKzhYEQJ;y!WQanXNQJ8+WM8Cc49o?B0g%y$;=%-{$+_tF~RqY38NYpA$KTKmy z-id))$68|cMH}jmvkdiXhfiKf@FY8$TyI^6QsM_W7NwG&YB|X!Rtlo$`Uc{ipaZG> zHMn>4C+L^o&$v`6qK%w8G1&GLBHBvG+qA84Xh@v@USux*)e_^$-dc=)O#~J{MO1AG zCJQHLfWWc8#Q*mIYTQ3glcMM2VJ=Uw{d+tt7!RV_$2Os4=u5(uq=Qa@41}OHxXES0 zpq&Ef4mFTx8m&b2K@I!CB@m-7u4Q#HN65#GdARhi2h2Tro&0m^qS;lO@Yf3g$k+B} zCd4#CiNGHkYL!cu_#DG=-Vi==72riXF2@Fp z5}&y*X`oLh{StDWeRQRdEEE*r3piMkFdr2xH4De>qO)lNuazcMWa5`JKkSv9z?TSe zVRlUs!tsUPcx6W>RDIq|BvR(!DwChY#-NF;y&ed88dYSA=?vcc!xzY%RRDvN0zf|e zE{NKQ;+{Q?^!2(by1m2#Y#n-uOzArkyeb)#kCww#dsmc{Uyq?%qKLtn4%+wb7L!*Z z2?cZljb40{4(<`+e?Rt?j?C_6&aF5NyShv8kBu3X=M|%cqY8Wqn}tp3MewX_g!m4; zX0y+)Woob-#Z<46ekm)A$^6L-+*EA8p=FFevVshhg#m&09= zb!hhTFPO~vORkN{Q5~B!*f4cIcxEgE+4P5)Tww*zPUfSQePwM|>0%s}K8yV(lAxOt zj6J4>@VM6!g49#UU)C4WCq-czmmlztoroFBcwlqb3EDl@K(Ma|c$G-=eeS%i6OOci ze3{GSY{O!ZHNODu1zs>YEtC`{CE}|<3piM2h?!$XaOZUbdQ=pn=71=#)=wUN>z5Fj zf^T#)H;>*kxP=oJ41wInUQ%j5Vz7Go4Dwsb8a>Y#lMMao*e!Sgr-k{`B<~ZT5K5`+ z!a@|#F2<4IAXJb&37b71f$e%NdS;g$oVu9@f**Bo%Nbc1ei#cWqNgz?@GGuMkHf`F zj-!iS4VE7`fKzvH>_@^j(Bvuezvca)CnkvSTGZcy&Bk!-FVH7(4u8Pj^)$HY@5gW{ zE6m(JljE+RLQo)wrPp1-&mBeZF+mCoKUAnBk2S&gu~6C-A_SW>5=dG7FOrt~gRDB8f|_HxFfk($rf=Dg zZ-T>MP)$q@!KHsOJ)UDRXp7A7l0mMv9S!?9U4%-`33 zI2bewjkdQ^U-=4pRA~(;X?dgNO99w1_M2fohJa|PI9~iHOk{eb_+n3TIle{?sgFF} z8nPBzy_dk_{E0+4Q@yVDj5Ra;N)2i@rh%r=8oYJf037nTzM06=XeYY~W^$bhQwkWE zGieVfa$N}h|9;cN3CeKKpqk`g>V$)qm!K`3%lLHpbDZK-q7-)mH7wu3qhTAaBgYG$ zuZtiFxl?$O!;a9ekxLxCHlU;DWBMypgctoS5c2gWb52e#&bk{5&z>KLt}FLRRNpUR z^4=PI?$|=?E3V6s&oQvi0b{xMNpXo5?zX;&PM+duvLhcKKkcEi2c_|7s1d7k?FEfK z@SIBhS4lk=#^Y~pUcJ2cO6`r=X|R5~1ew)-0jt-(AR^_VcxQ14488gUmujan@xqZf z-OmP1Ti#GNqZ?=^r4Q9Iv(Z-j9lP~=B=USG(Zo_Ya2&{B%r-}p>N+=g!%l$E&aeMh-9xP~ zSz#WwThAct0`u83l?n7}UJ$5=@eF?SUV$r1QYm#`#(#BVEB6m5glL$B&Yz9hW8?nt zXXaP3;^s{HZAJ*}sWM_`{*)$Lw+g~-xlV%-PTw0pa)E5SB|^k?!g1%PQEHiah5i<( z#Li`>h}8f$1Eo5UxxQ+cu<|uNT)d2$KKq2dkM7cQ8y5m^o;|tb<%dlk>mkUq6;fY% zK_L4U)e@p%f#@lGwx!WPb$1B->(~R=R?2}(Oc(t67R+6LDqNo-3c8h5^li)sR`49b zYN=hg_SZ6lmg2i8QCh+5{dkS;nl6p93qr8HT^F4L_epgAGq&haF}>L-!Pf~; zuKoKW2}|T%v9v@EA8I?%=dP+C5ya&^LpuoDx0xn)a_6kI%R*_xd8U#!5d9r;{3}9} zQOZ0S_JoL&7cT%@%>KCt~hW9-a)Db!xS6nQ;D zP_M0x7dKbXo+nlGh+!-S%FHEyUo?Z)i5dLv`J?nV6G`Rt9zuowBnY-?hUm5=)X03Z zS~zSih)*u04eO?Wb+0bo{kE8=V_txHzv|dW?f1~re`hFBQ=A#Aad|F^RQ`oeP3>3b<^41P+f25Pst!klYcDcAw6{fY*PtO28YY$_A4C zucC?3ClBb~S`1CQ1o1`tY`QUgF8p436%9SCNzf}VHty+a*!{knPT>4CWt7AHBB78s zo=a30Xb`_3XPlAn16VI5c45&!jCWiNCnx#Q*wHGq|Dy$uEWOE_zpL=cU?J)LauSxt zn?wJjxZ1GtW-_sG4Y@K=7Z$8dhLc~!c$1n|;^94eVEwyXdf9P|dM|Ro#pNfl!LXck zuc$$ZVg|N$D}(T(U{DB9VAL9#Fy_(#-8H@(OS;Nv*}+V(yqkh@2RB3a(C4~BpV_c2 zI1=N$!?ED01|B=_1a>QqStRgp={_v%5`D`~#rUaptm<7sdq zx?thWbxxWDkZze5tY&>4#Le%6NG{JH@ZJ?2T|&`tjuokKp8>hYyx`BCZr1#$B^ot- zA*I_J8LORNK=9HKc^x%OPc&V}FSlfncVZdXC|c0`**?T)$zw2b=rcGsz-2K^H(`ti z$L945F#B8O7kB)G?rY@pB1A4RSE+}V8S4Kb6#L3UFLTwG5NocENLD6{;02%e-q%q2*~@@8#1kbjza4+%vQkUd{eWJ+f2C8E&^y;|amzy^)x% z%=I2R{A8OJasBztYVh=G6wa3Shq@Du^!-l-+!~fe727?)X`(*LDYUbm8!C z9T_OuC(8fzF&cKc`J-%tASO%{g4CAv7g={yxNSeJZ<&aD^%tLD1zV2AU7VlTTSj@Rl!&KdV-QxoHyB zIiSF^y;Vn!{Tbj^s4qCSAqNTr8{ynK5$IR=K_id=?rcN3S#(?!Q&L;nJp9Lh0=!nH8N!~zX} zspBV+VbqPC1olG~=q1umM6EsHsZt=>rV@)XV;c1Dsdl*6Ern}CWpQtq8foEuAxb{y zaDdb5Yec!TTMb!&gA?)p%(Y(8K^%6^hH`;ul+P04$;=z1WpQo8y-rbllMn zZ!8>umoIP7KSkMKeomCi-0xw#g`$zKZV2y{rFlUgu93f?T<6HwgYbjxWvBTvpz&a| zF2q0_9!37D^PKNbBwF_npYceVttSp*k#4Xo!oSf4%V5x;imYVhA@lWh{IU2N zkqh;L)7k>C`N=KfFq=Wpa|grXPF!8lTwlHnFDS?( zX`4vo+~eW*(Swwp<#O=yv*EAkDu_@E!!^b0asERs+$=kdTz@@_%9_bS!^jcb`EV)8 zk4S{>|5bD*{#1Qk9446}AwozKC6!8saQ39OIiY0A5YAqg zBq1bZXwX1Jn$!5}J@21zKlj{o_uA|GeV)2VxT+sSJT6A#R1I#9vMhq#KRGVj99Qai zI+e7k9e`Ml8OmG9;t3TV-jxhSW2KdN%87H7>4(5k!8dFN$E8kgn#K>5S`Dvzf}tzD zjEw)#CwiWesGS%Cw!aMFonHa1G_ivg)wlR|-drN`J^({h)?x1yXGl#t&OF+s$3K(R zMLvIP!FA>N@~ zEI!+uMzV(lY5EyS@?wQFc%@okfI|qlm3!in-bQjGqJ)Za+!r~y)sPq!ffAFo@#yZo z$b01sMb+uJd&*z(a9b&krB#8H?M>#ZO)I9)Yb3@(HN-Sfkn4`!Vs^QAqEr*Np9~qo z+uq;EfX;U4`XR*4n5$6#q%19N+F|^wqmrhYXVAS5Ch{v~XX1?C1I+Ey5Al0ZJt&xn zf%-!(r(`x8^bv`5S6p=W1ACf{$P&9;T|M>NfvqO-iPViHsZ!IKD|*Ejzc|WP@o-6Y^vT8sW>UR zc7ZXK-robi#~%{umP@$2wuAZR{gKow))K3wqI|s@HDoF0_57wfAImjb;i=SY*#3Gi zY2IVPkA|_IF1dp6m@Ss59fp`BF*sf!4l(av)A5k~_`A)8c3B2c-=x=o z2Q2VVVl;U9j>3sY33Mc62lt(^=zBATeoT4?R;yPK0Z%!Qs}{piWfzoWfx83zNlGKr zNO)luI$f|M_M)B`b$mL%>&Q>?e(_ymg0EgSY5@r zS}4t25`}j>#rf)bzVPje6>rTZ50rc33Hy_MfjL;sdO5m7mWDf{vZRQeKmLloE%hUv zqxDd=a5buRa=n6m6PY8cH(`R(eK-%on7wp5zP>n@2vqozKHGc{VY;i|t3JYI&-C!= z6H$J4Zy|Nro&lC|Ql$ECG89e7hDC|7G);Ftm|81SH`y|a%}r);X;UCZTXrD0sm2MS~K zjfFqYhtT0!{Em?{I%il0$}`l_^V3mKn-Na!B=zC@ooIA(Hics^c)Yo9x%qt^0~s2l zMCHOt+;gXc-mF>*Ne7R!nZDPtcBmK{6w4Tu%m2tX>)ZGv$b~)Ievte)`iHhFOoG@6 z1Z~w;lTZ&qNE>?!zf2e5GR{p%|W9Ce}DU|6q zG71B&^zoN`a(-PhO)xQm9B)h1QFo#Tr1I#?G#y}?4#J%LP*D3mf<0kpV4}VXJ2mwI z*|#}`xK?~6q^gKYER^N7h9MN@*+H_4F+5k&By;2D!_D4Rj9+sJ?U@+~P78Nn?_VCQ ze8V#S!=msuvW*<`ib0#7{@D1Ib0);z#rQ8Zv|~Bv(n>8QX+Jtx-2y3?`E5DsjD|t$ z*JzGE9L$|(dr9okJlM79Dw&-89e2LCNZpElV!Zzz=2G?#@Cjc4SFS3-pPy;iy}pVS z8BykI&SOw!{3h9dECr{A-p4{)Q4o7Egyk|NwA@>m=jnIK=!SYO*|+F7qqVq)cyUg) zptC$O()f+NJ6Zw-vt&Uia}b_2_%KJF=fF>|45m4@9-B@L;JumWAo73^%@{gQKhEeU zR!5JLDO^rC{6sD|_6hU97)!y?^`dBc@)XJm-y`!DjMA#bXCW@}H%-@ch2fcTbSO3) z-luj}d&f=Xn>b%0;YT>8-lPc_dK_uuscR4;Ge)miyWlzZXz+JvVjZ%ZA?NQ|;v-x~ zh1V5vY&Q#do^MX}pMA&l?J|K`iv)T8>e1+W#u}%mW#NeEDSWZ?1?IcNVAs!`B(6pt z0?w$A3kJ)=l&(oBPVVXuB!A_Al>n#iK4rX^_QH zu1EP?+Y%j1Wk|h2Czo9>fm6N*sKu+}P%SPC5wEPV_pmWu%3Vq~)fLdst6yM6y)^i! zoJQrWPExwb9MmsmNOhL;1`kZOlJ7i!YdBGQRYRe zEy9)D?yPZfFiH8?WVrBUDNL=rhALJu|_#3;B~>(eiK zQZ#I11L`UX@oEmQVgwIdsIIkn26era^ulIQ3}30nTM-b+i+r{i25*(4j0)!$xW9mC zSvEuNQ+?Rs9?v*y9RP&|a&StZix|xp=0D};F6Dn(kf^u{XUptnU8N6GkKrg3`P5Gm zK2OARDgm%Kq!=uXMPQ0iCwbuXguctO1)=5xq)2cZWLedKfV(6dY864xzuBZ#><#Xd zs6g>tL7uOgJZf`inNO#4na<1k^!x1p=*}q@s7+ZNjBZV25_MN_XSVCO|MUnc{_g|w zbK@z8)W>;$jA8$3LCk2_0-L@M8b@!GQP zbOqkmvSv{54eoC=L#yaG)m7SdT!X&T z2qK9KA_0~YUb@T#Ug``rT5w{7Iob1*%%CA;<8&ijeCq)UNqT_PS2J*q)1z1CEhSHG z@=^YA4#&0dK`lp9;@Vq7jto^1&;8>xHBTL^r#>QG?h(-0uoLebNP?Z?Q!xHMk81t- zOGa4o;Fd0{lhNw&t zT*m$)TGdey^lUk-)xF0u3N9>9Zx*!YbReTFgl8Vwz^=3QcsAx6H>Y!R!KJBiJ)@ek z7PrWxD<@&T$yQ?OTS{sTgP?Puh^kKEf%c9ZtXSv3%se2(oBZxS&|23(ZPxuX$1V8BG0aO{23d;;XU>BeMSL|SAXb(8Op}ADz6b)nwiUnTi($OnCNRC0 z#ctT0g{IRAXrtIfm>}?ybc*hT&8Jy>c_jnff-;Scx~j8n4Zf&+ekN4sd?Eo};Y2>} zDRJV?`)m5TQ7d*T%kJ687yG>v*}x1oC(a8ND96&&gv&&zypS;EcZiPEPgq`%M;GN? zL5G!_Dt8M=K||cd#7-%EJkNzRc@l?amK{u6ne)6DUW#)MPsX7D%^TBez z5_n8*LWQmAM)qMhpnjmYddI6)4Dl62qrT1HFMSEmaZJ(sGIO!)f(O1lZ$wuwN&{C{ zWfX8pVjlVxGA5(J^dGk$>G5%-S$EoTP`jKSXw|@iAv^fiG>f01mqeKY5jbYpgGP^7 zEKlhn$7gM(gMGRXNo{CtPa6to)w5FXhEZMD7#DrfL-R#1$*{dJ^x1Il);r!XvNwo| zyB;ADC%c%OC#`U>@EXi1;Fy$n5+{F|1Hn24RHv>D*8LtP8uGdDrb!$3b_9}NngLY2 zd^Z|q|G?F{bJz_E*;M=j$GfwV#Z|^O^v1cX=v~2aW~`>eK=a)_CESeu2xI%8T>*f zJ0`=qE8IIr_XYWy^9U7-AA|G0n^5w(iM+VR<-2BCp}OA^_-pA4Q|6W$*Ugk;&#Nmz z#qQax+NE3&%qzhqSi07--qP7~|$hV84eTK94wHtahK{&k7E5EJ_79r#_c@PwW7RdINCz zC4`&b4>8`;Yp4?E7G2YqPtRV6gj(mv#@BRtAi9i?jiIK{{d^Z06|lg~{dcQ1JM3^p z^M9b*C;X_ek+)F}S@g5ar)juor{pA+2erB}wV{)_)gSWqSdq6{dmih$B{&s_;vq z#u;aMZ8S1hVigXppzmb1k~^Uru|wJg*G(#ciF1=-q)QRX#lw)Ss3AflJ5eAdlFarr z;Sa=V@QTA`(2vfu`AQ$Q_l&~Uh-Y?HaP!ap}*u6S?9?oK8h}2 zuQP*Z-zN{z>DhSd+*%wN%cZ^i2|TwK@pvUTi~0M|5oW*n0N3}~V)mr-;daQ02YZ+db74lj-~pzVCD77S6RTfZ<)C&;CnMIqkM8`F4J-O`$tn#g{xZcD zDEu-^GiP^GZAJvfrcI*0OcZYMnucYcUEpM{I$doT05R?o;9us0!@_>XXCI%#oU2tR z@?tvw{c&&bnC=2!|4qR052f^U;dLBeJd>&2*-N**93$%WHOBFKB|#$12p?q+;O%@( z;~xK1@~-1I`?e(>ROc5H*9ltml~)Jtv>(J%v%QH~Wu#I2g%)G?ubhMW^bwpn@(@>W zJm>M~D|BgeE~}g(4wp*eVRd{dO}yd<70=}8wh3-{d(I&BQIkSgJwlgOD1-N>W#pLd z6v!HMA`dT2<^QluK@JRzb^f9dy55d!Z-E5tM9PHd;`Bwj<`6#nJxOGJN<24g3fLcJr^KnJrp z2dErb6tod*J{AJ1H4*)>ZDdma0C4U}uq;^!E4>trEbIvD@i+vncd7H|^-KY^>)%LY zl@BiYtx5h_g%KtBGh_goxHCoz*?jLAwug&Bn6wKV;xhh&+K1?;S_xWNFaY;Fb4hVJ zL*2Pt!>+u8__lI3-|HsVKO6U;pC@tAw5(jZ5aigg`L}WLa4uBdf6B)A2N22pNzBAY zL8Ryo$57fAOp^@-i0^ZG44WCw+}jgJ{G;bkci~#hvCE_BT2shZSxNLy@gu?pfza1f zM>Zrn(lotsGR~KPOgsQAY{i6Cb>vig1$kgj@P2R&nR>2))H(PgDV&Xemg$2?!D7&~ z+=QY_c*Hhh6B?LjlF%8_plmCEEyHS5D|if5dv)o)_RFwPYaH+OW`oivCCEA2h_yes z`$rQuJZaZ}$=54z@#{&Du*H+!{&p5Pnk(A}Egevi;^iMRg;V}v&^G#&d}+ReX2PbpbFC(gi4?@PtAcz}|GVs#z2dxR_eT&h z7>+j6^|7%snm%c@f!D3;xh}~#$_=z~x8gfQzCqPuN!*#$r0b;i)WtZIlWAmB@sxR3GOjj}Z1r9K6gv zN|GnbqW$J2*j=g#uH2bv9mk_x+%Xw$?ouK;wR-4M)`7-fkJFV`?op+$*PwrXJ4Dh>afBc(i5?%;Wkt|3wG0L1sZjV^AL>8)bOyH)^m|Paey?%Had= zJbm}LoREBTSaq!vcS;EI(#u>(K=)m!wd6Xf+qotlmjDqCP=$AyAzW{^2qXRKu|Ibc zm!&m@Q0!9g2Qv!{o4G=(03GugoSU==fG}(Dx-LcbsM( zP3)q+0ZV9s&RMo$wKfC{PNoJIB%t*@;Vxa^TXGDg5lNv*0cN22!M^f;!h(Vnr^ZUfoT2JF1GCS3W0Z#1JQl znc!NAn7r-^-KlW|qUl`PU)_kFr5j-4t6i}B?ow*^Y8E_}%%(Fygb^B z-?t~?8xsMZ_r`o&f0~4{LkEfgO-5aOqa`{1uRCES}c6q^2V_fg89jN=2Bg8s-t zEIf9U@P~3xf;$r(UM`HqCKRr{RN$}DSK=+LTY!6SzM|PKZs?-31U!{PsP*Yr?Cx*1 z)nsZlekzm=@Q{DfI>vIWY zz?F4lDA`{^`mT9$m7+uN^K1xNx5gQEWp%UV_lwDgn=N#$`VRQ^w*^&KX2UY=I+||r zhlV?}D5VNXT^dHpRM7iseF_|h|YIzIrnXJ(Vk7OqopkHyY{QqV4P!RgnYVCO=0 zyb}{gQntin;j9e2%stObMwX&aiWBDe4EyLI=sk9oiu|5IdXM;F!C(#>l68^(t+7Dq zzMC+)mR6rE>wrqt+gPcvm=4sPf=!8pRTB3^zn7Jy!6b*go`0Gql(%4eQ!biKypOzF zwq&Wt1m4G{auVKn4OgF+>ZG@}u@#zIuE#8CGSrC5oD#XwCg6B89;d0Myl4mnc4`?Of zhw!B^5_*y2m)jkvBNiw%DCNtKYfwh9%~o84jQKc4Wlr�Z!Yaj2Z3$v@wH zkK-gNQ|nDGn6J}MORSoqPhvT{@VXC<6qKN)#yN1j^Nya)S&nkgyrF$v5Q*@1N8$TU zu+!xqZEf};`y(sqy;d!HyUY?*B;+yGvzQFcf5aL%T!w~JO5CfPF|chKRC}DlnQaf~ zPmX61baxI!HdSM((j*e7UBuMh*}!4!Nfgg!q9&d@|- zu5SfnDLXKhS&ClIrV|IZmjI_c@I}uT@@wD^y_^w?3jXpT(Sr9lF}I2*T>PQ z)`z?-<({w4*${om99~clRDAUmJKpR;wZ}u;yXP{SrSylUyPL!E`y;Ged@kGiyOxH2 z%jM464ea5J%@8~9E++SI{PYtO`TRq>(cU|j_Wa^pO!hB8!-TDwbd9S+l`u=pWyO+iO5S3pzHnjpuNEp{9xh?0^?D5 z-Ssyv2p1*sbuVa=iVL~g8O6?Cl2skhI6#B_oS<&L85(n5kkx8kTt2srraAT){qt1i z+!pcVq{|xO8P-CUZ(eQ1;?k@JpJFXRnIDR-$2SX?YQc{1vcmtRFV@ z??a#GlgRsl)5a+q!?3yC8LIswF@9gNv0P#hP2G@0TW%?%M^+qbZ#xOrec-P+rAhI` ztPwh}W&+Rb?nR)`kMKoo5c1No4%_&8D;%0(wZNR$fyyJ=eBznT|Gh zuYviLAS%u1GKxNSXxI4&U;K<9yC&$9efo##ez8Gf{E&%V^NB?Ko564hH0)DNgX!tcV3H<@ zDO1L&i|0ftvL%`3iHV|u-VSh|I)T@v+XE^ZMN~&`HSehUEMr?KhMEnXXV%%MU~T1X zIOet=zdim?6%*M*=DYiomWWY&`PPzX{^RliCKs`@dVqeFP^M2gp{1X>HzaCD5Odvn z@+q8qo)4(gTc+aZ?tFrCcKcJs$=A4hiC1uIawu5#%YnH0OpxQ;?o$JAGV{7e@S^f{ zY~1OF{mE`m3=!AqW&be6an&0LHgyQ|rB#Fsxw}2$(L!16y-othxa$Wbad% zlg?D^q9JNbRD{oKHP+?SmNDr5ZdqL1NCD?U89Wn|(!ne51q~NIye6g)3_7Zv+n^DFJd0%Ev z9?^#zQO&gL#A3=1O~5&|{TO{u94{JnlKLehbb|jH2n)T6|9(kAt%Wt-n;lJ*!kox_ zZ9#r~*D37u@PQq&F0_-&n*`@*f%LWv$lhlTayGH(ee(@zUV4wDuDwb>TZ?0$a3CRf z&(n}Ak#f?bKzLFAJi9_Dd<15*JAbGu6P@`f4nxqq>y@Hw$(@`=Z|9jKk% z&bj+u(hZ?H;MA>2-c+Z;u=#TO-S7}eN}kF&>L!BO(Nq}J_=op%3+Thg^FT}{i#6Fg zouAfF0@)U-aCmSoow>CYmnK-Ur#rTR>j38+uJ2`RFD*qmh2t13;l^|?tp}eSNf2gn z4qEd7zv*Pqz(rlK(Rdv$j_NXclC}(-))cXORoBAdyHdQu6^lTE$v{iTLRh9&M}MVG zg5@sKr_QB{V_Za?IP2zhciI8S?Ek@ls z2+ITyR-9Vq_+jbi4ZZq;0s^;b^ZeVHQ_nh>`Nn#W_QSfCUNZE=0R?5 zyN%1|CBP4%RxCK$Ls3u~M6f#3=QhN^b)gH)p4Q7mJywuDODF=FS=(`o z$`fdg9;fAB58@w@6qFfACB6zKXjS@-q`%w*a#txpLl9h8DT%IE7lMN^mn#o-C1xA5 zNW#oJIJ-=Yq|Yx0v+5*fk8lx&M=znv58TDq5?!dNpF*Bgs`0GaA27B;PvBSERLmBN zrdFF|pzY%pGW==^-zZ`i9$g{D_Ynw1!yIAWyMP$n(GdVmO{!GLsTBi?ZHrg~zCMr8=h7rPr{pt~^8eDccMn63m?nG-X=ltP1|d87Gwc4k z7jq_bvKBh4q5l0_bhk_FJj;&&O-Dkj7Ul$IIy5U6Wm2iV|-xZevl)j$;hdAHNGc<(eXyI&Fi%8b3kx(| zV9qYi7@)3o?PQC>LHyfu5o#~jq29DDY}?BS_KtBeyYPStdQJOLCECrB^UoJDW^W>( zHdcW5QzjX^Wdo>;bUdcN&7hBt_t6&_hT!9Ug;B{}hY%e>rrj9Ck6Zr(>3st5$sq<; z*WRENBM~?l8^z6Po%nF)1u&X%fq49QjfT_~mX-?OB0r?DvJ+^%e-2&An3CeIOxoOB zLxpnYLznwJ-0d=h8Qs9L7Xrmz)c$+<2S?&6lnQ3x$4Br%_w*e%L`==uBtsE{fq z(Z7nBc@HE|rxHkOekxWvn9y-&4St#AJ{Yu}0&*3jB+x|&k3D5cgl{SQcTk%ZHBg1@ z^W9X-IRW){=3{%oMtmr$4!Y$IxYekQ%u5x7on_b1kGpRw`yR{Of7L-UXNy)}*Xl&Q zzaf~J(2FOX_mD3-Li`7hl8KVidkmlE2m-bl&>Ry1!n{3D>v4_hx=!Mar<{W*hj4VN zUO@&YDAKkzXU6%dCp)>L0Nd*CL2;Y{qj4#l@*WrfqwNA?g^D=j(nBRDbN(yoaCmT| z6kWOf-$msZ5Dv+L=uH>l$Q5Cztoe%B4)bx_c|ma9QU)?k)A+h(2^gH-jI#_^!qrPQ zKxbSe=g)H)_XmckpXm>3*Oudrp(pgB&U5%9A;kZ2<~R8^{t^HC=1-;VRH@^YczBV~ zRUK_~8;|;xVbZe<;v}Dkrc1fsQ&v2hE*D{zuaf6IIVnc|1QXcs@*`?)6C{xaTz0PK zCq5KXz@j)y_&9BV`nsM5Kiz5kp@=VRcVYwZR=j7894dprXeYr1tFKC z;mQ3(Jf`xFDa=>InGfy~>swx^6TTPBPQQd%M2vNeDW}q|`3(M;Lr3-nV&a5kJSaRD MtS;BX{{D&ZKh9dc$N&HU literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/special_tokens_map.json b/onnxruntime/test/testdata/transformers/tiny_t5/special_tokens_map.json new file mode 100644 index 0000000000000..17ade346a1042 --- /dev/null +++ b/onnxruntime/test/testdata/transformers/tiny_t5/special_tokens_map.json @@ -0,0 +1,125 @@ +{ + "additional_special_tokens": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "eos_token": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false + }, + "pad_token": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false + }, + "unk_token": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false + } +} diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/spiece.model b/onnxruntime/test/testdata/transformers/tiny_t5/spiece.model new file mode 100644 index 0000000000000000000000000000000000000000..16ff05c4dd0f934f1bd09697bb72991f1a1e84d4 GIT binary patch literal 252835 zcmZUb4}8w${{P?i{xW|?TuJ_RBsr3tauAXbk|ZQay0_ii?)K-N-J7+9d;hm^BqSj@ zYc{r-na$WgjwIPqN0K8ak|UvUBsr4b^SZC?)A#ZCc|2Z^>-~OT*Y&>M*ZX>3e?RvG zwGHwgo){bTm=gZodDG8Ad<(eDe&3I5b_QdZA3JUTiL;3hGXf9-r z4O5?Z()ZB5KUuDD)uKbzo}gAiesFd*y%Gk+3F`g<*?WRo2KhL`)R;{<&E*qZs>5D5 zia6A+7nXRbFje{^6pcA!Bh>R#-ttOgRluL$Zm#EyRY^r~rkx4u+vTggg_6~{h&5iS zk9zB;_qX2@r0ow z)QE8f&5h%iE!*IXo09BqwLWOGw?e3zIo43a)O&y4(pdAUNjle>b?cV-XbyTM9Zzseg2c$I0VL&4|m0@Z?3_b{vGic&ib*Z-q-Yh&1$tWZ$cfak;ZG@}q(_l;+$*x58 z&;DiJ3N*L+B}g;qF%I?G`xb{gx*dW;S(2()w8LA$94Sqw*G z3~l2ENE3*0>emmgQrPj#R~AQvz22#&xnQW8-@n!`fTm zM!foX{vI#czrT9%?~u$5M{I&he131U-S+5cHSIN69P_AZcg)I|M!5Q2g*7H7sSW-9 z;nhWqoF52Dg(#)w8zEXotv4hVFW6?tc@EY88f24;oH6Q+zWcmN6600t=L{JdseDgB zni!07$RqfyPNpry@hjNZP z=SEzXefE|osI!K-Y7 z+Mp>@I?Sb}SHn@-9;>>y{>)3p+f`7!AsMq?g^*?lU9k>T`6;ZaO_dY>hSN(fR!tm# zxY;VV-5I9t+XzoddxFkQfBExfHFoAxb}X!JHca`)L7F~CtB6OwXjZ~blC0u}z*7!= z-_0_lBU)uUA&n7^*HpxDlYw>XV*c4&J;^~c-)?}XdZJr>|4+!Kh;SuFhpDXJ5SVtK zRX?;k;w{Lk^w7{Ry=1gY?HvYbiaf0@Pcd?Lq-qF(q}%ochnn{~w9$*j%(??L2$~#5 zB>v?Ftg$sQPKAv*>Q&Bqm!1h}lt-!~i(yQuP?uV<-js4AsP-R28f{6DE;aZw*yf>k z#Hh9HzcL+6P$!l^HZA3mEO;T8;hP$cRUh~qvvQrx*B|eKH@Oimm9ZGkv=T?K-0_*k zj$*6MxCCn~9i#p{;A?M-p;2nlOhYEds^Eo?+9MQCN`p4VpHRErZz>b5h8{3ve6rf{ zl_3e2%zy%E9cLFdMqLPb@86H^S?12vrYVHY7vP$M;_*3Ryh%JpfJP z_7JwPKV`$1Zn+%}^;In_6KbG}{HUo$Lb7^x?}_F%VqCP}>L+-uA(n|9+V7iYH^tf2 z)JHAO9j9KO1xLXcy{NuB9|i}^V?Fsj4cast!z7u$(W>PPSDzNb(FF$Y=dF;YcOec& z%=aR^aYd*%M3-p+WnD??;h>Yo!4VGC`vGVzj#1~vK$>BUajAFg7RMq}|0vjppQ+-EPzxV9?bQ^X7_EMI8XDsrI^O2Q7>0ezp}NPz;M%e39}A$2U6Fc<4V?X5 zv(;|9+CC4Ca%}#|P})M)!kx>YjZ>afFK>o13ZitkJ5-n|52=LzTE+UPfxp8TZ?OF3 z_C3?g#n{!USUB{>I^1sc>>?QB)JWE{B{{H0y-Ux4mp?RR>Be|b>7LH)xMdR(FiFShqb{-Ma`D+oH8?LsMaJ zLNxtM{uCOGiD9bGNl0S`JKXNeriOQOdZX3ZW>-yC2d2YN#bH;&9fk~bs!zXyG_}L+ zYN+i$%@szg4Sp6AuRd)7Lv3dIJFN^k@=vOvFQlm*60bHs4%akM=-L<0nsSkLH6;|1 zekABSOhi(X+^M>x8Zs_UC2uxGaP2e|RR?3dgxizVH+xJu)`H|8O*y9yy;rWlG|z!B z^_c&;W^=;gRZ=Usc0n!C=#KQRJ2&pJ@4&W}8rsQ@*geV6 ziL4w0-+(rq4Rfl~>)?!uVXmZDb)W(s2Qh84DBQKQvdt3$0thA)l<=eWA=E zU=MK-F4Klu1ry@cosYt4XERrxhcrFZwmtF^EGnj{pW~tQlwdnqmSv=URo8c*sF~nY zcXmGCY@jQa%U-~v@TSd(cn6!#-(I&0xDz=_{_j0_1}VuNAEqwn!I;iYNKnrohBH>g zv6Vb}?~l!4@{~F{0>(HZCJ|%eC&FV`BJ;UV0<;-|XlFtKTi2-VNQ_=KnG@BU5L2ODoJUtKR(!BvvyM~45`&?)` zMG)Mt)TE2e=7c!7COXuE&mb}8xIDyFoo+A^|X};w0o0P+5xL3 zz6lvuGoWJ}J z2K~>d{{%LAi?}#A9`6f{Ij%T0dH|#`XP#5Nyc5nCkwk~yXoS_O>|B-GUbgb|EZE|6 zx!Ge$wB%5K?TY{#bWA<>Bs9%Fr#^KwNztIK5!hqeNYf{CLuE3l^7AJKG!1S@6dQP{xlrjiAYq7{{v|{p+`1Z zMLz!XAC-081U33eM5c0xUFA-LGk(^S_dl~?F+?A5-?JM!40)0ZS_ge1LB0Az7<%-E zdTS??sU69hHRKFz(;&KV)W)AIKElZA6^DGJ6^jFcs3$*h-?fOeIAMFfxsGNcD_=?+D&|pYo zyEDP9T+2)jSM8wPkaX7T>k$WGj2X{xcIth-xe{@w`b~i~%|$x6^u9bB-V~k|scuJG zg%eyZ_2WEP+D;5n?N>r#G96W~7Fea6F>$KjHdv!#5;yi;aHauVAFEm%F%=UD@n0@j z6=&-Axa41($DUP=BiRoN5g1Kjc9r3QW6*}EQLCX$$GPLE;oD%f`#4}8TF+eK*8l?YCM-Tn)U zEu2pVw)$VQEwSF|{8=!9re5Rq()(aBX0ZB4A{6@cyJ_t_=%&uI>hr0D0 z9O}69(x8^Q|IP|U*(hGsk zWXgTkADTvos&djy=VPU|65*5d5pQ*0TN>pcuu(W7b6Z$RNV$a8b7+Z1hjb)))*J6H;^UI zS=piZAwJerObk_%ldY0T`b{9V2p;|VDdKi9v|0I|SHa~bBZfWmtN&S*67((*bpP+( zN^=vPs_(PV=2#dW@6y&S@;yG=7RswAdjQ7qm$4RSfGy!<^JgiZhq+cKUT!be!rmK!WSp~zj zyMKc5-DX>jdBb|&%;8X?f-G z*1$AHmpw_nooDjA=c~dZ7_+MK^}>6Md!iJPu_az_9Dgl?$1zW+zaO%481rPc`%8FQ zaqF`|^1ono*Z78V^*l5&!ySIjf2}&+V&7f2c$SbT19QdYa@Wx#KS4?duGfbV( zjOlWi3vF}l79Z~5^>9WuKaBv2jG}kwt%0b+PPSf7{}x>Ca{3 z*TI_!ro)>af1PV7h~NWKaz3mX5xX7|0`8pxM2x@;RrLv!=>{)NtX1I`5g2tb$=*%z z;3Xu+X|52}_%mG7V7hoBd;f;TJM?n-MOU9@g$xI$*-pI>mRQC%Bh z<+755smG^U{0#54Y&txn$Bjz;9s+Ir6vi#EBHSvr?GO+|t_{kS)-iB5=5R8={au4qR%=iwrFjO?%fske8*nTF%In2+3Tl-N1J%>N9! zsnKY5K)2fQA0(!~QMyNyZdsLM9ZBkc?R=ZFW0`pBAD!Th?u1CzpZl$BH}4qg^9L!qmrZ1jexOgxTL0z?xwjZ&$S&;Y=rW(5a4<7Vma3HXUoM%CUrW?|rZ|}(^kkjqi1W03Ttlo2%Jq6!1XmN4c6P0t2bO>tAeALgwX5IQM)v9KX=F{i2 zW$W0!LmA(?**Pv~ z*4sl=9zFwO9PN%$$A7U(YCFf@fHgzvPSCHYbN&3A8`Rf5LOd%7i7682(zD>1JFOz| z4)4LbZ#N`OD}uiC5-V@~8Bx=K>N}|Yukd&>90l%?mV%h3ckJ;aVX@6~gV_1t%sHiBX@V-`b9ZTl^#^=i*y`@Ek}SYPOSnT=lFfUI=BB^YMrsPkAiC zJePj<8NC<*#+Yqu(?+=F$mH2@;%1BIwZNfPmH)vfa#mSaZSgEB4)yLn_@<%Zd{z8C zEJH(J{Ds#Gt8BQQ+6}+`pR%#a-Y%edEco^j&scWrU`gT}t~jjE>x9H~htm<8_B(f5 zMM4}2`ZUn9w^bxGT3-qJJ%Rvdj8h4ZLK)*ixzH~h25b5nuA?Jw6ucRhNy+M|305vs zG+x;z{lVM0>^$2-`xXi+z@M5NBdZrA+BU~cnEA$B-*2+)Z?Qq z-W|!k?xz{>rZ+r)y7dC|?-#5hVRlX!AG+Z2jlPK9xd_^HE5s4OVe*kw1jd$eymEe> zYt@a^FJ67Oz&Fhto}5eJ%yQv~_3qspb|PsCcb9&c$Ukl=NYM7S`VTy#G(#V>zqtxy z8guj6_P(F3%AuUK!&Lb#OOV9NkwX>OS~T}QlHFJ>>}m1Lt{9cq2cFf6+kcmbAdMyL zJjBP3T7c=!dHNRg`(VQ{F(!wrpNCk5-E78T>iwaXfFCaq=ZCbw_&v(uh*Lj~H1*9< z+VzxGJef##tNUKG1ojyHB%JvY0^=%vVWBNp>a--h=D68)ianMj*6w}1`QMvJnp)Mn z?;T4lo^9WuPHcpyPY&;qcTzr_ap&AbyIQo(DjcDI)Umi4-gqS19?wU`ue89#iaR0R z9*byuouwk2_J;1Ws@T0R+W}{+{PFA#cVC4y_HpFpv%xiZ(@S@pGoByW46?OsE2^^|_Ph-e3meRl7|;Ujm#8S~j_ ziQn405SW_$piueVYq7i(sefqJ*camBUKX$Nhg*^e9KhT=^%N48@jt2PXP``9BOTFk z>g+6d(^x3Cx-hl)B?QJ-bM9AnN5UE9NiOeOQ+O;AMtBA%#yL6AEC@X5#Hh~~!!&uF zMKn@9^#KCYRFa)=`fa1dhsASutF47M-I~VyFaF$OpCLTAeGh9|j(5c9=kce{Az^{& zJ4bzf0TLq;V?xvmjnJmuXzf6C=M@A^UDW4^r+=~d82uXh&)e{(T{mXkYS*ec%($(Z z% zu0~?!499fd`IwVwJFHS+4%TWW+dq&P!}ZeOPzfJf0(YD~DR(=Jz*xw=|%Z;iP5=SE8q!h2kl+I7_u@b#&tnr40Sv8+ksOHj9onPC9C*HES~s)XyC z$>@pjdRNm|>t~*~>a(os#s9ydmV`Yq79S7$z)}$F(5H!Q@Md5_yx$G@komn;$<3Ej zDlNESN$8la_KlV_#Vz|ztePCurn&nL4nVd>)<};U9H1z>Q#sLw|_-OUB=1q|> zmOtG=XMd}RTi;tA{fkwE%_`C!=T>ne5HQM$eO$B!t1HQpJC)N_uTf zP?K8(H}}sGO@E&WviK1F4Q6sMd{dA*Vkt1ED+1$9wgg9veyJ{e(5jTAKRmttw8e+J z*sDJZxA=KZPDLGGwRj!q>e*F)@OlaVO7o^sE=jCff6B822`>Hng=+D>Myvp8$#0(j? zbH3Cw?%CCr8jc`g>gXPL^8likIP;5%H$S!t;jU!mJ_v87n>#V&RUPUjhY*>e;=PV- z?Vo=LIJfhr+xi?O=#Tj_<@p89Sm!bt_FgynbYMEaZs^#)xqDC9*%Zgz1#k3+JGG%d z_Ca85V6Hjz8_>r7R+%LIWTdtZu>`~qKKb|$0n?vN{nThmG_46P0w|Wdz18PlTm ze!S9QL3G?yA1?R?$N6+Kc-2)2ZAtdcIbi%)h>X`!j=;6@a!E|0cKg*n4{ z9MbpWq*(|#JUy=}9Z-z5`8`O06V5o)ou~_|m>8>ih{K+k;M6}J?3jVjcsW{cNOd`X z@J{y0C*QX!dEe&vouyl~&qZjQ=)LM;TaOY%Y-HYh*7)sKCH-STe$Bx#-e*6;Lv03Ilt>`<$;yW#we&TlP;P}fBWX6IBVpUxp zYVj-xNowJf@Wvndg_x7j2NRJnB;K>hOV3%^4(0=cblZ)@^fKPTT1C6v<|8up>9O~| z#`VdzirGWGhb5K14pEacI036K_rsf}W9)o*h)|IYR*6?#>}7lYWtHG_K?335uF;Z2 zJ7ObP1#bR^q-g=+)M2)q-+WcG>UiF`c;*iCLt^~QU!oAicenaKMPl?L+3!89BBQ*& zr`y`oD&l76qte6&ku)#DF)U#m)`kp6W*id9J{`~bD&i?bxX`=b%%1^cx*ea$syIFp z-dMsf5_$HIi?Is0?VLrv^;iY?WhnmrISqkvlsz;a533VzA~BuT$M;b0&rPSUvFatd z_0m^Ug1}ho3gs55Z*?IRmM(t2q@Av6t!hU3iv3oR(UI}`7o2a@TM~C@q>JCLJHJEH zG&kd%v08KAE0&&!MD6m8T42oP$2j_OaP(J8qEB~dzE|#S?no?qquZ^&Xh#JiGA zqIaJ|WNdZ37OHp7FYQR!A||R&!mYe;XM~<;&pVMA1H-(JFU;F_U$aWF(ds2QI2#FD zOK5@~jMXcxI$ZGCX*uCdSZ&n_x6jiDp9n26*2Xs7=90Hsh2}Zq6WI12t*}(FV8y%i zN6ekSSrw7QXzf4xb@J+(WBpVA?T^UB&1mlfh5pHU{1}9$?<^$={Cf28ACeG9vOde# zhf&4^Eid0VY*?ZtuzQaYDh+|Loaa-nX7OrF2BPN3=M&1fI;&0+4}}gjsop9OrI+)c zk6AjVaxK?iQAC@Y)rzO*zl;(J8smql^s4J>H4p9#bX2Y zzxha|zsS-*L4OZDLL^1g7ma+mriY6(RExadQal^MhajyRl{-@wjP53$VPGnl2s{Ik zgM7;6kdAo4SB8)GmC-@sc`VXbY#Eqfvx)Cg5uY3p|5YM>%S8g$iv+9@X}MXX#YT}< z#Uep@B5ihww5|~e25q6+?-yyeSENIO$Q=ho)KQU+Ux;)%DRSp=kT`q~- zeO{#7HIc4YM0(s3>3&1RKBT2YVQ1*$Z6)M#3vt{ZEMcCu67hAggkKI8XIyKEe5kcV zU2ZL}e%)GP# ze}1RD_H#Q4rH$8rzEkFty1}9aHpyu%o>3kjIo(P;qwf-VVvoq!@gieh5gGSZfIOLQ zlL_|+$oOcROdJv@PhAd_NpXSl^q4@IeA!Q)srQpD`1RQb{AKC~LGoNXf0-^pGVR$Q znellGdA?mMnK{0NyinOf(%Xx?IJ|{;=zq$3krTA}Fm|LleI#|PkE9Ip5f8|U@s-T! zzLGMOadG&_-Pri1%};WU`bzdCUs={tq>#D~AYTIg7t)-8zOo#;{%et0S|`|dw|FMw z8;=8BZO}PFB(0mT)VK4I2KtrSm+}d|lA97BhbZeQ#RhN$I)%JE#`FYq{SUs<@QRO2 zM^^#kHjC5_BET74)`^~P{3Nx#O)kL4AiqlL+eJLBz)k21d{qB|pEOXezJ*P8!53m< zCUs6rKRNYAA32jf-sij4Lws_PXDzo$6=@mp9Jk>c+W5#vejF3#vldwg^fvw);gixn zP*Shhsgz0AusE+4MX7D(C1{4WNb?HqK*HQMTcao2u?IZ^-c9M@hcgPCbTTHn_#L=gx?xgOWG6bI=uI?$Ht?Mjb z)ZZ(gf8AS-{BW<7PO-^jfs%o~`d|H| z7kod;WgQHVGVEARy=u~a$la6~M!J~%WqPb{1V~#_&(Q!$*&E>XM}wcgq)wraiGkuN zM!qXRG6w}pR^LELA0@IJ9r?_=(dfxOA1FBufwCIevb}+_gtpd0Um}+BX9vhOVlo$g zGsqnkAQP!G3wUUADrqPvo*N)hr2oLi`d^8Q2Yh8ebS`uJ6VfGrxzV9xe+jbG zHX=tTvuuLMw)6OpysPNW?MvMBM&ERsEJl_;h3t2Jz30-y#bNQsNEUCfw_hMU5py%^L%w5*fEMmbk9pBCrxlX+_`nQBQ zxIo=A;0yGmETGI>=2K5}Y-9c}@Rcu-=eGBitN1gezfDSSv0t#J6p!+i3&?U=lYF}~ zm!YqsCm-H}A5yxBltO3s7gd~4w}OvW;6 zdNA=GEUg*CR9kCFgZD6YDXbm&*tLu?UUErf74#YUuo%0tV}d1zx_3}#r>@sq(y?u^5_yw;GV z+kM0)zf#t75`Uc+c~Y;Jx3Ikd{)YBpptvX(0dnYL{r#L5pp(G&*stsVo76L#vJT?L zh7ERTV$U-{WH9Br;j68b(PxtZ(1XAn9LQS8dPY2D^~Hb7 z1LYd_z3C*Djt59KY0fpyp43^!-o4~FK;KQu3_#!Sq{}y=XB2vXp2vr2BNaWzNWTTS zt2iHI1d2Wr)W5~JpYoT|^Vp7`UqJ86APl?;Y#`4ODCekGU+F6a(*vauIu7}D(m>Yp zU~n7S4_R(8cLvfWy#pjjr;|iVuq!nNpKuOHwQ)YdPx-q4q;)!N&-tL(COe_)pT!=| zcqxpV=ODf$)$70K7GrnRCL1WTg#99CkjOmr>lo8}YG!}@g)DsmcMj}H&7dx{NAE4H z7d?=9*Z2~Pp0PX}!@LMHmEhs%I@)7AG>K&%u4jtnUF^AAQ2^`b9{A}_m zWs)e9pC|Gabna66)RDDm7vll)Gq@{KKGngvP)@h;i`I3qt2F$^{RP?9Vv%pCyBfNF z5BvJ(oIh*u*IR+|9r6^$zy7Xn($LdK^u6gPWDS+<{Y3$iPn{ohnZ6=Bp-VvSCCWce zdCo$0@CQIjOX8o@EC1X_3RnX=VV7=0uc!5|&~8|O{EV(1;233>_qAa>bsKufxA6Z% z-bi{*>-mWC*qVaRJ;z1Ga9RL+tY^ey2U*n zI`?=F$xZGqxr|*f`Ne~JNWQ(h2RUlXL^}9`wHx7y$YJ&o258Qt!c!oY~Ux%V6Z0Im{(u zBAYp!bKWN3qI>Zz{C1Xg9(#f*v+N{w@cDAqkQB;#G&Vwm-)PH+Hnk5r(Z`%sHd&iO zUIP_@ersvC%)B_uTZG=rE-`QO^t#CWe2IH_H{K`EQE)?~5BYzFo`XII7yz%&UxP_= znK$>6H&W}ELj9kq|G7;bLZ;78Gm!rkdK~E!T1LG&(33&d70&a=fj-wSXWk-9LjRH* z%z4iDS-X%!52s#z81Dqk`z4fh>AGJqmzI-%GC-DJqrCV@!$sBw2mQfU&rm0catqKm zUe~`1Uk+tXB3lINUqV-Jk%5e--hcI(KX<6FJOV!$9%|q`Gy}ak%z+gD z0GSLO0p(OYxr|#K z`~h$n)N^=jc-%*JcJ-ClsGG&z`dj43Krj5?kga2hd&fzC@4V`){d~$t&XJ#uPf{jf z3z$aTMr1FNE*}~wk5Vpsf1nh=zsZ^9I(cicKkICuBw=$3`?m*-pj_$=-amK`&}U!| zZwNXTGEWD{Lh7ayi_0kgCVT$kHJl%k+3(h~&f>deGdVlN1j=o6*LzrJ?)8yvoOd2a zXBKt(VE-c0EcAGm;xERyp4e*m!A}CoTZ%k)LZGZ54TjIH36xHxT`=QE%xgvZVP2qI z@S}Zy-h$u@?D(e*^9TA9mbLDjSBjk!?vH;*FsElT#+=3V{I8^55y*nhW^U({+vLp} zn=I?Aq#Aua_4vQW{Qa7D0^&iRxz1rr>MiPb7P*i7EaIk@F82uY;vqlzk^Bu#C4G@C zVSj1h{iUAyUpm1i_h5#8kI?TxAFNR_k7v3kk)>aw-}h7h0YCW|SqbZR!2;GN`mx1n zlj-zf2j_+IzQjjMoA{&q#{lvC1h)Izq-=yus?kw%OQiNVcL8)%+Ias0yTNeU7!5L8 ziwwKKTi4*DNbwPEw;XzcQoCQ zjXPuH+3@nMUtTBfZ7aVqc3j(y@MqRKJ}hp$>=MxgLX1lE8NJ+xCd{~2$s@= zHrdA8!A|bR6~s!dr# zU(ts6fW8gVkG7VK^KE4%gOhc#tyCdf!*_&zq=q(GjNH-+#7Dl@KE*f6ST`8q4 z=l`~{Y6&rs(^giGVNbyin=6IKA?Eod&PC)OS&eJQV$9L9Mkw1+X*dw=Qzkrm{x zJdJJmYXfkP=jlL-0VeL+#EjRRh&C|YqH%lc(BH$a? zdtIbSU=hgXj9-Wj@BOTr^Dp;;>FCSk9FR-ChdG>b3qNbU*qJf`Tbc6>-{1q%LdxWW z641c@yOMQf1^ODWv%WRH+C^R3NMrq2kq2Fjj-%*UPr8{sgR(Eso*paDK~Ro7h4ln^ zn$wSWIL3Jg>xtIMzFS1u6*fQC58j%7X8h=@wreGO>M?9M0lo#^`#a}ueNNSHXeHFw zzV>jw)AzK7NMdLuI@-15J@rnhf1xe+eBz>G8`k+C;)8cAE=KjIIsy10t)$`S7T)-p zg$F0T) zg3dh4{Z!{OmO6fOb$&OI$;b*djelq8{ORP!nD$qUW!x#N=hjH_R#VP9|IoXkss2Rd z`Azkw>iXyL-xXpPeI;71?FX~S8?EzW$j7HTR?_lp(m~r#e|7tvpj&}Hl&k*)e|+O3 z+v)QW-R@BA0w{uKlRx z+BVvK7@05Qm8I(=(=pu&e#IL4zl%LpkEw&QBbZN=SuvY8VlAUwLmY9Q;4dp}!(}yj zi$DWs(8anO(Brh0Gz|=+odFtJ-rLwz|116ch&jmItHiDp_I1xv_>b@r^EqP*;9tXTh;)Q_jE_91KgRPtBudQ4u{{oY7D zkP5Pw4wqTv={?T7j@?6BM@Pz9`sTTWAFl8olP59}K7BKN#9N_UEAsGv}7hvzh_)mZH8^9Kp!k+G7kI?>0Z6L)*sd|qg z&O9>#d%Yh2#pv+b&;25me(5(sZ+>6sx%ij4tk(lwe+6arnyzDO8T4w9M7!Q^G~bV) zAFMY&P^UHe*`xIPMk=wAc6Ou$Q??W60R~g2FE-969j$rn9!L5YWFGpNGK#*!yU5QX zjUx5*M&5U%tXNLo0+9zOyOQ}||21RDyN{bPE2d+cj#KQbVocMJ=`v;L@UHtCjqN&) z(;2@id09KR||L8aj?VV?;seFIRj}Td; z?bUIDKE3~?r9gi^LWcEZ{`S=Km$i~}{c6e$q8}Sbb9e_iqxGRf?MmW6&$Fai1ggzFVEdp0lh8 zt5fM17?lx+H^_n&3Rvhl|#(gi@r?^;s5 zzHKDUJk1=Y|C4kccI4}nIhxIwW%nhnSbwH!8L76j7&@arcajgVCmMT>Vh{aKwQ&V|my&bGSACc}M^_YH@QC@$WsDGDr;#uT9k?S^E z>vaRX2K?yPOp*Owd+^&wHhC8M5copZ?@0X?%+XJf^_ll2vLYe?R1H~=;Gbje*xdt6Z|BTSgZYz`$i(NZhQx%&hDofckT+6zY!w^ z=)#ZxK(4<{W$82E5Fd$xulMtj#n`lr{3Q5gow1X3;&tey+}*R$`7YnF*F4}WtB}2? z=hD+Y_yhe-{(D#JX|i{hrnMY>)zDej_+7%6zOtG9^bGuQ`pnOcJSPCxJI~5N_;aAh z@kk%}H~evQucY7KL$A7rb%y!yd^_%HcXBoAB%ZHHwT=0eF<~C(x2Z8 zjEC3dK*1RNiVrxhd-6#?#D{s=#L6IF**U^j-p0;y(lxWW>rY}0VvfD%&Yl)rrT8jJ=`Zzc>-beq2PKsXgkz)KPcZugWr^H=Ub7wO*)AL$5Rg1)V9F($()&v>;%wwg9iea$+O?kn%0qfT1O z`WTUQcA6uOTMwo}zX$lm1BJk|!^F+$7Wfytt|Q|&QnHk>z6pI=h;?G%%*uA6?;opkI74(~ z9eIs4R{UhfqkNkOb3iDF0PFEpK+H+p-%=-m=nJx#afM*+f zPd57zbQ=3q`ZU(cm;7WOd^+F5Jtx^u`*S{F9jYa^4k14bvY1Pm>-?mQz4r+GF;Gi? zYrFbO1!sctK{S@zpoKb4Yt3huys3q|8n7fm!!!AC>-`wr9g?0;jQ~&ACQak=`xj^|^UVwL;y4$Dx%Wggu z4|VrxWXu|opZPjI=mffelx;CMk@vZ-&q?anNs`g?JxPD7Roqn)JG7Af18M)3w4B|9cW zN%<<5^g#EiINp#+`+$C60Prx6^m~$?pAW+i0~_;v0}ql z-+Q+d@ZE3o=^nCWLJujlwUeT29i+IpgKV{Rl#&~rq+noxYzA8<1xVr804X9Z=FYx# zX@Hbu@Sg8sp5NswBWY(e7zZYT$zUp|!wVs@bHoE|6#@NwDR0GWZV!JwjBfXpJD1Im%_b_Pflc7?)6fZEOI z1=XMiR5eR)f?U#sGLg<$B)Ji;1s1elyD2TAfIIEnu#Y*1>OMohZG< z`m&e30qiJeZq_hINq16jE&4WqTu{b(kWX4pS^)~7Gl{J%&Xv2dt!fbO`OM)OP`kh; zb&0(DU&2mZ7wiO8U=y-DPzPO@OyB16dq3y{pkye0V{Is&PG7+xWQV~Ka15LPr;B)x zB0cj;fSe&c2QGldX#vtmdKJ{}xLdB1-UPQnW@J~%VomoQ&RhYlKrm>22hs7`0lo|9 z0eXQxpr9N3^eA810t!J9D4xK4pUZp)={>tiKgtaN4}-yA7#ImggUa))ZP!G0-{RhQ z1^+L{|Dcw&vkq)K&G$jD9h89`p!||Z#c}o;aHe&jobCx8VhwK*DC5vM5ljYC!3;19 z%mJaG@!dd)AdS*=HZh&!BQ9t+sP)_}Nu(9X%E5f-DhFc+7D1M=aM)36L7nYUXBD409qmKz7XykV;bT{kfR+Adfc# z^e+P|z-q7-lu&LfbEuelMW8T+`LKqVUmhR@q@5^}1vY@({oN#&G>>!>$cN4p=0E4F zEq%L7At)N!U5de0=#t*ur3|`|awVV)>;x6Jx=T5zg04E=U3T+(fja1Ypw8JtYVAFw zhO~NbcPY5iT{eR)pb!)dLO(FuS{KCoQ|xLv~QEobnZ(GU3SUb^`na!U5G;@u9Z@mW_wJ%b*L{DHX0I4&HuQlD}CUwelx=Y0reqRCYJA(ND zcK2ug_GZkP$2Fw2pic2UZxa2-wk_CLNLmD6yq-DAIie(m{g}Dfiu%Ez1Ly?0fF7V1 zs3ewl#h4hYVoj)quYuPwR!4kq%VYg1X8j>8t6}|tE=PaGDq?Ro>&MY<(g!{LzyRm#F)jROoas6*mjg}yeD}VCM|Q~f7au2PyxNu z&fgzYf-if>nIWKc7deFP!{7)w0lo!iz&UUM)DCYcjiim~T|^^yqmNvL&-}qpvbdaG zhu*Y+@dG!Z3w7V<<85ePo<~Y<5nG@b6pg|r_Q_-91(Mea1cQnk)}y5X(gC`Pbz(Ps zC+IGq?i%Y6d=2YJHE9oIy+9w(4-5bggTbINy_*apJdewC+6Tk4dbh(^*qzv$m4%fG;1&nhSPQ(rV z^}nDS{qJqgD21d&^t+gTY{lLZY+X&AwO|9t1^FO#7iaQP-rY$nFA;wk#NSflkFYM@Rzy(mm`Mr_!D!2|R*Z6Y& zVvgt0P7Hbz(aYSgC9Q+scEwjpZ}8iOy{rLXM=5JV4etQu+&?$_%1w0K2EHSi1E3WM z1|2|S!QE2J53^6Nl6TxIK70dv$ zK;vs&r1sZfnFAdPB0w2q9z|NdhVg}VX*qM-O}d*{sG3B4Oea2O6Cb2?6BvIUV*8Mv z1m=T9U=y;u>1`zqx-g|JcZar;1-%%QWVDs7YuYkKZKa6R`*%()@dtBy8TpNOwUia4 ztHD}uW_TOfKzjOx){;w_$y-rYHE+_;g`faEo6)o7U|T8VA+?AH(&D|e0ZOj5m2|#a zlu)h=>;zSy4(tO5K;_ zv=->|`L_ME-$47MW%O+aX?Z#AqkAW5nSWckfSyKh6(*hW34& zzRztdweU5_tJ}AgRPGph487k$9sKro*CJt?(s-=;w6$ ziM(Jo^UqF*NNI$oL;z{%olwjjlP;iv~pCqq8 z_pRRSi6ht>Nw>n6kcLt>0z?59aD(|^5l91-8LYoKtiS7-U#l4ZQpO+DCUgG)+lYtK zvz)(9bN;%)`g@-B_ayW4DC=(xd;ewT7JANfY%7aNo9~s&pi_%^+ZXori~h0#el=JN zHh{)g+Da~IJ}3kkFD;M~(lT%+4Be!scVH7~;|Fb}j&vvMT>7u9+0X~TAyCGilSFzL z90A8b1+sGX-V@MO8`;CyU%!Pu1M0Xl)E2XMf$DO8S0BTA%N-j1+73Z*n}((-5sC{*$ef3r4w`)P=YO6 z`?E)aB5dq|tc-VtUZj0M#e_iVM>+tM^Lvclpb9(;KN!>w;#@G4_k*#V6Gm|VN5^LN z$StIWoM(#GqkAcBl(PSVVbmE3MuTy{yZ)E5-hqkmmH1~DzVPnz*jx>5t*?`q|6j2G zg6&7yf63cHnettnKQ?pzpr5%l{9Y72Q$cz<@1$?>_dspvzv3MPSt02bkl6x%^1ZiY z0k+M>#$;@@1;`xAlob=Fq!FNEGkXB33zQ?@9YYKx+Qbc?1ZroqE)6119mMH$&L7Nu z@BAk%1Vx~jHDK#{=Ey4Uu+&)u(m)ni43>cvU^S?u%r46A-pD)!)pMEupcd4DZI_t; z*O>pHY(Mj#xmI58BNe6mb``8e#|DtAah7ifqow;8E&RNm@gK$f2irjz*a6Bx z1=tBr4+)T)=sCmh3~rP9KEYf7tw8$91yWn|h6F=*0G&W>1~VTfNuZGH)JCGU@#eERuXT# z&rgM(0cL?YAQVJ^#-49T6lqz`0&$VLK@yk`DwZzb{;)t6L064kD7!%#bQY+Ct_3yI z7jhO^$lt0gkj2QCffZmi*feQ@tX`yZtl!2X~3e7D@$Wc7j~&IfS0W;0QPdHkB`wJjWtA0bRI?{^u-|Z=uhC671Sae~a-! z5jclT_x}QEBdFMKldGiHLHQTNS+=RakYKhOfQsNX@4JbIdfc`I_{|k73Ss+E- zh<_XLKa}_fzN3j1&io;_a4`t`)_;Ze`n_ZJRMRf3OqO^1hTicY*gCgx>!*W%x)J^!EUH%bAxs%uA5TcipVk?Ac4r zyevXi40=&6{S$t7RPWFI##j2lmy=dp@|Awj1Hi*zcMSIf2j_+btWTu1K>sFqFnPm3 zo%l&^Z_XLed8C{A^R@v!4on1Fim@Y)^`VA#Nw)&MK29cYDwqLgfjQtzy|09l>UY!# z(nju0QKT;521#H(SOiYTEs_~}{`oOS;1_Ed_l;$wXI`-Jv5@r)r1oYGf4@*xAYTm{ zPc4+Sq-8d~Rgz}@z~9_GKp&th2C>HY^Og*)-$Zwx=69LUC7_OdtM&`tKhRl?yc4o4 zPzH8_jW$2|pgnpzi~N1RpA@iPZDxxiu@4VqA8y0G+nIeA)V5?F2KsOPt7x|l>;nhDrbPC? zvHZUf(1oSkzc&WTvV$>l7{25R_wVK0zt?d8M!xD~qO9DTAgdeV0~+moEK{_JbAuG@UsfNk&ZdQH}JTO{vJkCU|<-;noiydkOfXi3X($`N!Q1DWj; zB@3kUQ8Qy{B!9b`AdC0M%L($n1%EraP?il`AWKHfm8I+F%G;e6$cmcRvaD*EEbsk4((XSvs_RVn{2>ytd9kbz%n$}+g(AF!moS7E^AZ*d;vy_z z8J4hwWmv)zFYyvDW(h@Dh9X#CgcJ{92*HFfn3s@_grruhC0eatt?mv*DB>a%VHt{{ z2!&M&OI(;zD25^wk=f5}0&!;M-T7nx_}25B)3?vP=iYmMJkR-Y*AEPbvID~nzu%0G zL67+m?`-C8wlBxgoyx1Ym`S@oG5@<}z|+?4THjJXDAZ;Lh5DLdq0U%M91Z=$LZWj> zXlxl0lE!tKj(#Gv^gkb(ua63;_eX@|13nef13nX4w~h#v#vpSjte@EL{ZUUoaGt8K zSfl+7>&NLuUs5hEdM;NzrxTtNa+8Zg9^LM97RM8wYua-rTWUPl!=CG1&zYXy@7cWe z6u+5%6zb80BpMN|uXxHi2BQ>1F&raNhB2rcGBDJS;$xW34}r#s14F|7YnnGOBwrpF z#yMsJCSeMuVFqSlHab?Qe_m7noKU{eeP8)T!A?l)e+;t56vuniKWN>k{@JSjA=}rA zYbg$u#&B~MCd`%Ie6*b}4(XcWu#lcPTdWN!4vXnak?)jti*rnME-V)pyIUMqlB-a= zzc{QR*P*7TSp8M3{!(|@sj#+3Vj-A&Kz)fOC7=Py$C zzoiWzbIa8Kw@N~Ne@SS#TN2`H*@YX~g%l_?Wqmr4I z+26>{V}Gw_f1`OA`*#%kmrR{y|6XLTJbid{vBX`w3 zzNr6qQT}V>Us|c7@=s6G+YZaW`yU(iY$%$ejm14>axht2F8?T{$6s-6@;j719Ld*Q zo4CYA*Sh)HFj8C@#$X&KU=pTa8VdHxF!yJa{-E$I%tod82~qvf`&?<5FWmE9NvPBo zS2cTApW|m0w-`&Y94oO3eLpJ=tI0K3hYi?-El8~`3KeAJdvDulZWX;6yAb){GwAmI zXTATq_qD%0))4w_9}eIUjv$6(h@)=3{`uypA7FeCjR%z*G|`i2R@Mvty#@SxbNKgO z=3kiS{K{54I!5zPpbHsvBa0mJ*rtyj%>|6sp+w^keeOxpc~i)J!g$0lj4RT6e&uL=&}B`(^}$T6`w-d*wvYSmZQ$X?VeF;9rRi9X!H zJv_ie^i}fpG!}=RUwKFVd;fXP`dxA`N--2E@7Zv2B+4)bZT;GROrS?LNf#>LD-M%{ z^G7}RtalXMs2iw#AN9z_j8A-IQzy!`?^Ct!wG3UmTZK3a!)Gzhl|IXm{S&;g5%D(wl)1e!L>|HhApb^fyfo3I5H*nw*7LdQk{RVuC15s{RLwbp4KTo}cW5RLd%Du;dM%G;ZSm-5hp!WR7 z!cDRd@l(n$5}nFMS{c!wj(m*uYX^q9W!nA{zxyq+?IRl`IneLoa^D;k?)d*bJV0Sy z_aNoH|#I_7Bkqpw}s{ z^{%r4@$1gr?;3{j|BZ5QO6*HFS9wDzhGIBIq6}lup`YD3$bEKv#{aq}yRRtN|992@ z+Jqe=wGQYzZthD;fnVdjQ!jvfd^N)wh*PjnP)+bC8?rr9e zA|v}?Ruuk{cWMMXg+3SavGaq^Xf5b~`S1c~p2x z{Bo?sD%1{pA=KO*6;{*Z1C31^k6%MyhvXpR-vf+MlZ}px=KO9)WEXDm`zCBbwXwRY z?`RL`JEAalVGs7<01lz9rYzJajIon(WA2S)Lb!=c4zn+TV`4alIFd-A9T{|#82=w( z{C~9Ze{{2JBHJd%QIkKx|GM5D0XUA-9OM5l8~hWu5>Ar2AKM?qdw#?JZ=&iG%K5kL?LfbS zj;)dZiH(O0x{;Ol+->Q&y?EBz_ zFqq!+yHTO{J!SgyFNB`T0ijgfPz=XNq?Dnz`NYcTV=xX;xr*Mu3G|He)#V+XM4y7Z zaPBf6f%4W(P7^l+vk-gVyG+*HXMfY@(&u9#8ZIiI>Vw8%kLrkm|4(?^EABg@_iwS| zmZLHh>)Ys))2n_~9IC&<9;dIy8mz+xY(iZ^`Ohl<=_q~of0+9}%Kay!@*jcJ%Gg-t|LmhOmA&e@DPMWzta+>Zzr_7t;r^4Y3*7&5_kXJU?|(g? zdLbN;PVX092#3fch~XIGNFs&Y*Na0txqYK{0)6k56>PeUxI7B|kMHp9(<2|?8M61s z)}4?Sa0z{_)}xWv(2E;L4>b3VJdHN`O|lQEnt|aCnH`}`8=@U}MVm(66ZZg_LE600 z+OPhB;h}KRJns$$qjrV%3#Ihz6r3`f)TOfhHs| z(tpY@2IKI^|8D(Ki~fyp#{zci67Bp7?L65noZZNd-Kw2m&u%@%ZavG6B~w?~tz=rb zjcng6?)|62Bh#Hm&hksC-3#I%Kuu&k^eIP(fpsK{rWLuUEu-&|5dWK!lg-i4+$kTJkq8oKDEB~&e!F5G*Wg6$XuC4kW@|o<6 z`X43Xn*a6U1}a~FCfp?Za0eaAbEk6Mg=nr{xALAH=Kc?H|Iz#||0j;C>r!Z?r_tuP z_KnK_-?IIG#16B+P>=lu?n(0j9-`=fP^K^#r5K725t{FxA!zbKChG$M)US=8-j|L*;x{aeqbWS=J3r%hy%?LAyN z<1hh}Fa^^v1GCVv(fIpThov74XR&tKHv7vG0F z$VGj?sQvwtc{aiiQ8eE>jln2I-)BA+hLXcE5@i^JahQOp{hdTk!8G(*mo$Uy`GP($ znOb5mX>u;+VeKGe)9PSpZNe5*U`}Y?6*D=TY*(zkKaQZy^7wt&hX8-CpZ%?boa6y`F z?>nYP8rH^TCQEy~If~-1AU{mJaCWqFk=MknEYcLeFE~HQEt8b50rmQ5*J%w z4jFk*`Kq16R;15Bjraz6jrw4-glD7R*D06Jm*o@N*~rlvpUUrAGs|YKYJMqHTMv}8 z4rspP7h*A%VmVe~6;@*ndVj}9LiT)~tr}hm8|a&`1r^wVoiCP~JFWkKzGgmaavu)h z5RM>*+|OSM$H+GiD|3i^b9E)k=d0e~t={L2%I7lW6HR=8Ni;_`K8~~bQ)s29(YAvB zPuTg=>|Ke!#zx6Z3J)U29g?pglLXKBkD%Y4E1AYhK7kVL!4|ZpBWNllW>x3cO7ruwZ`9G0oyQ68dFf1m-LSN z>$uLzGeZ|L=srJ_Z8tOIkUu*!G_RN$T1L+d$EVM&j=HTfVa7k*!|{ z|Mk`B;qdJ*gm)Ib7!EC)8vbF?)Nt_j=fjUmCWiyBP7Xgj@%gZS*~IYnf{9^Y&*#Dq zE{_j;myHkKzx~Km4v^W{8wSu(J5h%wD;lfJLyCIOZeWX{~UHN_|L|j|6|xu zKf(K>j`(_Us5&|+R1f>BP&wj1g`IovP=B~Q)V)<6;+^H8AyMv`l!wNn z<$UPn#y87D?zhDu=D)`fM-nNtBZJOm<)LFyxv`h>(DiD$v6piF!t#)Jk8)(o_VUmy z?UeZAZ^3X2aM#e_J6!OwJiPJcP+KDfP8l0oYUw%p3_)@q)zl3DxOZ=8E z@ngQEE_x|k5qAx#t@2Ao>mF~AHxaFa>?7|Wb4neAY^ORX%|GdxM&pS0{PqA3(f2iV zanu&_B}MBk`@T2xQTzXgnW5-^jLQGaFqn+|f2C3Q)B62)i^5QPwfj`{dT|&|uU)46 zFDeQn>2Wqr1Ip-QkQ~bfQ$Hls4~^wT;ehi#C4L+xU=pTa8fKtQTT>skBfGUDJGC3y zy9D`oePDCH_Wfn{HBx9rdLH|l?cI)!(d=_{jb)!tXP=K}pATc7k7A$q`_EWylk?2R zT+GMg`G*VX8TNEE|8OyVDe`RUoVaXST39YF_KJCMMU6ul}EQE4N?&?=9`WK3~g5{r|1{|75FhTHm}4?MP{_H%Vs)s<8`g zTebh<_s}yf(yq713;h71xqCU`>`~_;4~dHn_;@%HN!04g93$hX5nu2t-qrsXPNCpe zT(9qUiw(dI>G`bd5Z`Ofc81L3Bu?WD&fx+s;R>R;@6j66KI`J&-0WKf;(Af}3;kQ~ z_f2}5Y{R4eKl}4b&&Y%Jx5m4lRR)gw4f*}v#Ubvq=NrvsOhngP<2i_{n=?Jsub&?J zq<07R@Bj}{w9q??!N}e69xd=LocB&#_pb2qWKMYRrs|hn^d7n&?IrqM-m^6Q_+)*q za{bap-doh^8`q;@yZ!|l5zQ-lGXMGYl296*=j$b5C^;M>QHC*iV*ju3{Fitp3p^Xo zxv|NOR8}n!8eJsouUWmn5j#_awSV@nMm$$Lr+b??#_Tf*Ckhh8Qh(>;x z!u_b6vR%5Vv21hcY{C{)piNwQs`Ur-%uZ>KVE@o}A^(=N zw>t;fy|*;%5f^)f%}gFZE&ULA1U2jBYlVEB@T~#iV`w^68j@$(|E@Pd)}3enUv}Jd z_A(mBD;H=|hNJbrasNpog?1GD0qm4$4RA)d!!ezX{geNV|6Li$A&+L|tmW<>{cq}! z)~m{Y`cMA1yfjWC)#;u2nRi2(J}rC((Hh{#>whz@t!uP*YlL^q_2oA^euy?+9dgdG zHvUc|H%+zTf&pj_tVlag`9!9 z5r16&J4at!-@H*|Vd>o_l5u8@*HFw)m|A zJ5Y^X*n_^`*z<)vfJ5m0#IxZD*<(M#7`biYAN?)ERzEvTT`D_?`GAzWMe`-tbK0MJ}1dz(SL9fr*Q`7Z~>Rl zp-t~Z*SqRnbYE5vBX?H4e2V{FAE0Hk{=qzLJz5=`9;;r~Cum1ZJ$*$w*U*a_sNHY< zo%;GFJ)Y%5Puu&Seg{eIcawfY;;=Rx_ryKGLliCYej?iIOSdm?}|NZhGl@UZ`Wu#-vFb3l=0h2HV)6k(jcPisu*B|-jy7zyi z{ok$rSI(mEG95<>t#_6Ge&wHR_rKH%V+hijh1r;k$Ty$fXwCyYT2s=6h4jV9PxtOk zc8;Cu0n|)1ej|Q4qH@2IT!q*`{U9>o`WjL2`>6-kh@0kK#m{;du}*jcDu1p$4*wiB z(LZ|swg^{X2XbuVUF06@!vR#iXWhSfLw(lK9}+%-7>*&1BvNQc20cIH7b1H<=Nnbz zX`I11T)-tj&8`XB0wXbo^)U69f~-f*6q=))bfjaCnful&lWkWs#)wG9u%KSW;H&WX#SyTv|Y z3%qCOdxwp-!g`(GxgUQ!O5bNxDEgngj~I+n3`I0HH=OKsFGrGP7=v+`fJvBwY3S3> zul&IH|F^s&!o6SN^CV|uF6JW|GhIk7#!@Utw05FK{7U-c_1mlHxw_}Wzg)jvH`)4g zG$4+~6~?9K7~@}HoSM8R&u^Z!r~louu&uu=td`Ci6z2cfgQ(-w3!&3^b{CnsYD}EW z3g^iDGVAZlt-l{={e6k`_hjoRW9#M*w9(u9#dW?A)=6&zHen0e{5NfEyn>!FUfy;8 zg|LHOjlAD-m!0FhbCJ8m#iX-`+=trj##6~dsM#xDS^3)eLO3EEL(^gTa!ezc*l+xO zy!@kKiR0Fa-za{o{F6!J_s9GvjwDiOM+SMEM92H`f7dnk%RkwD%e6Ug4tX?>lK<=S zFFr-KIxbDN3AdA}tM)jM&KaD;1w7tAq4ICkDWjz=pSjN(yY*XMI5*unCOa4T`2CCR zHy6SCSCf7rTyoqs)Y7Xxzg~J=UK(6aVzWH1f0VZ-vf#(zpHFR94jh*zZ<2jzqkq?U z(;a%oJJof|dw<<~f1mH_ymCOl=eGx_lt#|}A3fT_hr+$V9D+ZTg`&mY`IlY@eZMw` z;Ok}KDdE8=#Zc4_)CX0L;$#C7CHkdga;knRDqkNMhC6N~$}k4wFaeX$`M!6sN7=rw zjFVa6ZZfYf$dN7M&Hovz?_I7BK3cif|83RxZNJP$8Dia`G^Sw&VmtLO$QrU1v+47( z5Dn6eUswP1tAC{1gyco``aEsT68%BM)CsvC74ygF7htjfRoQp18inh8uN`T+yA zFD2?^a;amMV#9CZWC>qf&y^Ss&K zjoRXbHo2)@{{YR}`W80W@%!5MyW01I+IO_QrG4Md4kJ6!wO0S^Reg@F`W|FXI8R1n zE87m5bLm{s9Mu%rjtugsD;XH-x4M4|%n>`PeXh|y>!TFLC$!bgJK1r2*>&~oI(?W{ zzo-4)Mz(LZN6I{QAi9?E&!d~3#pC^nqW1Ts^HhD-c;4sqz3FX-rGYc_%v=5|-E;H{ z$oKm%3i}`IHZCD9HbNhUyoTD#>^SlUYUmC3^()Tm%Lw&!N1K!W(di`G< zmu596zgV$8x`|L^L9Do*t}&jFWfwt{XgCK{{Z9vXuZ$2M;pID`$gmL zo1GsGyGymx?DE6x^6jOeiJt5%4YQnMHs)eJ7Gg1$VmUhY@;@BpBRIPpv`rrhdmqC(KAEjZ4e&?z4FIw zzK!xGoOMh$`KGc~Sbwi9Mc?14o#S`y_9n;IxPJ``+}9=6-y55Z<_|RqC*6}qGU3=Q zj;p{9RAU$RV4VBDkF0Z!dNhoX4jSo+S3Dm?{)s341@BbqF8jjsPkXM9=a>AO{;Au_ zJ)-%62b|*&jv$6(h{pHhWMt1rd-_H51Cqiiv?GH&P9k-?B%CJC;2bWXZF@;b_mqT7 z^vojthIttYF z&2AD-=$k}q0Jo{zqJ4PYTwqO;-+R9C$(f=$>`xf?n>Mz1m^s2Ae zpXJL%VKBWEh4FuB{h9wyxM`<8$SC{0J7zdWq6}j&4iiw>F)(zv*PUCHaWXSVnO2t< z_GhE#2Y5c}ffjYdaWdt&*4I3r6`s!$_TK_~f=g!#reOwVVK(|+WK;a?*$|EW_xyFK z{Uyy2dgs|N*Kcn|?dDeH9`l74BKLFc?;PuO>1ncU0bd5a>WlLGeQTJ!7a4U#cfac+ zb3Lx_qPgPxpAP?Z;M3vo)spZ|`7`0r&q?4ACp@cokK!=6{34>#QR6#IE)bZ%|qQgRjAw9Bi>HOTDOjv~8+ zj{te(u+DEA@UO-fwreNT#+2*qz3cZah>aZ>D##kLcB1)d^lI$F9_+&b9KsRAa13!I zkwUC~VED=T;&Ak`b&jw4e(~s0VaL=_q1|s8RP8qwcl9~rTO-0w{9Vbgu&d>{koVh3 z{QapRVb8^9!uQU8BJ3VDB>do&lCW=MiG3*T^Xm5>o*HB=VsUtT_cO+~28Dlk*?c%u z{o-LX2446!?zYYLU>#i?-c(;4J*EBdzu163gr8hy&kySlKTY?CV>a!q9q@Z)|M#J8 z|9$=AyL_~FL!#w2U-|F6o4@0uy&YP5ZiVInAE;Y@8;pupD4B2hWF-zuz^SA6xey}*S;P^bgDzuvGpGF(K9kEfxA@|EagyGT}i89nK zD-JbNi^CXte1&VnIQj%64_jk{1R60(T#7$^3ONI9>YG{QY@|CM)jgRdk^j3tRR8P` zA;+f3vjw`9kt|tvRsQGcgBUN1uhr+^cTDWp2hqn!cIw~nHvXf$ys5m*mF9db#9}N( zhhsY(+eKy)`ZQ^Mo2)(#nRni1eVCSu{1Zs|y;c0<`2p?1%cZdrvGe*lWX;{8u$o+h z+EKo>Ms7fyFQZ|gYg_Lc2e~$~X)}B4v%bsa_uk*w?~?5Kti7nBu(cvP$ZG6D-{07u zhunt)QTP|uj*xW=`uSJ-L&N$05J%(fe&b^Op$SP$b4;{0YWoQF&H0Dnh;R&*->c0=I3HPo` zuc}e|$cBv5+t&Ao^k(O$XO{GbE~Mz~$RCvUUgwz8?-}-ojJVjS{*Wh6qIPP3I8B~G zO}TsxkuRJRzJR8SABLoBY#bn;s5|>G)XP@`;-keQfhHtz$$zfk8hUX9H_?YX=-4g) zuBU6i{3ql;?b*J9)^3;Ijwv>ARnUb zsAK%M=x^kIthDhIeK7Jvq&?9&&^`IX!o0NDsE58A@#q=VI!~$NhN9-yhoRw>4?`T4 z-%#fpFK&8GzLv=6M){zIX7pvbR7PB(pC|SK86uBRP7@ zAZ1WFPbr7T2e_`w%HVl(gM_2;`N$u)PCC86vwnr#gpb+}TZAjH1G}&X`_T6}eJ3*Z zK3jr(y#DV9yFjL^QUXzR$LxXKM6K9Mea?gZyFd0kYz|6Z-$g zTB@!H?9`VRi{=DXJaop>s2GhTjA_yG$3zdyM5x7gQrwe8yd z4B0K5UG%7JkH%%2SFq1Vv(Klqr=;6Df^ChqtL*cO)(;%C?}_w^mT6ls7_}|d4|G~T zK#zR#(f&U}>BEuqzi97)g!pJLf|24QzgNxi7oLK`x&Yzs zt;Q)f8vmat|5Kf#T>f2OVP5_m=RmanZ<_ziz%0zhT+GKpEJnxs|3?1z@)7Lk=ibdf zQ6m4Y^|)(Ik*)pmPqqoSlhNG8rP5iBl~{$^Q}Qp5!`+v{{zrTTtHrND(!Fe&{^%Js zk_G?MJpEtxN3_0Yons2?d*~bJRbN!EeuIBty#C)<&%E5TAMG7LwEyTP$814mvGNk0 z3BB5nzW3})_X+KY_`dJ+XXrogp!fVEdy?FRJ=li>IE2`VkA)*-4H+Ykp_U#elZYQx zz7yX28s%HNoK*IsJv9DZ{~!A`<^S!-AdizcjWhWF>;EgP|GDVe@MQguzI$Q(XQJ}v z92al}*U*a_xQRY=xR0IqSN&`K?fiB9fBpQH75e{VN_wqRmCfn;|MYgxW1Hu(y~guP z=TbdCSVe#U>fQMmFk0*vOn49 zXrw35RL>?v^JVt+E%x<&w)9>0^?vp>+r16#>C(`_uJ3%s`-cp=kwp%9#8#C2Y5nUc zYt)^y_ATq*`4DE&;|JNkd#w?m&qcDI?R%RIe4j16{n;>ITy);5-`c0RTb=G&7K&Sp z^mTrL&HMrj%v}&(j@(p!fwBAq^Y{tom>0knUnzbSR$~on$2=PZ9)8jDzRKSxT=z2n-y*&l#9!r`*~&+= zS38Ylgkw@DwBOqBD(zKurF$tZj}FIlq6-;xx46H^A=>Mu`8NOGeg3}_>IbxnOQQ|# zh}NW>luqtj%D*=JG`($zKI&b2{nIn$+SRG{&7xmGexu`%9j2YdC2_IC?0fPWYL}P? zN8Uh9i*mJIpKdeTUbqiUleKwhT%<3Hy6MLE@Za=*`p-Q)z(W)**G^zCO7Y+He|qop z`1kyuL!~hsBT*Sep~=J<;=f>&?V(o35XQXwCK{;i%4?LQcaB z%tGXQiR$3l^o(*I%^jFapO5?~K z6Dt4NUIoALF4ptqA@b=Z_Ir;GdXKQhF%_s)7wjOb5v>V%v)`CIxsBX@S6eB57xrKu z4&V@~I+UmHdp;%n|0DSS*Yf{sHygE^39<=E_IvY0{{K__|N002YJHt^boi}P|Do%$ z`2l#mZ-4GEAHaV9@%s_yi{TjJh}Pz%FG`=D8STIRpQ5)TKVF?EE=zV#m8Q6uHa}0E zL@oU^c?LCmUH9%s*L_a-0t(kHFOBQvgRC2-{B3vN5Jw{tZ>j%V+*e%kpDVbAUfjS< z^x+OV^t(IxUAxE(e@r)-70!`)WxV;Q`ahxmuTlSZs{cK!KkdKmdm_?!Q@t0>`P_yF z!VgjOHDxmD|22LrJVmd5TG{`ey};@1%0VeP6sdXYc5)=jFa~Yn(ilh2jQ9SH_3qLq zA)2$2^FC$~tyRzcQ&E^AzVG+?I^+z@io*H;v&pEfnM?MX|1&=dD;Eo+u<`!I^};gs0-ESa{rAH65eF%6BfS68 z*?=vG_Li)A{(1dR_y4y0f7kur?f&m~|F^sU$YG#y7l+C;h3To>Rb#)DTZP=Mxx_g>+dgGe}CTkdwcJ9-?#t%E&J~uwEsSu z$69|s(fWI7rL4DarKg>%&AHmmCrIrq3uV$7gK?OEwznLEN%SbquAZ_mg+2}Wccm>Z zE3VslW{8WOC=0X5*{D5R7Uq)kQA2O2k*`EqSSY+0P4wh$`K*^uzttJPuSdguDZC#&T5iuT;Hb|GV@0f0vc99{p?ltNFhRl>a5l{|e=wEUf>& zt^bF@{9j}6E2XyztFZ=cubCt8iZNe$X0Np0(wC=iLSg=|aCWq z{KgoyG5_A*mW62DedOERj%Zxuf@2=9|GPxLf@|nS->1D>17y$acC14?Ey4_UKoEIYoB5I6y)_;a(F!cST~go zvRyv~|JMB9ZT)|m|2@P1tN7BZ?GrSMUiq!!&@s>RN7pjXAKmmUa+}o;D9rz@H}@dx zTGQqpuzS*I^IJ6kceZrqVm=mPF_vOE`hN97Vf{nT*SsUbz2=^;B3EM#)*+hzyMf$< zEvUfb`M*2p@rm-rw^B{th2$`H7ZRh{VdME;*uM2_--adZ-&fhcTiKRmVV&G7+64dE zgMB!FLjP62G1~w3kZ{5NWdnEJ|D*lS?#&+li2d8c{>5>m`q{s1-Za}c+9$vLvbd|} zu1hC|V~8XAEq#~$P0x&#HmdZ)s`&`>{1Um*&Ovs&_LO5HA3}R{ENYLcL&=k<;YWD9 zufS>HGiZ8Mx@+Zgy?l}d`@h_AZ^=IzrB(R;5j}}>{&NABa0S=UiyOF!j@|5kd5*?5 zGBvI#>)O_P{wS=!cVAl0%72tsw7x5EXmeb9THFBkwsh{`9v+}=gky%V`RIlH2V7s# zN_8;uCGw9fx-nQ>Y|h8SY2~Gq9__s_l&s|Mtyv;po8@bP|ERBqi*K4IUx@ZzNMM_B z_U-SQyLOeo>a4vt9TV;0Q%f(SS9##oZ)=}VMfS1wS=mX9(ms<(;huMfhu%-|5j;nK zQC>b}Pfq_EhY9HYmAya69_tIHkkiojImi8GY?wih_To+~dgSX%zUqA(pga!p&MtGl zCHfQ}l!RH1n~k~1{k|m3Cl_Kd3f~dXU&y_}=ZB74{PFCH$NP;%-$G4aWEaX`JK4-$ zF8JexQ^LL4)TPpizQeJcto*7y^~qIOjic{>Ec|#FKaKeYKat-)KGZeh*I@%TVGDM? z_#Z>G7eNI*ebD*nJLpyRORM(5#jc%^k5d0Zp0X?WHOaj2F30S_J{-Uy9KoKeH$$}l zPwu_a(BpgcF>$@yJTLv6?fNcn;+VLDYsfNJ4 z)!t8qozp*M56lr^*O2FZqtCoSzooEe=dkei2aSDA|3vuS{!wAyqUXX7<~$eL{g%Oj zSL}hg@#(Pt@SyPa{b9zwj3*{aLf&sDaT;fE4)5H4CLCQ`5-!kV1B$~>c6w(I7Kfki zEe^*5bkg-|#C3(BT-SOcuP8u0nhIO?U49RGP^G@nxS@e@M|=fGZ0_Gzrk0KSkJ$)k$+=t zX}IH<2YB@T5qnP2i@vTbVlX<4<99AHM*tagziMv4TI1$qew6tSqxeTo@Q)yc)>Hf= zXZc6S_RZ!*Tr3Tx(iw{37>Tyqj`4dLJu{FGgO6nleH`+9FS!AH7sL24FhN{wZ)uoB zPC;$DG)yCBpk}*#9hR?`&7%;Wjix#BC6A4Zx47f=V%^o_P%rIKNsc^+}8H_Z4&NbCfRo}R-KYf41@7n0d zM_Db6UD$(t_+{YtClBEWI$TRsM87Jmsha1*tAttlPLzd(;?&Am(8 z3y6LX$@|7%?;3yIZ~PV8)HB=hCObQ|+g|35iRR8l-w=98FM35;LDvGd`W!a<3by;p zYAv9nA74$vRJKZoc?5S8g1qBg7>IW|!=ry}OJW2jZu<75&w^oGg8-no=;<$L-K z%0slTe&Yz`5V`NZ6#0d>J^r3&v?ev7zuq)a|AH*Ecm3+?6MV(`D)}f~vKA-lRbO|1 zziJO4`Wc) zJIGoP`YNnO*8uhjx{*Z=(fp*koijtdHSG{?<&C>qOQvc0T|IJeW%~Jo(3e9g>|BvI=@Tbs9Por(~tkCY5cK13q zeP-Att#PP**_wQEA8Ho4u6eEt2ZRryiJn9w5-5y+E%JUKwRcuH;+VAcnnGC<6YnAS)p!${4a4H#9x)}R_VSa|DDc*W73Eti4@wAK^`a3 z@rv??E@aS+EON-B`KRa0mDB01xrRUp+8{qE+6b4)qfT(@XJZ<6p{L z<5cBO8Ehhx!b2T193xSNF&Kvln1qh^^|#UWmi{fe^?kF*(er3t!vD5{|BXz&Z|wcP z{y5s`?LFeuAycGN^;zxoFYU)qFYMoyEebQ}8EJLxHOH7f8_~DJa>$~4yM6z|b0MZ4 znd`UtsFn6YaxrS?4Hx+puiF1dcsZguGf6a_l25Ytt20B-uV>j~*S&nn-Vu(8%GWA# zHP#?1pXVf>PdX3q5Jlf`4H%4448{NV_cxXQ5$t~)-!A`XMH+2r zNA&H$;nEq2GK@jneaGCk=MOz|RsJ!7J_&iYeh%3s?0-xV7kxu%8aV^e-pRAb*@(WO z6wRH8W3KRgG!2k1M17Y83g5rc4i)yl{Wr@0LjPHeXzzpNBPMYZ!^#eB0E8qKA*hF?oH?v>*yQM!_`p6?H`&<0J z^INZl3UUW(`;9}OnjXKb4mfYDAX@+4t?X}Aw;@_%+<3xzM#t>IJ{&+_v-juc=Je2y zp!Yj`8*lS%bXbS;YwNAW9YY*Rq|lDaFKO5RrX&>nV^ig)+<1ieJWitU{lBl3gfsMW zxPVKzf@|o-4ctT@?nIKkU)fk<{g3xhxL5z+0r?O`uX+~|&G{ZomSQM|BidUy+GB1c zy)gbb+L{3R807g6a>yDJ>Yk|mpJ;yhRAb!bY!9+9|9_`(MI<|)4X2%Joc~S0Bt&~Z zY)3S$&f$ z>!nr8UYVA5(w_ti% zX;@6pY;J{bxgkbatQ`yHGpC{DTqChCTG? znKWP@{Q!~!T^kaPiS{royl=xik5T-wem{a3D&N)zLDd(17v?wS8btp^3hl@skGi+m zzk8Mc{rc&h`sEk(%h}0INZvI!z%i$B2Imm1#lJva!WDEVN1e)17c%HZ_Fd)kw(^PQ z-R$2v+W!UGda`we_MdDMZYQJpE7zpciyOF!wmJIG`UQRT%ywzd^Nm~jJ>-RR2c2WD zbCD0k#g0)x=$n5@;YKo{Z?KIYX!|YW;>t^3 zhy4p2)ARGlhBKz|kM=bd&V5iE#*lqahcK@2JHHFr`wiElL z(dVbnz$|pVtbd4ZWiz|Lvmx{M`TzYk7xS?Yi?I~T(f6L~c)d9E{G<0!xc7PcT#~D? z2I~-;%m+eNe#Sgtatmt5TmL)yW1)inc%AnS`YsgK{k&@&=!9_~vhIEDKca8E#?eSm zAev(q?bSQnf8IR%Xs$psXP{bm52`-(XnsJ)dH(Oq+9>T<2HktLO^3Bn`}yJDGXHI! z_78vd{oUKzKeVH{hy9M@gV^tA9l?G_8@(Nc{RK+c@8UA(7MI22{eAbjmSdj%0rC)z zAQr_Tj=J0CFRj&N*H_9hX8oGH6?&{T=Q4qp-HN3n%HPk=MTF zkVWL{KO-)tA90SnfZ7rIGvpQ2y!yy@5ZB&b6YfRRedj|X5~%avdNz8)Jo68{6OC;7 z1li;rNs>4G=cDrjZVLC|4su@|5IVLS|2FR3wNra@kp2Ibx;?9oPa7-ICv7fg|M!^x zgA@wm-|rj$W?!}=Gf?@uY<~RbqVDzE?(zJd=$knYoa-Sf{a&=%{kg7usvDl7 z7xvA3*?Jm!DVpfXdCJ!!g(;na8&)|dK+AK;;J=} zNZ!_0>z9wuJs-w7b^<103Z`KOW}$N{A0(o^x4RJSz1@vGJ^I#J%YOI3JxMKa59sL? z?g83`+b~-ib1@$au^3CS94qlr`)QT%8mvS0@7=TSjM6VC4!K`E@B2L;4;#d9!WL9u z2dc3Pd$11&a0t;ph)2j6jv*e!{X)LU6xyS(G&5whJ}^&4`~RJc!s_+YQTQ7lf3*K< z)E?F{wdi;U?LKHu@d%9@6x#f#wC2l!XVv z50Mkji|-z03}1Znb@KymnIAx=`ppj@)9;%fFv9!*bc{E@V5)S=r9*ZP@xM{#07xS* zt)g%02jQOgb1+$op%{*ls5|fb0w~M_$o`A(3mh)9x7-V%%yDBd4iiu-t_G9nad~fe z`GqirJ`G9nO~MKBjqcG$+us>}pM}||Y;}*3|LuSdqJ0h~4%A7ha59tMb3w z{Gt2x8V4AzCN^; z>l=>!)BMxSTK*|)lGYYH*`NO^{}iHi^A+NEpc<9l#kS4L|9WFr!VTJ*XpgBq^nECN zH*}|d#6kTC91s_C{2}rPYNZz=kD+F&J;c_I3p;lIr%+X=9rb=y9sH|MeRfi)9P(FT zC;jh6e=_VE|H%+{d=h`Z_bH{_FH_mIB`KUn{lVc+$?3@N|$z5RcMAKteA z!}S-!+w=Z1>>u$$_y^Z^NFA2(dmbmz^XX59cW!InKm8Zs$mp{0Ur&^U!v{x(cP5VX zT{z=t+2P^f^x@%0EyKfsw}yrv)(;K)@%F~Q3j3x{vi@yS*xNEGe1GbMuqW{!L+{^~ zh5tJQ{yTf}D`TgfW7}>03gqgZ3TK4R;R2%P-}kw)aEX2eJwH{>e#!s$9p6{zHkV&q zFK(dn9X2qTd)ek=RzQzdlI)pxrAIj@>to zsb6+eHVrVTW%G;ivYNtQq!9sJ;74IA%}Ey3zKVJoPjm`nN-T(6{-lz8w;y zHio9n-{Ob)R;atK|8ZOY1M!LaA5--|%Jo0Ur0@*s&%$iX#e6KpVk|{Rzy8N=ZS+oc zWkQ?WsclB|jpBTb{>2jCe_P@EZ{(Bt_vgLCDC|GHxi~DB&PuGpYP4mGjnNc`HS~<} z$S&iN>*yPhAExgyT_0q!zR33Cut{93yf|zjD^PpCIP4&+QA2OISghYs9CiusLDN?A z8W-t@oU+btqxpxg>7Srsv;N6t{ervt1@ctbfAG5c{aw!wk-fFg|Es=bJXt+*h<*ee zTjhVC{Flf-**!}B$!Ly1o@_p>|Fu#7%W)~Pb&^qIY=?BE$)mJAI>V!r--v8r@|6D^aZr~>Ra0mBLnE%hlk9?1X z{XY&r@<9~r1aU1(j6ovuEgVPWdu;Xox4+K@AyegS2JJ}5M$mbBP z?W_7O|G|%qV^3%2Pv*bh={y+fnAm1}N|7T`d)Ho@6y7(DQV(??-Xy`+~Cn>0%f^?{u$F!ODw~x(pCFr%T*Cg{ zX$}2E_h48k%zs_uKegg&_M3lCkN2>D&B5P5--P7*{wpqVS6bL2F16GA|H%G--ZQ0F zh}(hmUbg>k^Z(8DuNK~g++=MPdDSiTnGm`+M2_z3Be7xW8ztcYpmacEWk2lR`T( zs1;Y^*gQS%{|)|sl71S|HAUZMObl?Xemf)X94_Dz3jL9(-Y50`72#{>MWuHphpNx( zhx|T-o8tOVcS0Zh{2%>)`t^nHUrpsBQ!bL^9mm|m13X008f^^*qZA$9?M~${Dtj4p z?|o#O7rwtqZ)WGWEMfnzP}a!8{#>^omA!T{)8fDN%8|5kmF$mU><{5+kI-&1rSCA@ zZzEBLF=*Sbd@9T1=nc1&ue;{@(I=rvIJt=ZK_;%7+bk}o&oPahf!g!N63E%88DiXk zd~@_4-#_nQU$H*g+vYlpUx?m+@?9Y^n*YC?T!~d!jWwwHx_-;kz6C&!_5#^Jrnf#C zU)@CCf(mr$YiH1X-}`aivp^m@{1#IVtI1uc&H4@mxeqnzXuj~H`TPfj520ynD;|N4Vr1`g&)UIFKjb^w-YEQ){}AG25;=89-{;j4^mbIfDBNg%%5?1m3jXPO z?Sr=S$@l4x+CS%g?F+iz)xMn4zFgJ5oY1}?U+%km()y@a-X2Xqd+j zjmBl#H$0w)R+rHJrL})q?H}1FoM5Ln>8~W&?5Cx323357(Kp4;(J$Zr zclH0r>i;{mM9UKl2Sy@%wN9AFclm2_HcWRlks*pst`NkwQB% z$m1kV;|$K>0;2B#RDSTC5ZT+8gnK_<6t0lhA{{r7dd)gpvJZD~4{fiovBW>17uH{l zHgAkxwAQ(_4~6wVo_pkfe@fh7lp?AJhLSa8ZNhP1{Z6Rb=DJ-&!!7T}b?--y_v3x` zp}Hf9k&f?SCsY~M#ltpo$FAihKzPHWI@h(K)NQ>sGj1xBjlcL`~P`-D+ z5jyw3p^x)M$ke>Sr}c*V=?(SM8|tSwLi4L{gqF2$gyWmv2&wgNgw|zm@U6cQ+8o!O zek0T^c_Y-n@?45R0)C%drxx(6O^Z|Gz^2zk>h0g8#jO|Eq%kt0LrARCxa@_}?q|-z)gvEBN0l z_}?q|-z)gv#oez6tEICB>#zZBL*#M98(|YYGu6Gp7J3Ep1Kk^B9n(Gbjl#D}V$S#Y zJ9M?~#}3EkzHcv&6@SWCwYXhqdf9zJ;XXOGj$XgWarF3B@$PrR{cgJN`QFxED^t}k zY7_i-9}eIUjv$6V+kb|g@UQ0o@GG<&X8)6^1?>MN-pv)-Coi?3_w=7PIiyhn=PLpR)Tfa4&BQKza-Y`txew6Ru z3SU9fMSc6L`WXZD^~r1EdT|3c@nnAHbZxQl9YlK&Js=;V=>OFJz+jXjT5~j%tmdDp z`k*)rr}ur=JZ7>i`u+9d(EFk}$@HGDS`$T1z$8pT9p6Vie|&&_?G9etTO^({x zXzYBN<7QwMW@9eqV<9?9%>Nj|_lPI!t1tTBRqZ?3tR85=@y+h_diQ^s`;WHi?*CMA z6Ybd}ouycgm3TaVXcax`vv*+)eI5Sg`u&f7|5_asHaMp5gNo4C?fs?qd_ukOkNBrI z*b^0DOBDClZ-ff6_cL#Vd+zCKdYrA;fWo{sGO1mRz7 zOOL+avxmM92XF|Fzu$9&p2_MvAVxoiXiOltUHeIP@7Ml~=l@2-bo~Q7`Tp(-*T6oF z`%e-nv?GH&PU18=-q-%4>%R6M-SjMSE42UG_b2_E0c_n-`Zw~HW*bM}I&8me{$Gpw z@gw%f8EMwmoBwz8sc?=S@7FiM1$yOAy%X>1o1D-`Asa6`&o4bg`MBiwD`>0NpCEe? z?L$~t7oz^J;@ho$#(P1J){RAL@3MH3|7G&ZHZOetZ>@WuR{raa{}=cfNuSkC*vFXJ*)iQ`|SZ?H5vKO){yJ40h_P|71)7l>_W7c`5tl~ z>J}*f>bC~O>*c9a-q1u(qVn~UaKLega0D?NLmatpmxPYB%Kt!RR6X#-{u9m#=gH>F z#y@e~aj93`|E=yn*@pHd_Ww5*tLH0h{?^C`_|&8MfB!FG_a7tGbtZWKRA@pNj4?|X z%wiyju*6GP!V;FS1QUy~h(#<05kxEo5kwHNutgZc5EhdL)6nC=3?Y~hf*C?O-E?<# zb#+r+)jz7cDu^J)B8Wu{B8Wkx)!`*9;q9=5+o)a0K7N%A%2rMCYd56Wo_pD#{MP9^ z?1$a#TO36OPwd-f_AT0kwI5_3yC&MxSoCShwjvq_yKgj% zkq*>WOP@5=lgW1BmxUjbKE$;KHs5^IkNcKqHC~*h`S&g6)6yrQ?S1bbagCMy*$?eI z&$zJP``_#RZ}WV-`zPzadGA@rrT6c=%*3a|6!A>M49r6AMd_Eu+4Q`;+TnN(eJ+ZQ z3-WLm+1YGdv9PMw%pWHgp{DQCVKKQB)zVq-I4KRw9j`>=Rqx($!yWBN@_)_0*EZIl z)o@VTnruWmtKIIJ)mV%5*obm$MJ3v_EB|lnJ2ahU|5vmB+4C8+(6cG|TN}R>n+Ix} z4)(ochxmGbFK?22P|%;#^GSJ7ecrvfqon(aSBy$%R6NCe)FH`=javuq8G^eZOVt6%7=R~4=Eq$ z>8r*S`|Sz}f6+Hoe5G&bp1g&_`n|#-sPmr$cY8?`NHF(eWfq!8GJ1`^JVQ!VG$Tr0<75i#{90ZnohA zWhgq)PuLvH#XRhDj|<2}Sd7}8>Sy&^{XzB9RrS*YZG^MxC#2ETtpA{0|G~>_X|%k` zzBc|Zhq%A)ll_0DtDjNY|L1x2=5X~h;`;wf{m*i.ORvHs0M`^wRi+5vHH;#zv) z$KIuSxv}e!55IxjJm2^8s_(~lm{H$v(*cs*1fnIkut_KN+LWoSFzf*0+6la9MaV|5Ka#$^I|Ofyezj zP1T-{cEC}xv_3JtG(W;Kjq^X_+QGXHZU{TXy$gE~_wcEn{PD1l9_Kv7IgAJBhmd~N zy$OqZG{!lM|M2!F!l7e*!+Y=d4+rrhb9N4NJ;irr4afF@;RlD;gnciq3GcqNF6?by z6TW|Voi!ZSh3{S65O$y55dLn-Uxytp{dK4kcVY8$;qR5TyH-3M-f92qu#^7Q^#2mJ z;z+y~Y+v&?p>qG%%QpYp@Y6e^!;z~aLJhs*7i{#eJQt2T=Oj+y49?*KniHQ<2mc3i zQ~rH8di~#r?45rXS`wcQ72g^eF8RGQzjvtbXQX@~{a1wbpt6mB|BEBT4SFwb<1X&w zA^QBaHWLP55QbnFdN!MnOm_d+m^-r9*uk;ncuc?~Ou;nFz%0c5{brLr`v2#|V|}!9 z<8cH3k9I)p8;|$b`yAh~@C7KejkX7{{C{2li{m)Qf4jW`meO;ceO7yBIX%uf?7&L; zDiqs&n-?GTL3ZBp{XIW2T$7$fep`*TsM$X&} z{Qu8eH(%Q{j%oC{zDnkIo&%@j?}(1D%8a>7Ks1Vuu0tewawo4Ut6^Q z8?*~ucMUhti`%%1`)EsPe`r&5yy1Vy(*DzA!EupndSCk=N9%km)!Lt3>W0JGA86fc z{LpL9@n1X_I*vUT^5{et3MiuKZO;!!$2=D@=7F}1d`|iLobvTK{R7X1+GXA!>XAgl zMeh%d?|Xm8Mu&&)vCmq01p_b$Lof^@FdAbKZTzbFBg1%l^@fq5X79(s1o|XQ!ISy< zx75E6)W3I>IllcFe(V0d`i<;)Gf~=$V~hT-I39ntu+sViKP?M$=yNd-3$O^i@9;go zto@JrCF*zOSi=VKqp?f;S#6IW_YI4kyA;b&=qw8>$yHd5wuzp<_t@dR=E>Nn*LB|W zzwG&+_WVz4|DV_Xzsv_owm6P;b8e*PPj*-E|Gz#u^cXwP{Wa_Ri*r3Tq8wXMi5=L5 z>#^Pcd;2MTWmMSXIJ4In3-SOCp$fTn|IsWx^vCNjm-c7Wmr>m9-lX^O`peVeHS_so z$s?$VeqXW`)$8=z@8rMb@69_dqS0|$ecV8%*#Dc~HZ~A%?N|S+KaV@-vH##C{S?mN z|1|%v_C@vYE05~@~fha~U9Nmip;4Yq zACv!oY@D_8reOwVVK(MqF4{Ku{?Kt+|NjYXy35*jWC3xkcat)t8Ao51|M8^%iQXE+ zhT1Rljh>ecR(Rfk5LIYBWAM_T)@eN!39@ik;K~~mk-*-M0cG34>9}eIUs&E8Jq>(`@ z^62@xd`HIm_c$5*0#A~sa0cga0he$EwXezlsNdi|(Lhh(asDqfSQF8C*Kh+*`X}q; zL&t6NJ^xod|7G$&I)}^ucw+zm@ACf|`5&$5`FZr$@%4X4-+ib3ro~zDthM~w*!5qG z^PdNW`@$Zg&pPQb_NN~?AnMFu%k*BfGQ*3S=CA zTq)k_P3B8m!}>0Lf^#Qf3aZS_Z`f--_(Ai*$@KHa=L?^KddJC~{E1hs)8}|L=3p*z z!m@Xs4)f^w!|Zpy?*;TlC|0xI+1Xvq?02$uDEoUHJCz-rBpYV3zsW|&X|iM=e%St5 z?E0lxjtah*m1LWHYDdR({R`-%ccJirpZ|{e2TR!B;yEh5xYuBd__Jg9-|4Nx`Aw?_ zg;nC&{u$5WE7s4X*9faNkA5vZ*=-K}{y||qeIwFW%|p0n?))ut=*e9Ygrc1wjPc4*w_Z`Pa9B|DcRN)Ac zNF#$*wB7Oj$=@BwqZ4s&m$=4b5l{AC=r8?f=~n+EhgS7dRcc_!i>HX=IEk9`*57AG zoT4Wm7`t(2U^qiRhx9mk1F6ft4QyT_|0)CDTEYIB&-Q+gZEZYEZa80=^W*%TD`aW^ zEq!{O!n;to$o@v{HtT=w<>NzA-#`O@UmTa;c$Te)lKuO6=l*y~=n>B~+(0jGqiv1x z2k1Z^o#&N*%D@6yR3KCOs(;A>ic|H!t7DsSlue#-ZVP)cYy4Xdt*DyF{uR$2?85=n z2#fpL9iqoQhw4#9KZ5jL_J1AwUq3(t`O)$r8GlCx6<_s@{S_ZKJ&*0bQ4fE`cSJvq zlQ@Ml=qW1;=g97szTpCS30Gn`uHgoHaT|A|&d+q8e2C0VYxAu4yF@taMJ^bM2gf#$iqXncTkW+S#a=a8Ah#?O%RPZ!VgA8DVfyHfIWW3%!>KVp-z zqWQA?O=fP&-*@Ei2l6-B>bOlAQyQP-+`RIowEr+!K-_;g?w`Hh|7=7#wxX1Oukw4* zALrj4^j$~~m-fN#fovF~{qmakgVOj+zaPLMR3XkIu6SMF<-3V+#BmQFP?Ahz``0}8 zzqBtoy%l*>RG9Ni9>+=a@(mPT|6=G?&!2MK^9}0}ljm>&mykJY%rM!5Yq){v+llLc z_tNuSz75=_-$ikqIPrM@$l9)%q0W5b`r$8xIM=*k@(Up~|Ao+q^eg7wyXK?gd+s}a zh(6!(&7;k{_V&v!gbp(Q@+{xUFj`pV;H)r~9FJV}tT2I` zgluY7=y+|G`fXO2;&>Vg?yYDofX+AE=ZaZjhOk+fjXCJ~x^))F?l3dVBYXcaGb|t% zVKJ6sIaXp7syw$R{ReBz6Bkx9#{EBUo;W=zt@YAb@oCQ;>0|ES^GbEQ|LZS=T4}9A zJ(5?236H-uiZ_jt|Gy%Hjp8cDR#ajKcA;&P=b!NWkw+)GtQSz2{DN_gFDQRK|8<_f z^D<=1tDgT$p1*h7O4e?ZzxK*sNLKr%wINgIedA~4Z|w0O`)~loPyauOLu3_>Ac?kx z^4F{K^&9fn3i)f3d`=b|7s;k9`&XPtx3GWFvPS+y4y}mu|I*^gpcQc+pxi?C$5i9{ zd}n!W@{Tpyu6`>13iVt>E0DKD<>b9zgJw}gF;*1aD(hc+jZqHI<&d++mz`C<*hB=HHum7 zub0_h3)x>wl)vPkuK(EkNqfABr!@cJpZkWp^op;kU&!8{zYrdh-DIB){`+&*C{Tv< zqsM*Q2avf<9}9!XA;_-drzJBh*a75dl=>l-xv$Ia>%9BC=suPEWBoQBRmOK;^B)uF zlQ0D}#&uV#3#QTIUhMS)jWedtLfn(5QGF8kYHuKC3!8(vn1_%0Hx@W9yw0afmi*uR zIg9B_u^cN=+iv_H>a`z|+71o<)$Q61jgyW4d%j<&&^}w`ywzBX_1K7VY(?Aq{7>k( z$o@U6O>orK)$`(j_;!2*%VQlhf3DUBXu#KAc=;o?_Yi`t&f$`|MlCa!hP30M4$hn z%*Ox>!Vt9ay|tr*-z|?P?R$Fk#WkIm|1Zn`Wac&X^M()Y1A6N+-4423&sCHewc#>WAcyoLWjcnR9 z+qS`ZDb&*Ima%`4L<64eZ%4o3nqJ(-UEIe*^x5cJM4Pqj+UFbRk32fp7+-(_ifB6a zC+qJy&LW3aWUdbi1H@C_xBt%g`hVj4aqd`*N5!}JXvskYbJ)CBd3aEHc$oj+fAs!^_VTv}g~IeeD+hcm*qCI316op#fXaZ^H->yF^>+oy(IL#KszrcMbv zw@l$rofh_7>>mn0A0Co^|3S0yLh}cOcQ*_OdzTFeKk7Ru9MB$5`z?c3=$;7gX(#3B z-Cy>dl5uYTaq=Wi;SA29`Nd&;Si?f5?ndHh;x~zG;rqY_`U7~A6nu$ zeXRVayQA-ANNBLeXZqr>(AalKIDE?(1?N@0-!J^+n0|@Gv*D*J`h_FrIo8}8Vf>l# z`AhWkFJ#}n!M@v|UmuP1^fJ%VwO7!CYbe><&E6MoIBt8pZ)iuyK|TV0g3fkx!%$$u z7SVLIZ)m=0{vDZlVE;FImTj3kZ%$d4b>ry0;<=3qa}4j2HTSeXZuJfK=}GrjKgPOB zKV%>13r`PsZ^BY&nA|r!bWUa&8~jb>0dixkiAxSbRvp@*?;yXkUl`(e7z*^_8vPXd z5xVFF_gci``|hCU(S~+B-lwi*llxvL9UG(rO+%$iSmP4UDL%KC+!MXN+MElrw(HMA zUFy%m2>&@6V=*2RFbPvI4W<1Rw0r6&YX7{f{qu_UkN4Bq%>Ks==gh)v%)wmD!vZWq z+d}g*jFIRd^J}z8v>m!`see#JQ;Pk+ll`xqlR0SoBR%W9oVG)&c0^Tm*&mI6TrAF- zt7W13L|Ir$PrfWoujyB!uR=O2&B9V>;5XX-b>k~OVV^p`Wwz=2C*vOCaqsZ;^o=OT z|EYb@uuwU&M0;bIas{>O_c~#v@p$vKKN_r~>-tLUKwSTR7r6)f&?z6sJRb9Q-1F;C z`vY5cYj5E3c%vqIGmavI1L8P@DjY!)aoxZ)*`rPZ!1G4 zK5ElN-@qwhH9O5;z!`e7ue9JC{SwmjMm+BS+x{uf@8=`K6~Fc18g8IBV&3mrz~(nTY|l!2?;nPTSKa+30!+G=tScLA+J{J~~J-^^TPVs-A_8%Adzt4*E)+l}JqeA1%Q6W9m+VZ~* zVX1SMV-rX2m8?Gn)VbwfAy%4kIz)wEpD!NBKVkb<%qyBIF3+|hu3>;$d9O}=UcW;7dXswn zwb;J)jUtT-eVs*d9mh$W!Wo>y1^j7#>pU+%>W?ds#namVXSIKE6dC+!|9j@9`bj)j zP}p1+ddS>l_J8-s!Zmt+DEl8b=)H)2b_I0FL!G!StctyUm%NXfb=CqR`+QgWtN&Ly z($Db#JoYOzyeOThy(s--_+ODk15#*28iQOj1j7*9KO@M|7>fyL+o}C84|X87vpT!H z|8?@%CUzFtbd~*oll^~>{eO%7e^K5id7zIuqjQ`HVd-$Su{ujfXIe{uWvC zfBfD&c*nCa8*|Y6^-*CiIS&i4?RURVEFu@9=No(iWGu&)lW|>w6B9FL+f3@%;J+4Vu?|zQcPa-{%{fpE% z{SOn_&cfoj!!zVLp9|>i+QMeU@i<}&88|Kl* z&!JU$cY(Zwp1%y?3K_>g^pL&!j&G2apNjhf4hp6D7-Kx2aq4T~nbQNqdh!}><1TU! z*#E}{hWqq9pK(Xx>F|)=XS4k8xZt>p?9>m?PgsvWiveW!AFO3h4#6;tz-Wxccuc?~ z^nU%RFom3ks#gYv8RRU?#vIga;(vb8J`eQL{(D>4zw`x2zs>%2oFd~|eX;(_OyxKI zu>Q;O`B(h2K1b(fjREL5t6u=6a`c~Lxy;^Lp`U>5-?hQ|fBgA%H~IMa@{?#_OQ+C? zG!~0zDVAd;R$(>PVm;c}q3zwC5%TD~>e*cPjQIA8?DMAi#vkA);y8hp2W(d7& zKvwCa*eITIY(*t%n$7=b+wPzz#Zix4^gT$Aac|Sz<4oz-53o;IT=(Gsc?h|C+H~X* zWRLkS>*RmsL(*{?rF9?n%Ks_fX|?=+)%pzjcw!qh&eJRPug&!RPnExxsIy(uiad%a z4`rq$I#hD>noSz-aJ{W2Jd-9Yx zD&Es)PgZTwPA040mj9de+0(aws!V^1@d4fL?}7WfDu3Q|e`K6T82x+&{>yFeJV->p z-zC>%$SY(I3d*9A|B){umP>Iia-5TV&2Kl*i`%Fuvo6s%?Ff3DdtBo_@6#Wm&lcrR z%KumU|1SSemgWcUwFa8s24E0|U>JJ%u||;H4a!}zSN%7Z9FLOyeAV;2$$uNq`MN%i zFUhN4&~Nvhr^6&+Q&4zUolia<|38a98*|Y62V?(@|DQ|GD8uKG{p8ODT+t@^4?eO0ecOtMECy45{5 z)j?O)+b7uf>b~Ze^slp9GwRwFGS<7X9&R0J{J*-lU47d@=4YyR^}TluWp@u&52I?Z zeP;d7R#ajKYF<(QzieCpJ$aaI{OZTU9{N6{cYo;ruVX9o8+_FNf57jDP=&aEL;*+W zNtFB#@900EXV8i~Y7c&xK6P|bS{kIaG{51z^qtlQan5m^#3`J?Ib6Ucv?an>K8=RJoG_55x6 zT@(+CyWM{@$2wfwL0FYG!9%joTb|ueV-?8(D6Ky*Q@REkC+2tv8r3=JtJ=BFOWkqb z=e?K9-qSJf35CgJp@_~~-V=_dyw|L89AtB~_j=HKz2iO8vwOXp*YsQ9@j6D0^fVff z!sd2s6|jZh(jOOnIotp84~f`cQ24w&;(lsZsDIa~e>cfrWWyWsS62Ui7e5_2+Bst} z9uqJLQ!ouP&^G@=|07>Q9-V{b^O52oD&P0l{$PWAbibd{en4yfm;Z5=IA$Z38FR?& z%|2l+IS;v++9Tv5=1YKJif3Gj#KK&v3Y*pr= zZOg+%J3971Oytq|wz#wYqxoT?n0lCKTJk}n`Rc>O(VGtwneK;)7J8PRyZA8CimK{| zi2>pngdrG)8e!Gq7(q{tac|-sO&^Q&^X^SpYN~sk{y}2Au*~%j5);Tt$nE_gF@>Cl ztniNJ4-)zI4-zvR&q8Tm7-c}`?hg`Os2wT&(poRANoj8&Q}g`?(wOal}(aq zWYDJnza4Q7U>=?N^t(`?7tthNH!A~mV;==qnG8*G(c`fU`I zDFt+Sj-B(hH-vS6(RXgG&z|2|GsN*j^r`TDV*mzW2!{FYhmj*N8oj^f$0x_5N|`o+ ztUhnQHF64S=+npZWV%{2bd zb#dIvY;q3fVjjA`;@n?b^Yq(g>U{f<2rJFw{*`t&J+?0fH;RalL+SdWb;$5ynhV}Eb*A7uWt_QiSi zminwf79BUKdz;05^dS42EUka1-i&o@E2>87zZm-4M5VZPU>9m$GX8&Rzp#g%oUe|1 zxnI~vKY-Hs!@cUZ7u9jX|KX*3i9^-*67TJPkU03ty~K|eK1du`@*wfUzPA$ll?6Yj z{_lx>%Wfs!edA7I@6~=C;SdoeLoiBo^*%1%t1V%Z6D8N$NfaTUTw|ApI#mq zj-2fuYWSt<5}!23`4b^|;*+8N^iXY^!J&b#D9vZoxNfj<2)&7|&-W(M;>cio_nk!L z;Qx`RnEu}q+jjo9#NTcBABi2^w-RyvxxC;1{+_x>nexue|DM>n?7t_z|MCZkJqJHf zr#}_8zy4JCLG%Ai?7P=Dy!-0^Ozg#v^j{n}rXA(l<2Z>^cuyPY3|X6sYXI^woaTSJ z%%?!69`G^T;a3@H-9YDDz$IKk53b<`deOFypJo&PQ-6LNbh@T1!T*HfOn#a*{4_X< z3|i*%;~kJNTZ>aY%1z|AmFpzeM`=8C2A=vt4%*r*H=6Z~>Rl zrrvL7&v&4-zGGJXzfS!h|A%avD*gHjj`nw7Xi@jay&-aFJ+J<+8yK#Lrw7+?1Eul* z)dNE>JsJB3j1Ra?zl-!3^@h6Z$@u?)-iN;4SRdZ^`$P2E?tOjFH~gl&^4qd7!0{jq z!7z-#XpBW^UWR)ttwTA^dzq+T4k~j>rn66JMJ1cD2x}! z1WdvdOv4P!!fce*b?^>qPk7FkJ=cSttLNKL?K|5me4zHnP<11cuc#Yel{Pfe(=YLV zSeJN?c;;drD%#4z0&)=+qwRtIj~6|Eqrd)-)7s!C^nYB|HXw73TgmQ! zV*fv5?EmlC|4&)xU!2Ra605KpYf<=gS=dNw0*Btez%S$t$8W9B|D`@J^?$u#UAKeA zY6!1HcCWU_+xlg&y;eKySKh}Gwu^Mdz1!j#$|~h$Kj*H;4(vkBtNicE$366+)tCx1!*<=(sbh4M5gjWq;q) zzd$A*sQ<|){R>N6>zX2t<0MYu49?*Ko~-}#fE{~B{eM&aul_E)qW&kF#;N}&s{hH% zO!YsRb(|wh>;Js*$Ls%G5@(IDYFwcwudDyN*=O{EKGn42M#m|#fqi^Uc%1iGnqOdC ze$M;9A*>f!eKQ@e_%6m7f9Lov3iRSc-^pa(37S&+hfnAqKBg}KE%fYZ@!XO>(Uy?E z(SbbvbpN*d;(UlcmD-EgC;tr~2Vn?mU-5kPpVUixa;oPm|EI33#dB;y_jtNqp; z?Q62Hq(^Z|kSp{%!gJ z-u(EZ{;a8w+TVHc7jYbgUyTf>$TR5ux@Y+t<3s7u_j!T5ge&Ml90MKqKDkDJJbz*P zmpvE$_O$mO`+%5tp<#^lZ{z>o%}z1ChtczV z)E#`@Bj}@1bX<6q|C>*{lN>9oYRRZDo}7T1!ThP@6vQzM_2NnPHICq?+B^E68b?Z( z;|4M{l>b|r>!i6J$@hg{6pluE`q-#HTK{L7IJaBdqVn6;R-w;phwjH2U$<2c8!bGLq7Varjq&OQ!g_3%+)6}cMm zSuFCN*3y&5__*Kq-pRPfK%83~=NPZ|+eVaQD=Ja(thN2gUD$(tIDkW_LK0~dzV*l^ zDb0V`V6ICjd$j-Ex7pf$?|sS`3$nYx*a))cccVg)JdTq%g)=yZ3%G>dubMAN_TXBS zKV?Ugas8iO@;2_`J{}_ODb(j}WgiA$5OTt@3#|)C&yRW3?k)USyWDZ{dEbGsuBqC= z)A|3V%m1j~DgSSi|J9!m8cKvo^x+}~2hOzYVX!CyCmGK>9eu;PT z@`v@mJYGa;{(rUlKPCSkR{zsW^K<=A>n7tu#W4v}Fby*>3$xMtx8{FqKXrd~RG8zq z=d1RTAm?EL7NP1TPtLRC2y#8hTs?paX{k*gZOHGwl=`QWBt8S=g z3n$-DKj>>N?XOEuuP|@THS4hv<@l)oXRG73s~@fpd{14C&g<%R#4!Rz_IA@q^{;b| z-cguBhtvY zrWJV6hJ*h!Cj0~NGyO7H)c^y4TpC#3(Fv>}I9WZISE;<n_kfJun`-BZY(Py6q0u_1k%DKx5s)4ti-k@90- z-z<{CDr%n!)0{s8vry<97-o}mFc+P#$jkD20dc-j+jaec=vd;Og|)n|EI{s}zCJV! zS0CdjJ%f4T==rrZzR9?L;36{ieQiPXl`nR@6w9#+tI_M3ttHo^>T;j3k=*{9IPbvz zzqLJ4e5SC+mkER92z3FT03cSU-~eIh0+*=1ifH zjhx0x*SvL_jn7uz%x1pe_zJe0+gRBYpEv(EIv%ib@38OL!d(m5Y4h1>udu(_w9R;8 ze-3BYAvchncai^_4b~&RYq)`4)STu2_S=UTRUHW~bFS|FS5ZCH^C@kZ?`t0z{ zBDckOesU19`#)U&e}%F9j)&oi|9=zvaUK6ZJF{-8|ClWOXjmxjm;49fTKgkhGa6$t z9uqJLQ!ovs^xyfD^zYWcfg+luv-zs@doFRUgn!}xZ~x={4`zt7=7jW1+bnugzd&67 ze>T0qzIfvQkM}yA4_J5{^OIHo%%R6QX7kAH-|>FT0Vz(`USMZ*jq|>dr^hu(@5<{7 zoVN&zQBkHZ=xu9$&>ydVx13)5%=EC5tluU--t^7h^X=mC`gc8F)3^OIwyU~omGf3( zE!JZr%CQxd*n!^9#5wQAGtj&L!n4oH^RJmBl91>7i<^vNeA1Ks2R*I}w8y#oZ~%u; zg(FC!{i<&ed32x)ohYJ!W_4YY@+C7)o=5h1b+E8F_8^DS_#fq5{T=BW82zH!NPV@9 z5a<7;{YM6Q6mc9UaSCTpTK{LJXL{4Kz3Lf1@T|##<09EKQTuNy`_4HTvc>U7*Zrqs%7VfEkZ>fLDjl!zd8N)zs zMU6VOlH7sP{(omZ*UQE-INpQCF3+{vb0$;S*#BYu|2x{|zMCZ3;JZorP8xj|X>zkM z8e2~LK2B&~f8BTW9sQKzsci7A@J+QD&(VHS`i=95V?8=|8`~k>g}u`Mw)DT^`&;Py zTjKj8AI(42Pjt)L2*|86hev!>ID#Z{S@~pzJV?*)e$f%6x2y?HKZ&>pWxal`<1}AY1DQJEx1IL=LmlE;r0FhWl#$wI zAHevV{;nj>x%L7s;R1;=cFrVB!8BBS)?E4@ zo2O2nh2A%(h1ukss6WddAm?HGH(!vyW`zaxMOcj9ca5DVV|lThjAH{=l5bs~WzD5o zVe_q7p{oB2VOQeQp`Y+oSdG&D^TOBCldruH>Q}rF*3&m4z2pV$mlr~6*$bh;Z~w6D z3*peZFNF7weLft_P7gn-o@&h+bH6rxF6>`3Is9PE#ISGMWSfd^FJMS)0+o=GBox5WXPD8bade-^^H6mTC&fEa{sjzmDqt@*n^*({i1PNiSXlf z)A_%?7!JR0oU!oegZYU(Up=zS`jBPe$h}X58osc)#8aX64gRmw{1`}`eddw>>-^x* zc<~wI*v5se6UT)E;y8ru$37b>2Tu$YBcBi3hCUzu?)iyfhx@Mb+Y$Wz$j^mc()!ND z&xM^MCx`DZn;Q0eQahJ?RYF|=;O%=NY0$8FK1>*O`I7TkRCcSG$QvJ zf4ASKAWNS{W?r@~AUO+hFQFnz`w}11M!2V~fZ2YVgW8GKA2QycwEj>^xs)~jpi4gy znZBrhLs{_HzcJVO^RNJw){5EwURh{U_O+v9s`qOt-l)0M5r z4b}$1VsZ6+{)MoV>~44=EGK*4)bB~I!fM3*$JdhGZ_0;c?{8iR8_9BPMJ1}(Iy=bf zb@oFc_n?Npk34|nRb??!m$k3(*#BS4&a6|{#WD8Dnd+r+>ZK*>|Ap!)?SMtDJ%lP8 ziSZzf3|djL|F@_kQL=yERyU$>nEi_;aW)TR|Mq3;-emvYQMYz~X#ZapR>w}A_~;pL z9;pr!XHIw=BVVNF-xs%f_Bg%5_=1xCug>n8uKrcG#=XO<#Cy&6chWgE`^^a;&!GCc zbahGBPW=a8)*gOc-J-58+5dZ`bCdeleb@QD-gTw%|MXZdm*(H4*yiH7fJ?Z79$do> z^rB5&-o8v3k32fjg~#iBHC>c`9F@+P))x1Z^;~jjJt%Cjv3=sXi~D$p+*IdyUVU~+ z|48XaKl%U^S4i^)>E9&%7$mG}p|%(~3~}w`5#(sZzJWM)GKsN{$D?tk^pEkLr%NYl z)y;Ljhx+HOzlDbBzJD~*)0p6zNtl8en1$IWwDC8SZ8zE5+vKY)@)hEqcwOw>LbG>; zrdPGWanyMk?eUfe>~S)O*7Ne0dU*@pLP1}{Tye%Z5c9|dD2*%my>TV<#aN2vScwYu zXY?DaqOZnUtViyi|G332r{~${9Vn-7MRA#X+u$CxLE>1UN?|*&3sn=XcS2TcQ`gAP z`{)O72=(%65`VfrLeI~Q|9Qsxeb(xU^Yk{aksieIw90kcf2LpHtLz(k8olnhH)wa# zTaiZ*$8i#;a0chl`_s7oKTd!Dh5EO{mBxQ5If{wA^)w{aIaZNAw4xKGc| z_ifT2())bRe?7JbU-YdCe`5d6{Lud0!v5XK{@up@%|0EDxUQe;24E0A+W$Aiaoa)m ze~SHE&HiWace4GvmazX{X8*s){y)wBJKu8NF#c$m0GU^Hq5 zvVZ$O9mdj=gW13I()<@=u+kgc+Zy+nVE+mq@0@!r2D!zq@2?* z?&&|OpEmlv99vPL%~!zoFBz9+P4peYc3}_p;Q$VycBlNmSN=y*{nem6h;>99Bbt7| zKkS?%NFt45&{iW`kw@Dm`Tv+ahCE93?ECVV{8vQNHuc|2^8YLHD%r9`-XwF5TgkZo zPfLTMdMr~q)SKt%7f{;QbHDt%+kcUlgvIrLu8=*b(RXl-yn*NgEA=Cu zkmnrVMx(MI?YM!A>kQr(7Wdz+DC3LQ|F`*l_V|NG{r!b!%rEzQ;WK5S&u;ku1JL`7 zwO+{~*#0Z+AbS=JqmMw3IWVKi?q3ZGW69o68lyl?z$8q;G|a#(%*Gtd#XKy)A}mJi z|JzpfZ;a9NjW~{L1eDf~QBTJ5Wx24-Wc~bP#V^e1BiADLyfy~gYdt-#NfOt9*hnu& zY5gy0>^dg@leO24ze4>zRo@us$@!^pI-OoUIqmCTZPvWVPO-@f}lPS1ClgK*f`0Au$$^)D330%{ZL z|8f3fjCv9cNKI7#3ybRj~u-fasFe4b*Q(0#v1B>p?nu_P3qD7$1C*Y9rt#fFMxgx>C5g7Da5%L zH-u$|@&S;yk(=qAk@u1HpB)#qOYqQfpYOZpP5Px)c=u!+CscdF`+wj2zv%tz-)Zm- zq|oRaioT+Lt{H$q7=m}AolB0uXtdqb{*}i&lq2~q+Q0NJdZA0cRyH)ro6R`tyo~l| zi!vqd4VXi#vL>!QJyty9F#(fMv%&lKT}+`T56Z)sMxTKv z?=@1F}*uX)z|tjC3{tN zldZj#U)%p53b<`deOGQ{C9Mm=HorVCx4l5o-CkvXH;lv9~qkMA8>S=F|M!h|1ad* zUc&!Rw!SHUqchi4h zG(A66+Qt}XKp&6d8foKK@A99W{^PCJwDS&+4x3-~{mnQ3zHW4w;Jitwrq{1zqVrIim+!eWx+aY&;+cjSn1$JxgSnW8w&(eu(J@^< zpX%G3C|{q|mPVZG^<@2j?>mDQWqua9;rf1&@s1aWXAu@-DRRQHSWeFm^xb16eHDuI z0=m$N)xxU0-?ij=)Wp3a$Z}NEqwhJ1t&S_vNKfOj->+m}5BB|Ihu?dD!6!!ULB;p< ziG9}peMXhX+Gc~dKEIu%<&?VNXKL3wCm#(-*z#c~=_ao~!TZ^Z&B`gwK|R0m25M_ovqQ|NW@Y9q^a- z2l%Xg0-8pJA$}W%5g3iJ7>|mIvJm$doIua&U(5|ngh})%n1(0g$L>h`1J8gg-qh!+ zuBq!%$7I!i@2gYPT`4ru)5nZ4cI_<8#vIJWJS@N>JlTJDpn6xIeJ8q5KoL!EtN(EH z4K~jT{qLLfzmqw{{df0y7FE;D6%bcH)GW~-PcBE?1E~IG_l1>?S0V2Gldk3`AX8cP z)*Fw?{kR6_YQL{VT!VT&xe?pH#P0uk2<7yxsKgHJ!X7-?|EJymprKCs(dZeZvClaN za0pd6f+W(&pv^OHM`@lt*?I9%+p3^_Rb-nz*&pd`^*>tX%YVqB7196DDxN%wIF85u zhm$dUlRA8zJ`MUA6!)rk(B(OG;+(MPf4D$iLi9geA$w5rKZrlBD_qgwI^!1~?;G1N zTsl#ES^NK{IzoN?FXq?I>=SN?rx&+T_{LM=E_ojh(PyvpYwNe8Bs$LO>=Z_7e`05AJ(g}R&`{SN)aI{-O)$^QTKqrQcX zx5dpKi0%H89pE_H?1P*;1j8@_aqez4M$?n-t)5*nmOdV7$Bm9tWP|(d`K3Cxf&KoT zIu;Y0Q((nos z)GuVyb@?Ah<@L-h`TwFkj$FI^pOyDh-dk4v-=+O~*jnP^%#v{}zuEM-f505FV~qIG ziLU3BFN2i8-6KNpd**-qO4;;J-l4Fb-}xrV z47NWTZQHW2|LU;tLmaqnt-a(Hp)+a-&-|~2C@^fM9(C5N?b!DOG_&84D6wcsBXUnW>RTkd0zQ^9Hp9nv|zU(K$ zIlo=N_g{S~?7`vPAzX4?m3TA!WIz91`AGQAnI39!{DDcO(sYBb*@jTm1pF!ss z_CE?JqDdLtjHAe))c-M6IX+XpuWukTvR@b>uI-=EPBGVKG(GN}nAJ8KOV4M;jq&se zDBcpcc0_6YrRtA|Ny4gL?H8ty(@>+$HG`am>cP_G{3K>Oo`c5I>Id z)g|>^?08-@BZ<2mjjozgxEH z6U08}zIBrgLLNdDj^K~VfBkI#>iWOhd>?K9CB>0O2CeA+oc72!%nA66_Q=n*+dj1^ zjAL*gr4UI@SrvV?`e>~It-SE&k*%jsd z&*h=d4`cgV*;l51xLzLe=)701eOS&1Tpo(2%R@is48Sng4I+m`9V0LrwQqbk)GhgL zs9*Tqkla=t8n%>&6dI96(~ISy8Ap*p%er!H$VdO*O13R25A74nL&rG(KhyuyyGHu| zq5hu@RP~@djP*a`F#(fMGv>S2@BeO?LQhuvZ%m`lKzfVx@0R}Tclm<88)gZcjX9W$ zd02o&Sd7woOZuf^J7uZk<*48*Dm0nPNv};A|Koks^#W6BMXkrHw;Z1jQ_z==Vh)M^TPJak~y@V7v}rfDxOO0 zz%JzW`+nq=J@lBTJFt&_07dn0VY)havbvazwt3ZXV~G4#g__GB3rEN#sxQiG_vAUG z9cR$ENgW*PUNW`L_5WBFT7~CP__?+(c^oHk3LkxbXB?kHh4ILj$Sa6*czVd~U)C@1 zRqOiDZ^Uri#$DXUL-g4%513!jkL>=Ebu-C9G3?XjVMq*9UJN5gU^K>};`P2^JUIcA zFa^EOmWOHN3}kM7EX*QjV=m?)cir>rwsr_TzlLr2nl_|;1h@Y}T{+#me^vfd4n$vZ z_m|4UBIosd;k)`D%fee1<#T%iY_8TWqA!lW{mi#RcK?%cJmgCBR(v!Z(iiT|AhKc=X0?+UaS7|dtCqKttIksf*tmf=S8pS zuO4JZ7;L`5y#Z#@nrsoHg+s)n>?c@&u6FS<5^~rqqlC8M!#PZ&kgkAHe%Z#J6%6M zJ^z~ef4Fsi=nqj`qW(wMtJ1&57=a&ozvAmh4nWNYV*R*Y zhN;pyQu@z-=>PYGT#1e?elHQ zgoBT4^uiYHbM5=4h1&m1wExKrJD}yB_CIp;)^6?cPq9OvF)mbGQ!ouPFblor^UWr^ z<%coMy=n*#$cnyHRVeF|8}-U*7|a;DdIRz;uOx{94?@(i~rmB`VO{#p6q1% zcaa6hMY8EU`}Z>Ymn_-;d)c=BCr7sW-wZqSl6bD52iFki24r!Ap63Ve7|cGSk4N!U z_CK4rWdE~YZwsqp2j3;{qlW&F>~p~PPp@AnT}#+eKkXCx32PiGT_dHF{T$c%t8JEk z)Sq_V3E}QFMK&VZ|E2j~xA=oG!1Zy=ZDot~Ht9p~Wc^3wZC;-5R33LdP{!|<|M$xO zJEi|c^)E7LK^AeIa4RzIW0-hGU^K=eCoJo}$J6uLp3(lFK%a!7;{v+G-H9o}syv5j z<>7|?@;@5sX?b{_YZhP; z7Go)vVS-r+~~ed}K3OP6x{ z!}4Xd_|~HEOZGEaj*15L6yRZjw-L8G)0USaV;=JKFkN5~Z|BCVf zNqQQ^amt73AGTklJ0q+$o)>>Z@7D%}u#PSFW?gXf6DGY&dRD> z{QnwYP}G6Y&`<{=MMFbF4;tD)OrhK4p8Dk@Gh&ePt* z%$_|@d-mR;k&%&+U-D3qO>@Y|XhK6n1Ap(e5sp^pd%nLvKCkOq>%Q-GKdyDHYdzi1 zq7TcoaV&Sw@n0MjZ?l#?|LA$~xwq2eK0g~6UL(jm!rJ!q*D&w_?cO*R z!*Bvl!YSx)GXDQhgZ$59Xc#RV=l`8Xo{6(@F5;T0=aU!WVoX8pZ25ntvXdUyG-$x3 z^vlpZR{ozP|MLl&%H;obuiN(oJCRlXvEvDPl8o)&&$-6fH&ggO_NJr4<n-SZAKOuz=DU9+J(p&za?I_x6L;fY+>eJ)jn4i2f5d)B>9 zhkRQ7Xt(=Et9?>vqo;SW|6AC9#5s|VN~aOcNTEIM!#D4sXIy(XGW2|8q_l;z=s}$0 zSG_^~XRddIICkK1`^Enc*VMSL`R)r9+AyCKpQOjRfQRq1;Qy}ija0G!UA_tRfx`G7 zvUzKq|EHh%^VY(OX?}KKc$$0$zrwTVTqOUO%VT6lKJVEfZy`s|Z({$m{D0}UuH^sA zhi$Xu%{lTv*&!Uq|MW?x;%Ieu@_8H{|I<%Dynfb;^p}xeC+)S)LB{p7HU{_adwARH?^49V@vwVlej5%E6FR}^;=PCd#59oh5gv;%B1+K)Wa22jb{NG8%7f%hnKhggs9OwV_8OM4(z4zVf{A9H>Zz5M3 zmvu9F3uLM-!=j>aD}5E3%lMW^%whvjw@3fK{_=)N`k&D>PQNsg>-9gc zweG)TZpWRt8~0+xe)p{ZblCyxU)SsZNB4C7_vo3e|9+bO`x*N0$&Gu>|KD%^|0Z+& z(blE^AMFYK|24)34A;MpR;091wjr&}vVD&J{h6af=R)HH78@ThRr=_uVqey?FQjqw z;eOZig!ldsS&c{0h|0fdcleq9O>Lg_#uYSd^MCrR|I;V@yFi*rG$ZAno9&-M2Qp}P z-|1<_FT`-#z2R~C6UeX8|G!-SzkPaK|C8dX%SVN$$fr@e-TxHGU!kVRb9MiXcviR% z$<5BU#dGfUob6lZ9n>#3&jr>g)xKfw%WC74TdY-z=N$7q`tc%O#;bS@10R(C*w`+% zwwsJ|VS31{aE{FTzBg_#_a$KtOpWiei~p}~nfCnJJ-;{?<|t{rseMy;7*0U$t^OlN zR@CWBBTvJbI2-5UPI)giePB4BUikkkTYVwDU0fO$(=+3g4Q%cd`X$JZlz+#|zv$71 zaH+WJHOA|Zmm~f=;|lUh#D8cssKYnz(dH<86_UGO&%gWBQ|P&hf#GWL*Wh~Gh?{UT zZowPd50(nwirZ1~Z^p@!sqy|VM6NRKpz_1kxuLgF0x(n z@=X5w*G7j&#rOTp_eD0N*SO16jJsADM`n;m|2GGQ$H^z6-ZVNqNj`2XVHh} z(EsnF!t-SBuZ;zW@u!XoFOsj~H4J>ne5LvFp?6)qOC8nwuOW{TU-8yKp_U%UE*>k~ zxLi4)yh$vS@7JjVE>aGlZVda!jx>yAC(76bvM~OQjfms_S2@qis8l|$`j-E5O6vri zgj3MTR(0W@?B5#pZzcOD%{PtzX9Lq{-^0G`vVE)hdE3p;+ommGkMRL~^Yj7j2fNh| z(5XGXYpnXkcb2brr;7>ih}WhgS2i!=VtkTtNc%9cFOPtAFp*{x_EY;d@Sv;eQ~Fc66XHu1$UL zW@+7m{ANBjvh05x=ayPu9F~f|6{`@(|Fsuu-`ZImZWk`B+sn4!NxvJ(#hKJoqJL#Umq&6#`@HS3DQinZ4nQ+i!!6mCXk*NI`(?vwm~>%_2f-HGA04abMu zk+Q7=cPMx7oINUhYuyQ9&G1p-u7xLuyLX)&GPd>q;q-9NUSl@AyYGmr^4{+oXAK|s zlehhGJb~VKo)R9|sowGSVd0@M)^Jp>T|ZIW_*26D{)=_r{?TFGq|xEKEu+J|MaP@N zc0#DqXZD?$Cx*NAo82|xq_DQ-r10%=*M~c2ULX35AE+2)oc^iCqm+1G6TPo8{{nKZ zr|>j#Z}(q3@>%qM_^43%3GE)A^))QlcST_xH~Sx1 zA7GR5@#yK|yRYZNSLvtc8>h;w|L>era0xC&dy6z|zl@&Q&HrDgAO4&C0^fa}f1X2j zhqU(kFMxfj7niUD>PpMZOXjm*A?`}lY~%mhw=rQIf8nc;lvXpE((c1`v=&d)FZFL> z>Z>E4ZdaX%hHH6BGHI!m>`c+TDS&5%81o{c;o`*`wOwLi@Ae&)DOvhaQ;dbajE z{C-l)OG2}BQpg~W_I3XM;NOh7j|~bLdN;lDn}fot9(DR&@zw*(?)U#k$F7*p_G~V( zZmf1fdabobAD6}xsM+qjL8G`Qg`Yw)?R?f2Y;sH@>;I4H|Mk=OA9K{xXDK%ptCyqD z{;-l);)9TbkDAB#BlXBc?`PQocjRT(2eo`$n=F5=jRbc=csJ>%ZGQCNTP zd)fr)IUN3far_@-@4Kx3d9-yf^z#?SLu^xi;6le=j48MTm*O&9j{a|I6ML8WBO}z8 zgjfFH>~JOdDb!9f{z3k}ir%={v&Gf)YtT$jBB6YbzFu7k`^Y90+KFeeKkQcm$u4#Z zXFBG3+=!cSGj73B+=|W_?DH)4c_#ZjpMB=jXXmlc3)p9J;}-TGtvmU;+xfp++5biC zdpY|~#<*3|xgB@nZnW>WPb|mj8Q0g1Li_)_K`qx53O5W-zL|G^cM9K=a2IfI*YaMm#71h znNoE=GAo=T^Xh<&(riWw9mpUbb>GqBWZihrccSNu*bm>d&3TbTGh+My6ZU%&PvL2_ zPjC&BjOn9iM!0|civBF}3)CglJF<)1|6+DQTx|b;j(i@q;`_-LQE304>AZMZ_*Epw zIPW;uQRX_F=bzgDXR22tiDta!n1PS5FMqPu4>=4c;3S-a|F!*pg8YZpiSnQN`aib+ zFOzSV^G#OpQQ{cD(b7zBmp}O~r_tm1pEJqB^LBgq0$iCy$VaaBs&=KW6-zAyH<9Gt`-$HSX*C*+P z^02Hf+kee3pE%jIO;%5x9GZj^D<_8}n!C(5cFZ&Q6`sW#=l}Hy zciN{5-P5P=|EKW(r-UqWGp2<6)G1+O!u<5K`ROg@r>`+TeVzH~XkTr9I;w4p^Ix8m z*7N8`ZSiDnSChkw^u~p*ZT{p#`JX>^Wc`8Ju65qz@UneUYo~-)$=A^C+ykrCi;(V` zqFu^$l}`!B3J*ihHO1>HT<0v;SLOQFyS{qY=bUXDTp!xefzDm-Z;$&UGY8C{r)PJX zKfm4ldC%|!X`X~rFdC=fDA#c&c{b|ic)nxa@O(#jzS2qV^L(XMEuC}icRnt}#i%WH z|Mr{uj*yMOz|wKZd%^D^7w7=z2nD^QsK_ZH($D-NbaX;E;^DngRJw(sUU_Vh!e-!xx@)@$|L8G{4q|kxh_o1iZJA5#kX_;GQ$zYPkN+Ui$**qWoq@dJLMt{#sy|L-aCX*`2p;aOC? zOPzy!4$mXb|LZ4TL|p&tW%5&96K;Y_!1nR|92_< z@ch5a=$GUF@BF_f+|z}QE7ZS@<+*}>B|e3#@Gs~8t!1N-$N$UxzpJHl4X($HsGWak z{@+dX!}I@crr&~pod35}TuR%)t>h}S?>#EqPTq+$zpmT1_@2SI{N89k?sp9jp*mj6m-r4<>@&SE{_lf)etK;C`08z1l`b-nMJ z8)MtmxCYlFj^DbGya_ks791Y`x0HT({NJtg+wsri|4PD1;#c8L+>OHe@BFlT>4(>U zFSP&Z|7jk0*S^sD|ES*We~Qw13Qyx1)bf#Q_E>9;et7+X zXX$-t);5vkrypK_;5l(`%-_!o_v1yx`S)?&&CB#vztwif&b&&04FhXE7vFo`0{6dK z+pIR(#CNrbpCJce^a&p;eQ-|FnmBbO*&`d zY@Cbs>Fh7gr)O5OzqpWoG4k{rvQ^p#vGTnqhd91$ifxymR$tqtLQNB$9>xhyT!~Prp0H zn^$))+3OwLPxgI68-A35&m7~g^^X*?ZlU%EG@!BGb#<}LNYa~8(PUh-{hEgHtZAMBW=|KPLc5?G%h&h3x& zk0+!V$NelA^x$)DB)T!yu zqaWQfmCxwmFBHb7koi4)9NV5jLyP-FVO(4(8^fkFmsp#|wwLiLs%KdbfvnLcTw7Hf z20rSXyNx{~kHs*YfVj4ATKq}$Obgq(!J0Jm(J1^scr6=S!`9ZbpUzc3hK<9K`S%4vuj;M;uRgUrt!{-&q*=Sc`v2lDr8lZi#P$Cx9yS(UxH z)3wi$c|4BF|1_>Z{rd^}lXwbo{(axu{cnrj`=g@p4B7u~V*A_6 zGep zub?-|^KlOLmGn=cc^}&%9RGbD=U~?@F#mkfsL-GfyHVeEQ%vwrR~9di|~ z#x=MeH{vGTjLy~i|Ixk9{C|BjJ^J>u$d&8=U!?zEe|O7P{r_ZYr~ZF3E!<9a*e|tj zRJcVtOK~e!p}o{TxSgIEB5nQXchc`hUN|S5C42P$#Q*q z|4jcIyxO zJn5N*?ti|q2=vDh#}pp<|G`}UXAoCSK1n`>+IgeG)8sR#acp5-1Zn+B_*oSGf3QtG z!+GQX4|+d#a_AG^_vvH8bL8{r$BTFwuOjCkIIocd>(vn_oE45G`+x9i7)IVb_ndH7 z>A7L;j-J!p1(ea_GM1R?)bHe?l`qQSK7}iZcF?_e=r0|eydT{tDVZDC4 z2NtV4Y#0z8S+75;YIJybwK?wJv?k`!uIpO=#{9c}?_V1u^9^G{Rv!#)MSl;eqE|fY zS3*nC-;5o3DKz)K6p}@M4T-TYgr+?&gvO%3ga&oG`t8Pc?lia5`j53+j!~aGMxV^l zA+C%5$X@?W+hy#J>t9iHcDNNM(N96;gmbM$e{QH)eRfzm?VNC%d%3;%1np08{$O#q zWB5toPJF9H|Kpq!!(C5Z%P zVRf0i5c~hXq5gls+AxS~#5Aof4$E5nFOVO-Lfd;B-*>BH(zCViPtfi}za4j?n+?sN z2U+BhXG`nY%la<%ZxQ>yl1*LDwzA_%ZS>6}`R$Iq7x&{KRO3-Jq8V?RUr;RlQt3N) z4tZ?UC((k|#rhi1Mt|e{glgwXNv8uDZiYmm+>m<))@b@PW^v}`hU!qd)5CD*O-XwPsjTI zYxW!1pj{EiVi-=qN$A|F|9`vwe`I#)|39Grzlx1pudjsMI9>f8t+UyGw9(_*aP9W% z*yp(7K_N3_Q0VkNy5f7G=h1^KTGx0!>N*?Ko}>2@*Hr3IziQj-Iif)wt8te1INdx- zBzJmmn`8fq_qg5MM%OqRr{PSTjdO86E<|dZdBo%t#Q)!2LbmVqeeUN+&=0RaavA+{ z{Nwr~h4GJU;F0l5FX@?;94D(qsSQ ztugNV`o_rHaVPrq1N=$*%iU4`ytOmP`|%K}k?Jz{icHt5|I6cz^yV0kSVm;fRi2sjnWJ;x9BK?WdFN^8>{#{E8f4`NlpPIq{pT+;5_=aU;MyE_s`#N(4KJ={aD1Y195G@1R4J!H%#0KI0>hq|MZeDnmi3>qK}_;Hre|& z|8^&rjZlB&^RCcVb-r-jHu-;t{69|qM_f}Tfh4^dIc5IE_N!DMj%$8Tphj9=_Be$l=7Z@d0O*N=Ah)8QWK^!e8>GET5uUjP~B^e46%KZ$1C>YS@^JD#hT zkI1`mFYd>(1J?T+;(d$^;UVE_^voW|;zIhx zh;@b>vb&@ueu}ticIy)IQq=A~DqKchjv9JHz3avm!dD`>&UK^kpMecWg-?mQ3RmMA zT#p-Z6K=-g{yTxMXq)()Oui3+vG^+qI#vF4-d2ypa80;GV8M5OUvpEnH&%OK}-4#}&8|o%^kS zfI>UZba{G?yggMON4}i@KZ5-)W&g?47WRLKvK8(04)nd9|E~@Z|8Lg!mceftKlmx> zUxll2J#Iu?OXw!@=BR(z_wlU*;TC%Jx&dJ+S+m;s19BB=v&yXR|J}H`ziV4|kM>E- za*y_j|5{3-uKZxAUw+WGgP{>k{Hz3$T?f6pgW($K+>SeOH}1v#cnH<#Odkwg*@N0Y zUeo^ZTIfL*Ipnc%%fZls)}05{fB10HOrw46!O(%!@Ppw|=`^AlDYOrS>=+}CvXg^G6$49|#5PI6ypvR`8A zLGxRc|7`FIq+Hjp?2~q#?b{EAXX%xnmCw;Fe`e&%9{Dp%=7i(_9sBI_9G*u%UPSNr z4}_P=zHj|Kyh^@?fl1rj{vM7ZkHs*YfVy#>KN`wh=S0`#UJ|oCf7jRS`cJaYDHx5@ za3;>ixi}whnt#mh9BKa>>H0?a{x-A!?y;3j?Nt9K3;!1-I~Es(3#D-}rl7j(K)8gg z*>)h*Za)wzel{?CR5)i0PHY2gEcWgAmJ?)BxS5P&{^HoH>LL8uImVxl92h?Cm`|d1 zxIF#+LB2n>xrB{IqKJ(ygQ)|CWECkPS$p?~Cq@?EMdQ7P1?; zuN8;K$ciuVThw8e?`E&}hwwvjm2AeUj}?a>)BE3dF#MG4{q(``b285V`vv(+{06^6 ziv9RK`A7U2FQDBw8rJ}PiJmF*?cx>sLF9Yc2Io4w{$XMK|4cqE8n^OkxASdx@^Q)L zE&9P7GoU#v8;oNx6vyL4oQyZE|EEq+@V|@LXcX4}qddJ`}N;>br88{1Z z4Zs>yJm8z-i#H&)AD?4eGn<|4QU_6YXd;*S{^B>dVz&ArKlD8Nq|4Pm<{uR#5sn0{^O-N zN!nwbgWgQuW}iE77w*B~ezNF4+$Y?*i~qUDJ0>#+}E!WZM4iWQTL5RvLrzBY8?%aSq^PF>P__s)6B$^um9=Rx3x2 z)?fdCG6mb-Z?t;r!0==H*X$e^eoFovwc>t3{t}G|Wxyu)w&742 z&`icM;5WAY4!_4A(f^}?;m_m?cnN)N1H&t1tbZRQ<5;WZi+pe8Aq?0kU*H(TzP;Qa zww*j)_(a4$zRLHNgjLoP%u>{BtoIDC44wM%yZF+D{{7kf@9F$+6#lcv z=ia#2`1Ae7pYxSdUFHYW9~#@=zTW)*a{j+Ifcl;M{~`Q;G>zo{7xVx5@y+Cyo$sso zI&#KlE{W&Is;~JbjKk_2;ryk}KZgI09&K7j=D+X}H}dgYTwg1nKgIWNqo*hG|0nSO zQ7Nr{Ya!l7-hsPt5AMT*cm%a*KoYI!t1AiZWbe01LTZz-_w*bd!w=EE**$I>8h%XA zY_VPVr}UpAuRS3rF6+1+GS1!qh4^3MH~1ZDi?u%t9~yp7k8=VVg#Sp7zG(BpH;+G9 zHq*OM_N|z!{M)Q-_syiq_N^hj;F!Yrzqk7Kw(t+ov%~X2j-I#QVY^&EL|wQ``X%xO z5@ee9apAnamrs(PL%%+tFOU`A84#``Z@?;bpUOej6bo+) zUl#r<>~XjQ`M|R*SZTR&|AxIzyXt zq|v@u`ve9{;}{IZ@#xo&)BF7);Y51h_eX|k*H5PRYM<@@^*alFRn^MRhesBN4Qs6F zGF$z{_IKb6oQ3vzZ0w@J;T(E~t?l-F&!b;}{0PqmS++gS-;ec=JJPLEBF32+_vd2;dXs%AGht3xTE*DaOa4j;ad}52y2R@mlzuEUVe1=jBTI8 zJ-Y{mdl#91xA>S)wfC5C-!}6xlr>+l?K&(k9T=A3f!W##_Q}shZ;_u*4E1YH40UL( zI!AxryYvAaADY%3AF69cg-5VKTg0E0KaY+)+1QhlLyiB%eQ*8faDz0zjIZMBSb`O( z#BE6JIxDoIC2?-pxa*v7hq$|tE;?OX{8^z+`BgtrnNsFj$fohinzS+}tNugYW8eGm zARfVy@}o;%vvB7O{{I~Q{{rpnL-+(E5B0s}==mb!AGa#|wkrd7DhtUr;kY(mY@hES z8>CV3BkSXnaUK75vK##$^u2w;+MjWJfN_6)#xeB;-@#jq3;0H9$o*BnvHc!H`#fpx zQ(vOTe=Pl&{3(8pLOacD{)`t;m#{uS+B)uN z9IOAkOuuod{%?K9&5QJZm+1c3#4@slETeZr}_^4hhc1~_8omR{?Rbmw)dlUcxm_m`61Mpl#-e? zDtv_gQG6VqMEgk351*lD$nHs_!sqB;K)%AYpTqo`Zd>PgL1MyX|W_v0B zzchTEz62}Ku+MdhYuf6%%J}~i)fL9`U*{cq?r{ucMHmz+?Ry(meM$Z7?}Nf!^m}k0 z9>gQ4MFWzEW7k{Bc67%u9>WjO|Lf7=$7CGC_fxX()S~cn@)!6eeuK;+-}8KR4*BJG z!g*y&4q5cb7ctNMUi=^NXS{&+a`|O5zvD~A>c9LS_Y&vkG?Gp3DXtZota5*8Wt4B~ zCC4n=aj2i*2kPIi2oGpe4?<_X{Es8;f3rPXwl#-B``^|#^#9qfO&u$Zc6!GK{~UU! zu@3)c+|yU&@3;BRr8yLporl^1D&BKcI9~WfoQ#~g#-qsopBNkQBjYFb4G8ZLJ_Bdr z9MsOy9=mHmIFBCZRL1c?7tk-lo8})()BZP?|B1uvh&Ry_IJ}PdLH9b@aqq_m@F9Ez zAH~Pf$)9rMQV#XlGR1%8R& zp;KM53x)M%{)`=%?Gc`pAoApBlh)y94N zk*sMkz7v0@zkrv}u*dk&UB-OGu^(g-&D*VGrw;#$?G-i^5t`{~ub)sx9lcn6x-cxOnU2?aksF)-ZWyFA18vv3Yp zwv~nR$O~{0Cgc5xV`vNgd&;K|2*K;l=^w`@@fmy${huBjzCd1w z+#k%%{m$TU1HIQ+q%V_S#n-U}shQf2$x7UYI}peAr56{4yXc48-|nH`hx`F$!#-t1 zv3G?B#XW*rRJ_kWYRM#8(J!yJlf9?=hR8m1xhlWyef|Bo@R;xqv5fDxTp7HA|5v?J zonKsy^lP2xr}UrW7l>`ahDcui16}#{2q+?Z3otki+lrd;Ae~>&^d{$YhUOd_~bn( zj6az%^uNcSOdlG~vS02k#vh7rnCZEp;&g2};*%3Sw=&Ohs^^HhN!nk~F#FJcP0~&v zxz_tZC3~}~B7_SZdl4q%{rCVrgg4JW`3L`gllBkaLW^&ql}yc0|Cr_5oTLAb>=5qu z%re?VI?1kSueaNHHa+z0BG0YJGs4CRo+H}n9VMRQaL*A9>s+^e>vp*hdUC4whNhX` zBR=99KZ=jzllTlihcDndq-K_c8^|x?tN1$F7g~Q{aYm_%rWju zV|32Z_NSixKd!&AUHx~b{%@Ucg3C6SFm-OG@ zcW5Y;KS#K}68ST&PSC;mW%d_^3xqF1VckjP zMGsq*McuZtP>%-hvT=8r`n~tEt1Kk2yN)3+tu_g6Ol`-8$~=%2$E za2;;Im+@769ZRqRab8g+S*J{?cMlD&|H%JO#ygjA93yj^eeS?rxCi&)K~!uU6doZv zx4Hiv?%(xg(6iS4uXq1d?tiuWmsX2=ZAGfs{VT`Pd)+@e(EGJ1q3_@L{zp&t|8VO$ zD9hsd-?h??Ylt)1f;^#8Q}zqls-4+*|y!Jiz$=XA~&(7?BB+*%x7 zqSu&bP>WaS2Qi>q8IEdkDfN(J=tFTlPDDGKnVvQ{oJ`M5a&GoC_xTV;2^ZGSWlyss z`QKyM-__L_GW?@{3_ z`=s`1>nG1c`$~Pa-gpM<2_&3+2}fBohmW) zP#vpz(ctg_$9xDM!AJ3Nd=j6*=g`TXbV;)taja<%8Pm;`I?o99rzEz&sDJKK|74Ha z$h2@f*HHY^LBqmN z$#!w+S?bU9xTZn(boCPYFXKMKxpnf+T6u{4jkw?8_xL0Fzi0da`2t=--&@o@$lgzA zAANgCSf;&tIbxg6fQ)!{zxQGD`ybZE{~t$%mESoo3>M%2!BfI9ar@~5!cemBODBip z$rEuh`s>)FKWNu_*m{u1mH3Vagi+#a!p0b08XAdt$ctHdEOq9RKlD zH;>=8i2uo-Kl1;(G(V1?9@qar=-SV7`~|oOlQA7LFcY2n)w>q(zvuBI`Gq|r_>HCf zNHVWKf1`GQmhJqRo!SS;HsSO_ek3{^m)bWp%#zM*%)wl=PqYtzavnW1od3-ipHE+a zJl`}YoYimMLl*q+mN)p{eCLJsEBN0V+!r6ban{hVSX_ni6G`Fbz5G)$F>PpgXxh=? z!IB|iJswzhY`A~X#Bks6iDBKk3(Z%X5bhm2A>4ziB~q31r`Y6orZ8B$Qz)Ql7&!ayn*UCfYsE*vBxNUReKQuKIy~mQ~sk-qe0F z#=1(gw0&zL!b^z01d1IYX&%+Nt&(8*?+VxKGZhdKA-(ZTz{)5>w86R*{NX&**?qnGjTvDp=TD$n+peo z;q(#6`?hj8ynf|KadG|qQgRGxhYtv2$#JN0T!VCCy?VUx1SI#fJ!rCD0+Ym*AvZ{$ zb{G|=(x+iMW?&gxzTCa7a6c9N_{xo*=XVB%nYPWsY|O!2%tPN72ZZ@#ud;Xn+5gr7 zVIjE)i&2i{Sc%o>{R{j1Z)`7rx$kX*!y0jGQH6Cl(tj{Ag!RH3P|;Hw`oC*^9({9h z{VmmwuwLpi>c0z1!w&oHL@#!sc7AE7nOhom(;L_5`^O&oUNqB_NT3P(#HF^63j4_e zXxDFEl=D3yt^d4xgMNPu5iUWl#$5J#efRp>vzX|Z8Vt9sVvzQn_`VU>Hya_YZjAnU z{L}vliuBK8BU;dk6xxdQeGf7IK;M4HMB@)ij6WFRI!av!*(03YW&FV&;}6K{wWGsG z=c#jl+ssH0}`|idGo)21)Lfbz1|A6{G+2Ocq?|Qy;7GNP3p>~`1zoRrP zrZ?*MkA45;^yMi0Pt!M_*ya6W`FwVDw(>^(XN5kf)%IC~wWvZ|e`_7N>YMWJp9Y2X z^bM#%J?d7f|5qIv)7MzTE@t)hZCC%_#!ez(pBALig)BBKD$#{XsktkOKI5XTW&$CaU3bM(F@;qwls94)eY-?KWOOk{h*1SKytC~2g_>Y zr-b}O7Ug~CKT{9*+n`WPAA*&xaUV+P!!ZIQQHn9BTgX140gY%xv^zfbpHHM`ij;x&nM5x` zUN|?B|2~}mPEHk9tu8W+oQ~K|FoT?ln!V~SY3&Hv;xJ2iHj*>-TO+PrkU;!*ZfrX) z{NJdzD9o`>?L6!Mlphu5(i@la|Lqgk|H(D6$-;3CVPdVi2szI_sd|3cAJ~9*$yaRg zd~pkq-r(Bh_vn`|6kdcl_9l;lpH9|o^L*W3VVr{UzG;EyyPo~8axVF~;!j0kvE$0I z94oOJYp@obY0{7CPG4<6CS?Bd6?+-)Da? z1SJ@b5g3V5jKNs+f0+L;OZ%TZ+@Ox!h=1(=$XO?BoPEb*0wyA^RUGrwGIV-|T_`+% z@1VzXKl1$P8|C%??*H)oeGh5hL!tiVxZZ2kKmNl1kL&;Z)psuaGEBvE%)m^{!ffR9 z{m&u$zo`E4PWHQgK$t6Bd985)))AaXuPyiPFrOahG&al}5EjrEBCaWy+^ddBHcfT^ zEBXIx_{n79|9|uZ-#?k=C-d2-Ic5_U(2|hV0R2oGs_0lX?FA z#(Mt0_*UCfWSjlt+Wv*{|786C-&*NZVI9_^z05wvL&FAohCkoEz<79iJ@Pa4zt89Y z&vh;`=H2-Jzd}C{y>_wdw_git^shIJb6*qnzgxRLEiO6UeT~rnPA10ce_!wZYwVY> zAKBzO6WR@uJMFjCe+RS~topon?AR@h3hVHHM-)8TBr}s}5`hVoTjnZpb zZ0{fK^bVw5$2RF~NBg9qVF$SrsWR)qk+H9~$Nj~=+W6nUUE;R;#xtHn zw`Wj2Z)n&pZV&ciA8N(dEE*d2(+l$lql8-o6y4GSgYaE!o6 zlwu5W*A5Kh$nog?7+;j^`~1)_k&L!~Iaa6#RD4UG{tNqJy@yG*m0>ETVLE1DCT3wa z=3p-7VLldMAr@gV%28)*P(2#75jLWUoZE@j`zjuLYc z?001T;2vcLpQzA2xLf@I%bjB-RwGrWorX-0*S?_re=R+ypMM?M-KBj3JqfmZC0lSn zJNiETBh#fZ%l)Gwn7{8CHzYhw1?;RM{JHFTazYSy!>XAST(&$1Ko3I&M zuoeCO2auD;d%xlv5svf!wv#)s6TPV3J0R>LcViFsqIS3Z-#Z}eqc<*+|FNHb07vR? z+W(rAcXi{~A2gJ`-u|pTJ@)M<7xNQP<(SyUcDQ|@=rMIV-$OAu1f5&hcSIYVK@UBP z9GjWP#v%L~w2o9iKpQ=cxW<16Qt82=L^_o^cH;QF;q>@#yx4y}f}YtbZH%OsB2UjD ziyn*-SG`vqf*gn1HG{)=asuKSx(%z{7bXf%LXzH$CL~a3f1mrh{Vf+iPy7P+Pd2X~ z9LgLs71J;sGcXggFdLow+`qa?H~CNN2QUA>jDKYJJ6!)9X&fFeIF}yBNX{eYV*&D$ z-0uYUOUC|+!~Gd!y_bcyS0{`gSbXRkTo%8llV;_GUTO8NLZf3KRbL6vY z%R|<2o3I&Muoc^|9bJ3n@!jhFWc)`!VVt{geuncnSL}P+I8NVN(V;%L^fqP0NNtB? z`wsn@ z1N*Kep;ur32;sOk+Q=xs5<)52tG-#ir6`P{kHyL_Ee_+z+D*oui62jIBpWstg$eYD zh--i(Ta^FyX=1bLc9wewOF~1@lF*1IB#=ZicDcSujw{1dOv9Vz|BYV~x_Xy{Ze-Ad zEON+W`;7~i zh8DCUHEn5Vo9Z3SSQ^^PmWGar;#}8U>CD4?EI@meYb;+97Sc0m_l8CE#mKLAZ!6v7 zTK8JBB$SJ*E?p9qlPgiXZAn;7u0hQt&vmcoinYR3NN)06w|dT=O=7#}qYl}kZL8H- zy%gH$>81Ezw~kT8;=@!ykV>St6gD&@XFt6yQar+LrpF6FM9u`u3}r?r$>h} zvj49G!&I`;I=idPx9t1Ik}yrUcUe)GPR_tg^#9ihVHTNMSQKWHb1)b45Z6{o&*cZw zGxB&`8*Bl6A@U>Td)u>Q&zPdHNZewSV>wo0HP)d22TQ|RviI*xLKWHfm!%$>a%z$K zhHqh=xb@h8>iyCUM~67)w_Z4b+I7mLy5i76k7Iuuy5#${@_jwul1$ou#Qw7{jc6Lj zHq2xrX0d-W*iFaAezP=LgX&)6%hnAF8%7Qa5AW43>6k7=8=cwAM(t#)$Q<%}*}sYG ze;NBvrb^iV5o~)Y`%iWZG52l57ek6KU1)!^zF_+X?e)%+MY=`1!7l9v+WI#MZ$^$D z*8u9-ryZaE(EhK52X}qVdXkI717p4s?%(^3aNpc={dWt)cXxa#+}r!5aL?kegsKH! z3E#opiTVB+cWqd^_}cL8(i_5xF$==2yKW3yq`eiDGp-G*suqQcb@RhY+*Y$F+}^b) zY_n}U?pXMxaOd)Ggl|n+7}nq}=eoPTJnXP-C+?ZQINa;`e5dzop{jhbwJ-hqPJ3;y zZM(1=d+&PO}c5129!u66IJp=Fb{BJD++AD7>xlkR<+wwRIO0KI54+kzn|*tsFTp92F! ziE#CZ;xL@7{3icVU3DbAcC7xNiN&Fm-Z)H z{O{TJn}fNShxu55++VdfO!p0X#u?YuO=g9A$h>RImHYOku~C{SX||GS=V%kxvDn-N z?LT$f2Zj2bgOrbhLgQHFg7PTNH7JZPR6Zvit*b<9ziX92x&KNnHr-!_`4h`LO5y;gYagT5Hh%y}@BESrzr4Xcy47(JQX^ zJ;n%`m#|L!dTc-q>XATd{Gez@mc=<3X|fCL^enjvnO&|C*`2Nt@!E12VcSY<#ujYF zHf+ZZ)J@eF{w+T?MYfIMyQ3W)=-jM*fFB*_z-Rc>J!Dom zXRUxdQuRZ_PUq>xF6>78Hfih_8urlRKLfiD3=Mnfxp%R7j?cw3?9*eP=yz7{;r~ZJ zbf)@S)zGldzWY(L-gS4m?v?y_>#D8dV&9^55yz^+W=Uf<=Ac@6GncHXDd9u-&)=_&sndQxUtGg(Wf7W; z8A$jCU=qzcjc1wWxzA9Zc>dMCw*~R|smASKA-%BvPhf|~v%_QMuQK_IOrm*&H3w$% z0an_++;;q9{#zuC#VE&eti)=p!CG|A%CBo$7xze1L@Z0Wzh& z)J9LQXJ@Lk56lraWI(8r&N{5e2DF#Rqo|=5*4O1H*V7ZoyWX7qoJCw;w?$kUUC5$W zzvCt{{`+?`8GVYl=3{IZh<@}Iaa*wsar{AC7qa&|#{a(u#{b8)2X@%D6TR4l-PnV@ z*oXb-*Dl=uH|tk?R{d;{@~w)k|B3Q#5ud{Lq9@!3y_g(=xb}4SY~RK{b;#+y4Kmh| z3;ypcJ|f~;w@qpGKg<4;&BEKIRpR*J7=e)}#Tbl5=X~}Whx_?^MzYJum9W!A{QvFj zzdAuHnX+HoV*T@o>+^KX)&FkWIO&YX1WZJ28UGcN=y6V59RFTMpNi(J_ID)ER5aL! z>-$q5UNKMod8YIJr}w*1`j}?_%HPWO+M~MXs7FjvZy4wLj7!Lsy1pImze@YZdgmbj z)%{PG#th8FEX>9n%*8x(E|mY!jSP;g|GM2XmKO{6-{Ss}TBH8sJn5O*|ImT?(x`Ti z3&@42RhOFQnJ=Q(&>Kd$u7!Mg;c^t}Woy;pq7Of3a9A#GC01h%)}jjQupS#wgL)+J zM*GzwT(Qjeyo^tEoVL3r|C-kx-6g*7yPgxd37Zk;qHQ6!VjH$&2X>+tyO5ISc9Vz4 z_wS+a#XfXLAAOhnd4NsYBY&!!=ds_m11S2D@)tu;g5el}I%PsVj+77d1d?dR#;Nl6 z4EcMSygW<(UhMs&eWd)2&T+~IbWd`A^w10I6WJEW@)Y`ghAX?q99p-qh8*dc!u32lFgdcJ>`_K7O(6R6OKko#b1SoL}R|9>)%R~y!N`^R!%0@?q-z%Y@V zgfdLUG)%_~%)~6r#vIJWJj_RbTdcpAhTd=ZK7`{xfEJRAuo&e?sgExwS7J5RAdc-! z?=#knp4s5r+`%6F*QsHha6Un=Q4X~DR`~;U`o!x;>OUN({}6@w{bThX{(q$1e^{sG zec=0>FW`s~BaI|ZA{x?=N|Yuvp(}P!=QMM!%x>n|a5e0PUS&6Pwwz{qh11Xm8&Xji zhZ%{YqN1Xr5`^%ZVc^T~>-#0s$~My-wqYCEunnhDGFxfGA#B4oY(&rN`HnMd+q0+F zb+`wq=YH@Im5qbultF72{W$EVu^Vf$$I1dm_q`6-l@ObGb)7t z7(eUzjS>1NR@}3SHC)67HnEKzOsxpNcbf4ovzXiPPDmR2pEnoa^nT&M8Fu5C;3keq z`dM_ZUfRPTRZirEu*=VA4}%`z+oKP50gjG%dVWPKyfq?}j{QrXjlpdBYOXeNrnYgKHZqQRUJYtdkLc{c2C@mwnBsmq z&v!2Lo$(LPcS!BOUSa-KmAO{rg#QsQk^h&;|9$_H))b!lc4lbd*VbGJtz;Y8Bl9Ev z@9p*g`O(dxgL(a?n?onLrcKZlnT-LC`&K>lehlM;K7h#u&sa6?%RIZ}-4>bY)0iI< z2hRKV=e#S~y^_;A^ ziqtCgzsu(; z4{q9&Huv?eHfSb|8G=BYuZ!4ITu0&KcYR)PJKn66Ft-S`=73VY|~c4 zKehk=mNDllejPLau9sD{Wa&Nh+J{I_PZ1y7p?*GgWV z|JFvoJpZko-hqEO|E-f<7kbdWCoM+$ruBc?s>Ad##4#W*i1LUbM0rG%H;m$)^9!cA zOW+)mpSw1kCr^G$`})J?^w5{Ej1{b64bj*`zjQu;K@3Uz!}5XD{>!CN`I{Xsa<_p^ zY-0zz*uzwj^e??#8UK~8Qv1L7m(e_r)c(um(!aDnUMT(ZGhQJ5<7}?By*Y}|egl=um1>q>6AI1^%W*a|7IX!BVMrYGk&?_-|RNJ&c8x=!o*M%x} zQ5*g!S&d2hF|r16`iwRBv#4dRLy|s^%licORcZg$ct*AMZ{#OA%sfJlPQN?UyQcw7 zXhsWK(S~+RSz|tJ4Z=)?=N#j&xd#br5t8N}%pW!X;JkI~IJ2U!0Tc8%Cb^5w|LfpK zw2pleo%BX^!PNfz#)Zan`IpB({v6mh%IK?O(v0n*Z}{afjZ^t_NfE z!6U+kIDHzU^k@yjFrqaGeYL`m0SscOlON6EA4cQy>L1F_+;G zU=9f+F^|*o{;?kMuS@*H1U)`1{ePsXR!{~OZ7A^Kq) zLA2-9EH3Xul9Z=LZQ#B`(tm~b#9+1eYVclT@)tz&o1*dma`#uD5>+^gY8*pq|EC)1 zzuNcD_Wk$!{z%g2GkyOheFV62{zskf-{AX`(fX^kuS&C@wD#Zr|Is}E8h+NI4)th2 z6I#%UHf;UC+JAEc+Ueb$+AYS0Qu8p&p2c7O7#>ZI7A@8X}Fe_Jm7;S8d^V*cU$+vrTfJ^q}$Rk{BC zw2-za{A1$Cp{qhBeYRcPLKZz6(b<8?VsWflTtlvVyX&qBIj-fRcgGkpnTKc(fq^CE z8uFP7Fe2VX`&y*V89kR43fUE*7$qo084ltQ4&w;QQGrTS;V6<{w*PK8U~I!U^{0%L zJ+jXQaS>6R+|mcu{3+M3SEt~9{d>2Clbikb>b`&R^Bc4RUz2~ri^H{_ZrplH7m_gLXHdpK4Ac=YWqxJvn z;<$YNUt`?&O88#n3ja=?wl4p*17VfE^*McXw_6wdIdPhK{h<&pk{j5>HoD8jMRNXo z9|^nU9(wDg|62L*f0X`9g{?RiGU-`Jo&P6}4Ce|f9xwWEXv@4cJdu5Ccyi^|@KkeA zXfL@vJiTyxcqU#Po=y9B=*azec&@!9JYV?9@IuWeLuW@xc(Lq`@KVVgq1y8%m+vy> za93ESk1yR7vOOmUxtL$MDdPjI_=aZqG z{#@6A@cf~&aKydkXlhX2;e~?-LNsTrZ{zOJzjwDf*4@6r-C-#2Ztb7DwSVr`{<%9; zxTg|TIErc6-E<(-@uwaQXhLuEfzZ=_AT-kl=>yXTLJPeWqbO%514IS__$;@kS&Hp@br zYweiaC<`5AC*t&(;j%CrFAH7FJxF$zh53AShn}*KXt)1Ew*3e4>_3oi|A8|54;0vc zpve9McvEyMGvCn2!9K()O2Lr`1Ph_8Wi0oVrQ^NzaI$bDCdcC1v3Z#xu*p zglEOOwEYq7zt`P=ASC#eTHhyMIY;ju7Je+y2e*Y^+&WKR#Avm?#}(mU68^OVVTs*% zVJs|@D~RSkt&(eq&M=!<_Fk*z=rL~~SubC}+=BNcH`#5Y`=WGA_LP{bNA97Qp7zJ; zQW(sUj)iYHF7Fn;sBSod^&iO}hVBk)_uOT!!rdW@+ic_@7peA*-(4Y( z%#ZXB-WB?a?EhP1?6vyR80?Vw^26rKkC3CrWaHi=+B+%vT6!pO&&lic6+df^1-%GU z%IE2*j8@h}bM@ykmCf0g=B&*t+fFYVgIzWDN{(|kQLk*rB>n7B2O~2MV@e%jT3uqsc)~2^j5#E5<@|wR?SK6WXE5HZ z{oiT)K|N(sedTN|J9U90{3%BTDlzGu;@-WAKC5h<@vcYd)rj^qOjZhGxv;8h9Anq5 zK2k&0B04*;j;u$Idk54#qILZZ%uN`{Q~%ge&&XHL$QAx+?SEW3|Eo;iT;SgpDW}P1 z_q?-zrG>c_ZAgAOElf3;AJnS!ozj!S7B)XMja#f6eCm|6fwhM$e?r>qC$B_D-OCOcT3F^UsiwPZa?ynkFD>9P(T(&`e&qXee7!!%76VY>(-SPu`fmm zN>PS`=)S10;#GduYIjeJ+`BLy%(+J*S_A=zHZl^?$o|+v9Fvq{B*PS zd27@@7e9Ts1d{Z5G<7NuQR`Vz9lMUKM+2I0G8&swUu>qgpcQRskMRA+JG9~Ho#;Xj zCab&y`suUfp55S`>0_8L)|Nl4O@HuGA4GShwmJK0BybMBo%%npKp$+=Hcwm^&eIn$ zx~=`*qW#{atxhhnTgD1j@y_wJHRcogVJ?!VUKa;KM%bWlVjDZ?6G!^RnE`UJz`rT` z`{{p|n?0m0DF={+Y~&ypQ|G0B%&bTQ((^ys|AL=m@{%*;IKL<8(b+JQo_BUvnZS=c z$Lg%WYkyQPDbm3JIGFSp$Gkl);$c9V~ArKYeVu8GU{J%EEY%0r1w1SnICJX zf9bk#E^>3bcogj)P^yh^t-1cMd!H|4hVSbGy?lP@dG2O?qo@wBNMFKyoqP$21>X|O zkzf2>A=f`^E=**`MQmUb+t|S__K^0U#06~q;N79OTHgvi8$C7FX_MW<=Jk;KF|sDD zBii$07y}1=f8@EAkG>A&F9!ORQy7}Q)Gs|kA4LH-?<{``nTt@2K@NV*=5-xXB*nzvos6Pt*qx?H{{9pDfeY&hJu0eE?D0e-5+WuwS9>gIWMsL0G3)ha&2l*ZK0hH4#5S^(rf?<9~d+nyy-`8+c zE&Q$Qywh+qH}p}m(mho;ifSA~4Qf$`DQ>2@opIll^ACpA5qi95gZAH^@Gl7eqVSUw ztHMuCGM^>KH;wJ{rvXi9#$+ZpIah@idTRY+sdee}HvGf&kL~Qb{ihDH6TJuRXF#41 z?|UkQt3kL9c^~;uKl_m?;bI;lhh6XM(EdFqUSJSI7?yrVr0Y>M8LMx^uzQd1nj`SI z_4oe!7;_v`3&z(MwXwwKiSw7%_>bp_I~c=h zoaJ^>{XC8dM0;`#AX?kshtURc7sD7riD#6e3=rXzR@(mzxSyq6$Y*jbo_6RKM|W%-GL=*16|%wZ_$vtTWDj>=yCg`1hjm?*-%E z!^Xd-jb&q!e%3huIK7rXb*M*=Z#|jE4H}qdv-n+lb7-PR`}fZ`7+Xhb|Nk6g=jssM zd)7H0@*m30|EqLexzHT>MIYdH@W{=V#=qs~Bm5f0kn#T1{{L0R|7*Cb=8oGTa+rC9 z9OZ8de_GLoc66WLC0=w@1o5Oi>5xw*!av44JflT4bHjjaM z6(h`}%tN`tN%rNdgJS@L7{V|{Fp4$zT*L;FUoZ|pZetgFm}-&!F(a+dMrm?d+C);i zn8)dh@(TIK88UUgA3ZLgm|T|r6Y`dR|4m!vctRb$Cq1Nn*Eb+1hpjQApLk9AM$Q!R zzkvT`{3nx`&(;3eFpt^wlV4Q+sw?Kud)Mrv#6Fikcud%in%7Lv!)T?ju^YxvZFhbl6vM;s-$ z)ZtJ3x;m5kL2CW|r!vDa_BE(Q9qQ45CN!f3Tc_3OUol7U`!|PH=Jo5%=^@+Eflfqy z%3Wj+`Z0{u`U7Rp7(E)3m_eLAjrl!gD55d)=&blu`&;=EopCqVCeMh=JC@`j=jA2m z%tdog0_U)RRDZ&l|Aq6+Q|9nZV+OO@)N|F^-^KuvzfYV@ykq_!eU+OvM0@{SB%{55Hpop(s();gJL2i= zLGP&DpE%?lF^^~upuT!}CoZoOOqKt>#pQK^JMQ1b9@3W8yO4!!CP8m@d5tquJgK z!x%y_yAqV54DW1z9ArKr4o3SHoO(Tklb?BaILz({%29#7PUXLP=)mIJvo`u_P-j|Mbh@`&;u&Ggw8emA9u7J4h@nUl;3a;_~sw6W_>Gl!S#KyQ|@0kR7{ z^nnHW+M@h`xgR6Uqs&9{pJ6h!zjsuAOTQ7{EU||Ij-(xTgutXhD?6r}}>q=DILXl?p#*&I>=HH3sr^U2#|nKFqx!%{3cVwuIRq~j*u&Accwyt3 z(3xw$!9(vg-f~TNw(`B9qx`+$>Dr$O&osR!JXP^Cp?&jb!V^n38|S(?JRX04Xj2C~ z(SJ*5F1RI}#Hq3Ogf-8&h~t$X2oIKjAUtyDXF_Yw`@*AmZ2El?z)#aQT>pCMd&0xR z{IzFfyLj~Uv3G}OR^J^qUE8vs{}bom6`pK(S9n1_xBgY@SJsy-UUia9aC&3}-No31wUy(Hj1<=j{JWruGM@S3f{%|GffbZ;moJTls%DGn9Bv zDavpVy+^D+!y)=$v+@sz=|?cCEF3|!ci9li*;SwtRXB=j977GFZ`Fh-zpQ1B#*9v& zp5B1I1?B&;XCON3cW95_dHP0k^_yf{pUF)VPFj0?>L%%v-hx)N;mY|tE$aW6>yWOH zq|f8DbT%fhJwuLf=zo(hM|txk{j7eO@hW>P@TUWvI5Fp1CpUH4@yxT+{@<9kJiQhB&SByuK3G@^T*N%S0J!?{!7mzylrCxuKd}5gF+g1J}wLV9A zKUAPxEK)}%qq8^9yJrzgSjIc+e=E#W?aKd7WptPFA9J4`T?I-E^?7DL8 zk(#G%Q6`Vc`MdPtv>&C96#Z@bXxiVV_vQRFy}#q9=>us$P9MzsyYz{)*VE(Gf0Lek z^^NosIGy&x^s$Pq^fO1c(#LE6uk-@`6`}~mC_yR8a1g2ee?OU_Us3=5>sN(C><;4y z%F$RN{+5ZqWF>PIjv{IsY<)}rmwdIF`J^zOx^FN27`;~>8_l7tp%2#hx2UDpAvLeM zQvO*kY)8%iX?-)jzx~bhfzCJ62g#waH`9j`Z>Ep*znMOY3is5b0ZnK|3tG{JDc^3o z=&ke_a<=TP^f@xYoFwNL-%3Btk1?ESdNX|-6NtCGnLc^!t@N{bZ>6{MW9@@)q<4_( zUwtFJlk7qd`Z0_##4(Lj`72%>$JVub>Ejh|rYG2+L-HQ=Gjg)QGwR<=KTn@6dNX|n zsrh+B;$-%l>B&s@b(igc~!ZKFSn|Ld|XZo%5Rr=uOTj>K>qhG|RFpVs{ zl|H=uR{9V&*o|+$nZ8MGW77BBA$Jj{&m59391(w+(^kAA^E~rhg)~g|dAI%&-@nZF zKkWM-^!>?^THha;?#V(na*&Jt$U{D+4omO+nyK;}a*m&gx=VGusIU37ynk#_{zHzh z%74f>b2LZ%Y=imV@xAl{{uCnWgDoO^&+n!8pqM_We2M1XmeP~P$48l?xwpe)w1?+A z_rHnO|CMpqL-yhzJ+=Pt25s;{_3#4ui#+B^|AKUOh?~PWf^t-#5>+^gz6SY|d}RQG z7{YMB{Haa;gwsv(msa^pv$QV1nrM->6Y>{%%-IJ0)81oR{xCz%R>>2{1ap#{-!-2` zzA~OI4SCivL}h0US&L{5;EXgfEB(|l*CSf{H(#ZmQ>UIoZ(!GiX0)IcYuXQOWV9Bj zo$Np-wv;=m`MPh{-@DkQ>V4)?pSn@s!0j2KpWQIVBKLj%6}k46H`Axd^&g41r}>) z(LSL)?%lv9wy}d<>>=$xi+|es)0x`V%JNxqPMbeLrpDjPwEuUMP0G|W&KjAKd&r4y(;|tIm5qkGBy6uuYS~VY5XJF6RDCvRXB=j zOctm^6`NZ?kH$V`xT&GnV!lRSe)XlXkGXnt4cK)HYdzV3UhbR7XbMEv@vt>`I4*5QeF4eu+k2aw#4!I; z=Qiq3i}nDC`U2+on~40TM|}a^@}V*A;?cVxfv684YWts~4=%_%us}bLQF_z|5bZG< z^#LrhTf#C*#OW>LcPsQ&tYKZh$;C*2BrR-^o7l!K_Rv_Pe6CX-HRwMukMZP>^ap%3 zJEZ-&dJ3|TjU41+Kk|@|0u-VM#VA23%5V@{7xe%AP@CR9K!=#uZ?p#qc?9LC!1zUL zLC6y)-W{sQqqw~O?-)JWdos2D@8xSl4fA}yxLGO>C>B@AzD?~vZKwh5)IoA6YFm@3 zee%d1VLWbJzv<$;Wd!dI)%>W%$!CqnSu>j2|L>4?_7UxDat;Z4lANzMKcGtccUSvY zdv?4>`#+)mOGfML&$eF|>iD%KjP+y#n$V0Ev?A&Iw~_7WKquDCqv#^n>^aeWQCpeb zk710VH?rID9D1~-U_g6(nw~(krhcUKQXj_ID>IaYbiri(td|@hmjU}0HX8fvfP)AX#edTG8g-ihb!%W_sq5_7pIkri0a_;IK3-<;*5M{ zT)r}~s{Kz+p40y4Zai*{Eq@A7h$2kx=SJP4m_F;hW>7*eMRcZi()EPv(OKJN?4mvJ z4w8ovoqc!7p>TS{fkJbDrS9(_-*3#=Dv-W@T zhx-42===)i^_%oZkx_f7DKguGG1`B)ncjj{wBhpp!|n9T`ww@}I}w#h$tCZY>-!-( z^Ysw>F7%)uz2@rmnEy9SPwoG|Z4Mtjj!|V%G>3ken;|ro%l|6ne@FF2s54AQ?rJZs zzfaIp>;FC{|K3zTQ1;Ft+P5dUr2W5WUmtE3a2|_T!ZNn*$p|at+Q;?rlj~1q7za_8 z!3H+5ji~LrL+)Y^X{+9U&;E4Cqz@W*7*N;9qGw~&IKW7i@}J$1Ykl6K-@6PTS|{-L z&fo1cuiibm*pEECGyUf?Pqhd$Qse*X5OdSYW+cm%|2Tb7`M;_B-&6jp1Eu;$7L@glI`4|2E$v~ENI)?UZmt%xJiW6V(zwXob(5Jqm3@Y@@A{3(}dOkPPm~qc+&ZRs( zQR*Ib+o*nfTK+$FQ2qZ<)YqW?PsWd^|C49AE9FNS4k9|Y_Yisce2v5OBPd7ed=B}+ zT&J|xEDdryPeyBeD_pNck91u{b}!qLmaN7IeRTCwonn|A*pwcZ%$fPIeMMaFD>nX! z0SscO%^X0CVAQ<58g6P)hk7)i3C(E1R6-wpwfRrV;aPG{Ih-Jq%=6@FbzS@7$bZC7 zV~rEj<^cAXqtj&$AQ}_WQkM9;Uw^q}tb2o)9 zvIqSb-<6M$V~ArK(cTWx9Rl_UDi)f6JIL$IaT8_k{)a>sMRvLT+6M zVUb+Ia%6A4=L)&@owTq@rsiM#_@)q@|F_26EpNL>ZeSDJ=oP1WR_rH5A3P^+?b;ui zzK7KQf5JSBA#U2)Mf;L8+2g(uY5%8k0$IpLU)C-5r?Cfq-YsD;*Pi#;_P#g1KY~%5 z&bh_>vRlF#{ioySZ;`*>65{7>5x;NI|94B6TDT=lv!7Y^E&9z5m^MEEN&0-3d#usV z@tj=jM;<1Z_|anxI(;^}cgOzw^g_&gPO_9AW&GlM3Fec_gHkX)a*DI6jX z;|R7wUMMFkP>CvZm)snVlGQkd8uS`h?u@d}y#A+<9<}*rP(&}r{F=N$o^W~m`}DMM;!KwBgNgmVPp0pKv%b|7nL1ys z#`mrEeUJLSxV*ly`PcS^68@H=3d}BEG@}Kr zXv35;a(Y<#*JJ!UOZmQE`Hs~7KbhM9OUgf-!8rcm`GC=$fbIP0KqtB|nWg=krVUS@ z&E+@x>BE?>SGLwFV>6Yt7-P5gaz==g>%XQxlI>fRh;L=e1$GIX!-+3wGk!^$_>sEX z{rT>q+Tz>3F9=gpf%O`utUKG$D%m3^2 zLUJHm{LK`9^Tc0rgn5*F#+cgE)yCEi<%Fj?-y5E+eQ$W8BG>+kf0O=rP7-=sf?6UBd> z-kf_wI9d9>aBA^=;l#_?q0IeXFStHDoc*5gNauS(YxYgy(fzlC$CQN^qdY4(Nz#mALwfs$HXyn|1p_o{Xwqv2i#4U=%2uBrsuOyY|C3QkM5(_ zg+iZV<#i$Cq!)bwc1U9|W8A^KsY z&c7?v2Zv}4Q1U`X=$6KgxK@tdbJ_!BC3=>WJ$v#EWpowuQH<2+w^trVYk!96ef;Ui zK&kpahUmi>=~Vx3524yU$54Y>)Zuu)G~>H9VyZ*x92S_{n+Z)51Hp zBm5X&5Po5g3-@GP__YVtzN!wcT^-f4*AHlC^S=Sf8!|!@d15FQTF6sh)jxl2W@x3i zA=;~F>(kob+vXlIcc2qph|b`RujzxNM|;A}9P^LqCtl77^QF>xr93*ytJNchBl|}( z!dN839qyA3kia<%h<{NW?3Bln{Wojkp8lcXowxhds`WGJ;~DGGucW{0Eb{~z zuhVx_74=JHhbeNpBI=jQ*6*Kf?q7CD>|}@N{MTmBS-^QLqSsvHs0>)5M{Cyx3azuJ zuOK=TU}V2CDo0tR+*)O~hKtz1JNxf9nYXcn)c%|L3wP;zNc&4^1ARSjpYNB@{ywiv zT~W4Tgg$ysJwiPwi@R*(AQ$_QhkX1`_rDQ;=G*;$W%*dO^?%y?;|<0i=L2CiPSa<*l;KB=1JKJb->?3`Eu>z zqOnYUBx+ygg;2%3_HAnk$#wfNRFmEOI7X)W|L(C*G`)94-Dk;OZ}dUmcwkXKKfNAN z-+k1FKTJk_6%Fjh6Ve0Oj7epB3)zY|eWpUapvrg@b2~2g3q*U+N9SPl)vBLj0E75P z=idw+2p#V0L>GF{k70~q>X`90%w*}G$6TJgAydAPt^bewd*|P9cV&M*`dRrxoFCIj zpj+GG9NAN>{ecDgc`PD28z4F(U`V|q+PC}i{=8c^s{iKt#?pG!7r(^q3QqpyfPB;3 z0{R**Vgu`6+81)gzqKz~d&~S!_5W>ivx8miA#Gi}MHaF#Ri}N>;5(DEi_)}wJh3W` zpI84nr~fDZKk5JTU(Ozp_gLGP!=LEvpIq|9jb&j!nTLE7pb$kUMhQx>WvxOP+0-E1 zwILj&M{`^blSiWK%8lgb?7i@KS}12;w})T_S&1r~{GRXgV{7I+%fhm79b$JB)#zO= z)Bjf%j?o8qt=lg?h39lf%w1Cz}x;v)2Exb?Inf zZbgzlk2xgJS8-S9ufEG1g}cHaIn==KW1cZ>{X5#+(~b^wq6LY&NH7rZ~Z&YtXTh!33?op+?=hwI~8}j*X|aXr6Kfga?jtS{+6EYXkEVd z!igVf7qTCrk75YJ7+*aQrrD?F7Z|Te&?l{nkMA4^=jgN6&d-clOHMzJ`AY9r?j5Uh$zoLCXwqCd^bTFs(|2gIx z9+eM}o$M~}|Iz>ywc-hcQAQMKpiEg1bso z;V7zc3^kalk^Z$4X0#z^F-K2i%lnI^f1F;C{&9x8@oMQ`SrsQIaaI}Blt}j@jlCPo ziTc2!z3FTDo0R@0mBID&2FxmZXAq6;&5h~%@0SmdO|JDGQ`glGbwc~KyH$OX-N~Qm zPl?uRZ0jpfA0Ad89wMW>AlehGg_~Bip&cFQ#JX?YMXt&BddO&Rpnh@~V~ArK37o_D zwy}M(z<)bWE@E;+y<#mrEYWAp1De4yeFgLF>Ly6^sH>o_kpCDE?r5)^A$l~oc%)K3 zC68)c^o_E_58r0h{cA|xr_W%*oco)u4XOSA;v4dUgA??2i`*-aDMMmxaEOPx7dm~(%8?xy+$VD{vxu48KJ_>O8 z{I5d#U|iTxL@&nWeT#>CgcVojzaQ4lsMM}Frd@%N4($wF^e!dtD@7R&;t&qw2&S|_ zruVcn$XV@_)ck+#f5huICF!!ZYX4!mbr< zXvg}s*`b46yHWoMxixfc=puX2k70}8|1clG~RCoj?YidXPVpkeokWAG-$khBjdBJgY?PBI`?_Nr#=HFZ2S4QtGmmkK>f20qp{|waWKcOGS zXoMw$yo&U&=5(U{6iv^&7Mg$y(H*9t~(hGotyOEo5As zFFN13mEMMSM03bzo5hb#@uP&lW#R|fpJ@!**(ig`#R28vaMTBl=4hJD5Asg&s^F+!vxTfYkar{hg`xb^1Opudj>F{)^5Cj?TzElcro($Cwy1_C0J2 zoa}D1_Wu#%6Sqpg>VN(G?B%A%wPE_;dGEES4ndD2)&EfITD|vNGWNi3yu)+JbBO8{ z3*>pE&JWVokM<>8WL`q*T*5=@DeM#a0G8RUU=?e)hz)FFt1mNblWU*M3_IkyGaYxy zJ*2&^9fJo<@SmFeev*H!Po=Kb0KKdwLU zFGlz~N+y4(@6Wxd^^YGEH|hB(Kq00Yd;|Y*Cfh$C=X~QtmitQWKY-KfLt}NmJ$K{e zM5TXl$hY@@&ysy@(np6l+9iEpXi3~$6-SpZjZYPMMlnh-f4lXtWEl?P5T>N}=_=_{ zdw#ZB`qZXRAc=XT#@AYvf6dB2{e2U4(szUOO`c^w%#R}&mrl#cxU_TPA$dK0QuLifZ)cNq_t8IY>{B}{D7PC!jv>M-KzdY z&PrQz^ef}L_4=R6)xU6M|Hp0hFQm?2zi1Bs_v9tYy(ayajcDa}8``n;s(l^EHGKn} z!tj6&dt{6@`6thPDRg{^UUvf$3o)+1%#u@Yu0}&|BvFm);zn;eN2r_pjzA`VRW4N00da7-kpkRq*`k4dJ%&X6w}cn#_lM5i{o#eQ4}>Q#7KJBrJ{H<)3d7@gW;Z81y`2-LVnkDRk&cE&m@5ZA4Ex%KyOvzKHU7KP4CO;1Kvb5nyI>v1)WS7k=2Pm2S>Bu7A6*q1{{sINA7cLRWC3~2KJ8iDh+TXPqwMb_ z?tn(ip&O_7-xmA# z@AeLNld7bR|As7;6&jO|x-}dBh`f#bS#HY6e@p%{d6fLLYc)8`oKF4cKm zZ^_y055@kJe&L2+jNQT<%?V3NXVDp&w(M+dJf?kDXZ*D`Ej+lIA3JeuUuZV=e-fwI zJ=CR6HJlc{Zan(o)_vg-{SU1@Y2jb;>oM~2HGS)w`@$0rns`zGpW>#y{3>ZIEj**$ z{p?a&=uqxHr~G|h{`qYt@*?%*x zeD2DL^_Slei_RxHn=c%5C9%Z=B{8qxIH2i1gi-u~Yk!0_ypHp(zZ+9s(t>|^7K)C> z@4BXH+PIqOpR$|Dlt(R#4;%KN*|Yb|d1dRx_r>P2m9=Tg?KOK`;k0)Bn7N{p)_|QbB-R_Ut-_LMRQDC8zP4nGQ&66cV}jXmp!Aa)VzYc%88OF(@b^Mv(x7oGe74Q6u9}10sE(|ZzpYZRtv4bc5^GyFg z3zp+HKEr%QTKsL-9>sI$!El6YX{NGUR^Mp&xbZ^9Ct{1IKOVdALGm^7dVCR||9EWi zkw`C&E#6QZyYSse{$lLHmp>R={LatCE_|H+VfNP^h%J8c?%0JJ?~W~gGLmJn#c%yW z?82uG&`V<%?)Zh+VjuHEGKeqVckHjtv;hsBU7oIJMEq?pX z*oB)u99z8p!?6n|e#!m6Z{^Bdy$qgedlN8Ni{ zY=GS__+A%Y@xCu}f5%5+f0V&|$DQI2|E@2MEq>vy*aaUmS!OJ7^Y+-Ex;`sU-RB!k zmwhPq$NX?KbYlqE1#~uHr&Vj@SzXJ{+;)4Dfw9Je(0nLkrC#?eIfDV2SV~E4PpL`-+8QW)<1k_EUM=XGf$Nm&yU=GR{K5fU2abg7jDqM$8OyGjtTQS zE(Gn1Eb~7QogY3Wvz)5)TzwRCh3^h4+$JUd$d6MOuL~Dm=fAvsYC01JtduI6vh^RD9!vjcluVQ&M6a?uL}?1nK5Tv`XBM=-GpsAlFSM699}y1OR-gQ zEwYck!>hvVTP!f2kL)g*?@KPdtxs)uS6sO8iP*)+u7LjfCt_3iA#5;jMs~hw^lzhY zefCJUwp@0ID?FpVo#?#iZEnW)n;TQ84{k^LHcux}Y0SUmT4TZ4VFuHfLSy2Z(4;PK zJU1gec>WsoFa5Wx=0z=E6HYBMe^&fgxA?mKwja*EIy{ndb!fF;_oMNji#>Mnn(+9s ztJN*9cBbyt;mI2L)rT`fd*0RI>1Oxdl&Le_^;TCqIC0CnYcy$=t z&IsR;uE$%i4ikm9#^U+cnBRJh^75K6mH)0VU2t{KCEPfxPBfRD7fY;)7sc-i^Jo;- zer5c?SXzk5mp*{z{aN8;M^-r1o)sQi%L*+81+kxJe-NL;Z{TZa#pA=*gto((=6_{| zCy!=^r_fG+x;isFlam>qEs4UP8J;7b&&~`lkgU(Ljx{Sh`0>op_0@ghZ-r%5+4>5-=QI1ld(zYk@vuDS zgXD+t(5EwkW@qE=P^E1ABs94i{|nAsYb+=13x7lZ5hhix&N@42hyLF&L!W&?zsm{z zE-Hm@v3to`>D?DHLI!`b@L3% zc-p=n&(!@~?5Txp`;LA%_8jx`D<6$LOLo-n3y-_^zu|?wcZHXQ?-lgHFi+!Ym=e}F zg*ki+FF2=uJokanmy;DrmBi{1JYPpWqE>E;MG~ zfO7CxjXH}4MH_1%Hj3Zx4-)6%T}_>IcGc z&wa4&0qx%hLUZQ>;bhAL;Z)ND;i2XSLQCrd;p^nXn-7FXb{+_=dk=(1Hy#L&;qeY< zwBw2X2b=@`KzM5UfzXbp>CfO<*E-7Y56|ttKRk~YvhNR_JNJhd_wElbkuNiM<=!8@ zktZ#XuQ2zN-XD4k?+@QZpL_bN?+*ht_nRMazxfgOYy00HMwmy*)9xE9xIdgJx<8DQ z6J@?XIa&F;;p}oZ~)JYWghNiN6!|}uSh6fMb z8%`X&H#8r)H=Nx4N;uVUulA3zI_9re-s>FnuZ2grYwi46cyvsEN8Z=M<8A*c)>e3L zc%tdv@Z{pX;i;8-L;J?P(!ssqnWf6uvt9Rwj_O~HJ-2;tc>c(*#$H&uH*_BTT6nSP zU&UTpzE}IFA#}C=YU~>&|2o#4b#Hhj|K8A3B>uJhYV4aGzZ&bC{?%B2-M!|p|8DqS z{jYz8e}n%G{|CN~N70J`oWbwo-xR4I;tc*h{v-Yq{t}r#FW4wU$FXZd6?qIbs6`7} zF^%JId@Vfq`q#n&eGwHESI`6~W9F5GiCwiph_F1+#2wLAVr z>>6p}W;~B?;w=6Ee~drFnZEnNIR2de7g)z%Vd7Kwh4|<1)2X>HG&S!F$MvBRu5pCR7@=@l;$j3YPg|=bs-=2NpN%uTOwpTa@qe}ai ze6}WP|E6jGriJIp7nnQQzv%i)#5~M?#Pw0~H1}h1{j2UDCnuQW75Z1JE{$)e#>eaQ&o=1$BvbnzxSn)Jv=e|u}{1bQ*PdU4#z2Z9mU)`8|);McN-F5!|b^gD7x|loJzv%i)!$J19pj^W#&O9Z=3(|Du8)$ZxgU!g-*o>tIl&yS zFuqx3e3P82F+N&ne6+#%C^^TRV4rk-o}4?D5fXJ7<}_u5d2;GdMwmX55oXBQ`V8|$ zGt3vw2$SSlZcgWAgt6?5a3(XueA0|CRH6T}DkF@Lqulh7{mcX8Ab(zIQ=daGzKNI7 zg>Rr6FO;hf;zhiKXVHP@@I0Q%QJ=)qi0YG%AClgVNN?nm%#RdEk44fW`B<6snkl_z zORwa^%qQ44yMB^9#oTyEdUyYE@My4)F>f!@tD8 z!*AfX@H}3^DEMm${eOFD;(wa>Z(NoAqpm+jKF)nxJS{xo{wK+&m<^eSU*`8OtF!#Jvglsi z_F-koSG9q)#i!XH|Bg8#&#H`>U({qTh2uZCDm?g5MmX`^4}|8Y-fwRc{rK8}54~y+ z;&6TVdY}E~hH}Cq;nvVPaa(wF>Z9SYxk6`Cd?l>E?Ch;6ertaw_?`TUeetr)5z|II z{v~s2*>!lQb(O!Z*K5Ppm&xyX{v(l{`7^Gs-(;_^NPf_s7?J#pxd7zW545c#c_KZm zMDly))J9UpdW~HFw)HIEH*fFdjIjQCdidoizVw*`5V?6JBm7zL9{k#f+^XMi@qg<; zv?m_@Q|1M*-^LDhvGw_kuouZ+<6q+?(tNx1XSx4MM#!XRAsack30q&_&bRv@JrR`u z_-FJF<97-}<8=kfbxhzjtiQsqPwDUZNN8-#`WLa2pH?1i`c}S6@;=`#N12r;PW+lW z&OP)(|NKkJj4#B(!^U7D6awRN9jC*HjBRrh?6KCMiocW9H2o`{8ydC$nt)cbj-Pce72 zDjOev`+c{Sd8fH2lb_XR%RXAe(b250LK|<+;L&+ zs5Wl=WzP|3UaU3t*vTAykDj-$_rGl(W4_6=Z*b3fcAs$%o-@|+;);H49G`PNdZ!)w z_w_43RJIe5&3i^Z{$V;@3~z1wRG>b^vS-+jX(L1yMqVR70h<)bU@11>B_%gfWUvd8scTd@aQODx?kMxmz zmb;C8;iX09PwJogwODxJ{J!wwg87y|C(70o1gaX;qCPAdyU?7$=&ch>_6rC!W{k2BKj*yJTq7{3~Q&ufiYUyob4*G^m4 zU|qk7o1#l@qIW#*TfSK4n)m9^zx8$ZC8O}aftN4&`Qn~%Y+rKobo5Vrj~63%(R25+ z_w9~<-u?2e;~DPxfw^+Y2=ztqJ3^8M}XCwxQS z^f`L;?~V_dmvHE#;rNf$eZDQsKk=+-u3+$8TXPI>*McYVmU7psE$N(j%5 z$iHnt@+KfZ)cx#_SyUFy`OzKQhF0>f&LsI0dr|*9mE}KQGiqvf8BEdQo}u` z^KJ~se-UV)98Rm}n*kdrx7h!ny8Ts=;5#Vi#NU|8IX~n2!$fYzO+9}H_n_uKr`#%? zNcskcJUEcYB_^V||%_|wW zsp;;|KQUZ0@u>Ayks9_D(u8+tBk8X`3pM?(-b7tHjq`Pe$=sW%^D*CrTnOVaM$vhs#(MJlXepb(|w%l$Lu1_diJB&yo3$_>E4PybS7i_m_7LU2s1#~A<|?J z^JI=)LtKv`r@}2T9d^R`iEjjSBS$_<2zM3 zU-H1-08!U}Hb5gZB?O4x#oPiP`%NNE%x5$2XRm6oVzymoek#&F{PP}Gt;djbh>Mt&lhRaJNfM-xbKIy=19e8#el}A)F z?vJR?2R6ZX4=VCB@>wV;R%Dy%PPm=O-S9N#XJH%chCQ$kUWd2f9ms%e$cG{*1CQ>g zR3Yo23HA`zJ}_ZUr@YvZtuPL^@h}0tTSgn^v%|_{%%>m!A7v`?7MKpRp%s17^AWT+ zk?%n_nCRDek>|~SRZPg!H)Ja##s5%73L2Et#XlfhvG*#c<*|U%8ly6sbDkrP^F8YV z&JT1e=jY@ruVKHIrr-HFRZ7XVWa4CHL_a~{)z7@e>y`8Kmn#pbVK&^OoL_v8a{As`3QaN1`8%d7 z=YuCHk7B-y>stsa_a9228Amxv;G=cjlJgRIH`@e0X^(EsmIfI6s!2B?R*+(RR>WdAi%eBl}?J9>?jo@6~l9Bq84!mko?Y0u<9KIDN8 z3ZMuIAq`Xobp|pWw2%qekOgiFWfZ*Nf&V=(eF*a)IH41|p$pV+WAs2D^n#r>Vl(fc zR%8q9Mn@7l66_se=t#hTS_q+>W?{Y# z8Zq;l*7U;ra0Rm94*Xh>6OjeT8<8|UG&hpB|BXKE7&?vYag4PFGG7N67Scq+{jd%m zhb@pE93a0&mO>qv;q-$q2iTA!>t7CNLGsO=00(l@-RMo$^G-@6kG;SNcyt62?mFRwL$g}V;y0GivX|DGR z`e~CX-&OQs_F%sgdlRx1x9Q77^J|VP#cdq=p{23-WA{KS#~) zt6}E-Nm_|B9lyVjKAqf4H}t~DC(8pyp1e8W^k)kL`2JVG$PM2IjNEr5;PicegLebm zgc*hNZ=4M{|IGIR4C89fs`gc<0?t>52aNRO2aMcX6>$1(W5DTZ%!^jY$cDCn)3?4u zpXdSkJ7F)V;g`Kdn|X!&6Y~$M{lmO~^E0voG_IQ@?chy}|BaW7i1CbjT+g@%^XVb` z@=cO+k~!`*H%s1`TO>asObQO%BDxE=NMY(kDH^$1ig7Pl&3@+z6Qm4T&bVy_vJ!h0 zvO1OT^C4@o*AY+s<_XdOjcX@J6X@L&!~n*F6T}2&*Lbn`*qZ@qJIen2=NJdR$ol`w ztp7*0VRzu(eu(w|(CK9TKXgGi^z3E*KlJWm{1^I}?BNE_G}iyazy;<)!XOO6e@KhV zAQaOXFfx|>j{OK+k9{$$gBRc(sDzW`^MAnv!cHQOuez48L0FD?`5e)_0e1KZhHhtG z4txZM;ZumYgZCxWgB}jRFr0xO;VJ~s*183jz;`z+k&Vdd`LC*Rmf`I;s2fglza{PKjuHh&~J;Q--gr=v(Nca=0EXn zH6hIxX#ao}Y|wm&cig34)^X84YNJo&fc9b9KL>a>`hMPHw2O9)y2oe_?HqNF(O&H8 z9;5xKw11GE6})3pnIFA_`GQ=7x`*n}M&h1A9wUFWl0RF(L0)Zx4m;}{oa}p%%sAcF z@nSkNUW^Ik&5`k9zC_-PRp%&ND{dOf{UssnZN<1c(&uKJo#U30wu4CL@et`e6vF)X z5a~j?@bAIB4|^{%o^TJtR_KS{LlxNIQ%D;P;RO&v{lOk3poL7xW*vW4#7&f~5UD24 zI%F+0tPPQRWYgXd`VApc!di}E{L7G~xr|97%WFdTCPIi*V*iT#aXaTJgTwG8Tu&a2 zh6mwa*abNWro&Qr9DW6F!v=T>UWF_ug<7z~mtcf`aKO9p7x)Io&EfycmOuQ zQ?MQ004)@N8Cszq4#5dH2jjS=8(=!jgS%k`Y=(DvCww)QI06}yg~``&9@qe6IZY>Y3qJPcdmRmg@~5aO5sw?PEl3%|Y={VC8a(OezJJ1dCzmQ9u=$OzmQ z!D5($-x=zlV~iPnMV<3L@=@xkI|+CG%gGXi{DQ1?n6Oz8NqC0+H9rw=2=*$7AWSfP zMY!+b6mIn}g>bpZMC4V%+mTgscvgfN#r;lbf~Vmoj{gtt-(a2!MmP&M!-rsj^Kct{ z40iYr2*>3UuMYEOWB}ZU+bUQOv2Y7qA?_atvk3D9_#5`4*h}C!j)}%?68s(aKjT&o z+i>qh{u+7uzDekRCZltKKf|>l=s<95gYA>(>xa=n3I;$MZVCVWjyoYZoB9kL#K1MZFZHzD=s;>2( zlJcTeW~?x}p=9od83g?n#kob*9|WSqFc16~*i<-7AR2t%OZ z`|fGndph@?5wct|rz{t3*mB82W@FEZVef*t<&uZY$6kQD4*x=A5%%I__9$R4fl_1{ z_Hx`SrY)Dspyg5p)v?Q^25K?aK|OvA(1^JS^p}>40gRYUV8+h^R?IeNj$JNxXu;eH zZTLB$9dieCrm$ZDbYbp>9{gO;i@6W_W7!`8Jea*OfS(TrF%N;}688`3YvUvXGB?MG z7P2sBLrx0MAM!BgLjis|D8yU@#j!kp@Ynwd*YKSk`bb--|B+SLtCOk!sdsCUb=d21 zZ@|A1*@Rv1qW^={EZ7G#5F%-xa(%-56*sNb?o8b--a z=g3dUYV0+um(ku{Mw?(6^HG*b#g1iCnY2u*ki{HR0;Ny}@A3{h0ZeDo`~y;WKZWzY zd>fewn=tEcm}CYTFLU^P4po8URv1r^Y!+PTJOu17}%>qw6NAasP#aUF4tr(cNMBk)x) zIw$0G-uv0~y{=IIbs%@rcl&^T-~Z4TyA(k^yC_EPL|%k1nVa!BeYPf)D|=#C=QwAc z)YC_3fJSHn8)N9FVJdOmMV~N(I&}hZdf_pS-GkpI)t&y~dCpVId8!EWIsPX6j^J*f zUe3l|hJ7ya+{Cqg!1>N&zkzF*MEJS*-$i^&iE9b%{*T~p;?fYd2>%oKU&X(UW4hrO z@mwWrH}QWA_t0;3&@q1t8BN@e5hfr1rwM1Df^LBOUBtOMB}|-S`97)KB;CQ&r01KP z#U)=#?@go9ck9>EFMk#HoDuQN_(Ht$tqd$aC%(mhM?ZdEhU6PLOZ=_GKg4sH!1b6n z(0*qh0PB;C-^;bq{2cQui^ogL3sa=^rK!@!Sf=CEP-%aAl60WEUdiz`uIUG^t%Yk! zRnvz1yNCPR1G9;H9rUT`!2S1O{tIdGDcCr6DfZpm+YtV*6VI)r&rakq(taax<#3P7 zxvn92isRRD%mW>PU3wPz!ZXAIjJgG(r>TFEIZZjG(UNH;1xz z5v*VX|NfzozpP(Is%sV<&<-8YxfdNebU`=tB+R1zV;q4skbTJh2)@r2!}uR-AiYR+ z&lYv>^g$Sc3itI=&K%~dgUs1LmS8VNmf5doP6u-}E;46h2mJ|TBh*}CPR9l2a-3mK z2T~iz+I-07_$=0}rx`*htTQCTLVpExgfAdm5&nh9Te2&jUx}40}K_AtJ>_va& z^v&R%&RibsUD(yW`oNi=`|5+2SZj&BKbN^YNDp>P40A@n239bD9!y{a$3^sE&;jkB z&LwIFbuN+mZLA;3Yt`hL>Exq!@<%Osa6EZrA9-pW`RG0T{{iy}a~E#wkzVrBc=Avo z9ENT9kLUOR{5NsTZt~*&#Pu(jLq6-_n0)f`BWhm9FQ4-HIs5?s!mpd-f8@CD$gdv~ z{u_7$_qRCaJ$Rk-)p6`{&S8SHgnf&1O(w1)_!rkOi*sGawf7M|0RM@^p@CJzGerDf zb9^-M+(Ou26VAoC3e+(4m(woXA?d8&&4A1l@;_u@&W4=L^#396=$(A;j{d)k{y%;0 zLSzy4;-mEcPtyNKmQjw%FVg?N%=ibg3VSu~HTc&e>j+=(V*G>S8<9=e^@)ss)G+=* zU)%)dy}Uob3N~ooNFNRafgf!U=Z;`Hbu#fco2L$kJmc!koR}pFVEN&;jOq%_` zd*fHQCz6KAU?z=^knSglC!6OomvCRH&lPzy&n1fVkB8}m*#u7$t`C+H?=75j9q0Ks z@xDv=hl#g_IF}RdJkRkN+}q#*j{gAvEBJp!oLa(s%sFP^z6S!-xQX)v*h!q@ICe68 z%`q<${%QRGhCGIRi!fDO=g0U}HJ~ep3Mhv%D20-9cQdyY9XY6D*bT_~v~g0$x`0~z zYoHpkXEL{F8gq<7nQP>lBN>5=bwirkNra*iboKb_@Gn5-k6~^SG8cOevhVUd>8;?I zX?b?gjkycdJ^R%8+(RWiE6Tf%G2H>R+++9Hd8X*H)xEE5#9<{a3(`#7CZrL&0jb~0 z9)es$J2<$eHfY7%0(SQt_C8@wI%$7eea@ueQqtxKX?KL@@&n8zojP#ar=}(8eh+D; zkcQu57M{rr(m#OkD|i-@3HLqr9|-FuU2nzzWy0N0S*wIE@H>TlA#wf#HWB|mcpdU# zJlF6evWatSBaW%Wu@aueeH-kA58xi$jzK(eJrA!z6xS3FzlA8y^)NgErO*gzTwgWU z^E-GSO1`{F{)#N%nlv$#|2XPDWCmp`lQO2=LitB#W6wEwm*i3o^A6o5`N@?3B+5U2 z104G|C=L&houpmq%mBHIG*|-_v6TOLlz*t6M)`-@Gn9X*zeM?m#*w?^b;9aH8G}Ts z-`hKje3rDagi!ti17tbru??PumLT>Ag*M`HKs)9R=uAQX2VI!Ep$9(~^kVLV{#f*X z@ZbFjMgcKy6Nm$Kwa1{T?WBjqV8EwU5WJ6uvR>gHRI3+z2JmS=!PzE zgs~?+?Bp7EgB^1-w6ZsF3s_ixZr(f{T_$zC(VH_w~?ZV7`}~ zF?sEDsfIeJg$mrt@v91?PlYV8(}rhkyv#kFHvFyh9hj3gyiAJHL<)B?9<_xzYa5xX zwwgI>35;bs7}KV#WK*WHc;}^sFjxZ_2bc>2*<5og48aLlLw4a zARjtF{gz7_sC&w0K&G2CgDlM1kb__D(OV^t^vg#U(C*MdArwJz31fs2w=y=!_#OZia zyH#uz)PD}@KNt0%kNl5p!|vZ7tcLs#o$Nd9JV*XN%Da;`YY(V-`7I0iq!IMV1An5yOjco+TwckvvbhUMgeop1tX^V}E0 zBk&kJ3va>tOuu7_LT4p;=s;C@&Ge41VJ1UwDf;1zfSQXw7kpa^Q95v-8G zvuQl#GPSbY~FW`Jd8QZ z&KN!9)G+^Gl(BuTTOH#sxcu`Ne<5~tjK8?y8rJ_XH-NBZ4)kA6(#u795l@vH{g)Q~ zR~q^+sKZ=O*anVitU&*TqC}s>_3T3bm4f~&mFwNg_3q$$akt^#oXGubME?b?nA_H( z|4KmrwHp1`3iMxb=)Ypoe;uU!lizwM?=JFQFR~BWe}?jZ?&rRemwY%dLir!1O@*7f zKUf-lL=FAG3`obUrEbU!;`=xBZ?ot-=HixvUq0kv*6pPaoJ`+0l|FC^ecwR(!0Z!H z2BnxQ*mtL#zGoF-)jn_yaa0pm9ew6n`k)On=>yYmZo<70cf)b|z$fYZ9#Z%Hr|-M# zF~ywpm|~+2R`(LOU#1UyiM@HSw_sQICQ`ql(Lr45UZT!GsO37&;?umkJaG)Lht@HtGI#4)f8HozZ&p#%+|6xYPVMtB}xg%r>O zDtwI(7`oA%ft5F)PlE*53_IXO_znCPs-XdnKeIuxAX}gVdcX~Xa0r^{mp2a6&)>gA zsh`F;Vj$y)VeDZS%DAF4SgLfvtYu?Ohb5SHNHA-Bg5^_=`ySYeP;)y(!9(x}JOinq z2M_!Yd;mw_pKv|Tg>7Rrcf)cRVqL~y3TrZwS&OlkH5$8EtD&yh*vi@s%<3AB-i_!9 zHnX;aH5=W~g<0Lxt`onGaMps%q@O>JwILC#5eZ?fNYKxF>NTU6@aqL4SyK{+o*)*z z0AY4h4bQoGtbs5=^1G$g~`A`5lC?tFl*ItY);rLQySs1z$ zWCiw0WEJPEM%G}jMb_b8k8Hr+h-|uyt^#SmZbX{!HzO_Btw|Mxi{Ckit?7hf7?zf+`aD!(WX$u3GeK5$oLaqNbl%urOl>G$W0m#fP zyaSL~*t3y2sk{S_dD!!j1^DZbh1iRb#T;Kk{a6ZRP!1JP2~|)HHBbw6P!A2z2u+~h z&m1K%f(guE0V|6rY+PUSX1?*kMl=5Jm~+i-CG0)OyRE$;L^=r5X{WCUT^AW+_woM2 z-v$4Bf8%}!Yu#&j|1k#cg@IVc=wWas`{08u@h4eBK3osa!gk1mN-%;GK7u3gPs(l} zWi=f$&23FSR6rBhp&NeWJ%Wl;a~-?|8pwmQ@EwE^M=Zp{gRqG*F`4*of<<71HuwYl zi?}9mOcBf?>`BhOn(#6B?Sg}lfcuNMTc97NQZ8r1LMY=s!SJBw7<>i+xLpf-2=^-Z zAf34k8K5~gUeb_Ro5xBvWJZi-9B8cMQK#lR=&Lixo4a=`<33{<_Zce%31da)L|1SW zoxu*)0j8oepl+^AVcy-w@lw7YodV|CB-TGuPggUCqUHj+1nf{r?FN5dT?_=Z!F_q(2v;->NkYFFo4;=Kj0&R$~DrmnsQEf6Lvk)K=?)-?|};53&;j7?}-wTI;h?nC^b;Ik#%oSzJhdx zQp{yge2I29{)NaQC>X=MY@~mk)+qfp+B)jGtt@2r0owIQE%tO|2L2jk8usrtT$N$& zza9+mC7glzl$S`@2`>S|6`CBV13j#RFJKFP8!4Z5co+T%pTd7&4DnnG*{~lx5XmvO zK{z}EiLebmhH&E2A=97*oUjtNC*ZfBg#vKE@8KZ)9e#p~@F-USp;^v6E%ABvO(m|MZu!mojW@w#xRa%g)wuNhn=S{kMhs4_T2w{fDed{Xf)y_%#xy390u{4p_%v z9A=L+9r|zj{FVm#|41A5W;gwRXvwAj4{bH{|Dhdo2XtOS{{>x`yP;>y73%*h(u)qE z5BllnyTJoq7_k35$9Rx9)Ngd(NS>Sk6|fx&p=9hhi6ifQ3gz$+c`J}S5D#@c|03|g z5cU%C);P?6BFrB#{~5P#xPtjz*iC%x@EUHv!u|qjwTd{;VP_jb&Fi>5h}&`~#_enT zej_@@JwWJ_JxG$EdXtIIVnPw99I^=Cg3-V562XYD0jl2hWl=}W@(xDLy z5Xn7116DW;e+Ra1)Ubu4W-@7UBXp8~oaCb}@>4gmhdk&)_G0ft_LB$QNDp=|asdAn zj(ZQ5kjBkiZ#R5c-Xr&N&b_$ti8GA_M&LfKYY!OV1U$|&`V*|;*}M$ZI<9KyN59g+%q7PIy0Yh?}6+{`v0Ny|1Wh)-o;MIztGA0-%in;V@zY@m;DcD)099d z{tLOj^4v0|;>^!uD(cuuHEpDtquo+_vRmpf*O&aV{s7sumj1t+{y!LJcK0%~qtySjC0dZJm$^RDC>x4_?PoNd71aL?+#fOzySlgX_vHUxGGd>L`k&|H z-w%^8UcwAu_a&1)siY4wy~LzsfQCtnX$>YN%WYD!btWYfv@Vm9S7B1}@y~IZl-wGV zQb>Eh$ig}({B@D^`43SaL-BFiK_{uN4^m$bQ(r^H0oJk8UZ|s;Pli=E5|?7DXq#IjFqyW=X&e~!Sthg6!{L)^@>c!P5m}gDQlvt zSm)rguc6v{?*%xgyDY^SPDLsSx6m=F}|C_`2Q}B>1Uk3hxh!S>8lf8CHK@3 z$G&urBd?t)a|!QRjeWf$^D+BYh*WY+2W$NDrv*!1STN&p!HmZRGpCLH^n%z=kA3wD zAR{tZ(%CmGEjE}J-+0Lm50@_rjHOTb-RLT;|J4L3#P3bEKRBG=a<5MevH@F zL)nU8DP0}R9$CT6l|Y}6$Te<6pTPcm<8L&lyZz7c3oXuSmN+m^oR&(gvoI zU@=y(hki}4=+lD5re$sk(xM9%Gk9_L5XRlWw-{jPc#iTN-)C^$%3KG+b`w{ZBUqe< zVCjsxB7MkS&f{_gOAn;&A1~i6aL^C9`Buv<-ujWf_!g-Js++N|fBuLCKp}s^q%{+5fFn z(NzpeVMLb{9cWaF&kRb5(?$QkR4KdAq?8{WlnTOEjtnyYuT-htQL5CWmMXRGLDGQz z-!7y7s9?{y8yNpThyG&<`VaPpGbUdvCN}3ZhhO`P{^L`zp=bHOejfq{D))ogAX(R@i6lr4@>F6!%_z2#}7*d zRAR1z>Pv^2Gjo`=?}zCJAC~%&W73d>{wD_g&j|N_=s5b16X-uqi0R}BF&{V~mf;hu z|2!eK%O_~-o?t%W3BCb$0v+fHX(Nn-u8?}qHh#I#2JI#E zS}}&OXCCOm>toF@VSM`wlqTd5@6N$c)(O)H8`whQg7@$5asShGv@>{xZ70jW2(JLI z35}LTi|-(_zhTUK2IJBZw96A|52}8U166>!NyDdLH72;7`e7LP8C2XCCgrQxtNX!Q z*yrIUDVfinpO4cQc#`p1=C?IGH%aQZPnM>fsnYmTsMNeNO{!nzJGdx`YUKt|epW$h zZa_|j*>D^2FGJn~{W4$NOaSpTFOZY8v2H|X{a2)iHd7z`5zdXJK4EU;=WsJkn)_fA zyb4A){cZ5?vt(fm6E|LW8gtqhxfiKP>qr0Tk@P9O%qR7r|MZAF?VY`MMY|7sOG z*VnSeDXo@Dr7fgRaYTBgop2q29@f@WD$f0tN*A&_%p*M;`}w|%M|uzRO5Y)m^m88f zpXSU&a)AmC?&yA=1Hq*ol5`*=5ar4?EZ_KE$FSDLrD#m0H8m#Y-Zxhlns zG_CcDakWW)AJX9HkIhbj~cr`>j%vV3yLvX6kw~dK$A-Y;8vWYo`Bemg==;^uK1Q-E5Y+ zM6=XKnx!Gm%-D}vn!?SZ-)a@ZsG0fie-abYJYp8hm}apeZ86Q#Jnv6p*EUN_N~Y4f z-z;q@W^u%rrJZ;>#+apZqZz$lzS0$BX8bEh>EV2?i#bX!;rb3XOaHV?#m)73!aBq| znxhOPXcgaHGkQR?46QbcCNx(`8LsAuELDylS-D{UxWZeNf^Is0h z2K*cCTBQj${aOq2$t_|e9#f=6%t*_$JjJ@%BDRKHr8(BZ{pTtzoUhewNB^f)99&;} zLOb){a+S{1OvSmv!uO9Y=sYaavp-jH9m-XDk$qfO|5h90e-`1Dr16eeWB`2o?J|gb z5;x5}tEA1eN_wnSGGeTfxzQ@m;GVVCDj%-TR-VJW9rEml(f?beV1-q5h88JA7FD!J zG4NzBwRS6YL!MH9#wrboc}nAPt2FIu z5q(OQVu-McG1Va^ZJuI|$W|<&R_4lB#TIUrW@nyaH{>ZT$ktS=wDH^>KC84_TBO5i zrTkmPd7*{1byn#8?{Qm!76Tt75%?eye=#AU(MpHurlU!ScZ^Q zZktrPY*L}K@$9&VY57X&NE>Y$n-q^`D@_qLX^d?Zw*S%8J9vg8HmQxsS8C$&m1<=6 zWt(ITlV=XvBvWgn9chzvZMKq@(n^Q^h!iEaGFQMRI`U}2MVsXB%~$d`UoLqx=bTOY zpf@pFaoJlLyP*xkxw>$3hO|m2a>$Uc4DPUrk23lS*WeAY$*V|rtPP#EP2Rw4C0+|* z-^R@LE*j%7*MiJ}j$E6x?>K^fl)9Gu&}z3yi^WEJoBP8}Q=*r&+#)6Ypq}+F1xjYF zUbHa<^aJ(0yV}ryYm{7_9{pFVZJkq#>(z z19P?vQk`a!8f5L6ql~Q@q<)M+8b%!KPh_AU>=1p>Q88E?V%(gjm_`iD6*Gusib1Tz zW1DGU{sgQE`CKO1=e8L5lfB^{X&VMPC76m6tYvgR4- z>lr0yt5I^3jFOjPWd5H~3P^KZqEQNII~O5~30rcgT}qKGQtFWzXF4Q3&Ln9kJE+f1w3$qjrOi;ZDIJn|ls>~r z6LUw%LuX8q!+DDK7Ab`;ljz8M1-N(P-W7OEoXAd|V_$5C^y2Oc>7c$h(PlA;CpklL z=XOYc_%Y@zn$TnO3}a0)kZckY{>I}S^dU^5Paw}+Fo_j63-z}d*?Qb0Ek{j^otdQh zfQdX~;@xQy2lvcx6?mrm(Jr3aYC1Y^o5?1cE(pp z-(d&!Yk|^yuwCrXa;9Bcp^d!kFcc{5+5)A+SD@(kw{vanVr=03UQ?i$S(IX_C{V0v z4*IwbsZMrC&E5i~HnBjdODa(6cR8d18bjNq35rvBzpPf@FAn++4k?dqmkOwy*3PqP zmz@0rN^Y!M$=f(Z@?k4=bUE*}!U%^H&7*wt-bzcJBL4Y(DN`i#(tx53bSqhxJW6(u zTS+2(HR1Om>ydQHHS5qn<|9#8Y6g)Xpqu;?asu*N+T>Npn~|vZG`AzOo@2~hgYI}e z6WnlnA0B~6VG9(aXBi=`DRa<`hBJPeMR3k7x6ph;(ImL%Q;z9$A1~ zl*ace()hLoGBZutLL7Uc2HpY_>;x@r=lWY>8MlCsIQI$W`F;4LoBj1YiaL+?2=>n8 z4)k_~N>^f`(w$VO^z7;o7xadeSFg)_eSXoOA7)+@6YkoO ztxUvg32URym@3U7d>bK$=k#EjVhNne+>)v2T06veE<-U~&QSD7O;Ep*78fe%=u9&% z`;^R!&7z$$sAPqQO7;cXC=80`LLPe5{6jvaAhKW4#SJQj&QK|WVsx)1PM=cBb1XX< zO8tl4m%+};jr~fM!>3el9aL&cd`j)Eex(jsZy3us??h>Iwn|g(M09%SeN!ij5oxLz zRLn@ru8Cr82u0TyD$Tx7+P|Uf&yOB>Ypb-;5qCHSm3GUZ(oqvCojSMTJQpfmqoLA$ zIh6Jv?f;Qb>Ai#=IMS!|^IY8E8R=KNOu`yCj@~!WrwoQQ%h2UPMH4qs(rBNib1fN= zIdiON&kQJ8)7*UjVo1rcPn2B93mq%@#|M;xkap2oCNlSpc@Vf4uXQUWt^uWV?T}LD z9#G0Rx|It1fKr)@9^4U1{nsKjC81KgYpm2U$X3sB4M{^vBlf1WP|=eXh6e7xVj}vl ziDJ$jE0)bI?0=%_I){{I-;iQYnE{gWohUvSJUCW{#tbN$F&@7EF`%TUO_mJE zoX1*@ks+SH1O4A*$_?{AoRcMQrbo#?ImGiHP;~o;l)_k#QiLonVSL9mNlMe~Qs$l{ zFVODvC>;!lcQV%Ej2Tk8B53~% z4=6q7CW|XJPwCw}S^A*=kUF1~`#W!#8-nzhTTWN(=ynJd~v3;unsYRGpRZRi~*QTE$p2nOto%TQK4^hdm$ zr=K)+la9UTJW3ze(c|(duG~rJIhp50x#~19?z6X>ToZ`EsHRx@Go)AmR`(NmuI5`pDlx!r$SxI z9Qhw)P04I=pJl$({s{Ry_J(<%a6Plxhl_ops2>brv*kLZEpoP)4Rhp1%q_Wdn5WA) zn0t=cN9QmHV77EP=13dv4(P(|VZwEunL|F{{0XzAFLk!`M9gNKZ?!s$na z)BX>aLhUTpe}+r()^I8D&5}~WlwF!7<(64eF+58u56nXUHA|`w%_9HLV*kHzsoNVa zjl^Sw?@2Ec^>Qy}!<1QKoHvVi^DMqM$rz74T&$RFv9sv^hBN*bEkUA z<^@GEPbg9>sgYvc5h=E{cT2P79D@S2UPQhO zkHS;XxneH5x*3em&y`;6J=z(3H*JRWj?R$2qcbF@WG?NJxsqp?EBR0WIw%aELH~NL zXdH7TEoO$K2eGDh%nbQ0acFbrqMw~1+0$mwzn+1va)#8NoJ;>|uGFV4kcPBl(zt5@ z`jrLf=jJjeXNHt=j@6*hX${jNpi<`lKXB^|-agx3^UNRtabG&FF3v)K) zq{K@)=gfjPp%C)G2tSc0i^Jks{}M0F4^ELm+X<&u`NT+$88DgW&M0b0lVlEr=v*%sR9?B|e6 z+bFN%ee@rUdowPrLl$0opYqSR_ZHeeJD8WYm2vQ7#=RM1u3#?_|9a-5XB?b1iav<;562jH+$$#9PUaZeKj)5$b<6u=OMG9NPaYLJaks3X z{j=g-XYl38QUEz>8`Q#{}~VGdbKkHB@1(Q&8LhB2TJY^?w@POPv!nc zKVZ!n_YXx-ocsZOXYQYSDci-|{}k2$KqclXsNT#P0H_UT4FGco)Vco+7uc_YbpTDE zAHx~|FoFrpU;!)Gpc(AY0{{JfcOY~BLumVM{hf4jE+=#avHl%;rqNbDJ}SMeKj^2w*Dw-LGfhx zc)1t9A;NCNZ#H4PJL1Iy?&Ns%d-2k@^-JkBe8)RIUV8S%OZTpL>Dn4EPGqO$JY)Fr z(w_UBI7a>{ZQAenMpQid|9^@->1)0n6ORrlUaXX7%f@(gOYve_5iiE!FT{`-&)VyF zSKj(id}z{i~HCFHB{HoO8ya4ScyC+zQ#N+jaZ6gi^jYs#f+nsKq-_#IaEL;R6+H{59v!Dms;ZVum9s54bX_a z3G^w<{{!Rjdt%BZ|JRWJ!HU^7!uYR?{7?U{1=*@&?MnrHy$13>vIBePMe_e;@;|a0 zdk^lei@%fJ67oOvJK6sMJm7_a683+9K^TH+9cw)(PqmblI%Itq>an7J><5qcbt$NYyXWKL)Z<0B#Tk3v`@6e0zY?D+tN2S1jgm=IpXtgnD{ z$bd}zw2%ea(0_*O1J5O{4+b#%U~n4O2c4VW6Q})S+Iid`_t}GVonwCsWZ!Y#56OQK z`vuYmTI1f6HvAl^aCEkXPY6jHkVK3(SUv5DhxQ zOhvAPN8lgC`7E*&_m#+ZpbB$6WT<8+f*%N1hinBKbi?s8lw+iUupc8^k*ARX=zcme zPetAWF3cWSig^wENL=fXSCQM0J7FKZ0|9q(PUH~byODoD&V!FJA4GlxM_}BY+#j68 z{Ac(AzJ>|tp(ew0n0hDYhYPs>igb@w-Ld}*`;Q>J|4g{e#;pU{4S~2_2OnUbi~9u3 zpJP4^cVWK)`&G;fRX@u7IG75z;l2wmGBrW#eN5V5pWM?O~~hxrjGYBFERs} z$vjDIGUY#&@=v+UiToV>$LEr_g7Oaqpo7BIl>gE9rFiq_QgVRuKTP=_^LzB)lz*r^ z`8)aV`p>N=rS<~lALSx8vV|>?FK1hWVcy-;M0S?m9&IfIjG_T)4q=@uYZpM+{Itd`Br?Cn;aZ zM)V;~P!A1I3w2NpHBecD9s|mUnZtoBZJ?glQtu;6Drg6sq#ZCyy8x*>N;_dc?F82; z$vH&30kTGDM?fZR8!e=V9iSb{Ly?$ zE-mjl2k!ywoe8JJX`!5Rj~&oP8F%dGJ-|J+a&OJy%ojvjXxqq_hMcFO_(1*+K^BD4LvP+W(f1Uumj<*}o+iw5 za2EFf^sMU$Gj$1N0B(WX={rqF&W5?L5E3~q8o376!BThxw!uo+1W&`W@DyRU!?W-R zaleCG2IRvVxD_FHAs@qU6TFOhA3Tk@1HV4-!h7&8d<-AJ5jX~)!?T3_8hIABVg3=B zN*v?SJx_q0xZQ%R<9(5idp7LGZ4a!$y#RX?(ga?34=Qo{hW8Uwa^wj1kKqKI!|iKi z9sYWVCe4<^8n9qrhkP9}ARFF+GN^(U{7uMxoVOL(f&F#Nr!hNuCO;y3a2tfTaDNA8 z$8z7;Gcdo8)J&uPhxB=rf5^Q2Ptj7AvM5X0l%^NxGU6!@qWnW;EcHKBW3GW(;;18z`Vh+hMautW>i>v$Y5!CH!N{>DFk`lW zm1AwtjM)w?__cz6oelQ(6v{tzVs=6oe%;W6*#*6^%>Rad%x>`D=Y;{xJ{T-{SB5Iy zrOg}0dgL(HBZn~`xQm12X)8;U#fJ%FqR6#N35-438CS_1CElhM! zI4_LxmN3Z)3zOWyFv$xEll%zATegIWHav{}L>S|VVPt?XNn0Hz=?P(yfgH%C+{0iE z?*Zsf3KKWw+tZ-F2Y$yq-eclQ43l1t>qB;KWWO@#f^KLF4HE~nLkBd29a^9j%p1dK z`-X`XY@i1N7{LVUWc@TqXWm%`WY&miAq#UhFN60mAH%&0^JmBr_zLQ(?L$wccmgB^6yg=o63I943zo`&Yq2E-5smO0C##HP#sbNcwck*8< zGft=1sDHIGQ)cp8F0*8|%#m=pUFPzktUDs-!6Nm~Z;Db)(dyq~^)E*KV}tEGBA2Rv z%hbPE{?uSm>QQP?HKZC)4W|ZEL#csQ!2PfiR>5j`0M@{RuofPIb+8^1;9+>{*>h+wp zspmc0sb1%|>22zNMW*^+ZT?pOi{V_I-_WS0)wd?~sBb&fEBw~2Ufa10HRf{#YWke3 zApUuBr`*LH&bq(sh_$ORI)h@UD*3H84| zhkt(nLa6?ceve4MN2K2)N+P51i1K?x`8}fi9?=pRjYqWKBiiq@SRxnWwAk;o*zXi0 zkql@@#`v9L{7y?GatTgL{7y^!PD>?nDNalMPD}kx%Or9cPRsmG%luBU5*dqAtluft z@5C)iB!B9SA-GuoO{@Q04F8;;e@@9iXW^fS`6n)aH2xb>ql%KK`NEw>E#jvN)jP_c zIPB0Ce66H^XD1RbEEtV*M0z~-}ASy5`93_jRWigI1vUrIsUMh>1 z$>La9?2o{IM~l@%{dW~3G4qAzin=}q|0VwaW#Yfl7&VmtNiUHl^Myz4zwITev;S!? zm8J8A$Gy~lQU0V@s(SjL`!ZQJUwH8TgjuFK`=5QR#LgEUzCW2_RcHV6zgzCUJ5KIl zrbL{?slPahm*uj2rYv7B_sI%bkti#^$f-z@`{n+LFS6 zl&pGFRvqxcpsbb$JMI&T`$Y7*JRfl@}lgP-791__qUs1yPuHVn`F0oDLlX3{3r2?f@sPKKS>BhprjR&^n@gBlBDM)X{RLZdP$P_;jQ|s0rp_sCrPB- zFaJ^Uvb?-PUVcDcenMW}Brm@xFDJ>%`(%&oc|u;1SJZ@iWre)*fV_fzlf1G`UfCym zUX^5dO2@^Tj-}g)bUT@Dr_$|o zx}8b4v*~s|-7cit#dN!rZkN;TTDmQ#+x2w2k#0BB?N++2q}yt`-AT8#bX!liyXm%( zZuin{Gu?hpxBKb#Al)9O+g7?gO1H=9_AK3=r`wBkdzo&p((O&U`;_iF(p_h|>q>Xs z>8>Z;^`^VNbl0Em2GZSNx*JM&!|84$-HoQZv2-_??xxb+bh?{KceClPl$O(p@>-t*5(8_RTj?&$6x;sgCXX)-d-Cd-+%XD{@H1XeerTgx5-;?fp(|upM?@#wb z>3%rfkEHw2bU&8v$J6~px}Qq-)9HRD-8)8DO80Z=em>nVr2EBmzm)Em)BQ@iUrqOG z>Asxq*VFw*y5CIqTj{=AscjkCKGK z{Ykn%P4{O>65;+L-CrgjQr=d78%=*3Pk&oWe=DcI)zjaa>2IIYmyz^kG<_LMU&hmy ziS%VMeVIyMrqh?1^kp`EDWxxS>C1fjvXH(krY}qB%S!sPn!c>1FXi-QJ$>0oU$)bi zO8QbwUv|=$TKZB?Uv|@%M*6aszBJPpi)f`UN9oIH`f`@OoTo1r>C0vMa+SVZr!P0@ z;Zu6(NDrOqp({Ofr-z>O(3>9m(nEiG7)TF;>0u~645x>Y^e~zp#?r%hdYDKLlj&h9 zJxr&Ene;H59!lw9EyQr!)kh1PY>Jap^_e|>0u{5)Y3yeJ?y53Mtayw z56$%OIX&#BhlBKRm>y2j*YWgqB7L1qU#HX8ne=r&eO*jnm(thO^tGJ6ZlteU>FajV z|NnI-eXXUh_4Kuov;lqnoWAa-uLtStVfxxiUyst))AaQ$eZ5FOb)=s<(@$OLr-Ag- zVESn&{WP3@8c9Emr=KR$Pm}4Vne@|g`e`-&be4X){6CV799uXxkep1V$KLeVpB@L& z<6wFmPLHGMaV$NKr^ku(IGG+zFr6M}(&KD;ETzY}^f;d$7t-TmdR$76%jt0?J+7w5 zwe(m{j~nT6Gd*sl$L;i3Nsra!L+`Pc9_#6GH$67e<6e4frpM3eaX&pCq{qYb*h-H_ z>G3!{o}|aq^mvvY&(q^Ydc5@Se^CEb{m<%uQU9y@-_-xE{?GJyl^(Ct<4yYcQ~J3h z{oI*;?n*y*r=NS$&%NpAzVvf{`gtJzJeYnSN_u=&Sk@WY`^!NGn_p|i(tMre-^pD~6kMZ=6iS&=D^p8^d$5Q&oa{9+glF0eT zN&422zICQ=02p%TS(s))3>GcZ8?2gN#9n}xApXGBYoRU-?q}X z?ewjZzSYvVdiu7TzBSUfz4Wb_zI{&L_S3h6^zATxYo%{T>Dy`gc9#Bq>pwcvzqkH< zt2n6_CynCdIQ{#zlYfr;_a7(4$!T$N>ExeF>7Nt+6;~$y<0k!c(!b)$lz+wfw136< z%zvB}CoatvCv(Ng{C~8H6PFf>lSTj9=f!-M{41_3r+=;#=WE4Dxj0!*|J*3fH$P5H zyIowW6em^xiu0WxC;#kdU;byOv-aiUQq8~O{sWd@%ITN&^vg#2Wi$PCm$0uJ|?h)nkBR+-usxiy}Vj6&RVg&TKmpld)g0k zR?Ng%@xWhu+K+Hn%)S^>tr$}6<5suT{VN_=YxjRCPTH%?^lg@t_LLusckN@!;!(vVGie*0w67LRq%G!JoE1}iTy}|K zuUPb6@u>D{Xs?9!Drlx(KKp0?Niq8UUk-om|FzqN_6@%e7eh(~>CnGo9!`q6I4fp< z_;I;ClEY#-PCjmL&-}2M=V384C+$anpj`X75%#b>eKBA!kXA8~llIkO-mOCOaaK%G zETUD+wAH@#;~8@KD0gCjx+y?#W`tT{TQt4AJ^K0bGdk2 zapsX{AD3M^_pf;Dc`>b%f1R1OxK>P2OndIqub;ekos70mew`@J#@Z(zm&c3C#cnuf z?UTv$YlnYk@1#+j?6prULCvluAuFu`E)Fee|EjeYQA-47OH8Z5>% zSd3|~n5~n4ofVHP#^l{woS5NYdk)3iJ9@o5+j;u!BK>xq ze*cty??}IQrr&##zmEPk{@!PS{yhFZkbWOZzYiyWCB4FbpGtph&it`?>1_7ntn_iV z^l?`HI9vZX+c8=F<6`sUY~L-d^v8Djk8ShVUjI02w$Ca<>5s~A`lCAgN7bFx(#P4- z$65X3?BL_`Zz0poNa%c)j!S-{_`;h9}hkJ z&l?Vl8~*&Xo&M}vO7?oI4%Ml;RJZC;y{b?3s{u8rhSabcQKM>1jjIVYsixJ8T2RHj zm(_||Q)RWTHdICJsJhx!4YjA5>OdW*KYNU;$MSnDucxHu)VwmU9`oukuO9R2*;HGK zr^kGIs>-~3YRde3%)iI{d(2-v<JAzz0bJ&tc$)?<#Bx;w`=|G zns(QE-8KEL>31!2_d;EzKO6iF&r8E|((>H2W|euhtk;%#wV01gdu+_7rad+7sp(El zf68)N+-@1C#&l{qr=G)8%R2QOo?70i=kU}rPd$gHp2Jh-Q_DX!=2Pxd&*Q0Oo?7Oq zb$`lm>Ulj~RK{>>45!x3DbuOvb8>2Zo?0*7JAa;9pQqO6sr7m4b#Qv3PSu$@SInoE$~ro|RyXO-GyXIF zGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIF zGyXIFGyXIFGyXIFGyXIFGyXGvk?TLt_|N!7*Z(}@KjS~+KjS~+KjS~+KjS~+KjS~+ zKjS~+KjS~+_cL98p7EdYpYfmZ`$?HU&-l;z&-u^!&-u^!&-u^!&-u^!&-u^!&-u^! z&-u^!&-u^!&-u^!&-u^!&-u^!&-u^!eW3k$&Uwyx&Uwyx&Uwyx&Uwyx&Uwyx&Uwyx z&Uwyx&Uwyx&Uw!1c%Co#FZeI`FZeI`FZeI`FZeI`FZeI`FZeI`FZeI`FZeI`FZeI`FZeI`FZeI` zFZeI`FZeGxFF7wcFF7wcFF7wcFF7wcFF7wc{aN|*lJk=DlJk=DlJk=DlJk=DlJk=D zlJAo5lJAo5lJAo5lIxP|lIxP|lIxP|lIxP|lIxP|lIxP|lIxP|lIxP|lIxP|lIxP| zlIxP|lIxP|lIyZ?d0sC)ua}^er@d6o~vum)iuL4 z!!^S-!!^S-!?ow?+H-Zya?Ntha?Ntha?Ntha?Nt>IlJb$_MBZaU3<>1xvsq?ui38I zuGy~HuGy~HuGy~HuGy~HuGy~HuGy~HuGy~HuGy~Hu040xeAk}4YsPCvUr_$M=Dha2 zU9(=Z-Z0)U-Z0+q-SFM;-LTzo-LTxS+_2mj|BdnA82^p&-x&XmvECT#jj`Ss=Z$gR z80U>~-WcbNao!l`jWOOB&yDfi7|)II+!)V|@!S~8&1L%Q)3};a)9S##A7}sFrH?B| ze|h*Ac=Ku0%{;yuM>0MBZYA^lOH=;(>So*8KQ+2C8HK2x-$Mt($ z|EAhjb^m^x{dbo>uI&BQZ>IglS^LsJNBV2PECF~b80~?sTH-R*437(s2%lL?W;r8Qpf5r46-N)c3BT zVv0`VDXy5-y6-g7&h4VUckZ~+CFAa_7WLga>1?(a=9zKbVmmF*NWHGVch-t(&l07$ zWQkTlXR*|Jdl|(P9$>~@9|Lx!@x7~<)IGaJwQndE>yjZA)J9R?ySDywLRWs=)-e3` z{EFoiH-GOcx0l=hf&IA2n13v9&t!WaOWONh_>1MbWE`J9t~A|XdgFz&T8ag^ZbmdC zt`w{5zb*5}C7O?w<%#XwFQ(P>@V)au6&7px=8x}jK>mrmzJQSJ3sJe41p`duoN#cSzW-6Ync{x!vtq#B5*zKM7Lb|tJ;kK6MSV9?tF*K7F_)6typ6l&iurclv>#Q>ea_t< z>&M%$YrehqigoD?S-i=tUT4Kisu;6No*qw2amkCplhn0XRQpv@oO#}hxqe(K##|>Uh?c0j?;m31RjLZwJ%ZH5jQ}M=ZpZ(`+;Q#*~>+BPyu*R2WL*WY*N)AxpTvFFMB>?O7D zjnd*j_Oi2m^4&Jaci)A-`%dxX@7>dDif^tA0UmF@Jjv!{;J zQ|%xcNKl#f0H|ud`3SMm}9%sGIccE5q}rdV2N;^x2=uXYYY$ z@62Z}wdd}dGL79j&pkbAL`|zrwWUmB*UhtCH`*UnL!G4OUeouQZ?EZnS9|WAQM0O~ zETh-sdrfcG%(GoE&%GYgH=u^ql3Gz~%6A~G`lZ|F5sw?S4n~jD^O*6E^{YX}IJT;cZ_GLz zvmVBpYF~N$xN(e|cARP4b1}|4ZY<-*I$?ej?whdAz1^NC*Og^WS;q8udY&=;%#`Ao zG5=X(o@Jl4&S%YM*0N?TW7hN~>$PNlCG(iG%z37H^PRW87OjIt>u}LBmppGvt}hw$ z664BHdR`q>rdu<{HRE2h?#t#^wm!G-HmQ}xHk}b2Zn0>{fs)k$jkR7-0 zY^Ud%r@<%5^RA)nUZ>}V)ziT6qk7MKhPvme+;hF@scD)=(_@>4*EG+j)!p>;eKxeu zR_SN+{Oq>RZrfi|uJ3yZ?R)z6J!ao3IIt@0cz$kK)ko%eWO+x(NA5qmOwY&2$LHz! z#5hmN$~;ay{=|4rJpRPfcw(GB6`p+pJlpg1Y|qm3+2KpSS=qVtY)8_wok-7i9zEN6 z^K8e=vmG+ecEmi}f%0qz%Cns$&vueL+adC7N5-?A70(xDYiGo>oes}-EIiv`@N8rJ z*+%%Y4eVzd*v~ekpKU}xUzwjzh-VwT&o*SAZNNU;5Pi1s`D`Qd`3BPl;`5Ewdvlgv zY(%_#T1qb+N9m=rLrtd_-+o?v4|wr6@Wqbkm!57_oDZu}wWg}-JiYX~ZmaIaC&Ei_ zQyrui@BSA%TVMK)(~EciOTWij2QU4LYEQM4`v!*8lv++NgEMMBy?B?u42>zb4;jnQ zrMgZp!^Sjxm0m{7XT-E4mOpZlUPil=@r>@ImoeiU>ruus&NRNBUMBb^+&6Ke%x7{z zS>BXsr;XSDf8fQt?qz0H?W)uC;vM%gTT=7Nyk#AhlCCl=Tdns+Gt@JWC`f^|x zbA~(TuDM3>x&1Ov;eGhBK)x`cjAp_0#a?A@i^XM2TC#SuoW3lX-h1?A$r@U+)|cp( zt=VO>T{g01YjoLSR*Yc9bgPHT+Fx^dZB^BZdcGWcx?Ipzo?gn>>z>Ya4_G%NZ|IlJ z>GZPInO?RHz2X5?m#Y>~b6?$g-NJXRmR*irgJ_t(f$AOn((rUPPL$QKXMua3#yx}B zGl)F{bNJ?^IiftKX+GX{FP~lh+)6M0_P^{`(#rwp!A*KOw1N&zdua6?TDE=cFD;L0 zLAFfaGX5iDKk~F48RwDZ9$8uTxxbuPj>A7MCvHD67W>9u?8|T`oJW^6C%jYtMk%ORv34>DA7Q*S_)e>ZShbrT*GqRW)T^{YUCp zU8tM%YA?j=fawOzYrwSjL`VjtS9=;>y%k>VS$MTa;dRJ$Z-Lig^YMr2b>uv~j&>`L zAGPe!A+@Cr((9P<`{VOE?shNz*9p^17?+p->%@L~oiyG__f5{F*D1y+_f2i5*J+QL zcH8u-+Em6p%|30O(}&7Bm^SWd>uJV#XDn~V{j-)mJDFa+9bV^H=9ZOt%y%lwoaddl z?iQ?{1?EM|^hZhdK~vDZq zO{CWi(`~rCVQiZKer-dp)6y|*td*j+cLLDlzDECDP!3_ zRUTV0Uw@TeE0$HYj&_V`$89^N+cDl9%c*&M%{r|cXWe7#o;&ZG*FDoTP2aRmo0k9C z{QSjv-8cSy<2DCdufChUI#%=QyXLE7FR%9fzS_V0YCr9(eW$Ni#$})Bt9_%d_JzLM$NB0{ z!t1r?#Xh|^`<&iB^{8PrsSeYd@8ECt-n?}*)n|3BZqi%lfErQ_b&%d1w|wh%U*DYC zP*qh^?(Z|7zRUF1Z~k`Vz1e~H)^9rRi?{yO^k$FSn>}uCzVyA>%l78A|2AmegA;05 z?JM&byh?9FTWUMK4ZD5Va)yu7+laA_Oexn#EpOCxW5(wT+M6$EZ(~cUqAbG~v$t{g zPq=@gl-{N+d&+H7=09bO)3fPqW;4B&MwE5p%hcPP`Olf}9QVB2=f{r|TX1=CJ-scBD*k1+FSD$e$BKEamebpsb>Kt#%@?eVpNhR1DM-j>I08P}F|Y)|3aw)L}ZtQBLcczo6TYUWk5&TGc$wfI(dU)?lyW3QW6 z-D7vnXV;h-*1vB~Z+q6!=acldZ=MdfzwOT`(;isA2gY!~bii@wafim}Q2d)i@o$IL zcgwlY>bE1~I`Z1^+5C2FJsw++KAYc8tnU-II}Y{c>&%;DJ#UU@yg7#P=6J-L;}CDY zuDsc&{$^kLoBiN#j?KT>_x=89L!G8~pTF<+7QS~JsLS-;Ii@Dmbb7ag<=tL@ciXk^ zU03PdG4S{9#q{oT_}#|MyW`LAHc;Lj8-DNWRl~~T`%LF+$9uo|`+4{G0rMRysk!t% z+@0P>EOYEEy^qhN_nDLQKKn@xsfKcWZb|K>_j$K@J-o|SzR#Q2y!k9x&VsQonD2sV z7u>#JUW;97UAb?us@%Wm{w3F!*p~a1arp!P?hpL?vT2vOS1rTm-uvpBvV5O?@2fZI z-RtOmtw*_k&A8W0yLOS@ePMt1_x*jtV|-D6-!PwzrZTooxBK?}?sfCNZM|$))NXpO zbSmqxa-H6HtTW#M-s|RB_jt#{-*>l^dF&de&W-oRf^vP|df6|fcYnLz53TOx(rD|M}IQuh4heg1v^eg1v^eSYutywC6bp7;6p`S~lLG@*naa@*nd19M3+- z^C7>ss;sRl`!1e+7ti*8PqNSZe8_*u@4HGqe=^{J!U8-*fUI{~`Y&{~^EqZuyY^kpGbXkpGbXkpGbXkpGbX zkl%Nte8_*uf5?Bx?{g?0@*nd1{*+t%dUtY*zs29;Z}GSI{r$=<{uY0Wzs29;Z}GSI zefP>O{uY0Wzs29;w~dnZ0p%9IJp{SM@9$vN7nJn{W!o;f#oyv@@%#RkTl_74Jwv(0 z-{NoaxAcJgt;k3Gw(GL(x@_-CKH@*( zx0faRnd9s`MLyy`;y>a);y>a);`d!6+YZb}{73xyu(CZf`H26B|A_yX|Cs-n|Cs-n z-*#g@=0D~?=0D~?=0D~?=0D~?=0D~?=0D~?=0D~?=0E1Q-#Q=jAM+pcAM+pcAM+pc zAM+pc`;MNE`H%UJ`H%UJ`H%UJ`H%UJ`H%UJ`H%UJ`H%UJ`H%UJ`R#4WzE@>`Tk|ph zG5<0DG5;~YJyH3X-}kP3%x}9OAM>B^pYWgXpYWgXpYWgX+iu7w{3rY;{JyW{6aEwa z6aEwa6aEwa6aEwa6aEwa6aEwa6aEu^+u+%ru&fO;Ys1XiF!Krj3BSE#+1{~y!hgbV zFIl#iET8b7@SpJ8e$OZTC;TV;C;YxUX5SsNy=nP`|AgOmPCns3;XmO&;kVtNec#9@ z{3rbOyk&dd@(I8F_St^>Y}+W?cc1m-Wj%RWPhQrOm-Xaj+f3R1{A_=I){~d*)6aVH zvYx!GCok*C%X;#%p1gd@uO~0-$;*23vYxzb|9`gMA?wM@r~G>IvhP0mlwVI?){~d@ zF@>xrFYC$6 zdh)X43)yyFc8noA#*p>oWj%RWPhPgSG3&|8jyYsKdD*sL){~d@+*plb7}6 zWj%RWPhQrOm-XajJ$d_s(n| zP}Y-|9dF5c^0J=1?6^yI+$HPD%jf)h^0J=1tS2u!7L)blWj%RWPhQrOm-XajJ$YGA zUUr-&>&eS{^0M!=Sx;Wplb6r=&-v|d%IEy&{J!sI$8@q@y{uO+pYuDulYIxycK2qz zdRebt)~lD#`E4U*$HKB+z3doJ)~lE863%+{vR=Jx*KpRWm-XspyNI)1z3jMI)~lE8 zSeupS+8EUPb}-z%XT$q+h*DRvFvzL z_Psp&UY_;pWxaaY_w#HwbhaBh+kVS>^|D^QtXD7V)ysBGXT5saezmMuFYDFIdiAni zy{uO+>($E_{Cf4WV_8|RUe>FZ_3Gsde!Y5GuU^)xm+j)tdiAniy{uO+>($G8^|D^Q ztXD7F{hjsdWxaY?uU^)xmu)-b3;qlK3x3-X*>*&};Mc>K9W=|A{CfDZ-R9Z$Mb^WY z_3&jqeEE`J4_~%BJ?r7idib*Kk8JxR>*31|xMe+j*|tcw&oJxZ%eG1KCBI(2td}qA z<;#v=X1#n_FJHdozvQ>wlJ)du`x&$Sj9E`#*3*}517|&b`I28xU$#A*_4H*ueOXUm z*3*~u^kqGLSx;Zq)0g%1Wj%daPhYlQC+q3UwxP40zO1J&+dj&A`m&zBY@bio)0g%1 zWj%daPhYm}l=bvwJ$?C#|BC;LUvFQwO_lZbWxah_Z(qLRzv6dTA=`J9ZEt0V7qT9| ztj8~3@$2!+SN!_?@)f^czkJ27-!EVB>-ozLRAz@HvTgjV=P&E|%XO@3(WR~WrsVw!0d2J))$!d1!nuuvV9oYwrJKDnC;8Rwn=lbO{y<2>kG{K z0<*rrtS>O@3(Wcgv%bLWa7@-0nDqr_eSz7bne2dW))$!V56Suhv%bKrFEHy1%=V9D z`$w|gz^peg>kZ6$1G59bS$|-*FE3y7I~bgA_;2|23}%OWvYx?w!*5@A);E~-4dxqu zy@UCNU;kisNGRX%-|*`t%z6p4Uc!9Cf5U&nudgsWY?SpCW_^WOUtzxCzu~{(zu~{( z*K3&d8fLwQ`G#M=Vb*V$^&4jWhFQO1)^C{g8)p07v!26z!+*nn!+*nn!>xSyfVVYF;gQY^)YsKHe-@)I(-@)%!Y@&nTKHccx z@8Iv?w~sBf+J$bu=-}7U7ajb%`l5qhXJ2&i>+XvVejR?%!LQ3NI{0<^MF+obzv$rC z@fRKZ_8UhBzs|qt;P2qq0T>adSGI{6*Oj86Ve{!ac*{!ac*{!V`T zu|r>B*q0rh{GI%r{Pr_OC%=7-(aGP*Z=Yjy^6N>7PX11Q$AUsHVs!F%@^|vtb zPX12*PX11Q?S`SRFgp1=`8)YF42Fim&>R?@{GI%r{GI$-?4pz3{`Jr|7n@POi{>7G3r^;w96F;y4^QZf3SCg43o10Egx;sn;}m+ILPJw%XbO#7(Z#QODfBFbeY>G&DfBEw z7k?Lj7r)-6(7P0RmqPDS=v@lEOJP57=wFI1ez~fUs|vZQaC{=3c0F~s|vZQkgE#<Zp6y7^_RLbfWp`MdeM`TbU3$XbQ{&LM9V@>U^l z72W(YSK-)Tbo0wxMK^ype>cDURdn-r^J~lrIjoSw3OTHh!wUUQ(aqn@FOL=7{N4QB z{IXfm&EL)6&EL)6&EL)6&F?r&X!Hqg89n@RUEwf(*jFAs{5|{* z>4*L1;jn)6@b~cd@b~cd@M{)|9{wJFd9aWN3wf~U;qT$^;qT$^;qT$s8W3_~Atx4c zVxiF}G#Z7RSZFp1Z3Cg%DD0;X4M!m-7MhO2G1QO~3pufn6AL-9kP{0zv5*ss9)68U z(Zk=vuk|2$_>j9X}<2pP9<93wPXMK8Z5tLWwLu{_j z`uOGOqL06izmH$0E*$F%xw`1%@8j3(6*6|Ah4ztf3^DrnHIao@lIY{_{rryIhoC_S8bm*TKYu@e zKfmU+a11m0`TO}D%Zz@04Q{rvs>j#-7?fzUe;{rrw!h2I7Z&2yobAo}_H`TP0x6~q9)q(cnw z5AaJo!~nl0yU=qG1N_ntF~G0=CICza&OTVuWLMp*b)dD-OqsV}O5v-*LR~zo(A@{sDgd6CtS)gZzX15*s105rh1L z{E{1?!7v8-9dC|7{z3jh{z3jhe#f9=kbjVWkY7JW4Dt{15AqN45AthLj6r_Kt7DLV zkbjVWkbjV017i&G5AqN45AqN45AqN45Ay5t2nmvqAPM~*G05-OcMS47{vDbhV~~H4 ze~^EWe~^EWe~^EW-!bwS1>l2P){$YN{c0+S$Xbuf6WHHP?%s(-`I-=GT`H!~Dbi!~Dbi!~A*`VwiuJf0%!mf0%!mUq4R_^AGb6^AGb6 z^AGb6^AGb6^XqqxVSYUiG0d;2HHP_z`8Bu3Fu%6A80OdL8YBFgU1NlQgkRHZXnKti z{t^BWehskUcz2BOkMNK1kMNK1Yp)BD4{t^BW{t^BWeoeSB!au^V88=4w z^*zN1{|NsGzyF zy;CvDKgvJKKgvJKKgvJKKgvJK?>CoYlz)_elz)_elz)_elz)_elz)_8D`JfDkMfW5 zkMir!ic$Vi{!xCdiZRMR%0J4leOU$0J#@$1)#F@DX|F~&c}KgK`CKgO?5BgXj0_{aFi_{aFi_{aIj`N#Rk z`N#Rk`Sr!cIKRg1&>t7${IUZv&aY8B#`(wj$N9(k$N9(k$NBYy#5n&r|2Y3R|2Y3R zzc$m*;2q=qyD;B)?|h5pW>h5 zpW>h5pW@eN8dLmJ{8Ri>{8Ri>{8RjT@?wgAieGPDO!4c_iz)soegTP?;-BK5;-BK5 z;@7_yQ~Xo>Q~cBX)BKXQG0i{CKh3YlHKzHe`KS4(`KS4(`KS4(`KS4(`KS4(`KS4( z`Q@NOk6=vm>ywRX{%QVc{%QVc{%L;wvoXy-%|FdQ&99#}runD&r}_2P#x(ylzsyoh z^H1|n^H1~ZyNzjny|)VT2{#pK6egT@8<)7u()*rL{v;4FC`uk#*f0loi zf0loif0kcgbIkJ3^3U?m@{0t-EWcPl%<|9j&+-fA#4P_T|1AG3|1AG3zxY7R^3U?m z^3U?m^3U?m^3U??F^pOMS$210{;U40>6wzEbuSzFYqt$FYpTu#R9+H;?P?hdW%DEaV+pJ z@GtN$@XNS{j72Q+FY+()FY+()FY*f>#UlSA|04e)|04e)|04e)|04e)|04e)|04e) z|04e)|04e)|04e)|04e)|04e)|04e)|02J>=g{{Yi~NiHi~KSlp$|G1`4{;Y`4{;Y z`DH<3kzY6}7Wo(X7y0EwVv%3(bS&}{3<0fJ;$Pxl;uqG6CH^IT z`IV4gi6wpku2|yN=N(J@OZ-dxdX+;)AeQ)-_?P&X_?P&X_?P$vG-HWhe|RkMFYzz& zFYzz&FYzz&FYzz&FYzz&FYzz&FY_<+FY_<+FY_<+FY_<+>p72Q{$>7U{$>7Ueqpm% z=3nO5lOD_b!e_C}zs#>kJ(l^G`Iq^Z`Iq^Z`Iq_iug5a~GXFBaUiMh#U*=!tU*=!t zU*^~29?Sf)60yv`%)iX9k2{w6m-(0Zm-(0Zm-(0Zm-(0Z1jj1>D*r0~D*r0~D*r0~D*r0~D*r0~D!+_Etn#n&ukx?*%PfSC{AKL24aJMgMWj6gWnGhgnV3V@XN@B z+-Jx*#RmTd{|5gi|0cg5CWuY`P5w=OKT;5z{G0rn{G0rn{G0rn{G0rn{Bn1($-l|J z$uBb})Alt*{8j!cf0e(=U*)gzSNW^_Rery}9aa7+f0bWW zJ$Cqa_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs_;>hs z_;>hs_;>hs_;>hs_;>hs_;>hs_;>jIqD$=X@9^*N%bdmz{|^5S{|^5S{|^5S{|^5S zzr20y@bB>N@bB>N@XO%G4*w4S4*w4S4u6fm#$V&F@z?lk{5Ad>e~rJ!U*oUw*Z6Dv zHU1iZjlafUe~rJ! zU*oUw*Z6DvHU1iZjlafU-=^8I)9zN z&R^%R^Vj+7{B{01f1SV1U+1s$*ZJ%Gb^bbkoxjds=dbhE`Rn|3{yM)*d-$z|sPotP z>-=?oIrpgZ@AAvL$1eXazuz;7UH)DEU4FkP6ubO>|2ua1{RVjK^7|d|*yZ2l-{qHq zj$Qs;{$2iE{$2iEe!p!NyZpQSyZpQSyZpQSegh)>c1rB>@AB{R%TmWK|1Q5@Gm2gQ zUH)DEUH)DEU4D7%*yZ2lm%9$XO%}WSyZpQSGS0EfFUudh{C=}MWV6HXmWN+Rie3H& ze}lil-{5cXH~1U;4gLmygTKM=C-}op@JEBc!QbF-@HhBnsiVQ~H(;W{-{5cX`wf9; z@XLcogTKMw;BW9Z_#6BUe!m+N4gLmygWs<L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y z|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY z|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ z{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv z=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIz zkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y z|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY z|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ z{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv z=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIzkN*GY|BwFv=>L!Y|LFgZ{{QIz zkN*GY|BwDZ{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJ zr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c z|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUc zPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>? z|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm? zpZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v) z{y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6( zzdzWo|4;v){y+VH`v3l5zy3e{fBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6( zKmC9D|MdUq|I`1c|4;v){=Yxkum4Z~pZ-7nfBOIaXutkH{eSxZ^#AGq)BmUcPye6( zKmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp z{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7n zfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH z`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D z|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ z^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ z|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I* z>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq z|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq z)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ z|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJ zr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c z|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUc zPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>? z|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm? zpZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v) z{y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6( zKmC9D|MdUq|I`1c|4;v){=b|3H~Vk)-|WBHf3yE)|IPlJ{Wtq>_TTKk*?+VDX8+Cp zoBcQYZ}#8pzuAAY|7QQq{+sHpLJr~gm?pZ>p_ z{Wtq>_TTK+|EK@&X8+CpoBcQYZ}#8pzuAAY|7QQq{+sHpLJr~gm?pZ>qQ{dfEC_TTN-|EK@&ZomG&yZv|j@AlvAzuSMe|8D=?{=5Bm z`|tMO?Z4Z9xBqVc-Tu4%cl+=5-|fHKf4Bc`|K0w({dfEC_TTNl+kdzJZvWl>yZv|j z@AlvAzuSMe|8D=?{=5Bm`|tMO?Z4Z9xBqVc-TsID5BneXKkR?l|FHjI|HJ-={rdm( z|LOmG*#EHqVgJK^{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I* z>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq z|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq z)BmUcPye6(KmC9D|MdUq|I`1c|4;v){=cXFPy3(tKka|o|Fr*U|I_}b{ZIS#|LOmG z+W)lwY5&uH{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJ zr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c z|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUc zPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>? z|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm? zpZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v) z{y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6( zKmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp z{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7n zfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH z`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D z|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ z^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ z|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I* z>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq z|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq z)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ z|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJ zr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c z|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUc zPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>? z|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm? zpZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v) z{y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6( zKmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp z{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7n zfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH z`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D z|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ z^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ z|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I* z>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq z|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq z)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ z|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJ zr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c z|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUc zPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>? z|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm? zpZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v) z{y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6( zKmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp z{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7n zfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH z`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D z|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ z^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ z|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I* z>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq z|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq z)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ z|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJ zr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c z|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUc zPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ>pJ?El4n{eSxZ^#AGq z)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7nfBOIQ|LOnJ z|EK@&i~V2h*Z-&gPye6(KmC9D|MdUq|I`1c|4;v){y+VH`v3I*>HpLJr~gm?pZ-7n zfBOIQ|LOnJ|EK>?|DXOp{eSxZ^#AGq)BmUcPye6(KmC9D|MdUq|I`1c|4;v){y+VH z`v3I*>HpLJr~gm?@9i(&mM{Qe0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp229 z0AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPU zVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I z0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy z!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a z0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1Da zgaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!- z0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K; z2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu z0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx z5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S z1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rX zAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv z3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L& zKp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST z7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhl zfG_}I0Kx!-0SE&S1|SST7=SPUVF1Da^kM&p{U7#!*pC4S1JH;4ANGIP|6%`!{U7#! z*#BYwhy5S+f7t(F|A+k__J7#_VgHByANFGa!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S z1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rX zAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv z3_uuwFaTiy!T^K;2m=rXAPhhlfG_}k+W%?)r~RMyV*tVcgaHTx(5L;M_J7*{Y5%AF zpZ0&+|7riH{h#)K+W%?)r~RMyf7<_P|I7ZD{V)4p_P^|Z+5fWtW&g|mm;EpMU-rN3 zf7$=C|7HKn{+InP`(O6I?0?z+vj1iO%l?=BFZ*BizwCe6|FZvO|I7ZD{V)4p_P^|Z z+5fWtW&g|mm;D%kFaW*mf7$=C|7AZ0APhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1Da zgaHTx(A)mE{cro<_P_0a+yA!zZU5W;xBVD^FaW*nf7}1I|7|}8APhhlfG_}I0Kx!- z0SE&S1|SST7=SPUVF1DagaHTx(A)mE{cro<_P_0a+yA!zZU5W;xBYMX-}b-lf7}1I z|84)<{a0E7Vu z0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx z5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S z1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rX zAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv z3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST7=SPUVF1DagaHTx5C$L& zKp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhlfG_}I0Kx!-0SE&S1|SST z7=SPUVF1DagaHTx5C$L&Kp2290AT>a0E7Vu0}uuv3_uuwFaTiy!T^K;2m=rXAPhhl zfG_}I0Kx!-0SE&S2Eg0Ds;#2|L<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLaw zq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V z0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?W zL<5Kh5Dg$2Ks1180R7p18bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4Immo zG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4 zfM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCF zXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks118 z0MP)V0Yn3c2GEaxpEQ7I0MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G z0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLaw zq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V z0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?W zL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz z1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$ zhz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c z1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh z5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC? z4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1 zAR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ( z8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2 zKs1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4Immo zG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4 zfM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCF zXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks118 z0MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT z(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G z0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLaw zq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V z0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?W zL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz z1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$ zhz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c z1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh z5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC? z4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1 zAR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ( z8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2 zKs1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4Immo zG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCFXaLawq5(t$hz1Z1AR0h4 zfM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dg$2Ks1180MP)V0Yn3c1`rJ(8bCCF zXaLawq5(t$hz1Z1AR0h4fM@{G0HOgz1BeC?4ImmoG=OLT(Ey?WL<5Kh5Dj27fYAU( z0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy z07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=F zfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfP zU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR z7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|n zMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y z(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifp zG=R|nMgtfPU^IaJ!G0RRXaJ)Dj0P|oz-R!Y0gMJP8o+1(qXCQtFdD#U0HXnn1~3}H zXaJ)Dj0P|oz-R!Y0gMJP8o+1(qXCQtFdD#U0HXoykM`35MgtfPU^IZy07e5C4PZ2Y z(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifp zG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C z4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU( z0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy z07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=F zfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfP zU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR z7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|n zMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y z(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifp zG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C z4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU( z0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy z07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=F zfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfP zU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR z7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|n zMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y z(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifp zG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C z4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR7!6=FfZgn; z0gMJP8o+1(qXCQtFdD#U0HXnn1~3}HXaJ)Dj0P|oz-R!Y0gMJP8o+1(qXCQtFdD#U z0HXnn1~3}HXaJ)Dj0P|o!0z_b07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfP zU^IZy07e5C4PZ2Y(EvsR7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy07e5C4PZ2Y(EvsR z7!6=FfYAU(0~ifpG=R|nMgtfPU^IZy0QRu|VgJMahy65w(EvsR7!6<#`yci{?0?w* zu>WEI!~Tc;5BneXKkR?l|FHjI|HJ-={SW&e_CM@@*#EHqVgJMahy4%xAND`&f7t)9 z|6%{b{)hb!`yci{?0?w*u>WEI!~Tc;5BneXKkR?l|FHjI|HJ-={ZIR!_CM`^+W)lw zY5&vyr~Oa+pY}iPf7<`F|7riz{-^y<`=9nd?SI<;wEt=U)BdOZPy3(tKka|o|Fr*U z|I_}b{WO5l07e5C4PZ2Y(EvsR7!6=FfYAWppS^wi@y>tw|K9PybN!#+^{eOne-Hl0zkl$L|Ng?G85w(a!aYO5pn9`u+9A$#P5K*H;%oMXSfIWcg3^PT_t=G(>f&DY`U zn{M^`CJ4K}{ewT_oBP$TZ*IE2zPUr?`tGvI_1!gs>${Wn*LP=HukTLnUElq@b$#~( z#r54Q$m=^;!ojEZ{pI<-|M=9tyG{H0?w;D~yPJxx@9rYGesvl5`qjCf>sQ}=uU|Fi z*RP7)>sR-oU%$G+>-yDQN7rv&?m74i`^^`k>o<|b^_$ymuisreync6K=lb0hkL!1* rO|IYlEPVa$1?lzs%fGV^myWLw*I2I)7g4ScXV0$>r_Zhruf_fiFeKbq literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/tiny_t5.py b/onnxruntime/test/testdata/transformers/tiny_t5/tiny_t5.py new file mode 100644 index 0000000000000..6a25cb89f6327 --- /dev/null +++ b/onnxruntime/test/testdata/transformers/tiny_t5/tiny_t5.py @@ -0,0 +1,85 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# -------------------------------------------------------------------------- + +import os + +from sentencepiece import SentencePieceProcessor, SentencePieceTrainer +from transformers import T5Config, T5ForConditionalGeneration, T5Tokenizer + +hidden_size = 8 + +vocab_size = 1024 +save_directory = "tiny_t5" +model_name = "google-t5/t5-small" + +config = T5Config.from_pretrained(model_name) + +config.num_heads = 2 + +if vocab_size: + config.vocab_size = 1024 + +config.d_model = hidden_size +config.d_kv = hidden_size // config.num_heads +config.d_ff = hidden_size * 2 +config.num_layers = 2 +config.num_decoder_layers = config.num_layers + +model = T5ForConditionalGeneration(config) + +model.save_pretrained(save_directory) + +tokenizer = T5Tokenizer.from_pretrained(model_name, legacy=False) +tokenizer.save_pretrained(save_directory) + + +def update_tokenizer(sp_model_path: str, vocab_size: int): + sp = SentencePieceProcessor() + sp.Load(sp_model_path) + + # Export the vocabulary + with open("vocab.txt", "w", encoding="utf-8") as f: + for id in range(sp.GetPieceSize()): + piece = sp.IdToPiece(id) + score = sp.GetScore(id) + f.write(f"{piece}\t{score}\n") + + with open("vocab.txt", encoding="utf-8") as f: + vocab = [line.strip().split("\t") for line in f] + + # Sort by score in descending order and select top tokens + vocab_sorted = sorted(vocab, key=lambda x: float(x[1]), reverse=True) + pruned_vocab = vocab_sorted[:vocab_size] + + # Write the pruned vocabulary to a new file + with open("pruned_vocab.txt", "w", encoding="utf-8") as f: + for piece, score in pruned_vocab: + f.write(f"{piece}\t{score}\n") + + # Train a new SentencePiece model using the pruned vocabulary as a seed. + # Example corpus.txt can be found by searching "corpus.txt download" in search engine. + SentencePieceTrainer.Train( + f"--input=corpus.txt --model_prefix=spiece --vocab_size={vocab_size} --user_defined_symbols=pruned_vocab.txt" + ) + + # Load the new model + sp_new = SentencePieceProcessor() + sp_new.Load("spiece.model") + + # Test encoding and decoding + text = "This is an example sentence." + tokens = sp_new.EncodeAsPieces(text) + print(tokens) + + detokenized_text = sp_new.DecodePieces(tokens) + print(detokenized_text) + + # Replace the original model. + os.replace("spiece.model", sp_model_path) + + +if vocab_size: + original_path = os.path.join(save_directory, "spiece.model") + update_tokenizer(original_path, vocab_size) diff --git a/onnxruntime/test/testdata/transformers/tiny_t5/tokenizer_config.json b/onnxruntime/test/testdata/transformers/tiny_t5/tokenizer_config.json new file mode 100644 index 0000000000000..da3a2f5a033d6 --- /dev/null +++ b/onnxruntime/test/testdata/transformers/tiny_t5/tokenizer_config.json @@ -0,0 +1,940 @@ +{ + "add_prefix_space": true, + "added_tokens_decoder": { + "0": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "1": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "2": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32000": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32001": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32002": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32003": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32004": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32005": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32006": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32007": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32008": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32009": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32010": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32011": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32012": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32013": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32014": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32015": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32016": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32017": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32018": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32019": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32020": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32021": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32022": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32023": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32024": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32025": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32026": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32027": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32028": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32029": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32030": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32031": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32032": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32033": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32034": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32035": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32036": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32037": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32038": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32039": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32040": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32041": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32042": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32043": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32044": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32045": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32046": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32047": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32048": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32049": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32050": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32051": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32052": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32053": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32054": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32055": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32056": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32057": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32058": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32059": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32060": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32061": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32062": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32063": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32064": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32065": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32066": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32067": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32068": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32069": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32070": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32071": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32072": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32073": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32074": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32075": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32076": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32077": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32078": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32079": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32080": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32081": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32082": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32083": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32084": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32085": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32086": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32087": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32088": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32089": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32090": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32091": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32092": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32093": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32094": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32095": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32096": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32097": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32098": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + }, + "32099": { + "content": "", + "lstrip": false, + "normalized": false, + "rstrip": false, + "single_word": false, + "special": true + } + }, + "additional_special_tokens": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "clean_up_tokenization_spaces": true, + "eos_token": "", + "extra_ids": 100, + "legacy": false, + "model_max_length": 512, + "pad_token": "", + "sp_model_kwargs": {}, + "tokenizer_class": "T5Tokenizer", + "unk_token": "" +} diff --git a/tools/ci_build/requirements/transformers-test/requirements.txt b/tools/ci_build/requirements/transformers-test/requirements.txt index 14aeff3df9c62..0fb37e3a1550a 100644 --- a/tools/ci_build/requirements/transformers-test/requirements.txt +++ b/tools/ci_build/requirements/transformers-test/requirements.txt @@ -8,5 +8,6 @@ torch coloredlogs==15.0 transformers==4.46.3 parameterized>=0.8.1 +sentencepiece psutil einops From 3012d445f1e3ded81d2e011428c385076ef7d87c Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Sun, 23 Mar 2025 19:14:25 -0400 Subject: [PATCH 150/266] Update package.json to make the dist avaliable again (#23991) ### Description Adding back missing dist folder ### Motivation and Context --- js/react_native/e2e/src/App.tsx | 2 +- js/react_native/package-lock.json | 2608 ++++++++++++----- js/react_native/package.json | 29 +- .../react-natvie-andriod-e2e-test-job.yml | 54 +- .../steps/react-native-bootstrap-steps.yml | 25 + .../templates/react-native-ci.yml | 50 +- 6 files changed, 1873 insertions(+), 895 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/stages/jobs/steps/react-native-bootstrap-steps.yml diff --git a/js/react_native/e2e/src/App.tsx b/js/react_native/e2e/src/App.tsx index 1045bb1c0e2ce..2d8d57b576991 100644 --- a/js/react_native/e2e/src/App.tsx +++ b/js/react_native/e2e/src/App.tsx @@ -44,7 +44,7 @@ export default class App extends React.PureComponent<{}, State> { // test creating session with path console.log('Creating with path'); const pathSession: InferenceSession = await InferenceSession.create(modelPath); - pathSession.release(); + void pathSession.release(); // and with bytes console.log('Creating with bytes'); diff --git a/js/react_native/package-lock.json b/js/react_native/package-lock.json index 3c23bc1523bd8..0c797ca2a2a16 100644 --- a/js/react_native/package-lock.json +++ b/js/react_native/package-lock.json @@ -9,7 +9,8 @@ "version": "1.22.0", "license": "MIT", "dependencies": { - "buffer": "^6.0.3" + "buffer": "^6.0.3", + "onnxruntime-common": "file:../common" }, "devDependencies": { "@react-native/typescript-config": "0.73.1", @@ -17,7 +18,8 @@ "pod-install": "^0.1.36", "prettier": "^2.8.8", "react": "^18.2.0", - "react-native": "^0.73.11" + "react-native": "^0.73.11", + "react-native-builder-bob": "^0.37.0" }, "engines": { "node": ">=18" @@ -30,7 +32,6 @@ "../common": { "name": "onnxruntime-common", "version": "1.22.0", - "extraneous": true, "license": "MIT", "devDependencies": { "typedoc": "^0.25.7" @@ -76,9 +77,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "engines": { @@ -174,29 +175,16 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -244,12 +232,15 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.17.12", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -259,31 +250,30 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.1", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "resolve": "^1.14.2" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.4", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -295,54 +285,11 @@ } }, "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", @@ -373,16 +320,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -415,15 +361,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", - "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-wrap-function": "^7.25.0", - "@babel/traverse": "^7.25.0" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -450,20 +396,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", @@ -478,17 +410,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", @@ -510,9 +431,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -520,15 +441,15 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", - "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -564,13 +485,15 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.17.12", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -579,114 +502,81 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.17.12", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.17.12" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.17.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-remap-async-to-generator": "^7.16.8", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.0", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.12.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-proposal-export-default-from": { + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", - "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { + "node_modules/@babel/plugin-proposal-async-generator-functions": { "version": "7.17.12", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { "node": ">=6.9.0" @@ -695,14 +585,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.17.12", + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -711,14 +603,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.17.12", + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", + "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -815,14 +707,49 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.17.12", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", + "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -831,16 +758,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.17.12", + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -849,24 +774,56 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.17.12", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", "dev": true, "license": "MIT", "dependencies": { @@ -876,34 +833,40 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { + "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "dev": true, "license": "MIT", @@ -914,10 +877,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-export-default-from": { + "node_modules/@babel/plugin-syntax-typescript": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", - "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -930,26 +893,31 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", - "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -958,13 +926,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" }, "engines": { "node": ">=6.9.0" @@ -973,24 +944,32 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -999,80 +978,119 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.12.0" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1081,13 +1099,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1096,26 +1115,31 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1124,16 +1148,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1142,13 +1164,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1157,12 +1180,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", + "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-flow": "^7.26.0" }, "engines": { "node": ">=6.9.0" @@ -1171,19 +1197,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "globals": "^11.1.0" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1192,12 +1214,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1206,14 +1232,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1222,14 +1248,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1238,13 +1264,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1253,14 +1280,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1269,15 +1296,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz", - "integrity": "sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/plugin-syntax-flow": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1286,13 +1313,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.1", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1301,14 +1330,17 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1317,12 +1349,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1331,30 +1366,31 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.18.0", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1363,15 +1399,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.18.2", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-simple-access": "^7.18.2", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1380,17 +1415,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.18.0", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-identifier": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1399,14 +1431,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.0", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1415,28 +1449,31 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1445,14 +1482,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1462,13 +1500,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1513,12 +1551,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.16.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1528,11 +1567,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.16.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", + "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1542,15 +1583,33 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.17.12", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-jsx": "^7.17.12", - "@babel/types": "^7.17.12" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", + "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1591,16 +1650,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", + "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "regenerator-transform": "^0.15.2" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1609,13 +1667,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1624,57 +1684,58 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz", - "integrity": "sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==", + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", - "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz", + "integrity": "sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.3", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs3": { @@ -1691,50 +1752,47 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", - "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { - "node": ">=6.0" + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1743,13 +1801,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-strict-mode": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-strict-mode/-/plugin-transform-strict-mode-7.25.9.tgz", + "integrity": "sha512-DplEwkN9xt6XCz/4oC9l8FJGn7LnOGPU7v08plq+OclMT55zAR9lkX7QIbQ9XscvvJNYpLUfYO4IYz/7JGkbXQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1758,12 +1817,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1772,13 +1833,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.2", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz", + "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1787,13 +1849,18 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.17.12", + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", + "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1802,14 +1869,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.18.1", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-typescript": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1818,13 +1885,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1834,12 +1903,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1848,87 +1919,99 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/preset-env": { - "version": "7.18.2", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.17.12", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.17.12", - "@babel/plugin-proposal-async-generator-functions": "^7.17.12", - "@babel/plugin-proposal-class-properties": "^7.17.12", - "@babel/plugin-proposal-class-static-block": "^7.18.0", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.17.12", - "@babel/plugin-proposal-json-strings": "^7.17.12", - "@babel/plugin-proposal-logical-assignment-operators": "^7.17.12", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.18.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.17.12", - "@babel/plugin-proposal-private-methods": "^7.17.12", - "@babel/plugin-proposal-private-property-in-object": "^7.17.12", - "@babel/plugin-proposal-unicode-property-regex": "^7.17.12", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.17.12", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.17.12", - "@babel/plugin-transform-async-to-generator": "^7.17.12", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.17.12", - "@babel/plugin-transform-classes": "^7.17.12", - "@babel/plugin-transform-computed-properties": "^7.17.12", - "@babel/plugin-transform-destructuring": "^7.18.0", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.17.12", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.18.1", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.17.12", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.18.0", - "@babel/plugin-transform-modules-commonjs": "^7.18.2", - "@babel/plugin-transform-modules-systemjs": "^7.18.0", - "@babel/plugin-transform-modules-umd": "^7.18.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.12", - "@babel/plugin-transform-new-target": "^7.17.12", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.17.12", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.18.0", - "@babel/plugin-transform-reserved-words": "^7.17.12", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.17.12", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.18.2", - "@babel/plugin-transform-typeof-symbol": "^7.17.12", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.2", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "core-js-compat": "^3.22.1", - "semver": "^6.3.0" + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.40.0", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -1938,13 +2021,15 @@ } }, "node_modules/@babel/preset-flow": { - "version": "7.17.12", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", + "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-flow-strip-types": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1954,29 +2039,53 @@ } }, "node_modules/@babel/preset-modules": { - "version": "0.1.5", + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz", + "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-react-display-name": "^7.25.9", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/plugin-transform-react-jsx-development": "^7.25.9", + "@babel/plugin-transform-react-pure-annotations": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/preset-typescript": { - "version": "7.17.12", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.17.12" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2235,8 +2344,46 @@ "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/@react-native-community/cli": { @@ -3000,6 +3147,20 @@ "node": ">=0.4.0" } }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/anser": { "version": "1.4.10", "dev": true, @@ -3089,6 +3250,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -3134,51 +3305,105 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", + "node_modules/babel-plugin-module-resolver": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz", + "integrity": "sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-babel-config": "^2.1.1", + "glob": "^9.3.3", + "pkg-up": "^3.1.0", + "reselect": "^4.1.7", + "resolve": "^1.22.8" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { - "object.assign": "^4.1.0" + "balanced-match": "^1.0.0" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.1", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.3", + "semver": "^6.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.1", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1" + "@babel/helper-define-polyfill-provider": "^0.6.3" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-transform-flow-enums": { @@ -3272,9 +3497,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -3292,10 +3517,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -3349,18 +3574,6 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -3397,6 +3610,16 @@ "node": ">=4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "5.3.1", "dev": true, @@ -3406,9 +3629,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001660", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", - "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "version": "1.0.30001704", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001704.tgz", + "integrity": "sha512-+L2IgBbV6gXB4ETf0keSvLr7JUrRVbIaB/lrQ1+z8mRcQiisG5k+lG6O4n6Y5q6f5EuNfaYXKgymucphlEXQew==", "dev": true, "funding": [ { @@ -3460,19 +3683,6 @@ "node": ">=12.13.0" } }, - "node_modules/chrome-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/chromium-edge-launcher": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", @@ -3488,19 +3698,6 @@ "rimraf": "^3.0.2" } }, - "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/chromium-edge-launcher/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -3519,6 +3716,16 @@ "dev": true, "license": "MIT" }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3707,13 +3914,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", + "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "browserslist": "^4.24.4" }, "funding": { "type": "opencollective", @@ -3836,6 +4043,13 @@ "node": ">=0.10.0" } }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -3859,19 +4073,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-properties": { - "version": "1.1.4", + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", "dev": true, "license": "MIT", "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/denodeify": { @@ -3917,6 +4139,19 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3925,9 +4160,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.24", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", - "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==", + "version": "1.5.118", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.118.tgz", + "integrity": "sha512-yNDUus0iultYyVoEFLnQeei7LOQkL8wg8GQpkPCRrOlJXlcCwa6eGKZkxQ9ciHsqZyYbj8Jd94X1CTPzGm+uIA==", "dev": true, "license": "ISC" }, @@ -3946,6 +4181,26 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/envinfo": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", @@ -4008,6 +4263,19 @@ "dev": true, "license": "MIT" }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/esprima": { "version": "4.0.1", "dev": true, @@ -4022,9 +4290,10 @@ }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4088,6 +4357,23 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-xml-parser": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", @@ -4107,6 +4393,16 @@ "fxparser": "src/cli/cli.js" } }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.1", "dev": true, @@ -4145,6 +4441,16 @@ "node": ">= 0.8" } }, + "node_modules/find-babel-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.2.tgz", + "integrity": "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.3" + } + }, "node_modules/find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -4305,9 +4611,14 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -4325,19 +4636,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -4370,6 +4668,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/globals": { "version": "11.12.0", "dev": true, @@ -4378,22 +4689,32 @@ "node": ">=4" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "dev": true, - "license": "ISC" - }, - "node_modules/has": { - "version": "1.0.3", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.1" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "dev": true, + "license": "ISC" + }, "node_modules/has-flag": { "version": "4.0.0", "dev": true, @@ -4402,26 +4723,17 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, "node_modules/hermes-estree": { @@ -4491,6 +4803,16 @@ "node": ">= 0.8" } }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "funding": [ @@ -4509,6 +4831,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/image-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", @@ -4521,8 +4853,25 @@ "bin": { "image-size": "bin/image-size.js" }, - "engines": { - "node": ">=16.x" + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { @@ -4533,6 +4882,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "dev": true, @@ -4557,17 +4916,36 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "dev": true, "license": "MIT" }, "node_modules/is-core-module": { - "version": "2.9.0", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4599,6 +4977,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "dev": true, @@ -4607,6 +4995,124 @@ "node": ">=8" } }, + "node_modules/is-git-dirty": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-git-dirty/-/is-git-dirty-2.0.2.tgz", + "integrity": "sha512-U3YCo+GKR/rDsY7r0v/LBICbQwsx859tDQnAT+v0E/zCDeWbQ1TUt1FtyExeyik7VIJlYOLHCIifLdz71HDalg==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^4.0.3", + "is-git-repository": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-git-dirty/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/is-git-dirty/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-git-repository": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-git-repository/-/is-git-repository-2.0.0.tgz", + "integrity": "sha512-HDO50CG5suIAcmqG4F1buqVXEZRPn+RaXIn9pFKq/947FBo2bCRwK7ZluEVZOy99a4IQyqsjbKEpAiOXCccOHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^4.0.3", + "is-absolute": "^1.0.0" + } + }, + "node_modules/is-git-repository/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/is-git-repository/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -4617,6 +5123,26 @@ "node": ">=8" } }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4630,6 +5156,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-stream": { "version": "2.0.1", "dev": true, @@ -4641,6 +5180,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -4654,6 +5206,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -4788,6 +5350,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4848,6 +5417,13 @@ "marky": "^1.2.2" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/locate-path": { "version": "5.0.0", "dev": true, @@ -4985,6 +5561,13 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -5034,6 +5617,16 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/metro": { "version": "0.80.12", "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.12.tgz", @@ -5752,6 +6345,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -5871,9 +6474,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, @@ -5948,31 +6551,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -6018,6 +6596,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/onnxruntime-common": { + "resolved": "../common", + "link": true + }, "node_modules/open": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", @@ -6090,6 +6672,22 @@ "node": ">=8" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "dev": true, @@ -6098,6 +6696,38 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -6111,28 +6741,65 @@ "node_modules/path-exists": { "version": "4.0.0", "dev": true, - "license": "MIT", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -6167,6 +6834,69 @@ "node": ">= 6" } }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/pod-install": { "version": "0.1.36", "dev": true, @@ -6239,6 +6969,17 @@ "dev": true, "license": "MIT" }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -6249,6 +6990,27 @@ "inherits": "~2.0.3" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -6344,6 +7106,172 @@ "react": "18.2.0" } }, + "node_modules/react-native-builder-bob": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/react-native-builder-bob/-/react-native-builder-bob-0.37.0.tgz", + "integrity": "sha512-CkM4csFrYtdGJoRLbPY6V8LBbOxgPZIuM0MkPaiOI2F/ASwxMAzoJu9wBw8Pyvx1p27XnrIEKPyDiTqimJ7xbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-transform-strict-mode": "^7.24.7", + "@babel/preset-env": "^7.25.2", + "@babel/preset-flow": "^7.24.7", + "@babel/preset-react": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "babel-plugin-module-resolver": "^5.0.2", + "browserslist": "^4.20.4", + "cosmiconfig": "^9.0.0", + "cross-spawn": "^7.0.3", + "dedent": "^0.7.0", + "del": "^6.1.1", + "escape-string-regexp": "^4.0.0", + "fs-extra": "^10.1.0", + "glob": "^8.0.3", + "is-git-dirty": "^2.0.1", + "json5": "^2.2.1", + "kleur": "^4.1.4", + "metro-config": "^0.80.9", + "prompts": "^2.4.2", + "which": "^2.0.2", + "yargs": "^17.5.1" + }, + "bin": { + "bob": "bin/bob" + }, + "engines": { + "node": ">= 20.0.0" + } + }, + "node_modules/react-native-builder-bob/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/react-native-builder-bob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/react-native-builder-bob/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-native-builder-bob/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-native-builder-bob/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/react-native-builder-bob/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/react-native-builder-bob/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/react-native-builder-bob/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react-native-builder-bob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/react-native/node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -6784,11 +7712,15 @@ }, "node_modules/regenerate": { "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.0.1", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "license": "MIT", "dependencies": { @@ -6809,48 +7741,59 @@ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.8.4" } }, "node_modules/regexpu-core": { - "version": "5.0.1", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { "node": ">=4" } }, "node_modules/regjsgen": { - "version": "0.6.0", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", "dev": true, "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.8.4", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" } }, "node_modules/require-directory": { @@ -6868,22 +7811,44 @@ "dev": true, "license": "ISC" }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve": { - "version": "1.22.0", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -6898,6 +7863,17 @@ "node": ">=8" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -6915,6 +7891,30 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "dev": true, @@ -7506,8 +8506,20 @@ "node": ">=8" } }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", "engines": { @@ -7516,6 +8528,8 @@ }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -7527,7 +8541,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, "license": "MIT", "engines": { @@ -7535,13 +8551,25 @@ } }, "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.0.0", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7553,9 +8581,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -7573,8 +8601,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/js/react_native/package.json b/js/react_native/package.json index 253f7e24cf7ed..4ac4fa79d49fc 100644 --- a/js/react_native/package.json +++ b/js/react_native/package.json @@ -25,7 +25,8 @@ "pod-install": "^0.1.36", "prettier": "^2.8.8", "react": "^18.2.0", - "react-native": "^0.73.11" + "react-native": "^0.73.11", + "react-native-builder-bob": "^0.37.0" }, "peerDependencies": { "react": "*", @@ -60,17 +61,35 @@ ], "description": "ONNX Runtime bridge for react native", "repository": "https://github.com/Microsoft/onnxruntime.git", + "react-native-builder-bob": { + "source": "lib", + "targets": [ + "commonjs", + "module", + [ + "typescript", + { + "project": "tsconfig.build.json", + "tsc": "../node_modules/.bin/tsc" + } + ] + ], + "output": "dist" + }, "dependencies": { - "buffer": "^6.0.3" + "buffer": "^6.0.3", + "onnxruntime-common": "file:../common" }, "scripts": { "typescript": "tsc --noEmit", - "bootstrap": "npm run pack-common && npm run unpack-common && npm run pack-libs && npm run unpack-libs && npm run e2e && npm run pods", + "prepare": "bob build", + "bootstrap-no-pods": "npm run pack-common && npm run unpack-common && npm run pack-libs && npm run unpack-libs && npm run e2e", + "bootstrap": "npm run bootstrap-no-pods && npm run pods", "test": "jest", "pack-common": "cd ../common && npm pack && mv -f onnxruntime-common-*.tgz ../react_native/e2e/onnxruntime-common.tgz", - "unpack-common": "cd e2e && npm install --no-save ./onnxruntime-common.tgz", + "unpack-common": "npm --prefix e2e install ./e2e/onnxruntime-common.tgz", "pack-libs": "npm pack --ort-js-pack-mode=e2e && mv -f onnxruntime-react-native-*.tgz e2e/onnxruntime-react-native.tgz", - "unpack-libs": "cd e2e && npm install --no-save ./onnxruntime-react-native.tgz", + "unpack-libs": "npm --prefix e2e install ./e2e/onnxruntime-react-native.tgz", "prepack": "tsc --build ./tsconfig.scripts.json && node ./scripts/prepack", "pods": "cd e2e && npx pod-install --quiet", "e2e": "npm --prefix e2e install" diff --git a/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml b/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml index ed7d77246e862..5f5628a4326d3 100644 --- a/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml +++ b/tools/ci_build/github/azure-pipelines/stages/jobs/react-natvie-andriod-e2e-test-job.yml @@ -44,9 +44,8 @@ jobs: versionSpec: '20.x' - script: | - sudo apt install coreutils ninja-build nodejs npm yarn - npm install --global yarn - displayName: Install coreutils, ninja, npm, and yarn + sudo apt install ninja-build + displayName: Install ninja - task: DownloadPipelineArtifact@2 inputs: @@ -62,44 +61,7 @@ jobs: targetFolder: $(Build.SourcesDirectory)/js/react_native/android/libs displayName: Copy Android package to React Native directory - - script: | - npm ci - workingDirectory: '$(Build.SourcesDirectory)/js' - displayName: npm ci js - - - script: | - npm ci - workingDirectory: '$(Build.SourcesDirectory)/js/common' - displayName: npm ci js/common - - - script: | - yarn - workingDirectory: '$(Build.SourcesDirectory)/js/react_native' - displayName: yarn js/react_native - - - task: PowerShell@2 - inputs: - filePath: '$(Build.SourcesDirectory)/tools/ci_build/github/js/pack-npm-packages.ps1' - arguments: '"-dev.$(Get-Date -Format yyyyMMdd)-$(git rev-parse --short HEAD)" $(Build.SourcesDirectory) react_native' - workingDirectory: '$(Build.SourcesDirectory)' - errorActionPreference: stop - env: - ORT_JS_PACK_MODE: e2e - displayName: Pack NPM packages - - - script: | - mv $(Build.SourcesDirectory)/js/common/onnxruntime-common*.tgz onnxruntime-common.tgz - yarn add --no-lockfile file:./onnxruntime-common.tgz - mv $(Build.SourcesDirectory)/js/react_native/onnxruntime-react-native*.tgz onnxruntime-react-native.tgz - yarn add --no-lockfile file:./onnxruntime-react-native.tgz - yarn - workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' - displayName: Bootstrap Android and iOS e2e tests - - - script: | - yarn add --dev jest-junit - workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' - displayName: install jest junit reporter js/react_native/e2e + - template: steps/react-native-bootstrap-steps.yml - script: | keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -storepass android \ @@ -114,15 +76,6 @@ jobs: targetFolder: $(Build.SourcesDirectory)/js/react_native/e2e/android/app/libs displayName: Copy Android package to Android e2e test directory - - script: | - yarn global add detox-cli - echo "Path: $PATH" - echo "##vso[task.prependpath]$(yarn global bin)" - echo "Updated PATH: $PATH" - echo "Detox bin directory: $(yarn global bin)" - ls $(yarn global bin) - displayName: Install detox cli tools and prepend to PATH - - script: | detox build --configuration android.emu.release workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' @@ -199,6 +152,7 @@ jobs: contents: onnxruntime-react-native*.tgz targetFolder: $(Build.ArtifactStagingDirectory) displayName: Create Artifacts onnxruntime-react-native + - ${{ if eq(parameters.is1ES, true) }}: - task: 1ES.PublishPipelineArtifact@1 inputs: diff --git a/tools/ci_build/github/azure-pipelines/stages/jobs/steps/react-native-bootstrap-steps.yml b/tools/ci_build/github/azure-pipelines/stages/jobs/steps/react-native-bootstrap-steps.yml new file mode 100644 index 0000000000000..d0deb57cbf303 --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/stages/jobs/steps/react-native-bootstrap-steps.yml @@ -0,0 +1,25 @@ +steps: +- script: + npm install -g detox-cli + displayName: Install detox cli tools + +- script: | + npm ci + workingDirectory: '$(Build.SourcesDirectory)/js' + displayName: npm ci js + +- script: | + npm ci + workingDirectory: '$(Build.SourcesDirectory)/js/common' + displayName: npm ci js/common + +- script: | + npm ci + npm run bootstrap-no-pods + workingDirectory: '$(Build.SourcesDirectory)/js/react_native' + displayName: bootstrap react_native + +- script: | + npm install --save-dev jest-junit + workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' + displayName: install jest junit reporter js/react_native/e2e \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index c1309d345d819..c4de3271f5ca9 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -120,11 +120,6 @@ stages: - script: brew install coreutils ninja npm displayName: Install coreutils, ninja, npm - - - script: - npm install -g detox-cli - displayName: Install detox cli tools - - script: brew tap wix/brew displayName: brew tap wix/brew @@ -133,50 +128,7 @@ stages: brew install applesimutils displayName: Install applesimutils tools required by detox ios - - script: | - npm ci - workingDirectory: '$(Build.SourcesDirectory)/js' - displayName: npm ci js - - - script: | - npm ci - workingDirectory: '$(Build.SourcesDirectory)/js/common' - displayName: npm ci js/common - - - script: | - npm install - workingDirectory: '$(Build.SourcesDirectory)/js/react_native' - displayName: npm install js/react_native - - - task: PowerShell@2 - inputs: - filePath: '$(Build.SourcesDirectory)/tools/ci_build/github/js/pack-npm-packages.ps1' - arguments: '"-dev.$(Get-Date -Format yyyyMMdd)-$(git rev-parse --short HEAD)" $(Build.SourcesDirectory) react_native' - workingDirectory: '$(Build.SourcesDirectory)' - errorActionPreference: stop - env: - ORT_JS_PACK_MODE: e2e - displayName: Pack NPM packages - - - script: | - set -e -x - npm install - ls node_modules - mv $(Build.SourcesDirectory)/js/common/onnxruntime-common*.tgz onnxruntime-common.tgz - mv $(Build.SourcesDirectory)/js/react_native/onnxruntime-react-native*.tgz onnxruntime-react-native.tgz - npm install ./onnxruntime-common.tgz - ls node_modules/onnxruntime* - npm install ./onnxruntime-react-native.tgz - ls node_modules/onnxruntime* - - - workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' - displayName: Bootstrap Android and iOS e2e tests - - - script: | - npm install --save-dev jest-junit - workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' - displayName: install jest junit reporter js/react_native/e2e + - template: ../stages/jobs/steps/react-native-bootstrap-steps.yml - script: | ORT_C_LOCAL_POD_PATH=$(Build.BinariesDirectory)/ios-full-pod/onnxruntime-c \ From 2b3d7fb1e1a389abaeea5781d23d4f9491c0651f Mon Sep 17 00:00:00 2001 From: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com> Date: Sun, 23 Mar 2025 19:43:09 -0700 Subject: [PATCH 151/266] Fix attention QK linkage error (#24134) ### Description This PR moves the CUDA memcpy for the QK output when type `T` is equal to type `QK` from `attention_impl.cu` into `attention_qk.cu`. ### Motivation and Context This PR fixes a linkage error when type `T` and type `QK` are the same in `attention_qk.cu`. --- .../contrib_ops/cuda/bert/attention_impl.cu | 8 ++----- .../contrib_ops/cuda/bert/attention_qk.cu | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index 84a7cc19f1576..51311715d3b2a 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -762,12 +762,8 @@ Status UnfusedAttention( } else { // no mask if (nullptr != data.output_qk) { int64_t qk_size = (int64_t)batch_size * num_heads * sequence_length * total_sequence_length; - if (std::is_same::value) { - cudaMemcpyAsync(data.output_qk, data.scratch, qk_size * sizeof(QK), cudaMemcpyDeviceToDevice, stream); - } else { - ORT_RETURN_IF_ERROR( - (CopyQK(stream, static_cast(qk_size), data.scratch, reinterpret_cast(data.output_qk)))); - } + ORT_RETURN_IF_ERROR( + (CopyQK(stream, static_cast(qk_size), data.scratch, reinterpret_cast(data.output_qk)))); } ORT_RETURN_IF_ERROR( ComputeSoftmax( diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu b/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu index 78c407fd3bb3b..b81783377936f 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu @@ -24,11 +24,23 @@ __global__ void ConvertAndCopyQK(const int count, const half* input, float* outp } } +template +__global__ void ConvertAndCopyQK(const int count, const T* input, T* output) { + int idx = threadIdx.x + blockIdx.x * blockDim.x; + if (idx < count) { + output[idx] = input[idx]; + } +} + template Status CopyQK(cudaStream_t stream, const int qk_size, const T* input, QK* output) { + if constexpr (std::is_same::value) { + CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(output, input, qk_size * sizeof(QK), cudaMemcpyDeviceToDevice, stream)); + return Status::OK(); + } const bool half2float = std::is_same::value && std::is_same::value; const bool float2half = std::is_same::value && std::is_same::value; ORT_ENFORCE(half2float || float2half); @@ -40,6 +52,11 @@ Status CopyQK(cudaStream_t stream, return CUDA_CALL(cudaGetLastError()); } +template Status CopyQK(cudaStream_t stream, + const int qk_size, + const float* input, + float* output); + template Status CopyQK(cudaStream_t stream, const int qk_size, const float* input, @@ -50,6 +67,11 @@ template Status CopyQK(cudaStream_t stream, const half* input, float* output); +template Status CopyQK(cudaStream_t stream, + const int qk_size, + const half* input, + half* output); + } // namespace cuda } // namespace contrib } // namespace onnxruntime From 5ed900e9712ce2f02e40c15b945d18453d1960d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Mar 2025 21:24:50 -0700 Subject: [PATCH 152/266] Bump next from 15.1.2 to 15.2.3 in /js/web/test/e2e/exports/testcases/nextjs-default (#24132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [next](https://github.com/vercel/next.js) from 15.1.2 to 15.2.3.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=next&package-manager=npm_and_yarn&previous-version=15.1.2&new-version=15.2.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) Dependabot will merge this PR once CI passes on it, as requested by @fs-eire. [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../nextjs-default/package-lock.json | 80 +++++++++---------- .../testcases/nextjs-default/package.json | 2 +- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json b/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json index 174812402f578..11a5c1ac3f2ee 100644 --- a/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json +++ b/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json @@ -8,7 +8,7 @@ "name": "nextjs-default", "version": "0.1.0", "dependencies": { - "next": "15.1.2", + "next": "15.2.3", "react": "^19.0.0", "react-dom": "^19.0.0" } @@ -385,15 +385,15 @@ } }, "node_modules/@next/env": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.2.tgz", - "integrity": "sha512-Hm3jIGsoUl6RLB1vzY+dZeqb+/kWPZ+h34yiWxW0dV87l8Im/eMOwpOA+a0L78U0HM04syEjXuRlCozqpwuojQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.3.tgz", + "integrity": "sha512-a26KnbW9DFEUsSxAxKBORR/uD9THoYoKbkpFywMN/AFvboTt94b8+g/07T8J6ACsdLag8/PDU60ov4rPxRAixw==", "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.2.tgz", - "integrity": "sha512-b9TN7q+j5/7+rGLhFAVZiKJGIASuo8tWvInGfAd8wsULjB1uNGRCj1z1WZwwPWzVQbIKWFYqc+9L7W09qwt52w==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.3.tgz", + "integrity": "sha512-uaBhA8aLbXLqwjnsHSkxs353WrRgQgiFjduDpc7YXEU0B54IKx3vU+cxQlYwPCyC8uYEEX7THhtQQsfHnvv8dw==", "cpu": [ "arm64" ], @@ -407,9 +407,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.2.tgz", - "integrity": "sha512-caR62jNDUCU+qobStO6YJ05p9E+LR0EoXh1EEmyU69cYydsAy7drMcOlUlRtQihM6K6QfvNwJuLhsHcCzNpqtA==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.3.tgz", + "integrity": "sha512-pVwKvJ4Zk7h+4hwhqOUuMx7Ib02u3gDX3HXPKIShBi9JlYllI0nU6TWLbPT94dt7FSi6mSBhfc2JrHViwqbOdw==", "cpu": [ "x64" ], @@ -423,9 +423,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.2.tgz", - "integrity": "sha512-fHHXBusURjBmN6VBUtu6/5s7cCeEkuGAb/ZZiGHBLVBXMBy4D5QpM8P33Or8JD1nlOjm/ZT9sEE5HouQ0F+hUA==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.3.tgz", + "integrity": "sha512-50ibWdn2RuFFkOEUmo9NCcQbbV9ViQOrUfG48zHBCONciHjaUKtHcYFiCwBVuzD08fzvzkWuuZkd4AqbvKO7UQ==", "cpu": [ "arm64" ], @@ -439,9 +439,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.2.tgz", - "integrity": "sha512-9CF1Pnivij7+M3G74lxr+e9h6o2YNIe7QtExWq1KUK4hsOLTBv6FJikEwCaC3NeYTflzrm69E5UfwEAbV2U9/g==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.3.tgz", + "integrity": "sha512-2gAPA7P652D3HzR4cLyAuVYwYqjG0mt/3pHSWTCyKZq/N/dJcUAEoNQMyUmwTZWCJRKofB+JPuDVP2aD8w2J6Q==", "cpu": [ "arm64" ], @@ -455,9 +455,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.2.tgz", - "integrity": "sha512-tINV7WmcTUf4oM/eN3Yuu/f8jQ5C6AkueZPKeALs/qfdfX57eNv4Ij7rt0SA6iZ8+fMobVfcFVv664Op0caCCg==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.3.tgz", + "integrity": "sha512-ODSKvrdMgAJOVU4qElflYy1KSZRM3M45JVbeZu42TINCMG3anp7YCBn80RkISV6bhzKwcUqLBAmOiWkaGtBA9w==", "cpu": [ "x64" ], @@ -471,9 +471,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.2.tgz", - "integrity": "sha512-jf2IseC4WRsGkzeUw/cK3wci9pxR53GlLAt30+y+B+2qAQxMw6WAC3QrANIKxkcoPU3JFh/10uFfmoMDF9JXKg==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.3.tgz", + "integrity": "sha512-ZR9kLwCWrlYxwEoytqPi1jhPd1TlsSJWAc+H/CJHmHkf2nD92MQpSRIURR1iNgA/kuFSdxB8xIPt4p/T78kwsg==", "cpu": [ "x64" ], @@ -487,9 +487,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.2.tgz", - "integrity": "sha512-wvg7MlfnaociP7k8lxLX4s2iBJm4BrNiNFhVUY+Yur5yhAJHfkS8qPPeDEUH8rQiY0PX3u/P7Q/wcg6Mv6GSAA==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.3.tgz", + "integrity": "sha512-+G2FrDcfm2YDbhDiObDU/qPriWeiz/9cRR0yMWJeTLGGX6/x8oryO3tt7HhodA1vZ8r2ddJPCjtLcpaVl7TE2Q==", "cpu": [ "arm64" ], @@ -503,9 +503,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.2.tgz", - "integrity": "sha512-D3cNA8NoT3aWISWmo7HF5Eyko/0OdOO+VagkoJuiTk7pyX3P/b+n8XA/MYvyR+xSVcbKn68B1rY9fgqjNISqzQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.3.tgz", + "integrity": "sha512-gHYS9tc+G2W0ZC8rBL+H6RdtXIyk40uLiaos0yj5US85FNhbFEndMA2nW3z47nzOWiSvXTZ5kBClc3rD0zJg0w==", "cpu": [ "x64" ], @@ -651,12 +651,12 @@ } }, "node_modules/next": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/next/-/next-15.1.2.tgz", - "integrity": "sha512-nLJDV7peNy+0oHlmY2JZjzMfJ8Aj0/dd3jCwSZS8ZiO5nkQfcZRqDrRN3U5rJtqVTQneIOGZzb6LCNrk7trMCQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.2.3.tgz", + "integrity": "sha512-x6eDkZxk2rPpu46E1ZVUWIBhYCLszmUY6fvHBFcbzJ9dD+qRX6vcHusaqqDlnY+VngKzKbAiG2iRCkPbmi8f7w==", "license": "MIT", "dependencies": { - "@next/env": "15.1.2", + "@next/env": "15.2.3", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -671,14 +671,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.1.2", - "@next/swc-darwin-x64": "15.1.2", - "@next/swc-linux-arm64-gnu": "15.1.2", - "@next/swc-linux-arm64-musl": "15.1.2", - "@next/swc-linux-x64-gnu": "15.1.2", - "@next/swc-linux-x64-musl": "15.1.2", - "@next/swc-win32-arm64-msvc": "15.1.2", - "@next/swc-win32-x64-msvc": "15.1.2", + "@next/swc-darwin-arm64": "15.2.3", + "@next/swc-darwin-x64": "15.2.3", + "@next/swc-linux-arm64-gnu": "15.2.3", + "@next/swc-linux-arm64-musl": "15.2.3", + "@next/swc-linux-x64-gnu": "15.2.3", + "@next/swc-linux-x64-musl": "15.2.3", + "@next/swc-win32-arm64-msvc": "15.2.3", + "@next/swc-win32-x64-msvc": "15.2.3", "sharp": "^0.33.5" }, "peerDependencies": { diff --git a/js/web/test/e2e/exports/testcases/nextjs-default/package.json b/js/web/test/e2e/exports/testcases/nextjs-default/package.json index 6688445cded26..9bad599248259 100644 --- a/js/web/test/e2e/exports/testcases/nextjs-default/package.json +++ b/js/web/test/e2e/exports/testcases/nextjs-default/package.json @@ -11,6 +11,6 @@ "dependencies": { "react": "^19.0.0", "react-dom": "^19.0.0", - "next": "15.1.2" + "next": "15.2.3" } } From 2b5c9da6166c41cfb94f26101c51d4f31818a1d3 Mon Sep 17 00:00:00 2001 From: Praveen G <65328375+pravg-amd@users.noreply.github.com> Date: Mon, 24 Mar 2025 22:41:57 +0530 Subject: [PATCH 153/266] [Shape Inference] Add shape inference for QLinearAdd and QLinearMul ops (#24090) ### Description Support shape inference for QLinearAdd and QLinearMul ops which were missing in symbolic_shape_infer.py ### Motivation and Context This change is required to enable shape inference for models with "QLinearAdd" ops which are defined in com.microsoft domain and the shapes of which cannot be inferred using onnx shape_inference alone. Fixes issue https://github.com/microsoft/onnxruntime/issues/24028 --------- Signed-off-by: Praveen G --- .../python/tools/symbolic_shape_infer.py | 18 +++++ ...untime_test_python_symbolic_shape_infer.py | 81 +++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/onnxruntime/python/tools/symbolic_shape_infer.py b/onnxruntime/python/tools/symbolic_shape_infer.py index bd88eb1b6b353..33f5b5e5853a5 100755 --- a/onnxruntime/python/tools/symbolic_shape_infer.py +++ b/onnxruntime/python/tools/symbolic_shape_infer.py @@ -219,6 +219,8 @@ def __init__(self, int_max, auto_merge, guess_output_rank, verbose, prefix=""): "PackedMultiHeadAttention": self._infer_PackedMultiHeadAttention, "PagedAttention": self._infer_PagedAttention, "PythonOp": self._infer_PythonOp, + "QLinearAdd": self._infer_QLinearBinary, + "QLinearMul": self._infer_QLinearBinary, "QuantizeLinear": self._infer_QuantizeLinear, "QuickGelu": self._infer_FastGelu, "RelativePositionBias": self._infer_RelativePositionBias, @@ -490,6 +492,8 @@ def _onnx_infer_single_node(self, node): "SkipSimplifiedLayerNormalization", "SparseAttention", "SkipGroupNorm", + "QLinearAdd", + "QLinearMul", ] if not skip_infer: @@ -1040,6 +1044,20 @@ def _infer_QuantizeLinear(self, node): # noqa: N802 vi = self.known_vi_[node.output[0]] vi.CopyFrom(helper.make_tensor_value_info(node.output[0], output_dtype, output_shape)) + def _infer_QLinearBinary(self, node): # noqa: N802 + # Get the output data type from the first input to QLinearAdd / QLinearMul. + output_dtype = self.known_vi_[node.input[0]].type.tensor_type.elem_type + + # The inputs are first and fourth operands respectively. + input_1_shape = self._get_shape(node, 0) + input_2_shape = self._get_shape(node, 3) + + # Compute the broadcasted shape + new_shape = self._broadcast_shapes(input_1_shape, input_2_shape) + + vi = self.known_vi_[node.output[0]] + vi.CopyFrom(helper.make_tensor_value_info(node.output[0], output_dtype, new_shape)) + def _infer_Einsum(self, node): # noqa: N802 # ref:https://github.com/onnx/onnx/blob/623dfaa0151b2e4ce49779c3ec31cbd78c592b80/onnx/defs/math/defs.cc#L3275 equation = get_attribute(node, "equation") diff --git a/onnxruntime/test/python/onnxruntime_test_python_symbolic_shape_infer.py b/onnxruntime/test/python/onnxruntime_test_python_symbolic_shape_infer.py index d311b4b8517cf..5267ffcc65ab7 100644 --- a/onnxruntime/test/python/onnxruntime_test_python_symbolic_shape_infer.py +++ b/onnxruntime/test/python/onnxruntime_test_python_symbolic_shape_infer.py @@ -644,6 +644,87 @@ def test_matmulnbits(self): ] self._check_shapes(graph, inferred.graph, expected_shapes) + def test_qlinear_binary(self): + """ + Test ONNX QLinearAdd op ('com.microsoft' domain). . + Check that the output shape is propagated from the inputs to the op with broadcasting. + """ + initializers = [ + helper.make_tensor( + "A_scale", + TensorProto.FLOAT, + [], + [0.7], + ), + helper.make_tensor( + "A_zero_point", + TensorProto.UINT8, + [], + [158], + ), + helper.make_tensor( + "B_scale", + TensorProto.FLOAT, + [], + [0.02], + ), + helper.make_tensor( + "B_zero_point", + TensorProto.UINT8, + [], + [5], + ), + helper.make_tensor( + "C_scale", + TensorProto.FLOAT, + [], + [0.26], + ), + helper.make_tensor( + "C_zero_point", + TensorProto.UINT8, + [], + [0], + ), + ] + + nodes = [ + helper.make_node( + "QLinearAdd", + inputs=[ + "A", + "A_scale", + "A_zero_point", + "B", + "B_scale", + "B_zero_point", + "C_scale", + "C_zero_point", + ], + outputs=["C"], + domain="com.microsoft", + ), + ] + + inputs = [ + helper.make_tensor_value_info("A", TensorProto.UINT8, ["b", 4, 128]), + helper.make_tensor_value_info("B", TensorProto.UINT8, ["b", 1, 4, 1, 128]), + ] + + outputs = [ + helper.make_tensor_value_info("C", TensorProto.UNDEFINED, None), + ] + + graph = helper.make_graph(nodes, "QLinearAdd_Test", inputs, outputs, initializers) + model = helper.make_model(graph) + + inferred = SymbolicShapeInference.infer_shapes(model, auto_merge=True) + + expected_shapes = [ + helper.make_tensor_value_info("C", TensorProto.UINT8, ["b", 1, 4, 4, 128]), + ] + self._check_shapes(graph, inferred.graph, expected_shapes) + class TestSymbolicShapeInferenceForSlice(unittest.TestCase): def check_slice_of_concat(self, input_dims, start, end, step, expected_output_dim): From 8eb8c2b08bfad112732799fa6771679a853eb477 Mon Sep 17 00:00:00 2001 From: Caroline Zhu Date: Mon, 24 Mar 2025 10:50:48 -0700 Subject: [PATCH 154/266] [mobile] Add Android NuGet BrowserStack test to NuGet packaging pipeline (#23580) ### Description Follow-up to #23551 Adds the BrowserStack testing stage for Android to the NuGet packaging pipeline. This test tests that the NuGet package produced will be imported and work correctly on an Android device [Pipeline run that shows what a failing unit test would look like](https://aiinfra.visualstudio.com/Lotus/_build/results?buildId=670961&view=results) --------- Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com> --- ...rosoft.ML.OnnxRuntime.EndToEndTests.csproj | 1 + .../BrowserStackTest.cs | 4 +- .../RunAllTest.cs | 2 +- .../AssertUtils.cs | 81 +++++++++++++++++++ .../InferenceTest.cs | 72 ++++++++++------- .../nuget/templates/test_android.yml | 63 +++++++++++++++ .../templates/android-java-api-aar-test.yml | 3 - .../azure-pipelines/templates/c-api-cpu.yml | 7 ++ 8 files changed, 197 insertions(+), 36 deletions(-) create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs create mode 100644 tools/ci_build/github/azure-pipelines/nuget/templates/test_android.yml diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj index 67addd2731744..4da9b5ffae3e4 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj @@ -50,6 +50,7 @@ + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs index 84377d65d1213..6ab341d75683f 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs @@ -45,8 +45,8 @@ public void Dispose() { String failureMessage = TestContext.CurrentContext.Result.Message; String jsonToSendFailure = - String.Format("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": " + - "{\"status\":\"failed\", \"reason\": {0}}}", + String.Format("browserstack_executor: {{\"action\": \"setSessionStatus\", \"arguments\": " + + "{{\"status\":\"failed\", \"reason\": {0}}}}}", JsonConvert.ToString(failureMessage)); ((IJavaScriptExecutor)driver).ExecuteScript(jsonToSendFailure); diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs index 5db3dc9957d1c..b62c2f052455e 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs @@ -89,7 +89,7 @@ public async Task ClickRunAllTest() await Task.Delay(500); } - var (numPassed, numFailed) = GetPassFailCount(); + (int numPassed, int numFailed) = GetPassFailCount(); if (numFailed == 0) { diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs new file mode 100644 index 0000000000000..7d689628ceab7 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace Microsoft.ML.OnnxRuntime.Tests +{ + internal static class AssertUtils + { + + /// + /// Check if the action throws the expected exception. If it doesn't, the method passes. If it does, check for + /// the exception type and the expected exception message. More detailed Assert method to be used for unit tests + /// written with XUnit. + /// + /// Type of exception expected to be thrown. + /// Action to be executed or tested. + /// Feedback message if an unexpected exception happens. + /// Expected exception message. If null, the exception message is not + // checked. + public static void IfThrowsCheckException(Action action, string feedbackMessage, string expectedExceptionMessage = null) where T : Exception + { + try + { + action(); + } + catch (T ex) + { + if (expectedExceptionMessage == null) + { + return; + } + else + { + Assert.True(ex.Message.Contains(expectedExceptionMessage), + $"{feedbackMessage}\nExpected exception message to contain '{expectedExceptionMessage}', but got '{ex.Message}'"); + } + } + catch (Exception ex) + { + Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but got {ex.GetType().Name}. "); + } + } + + + /// + /// Check if the action throws the expected exception. If it doesn't, the method fails with the feedbackMessage. + /// If it does, check for the exception type and the expected exception message. More detailed Assert method to be + /// used for unit tests written with XUnit. + /// + /// Type of exception expected to be thrown. + /// Action to be executed or tested. It is expected that the action will throw. + /// Feedback message if an unexpected exception happens. + /// Expected exception message. If null, the exception message is not + // checked. + public static void AssertThrowsCheckException(Action action, string feedbackMessage, string expectedExceptionMessage = null) where T : Exception + { + try + { + action(); + Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but no exception was thrown."); + } + catch (T ex) + { + if (expectedExceptionMessage == null) + { + return; + } + else + { + Assert.True(ex.Message.Contains(expectedExceptionMessage), + $"{feedbackMessage}\nExpected exception message to contain '{expectedExceptionMessage}', but got '{ex.Message}'"); + } + } + catch (Exception ex) + { + Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but got {ex.GetType().Name}. "); + } + } + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs index 17738da515134..0a39d965979ca 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs @@ -93,18 +93,35 @@ public void TestSessionOptions() opt.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_EXTENDED; Assert.Equal(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, opt.GraphOptimizationLevel); - Assert.Throws(() => { opt.GraphOptimizationLevel = (GraphOptimizationLevel)10; }); + AssertUtils.AssertThrowsCheckException( + () => { opt.GraphOptimizationLevel = (GraphOptimizationLevel)10; }, + "Set an invalid Graph Optimization Level."); opt.AddSessionConfigEntry("key", "value"); - var ex = Assert.Throws(() => { opt.AddSessionConfigEntry("", "invalid key"); }); - Assert.Contains("[ErrorCode:InvalidArgument] Config key is empty", ex.Message); + AssertUtils.AssertThrowsCheckException( + () => { opt.AddSessionConfigEntry("", "invalid key"); }, + "Added an invalid config entry.", + "[ErrorCode:InvalidArgument] Config key is empty"); // SessionOptions.RegisterOrtExtensions can be manually tested by referencing the // Microsoft.ML.OnnxRuntime.Extensions nuget package. After that is done, this should not throw. - ex = Assert.Throws(() => { opt.RegisterOrtExtensions(); }); - Assert.Contains("Microsoft.ML.OnnxRuntime.Extensions NuGet package must be referenced", ex.Message); - + AssertUtils.AssertThrowsCheckException( + () => { opt.RegisterOrtExtensions(); }, + "RegisterOrtExtensions should throw if the Extensions package is not referenced", + "Microsoft.ML.OnnxRuntime.Extensions NuGet package must be referenced"); + + // The below tests what happens when various execution providers are added + // to the session options. + + // We can only check what EPs the package was built with for the + // Microsoft.ML.OnnxRuntime.Managed package because the managed package defines + // the C# preprocessor symbols (such as USE_CUDA) for the EPs that it was built with. + + // The Microsoft.ML.OnnxRuntime package will use the appropriate platform bindings + // (ie the native Android bindings) where the C# preprocessor symbols + // identifying the EPs included in the build may not be available, so we use + // IfThrowsCheckException instead of using ifdefs. #if USE_CUDA opt.AppendExecutionProvider_CUDA(0); #endif @@ -157,30 +174,25 @@ public void TestSessionOptions() #if USE_TENSORRT opt.AppendExecutionProvider_Tensorrt(0); #endif -#if USE_XNNPACK - opt.AppendExecutionProvider("XNNPACK"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("XNNPACK"); }); - Assert.Contains("XNNPACK execution provider is not supported in this build", ex.Message); -#endif -#if USE_SNPE - opt.AppendExecutionProvider("SNPE"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("SNPE"); }); - Assert.Contains("SNPE execution provider is not supported in this build", ex.Message); -#endif -#if USE_QNN - opt.AppendExecutionProvider("QNN"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("QNN"); }); - Assert.Contains("QNN execution provider is not supported in this build", ex.Message); -#endif -#if USE_COREML - opt.AppendExecutionProvider("CoreML"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("CoreML"); }); - Assert.Contains("CoreML execution provider is not supported in this build", ex.Message); -#endif + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("CoreML"); }, + "Appending CoreML EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "CoreML execution provider is not supported in this build"); + + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("XNNPACK"); }, + "Appending XNNPACK EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "XNNPACK execution provider is not supported in this build"); + + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("SNPE"); }, + "Appending SNPE EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "SNPE execution provider is not supported in this build"); + + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("QNN"); }, + "Appending QNN EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "QNN execution provider is not supported in this build"); opt.AppendExecutionProvider_CPU(1); } diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_android.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_android.yml new file mode 100644 index 0000000000000..c988a97b6a56c --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_android.yml @@ -0,0 +1,63 @@ +parameters: + AgentPool : 'Win-CPU' + ArtifactSuffix: '' + SpecificArtifact: false + BuildId: '' + +stages: +- stage: NuGet_Test_Android + jobs: + - job: NuGet_Test_Android + workspace: + clean: all + pool: "${{ parameters.AgentPool }}" + + variables: + - name: OnnxRuntimeBuildDirectory + value: '$(Build.BinariesDirectory)' + + steps: + - task: NuGetToolInstaller@0 + displayName: Use Nuget 6.10.x + inputs: + versionSpec: 6.10.x + + - template: ../../templates/flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline Artifact' + ArtifactName: drop-signed-nuget-${{ parameters.ArtifactSuffix }} + TargetPath: '$(Build.BinariesDirectory)\nuget-artifact' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + - template: get-nuget-package-version-as-variable.yml + parameters: + packageFolder: '$(Build.BinariesDirectory)\nuget-artifact' + + - task: PowerShell@2 + displayName: Install MAUI workloads + inputs: + targetType: 'inline' + script: | + dotnet workload install maui maui-android android + workingDirectory: '$(Build.SourcesDirectory)\csharp' + + - task: PowerShell@2 + displayName: Publish Android MAUI APK + inputs: + targetType: 'inline' + script: | + dotnet nuget add source $(Build.BinariesDirectory)\nuget-artifact --name local-nuget + dotnet publish -c Release --property:UsePrebuiltNativePackage=true --property:CurrentOnnxRuntimeVersion=$(NuGetPackageVersionNumber) -f net8.0-android + workingDirectory: '$(Build.SourcesDirectory)\csharp\test\Microsoft.ML.OnnxRuntime.Tests.MAUI' + + - task: PowerShell@2 + displayName: Run BrowserStack test + inputs: + targetType: 'inline' + script: | + dotnet test + workingDirectory: '$(Build.SourcesDirectory)\csharp\test\Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android' + env: + BROWSERSTACK_USERNAME: $(browserstack_username) + BROWSERSTACK_ACCESS_KEY: $(browserstack_access_key) diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml index 366ee3fcf4e92..7b257a4cdcdd5 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml @@ -24,8 +24,6 @@ jobs: pool: 'onnxruntime-Ubuntu2204-AMD-CPU' workspace: clean: all - pool: - vmImage: 'macOS-14' variables: runCodesignValidationInjection: false ANDROID_AVD_HOME: $(Agent.TempDirectory) @@ -114,4 +112,3 @@ jobs: - template: component-governance-component-detection-steps.yml parameters : condition : 'succeeded' - diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index 7a46bdc7cde0a..d9b38e3eaba2e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -778,6 +778,13 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} +- template: ../nuget/templates/test_android.yml + parameters: + AgentPool : 'onnxruntime-Win-CPU-2022' + ArtifactSuffix: 'CPU' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + - template: ../nuget/templates/test_linux.yml parameters: AgentPool : onnxruntime-Ubuntu2204-AMD-CPU From 828e3726b6989dedf771a0fc8decfb719ac7b1f0 Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Mon, 24 Mar 2025 11:01:49 -0700 Subject: [PATCH 155/266] [CPU] Add fp16 support to sparse attention (#24015) ### Description Add fp16 support to sparse attention ### Motivation and Context Generalize models for CPU and GPU --- docs/OperatorKernels.md | 2 +- .../contrib_ops/cpu/cpu_contrib_kernels.cc | 2 + .../cpu/sparse/sparse_attention.cc | 24 +-- .../cpu/sparse/sparse_attention_base.h | 157 ++++++++++++++---- 4 files changed, 140 insertions(+), 45 deletions(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 8d256a2088279..60d9e8e747eeb 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -551,7 +551,7 @@ Do not modify directly.* |Sampling|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*in* presence_mask:**I**
*in* seed:**I**
*out* sequences:**I**
*out* filtered_logits:**T**|1+|**T** = tensor(float)| |SkipLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* beta:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |SkipSimplifiedLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|SparseAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* block_row_indices:**M**
*in* block_col_indices:**M**
*in* total_sequence_length:**M**
*in* key_total_sequence_lengths:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float)| +|SparseAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* block_row_indices:**M**
*in* block_col_indices:**M**
*in* total_sequence_length:**M**
*in* key_total_sequence_lengths:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |SparseToDenseMatMul|*in* A:**T**
*in* B:**T1**
*out* Y:**T1**|1+|**T** = sparse_tensor(double), sparse_tensor(float), sparse_tensor(int32), sparse_tensor(int64), sparse_tensor(uint32), sparse_tensor(uint64)
**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| |Tokenizer|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(string)| |TransposeMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| diff --git a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc index c742cd1e95bdd..345b5e793a764 100644 --- a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc @@ -24,6 +24,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, GroupQueryAttention); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MLFloat16, GroupQueryAttention); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, SparseAttention); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MLFloat16, SparseAttention); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, RotaryEmbedding); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MLFloat16, RotaryEmbedding); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, Sampling); @@ -299,6 +300,7 @@ Status RegisterCpuContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention.cc b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention.cc index e337f41a8688d..469084e7b4491 100644 --- a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention.cc +++ b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention.cc @@ -21,16 +21,20 @@ using onnxruntime::concurrency::ThreadPool; namespace onnxruntime { namespace contrib { -ONNX_OPERATOR_TYPED_KERNEL_EX( - SparseAttention, - kMSDomain, - 1, - float, - kCpuExecutionProvider, - KernelDefBuilder() - .TypeConstraint("T", DataTypeImpl::GetTensorType()) - .TypeConstraint("M", DataTypeImpl::GetTensorType()), - SparseAttention); +#define REGISTER_KERNEL_TYPED(T) \ + ONNX_OPERATOR_TYPED_KERNEL_EX( \ + SparseAttention, \ + kMSDomain, \ + 1, \ + T, \ + kCpuExecutionProvider, \ + KernelDefBuilder() \ + .TypeConstraint("T", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("M", DataTypeImpl::GetTensorType()), \ + SparseAttention); + +REGISTER_KERNEL_TYPED(float) +REGISTER_KERNEL_TYPED(MLFloat16) template SparseAttention::SparseAttention(const OpKernelInfo& info) : OpKernel(info), SparseAttentionBase(info) { diff --git a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h index 2c719b3724106..cccaec0b16ce5 100644 --- a/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/sparse/sparse_attention_base.h @@ -67,7 +67,10 @@ class SparseAttentionBase { int present_buffer_sequence_length = static_cast(present_key->Shape().GetDims()[2]); // Allocate a buffer to store Softmax(QK) - size_t bytes = SafeInt(batch_size) * num_heads_ * sequence_length * parameters.total_sequence_length * sizeof(T); + bool attention_mlas_supported = MlasGQASupported(CblasNoTrans, CblasTrans) && + MlasGQASupported(CblasNoTrans, CblasNoTrans); + size_t bytes = SafeInt(batch_size) * num_heads_ * sequence_length * parameters.total_sequence_length * + (attention_mlas_supported ? sizeof(T) : sizeof(float)); auto attention_probs = allocator->Alloc(bytes); BufferUniquePtr scratch_buffer(attention_probs, BufferDeleter(allocator)); @@ -77,21 +80,37 @@ class SparseAttentionBase { auto* tp = context->GetOperatorThreadPool(); const T* k = packed_qkv ? Q + num_heads_ * sequence_length * head_size : K; - ComputeAttentionProbs( - static_cast(attention_probs), Q, k, total_key_lengths->Data(), - batch_size, sequence_length, parameters.total_sequence_length, - past_buffer_sequence_length, present_buffer_sequence_length, head_size, - past_key->Data(), present_key->MutableData(), past_present_share_buffer, packed_qkv, - block_row_indices->Data(), block_col_indices->Data(), parameters, tp); - - // Compute the attentionScore * Value: out(B, N, S, H_v) = attention_probs(B, N, S, T) x V(B, N, T, H_v) const T* v = packed_qkv ? Q + (num_heads_ + kv_num_heads_) * sequence_length * head_size : V; - ComputeVxAttentionScore( - output->MutableData(), static_cast(attention_probs), v, - total_key_lengths->Data(), - batch_size, sequence_length, parameters.total_sequence_length, - past_buffer_sequence_length, present_buffer_sequence_length, head_size, parameters.hidden_size, - past_value->Data(), present_value->MutableData(), past_present_share_buffer, packed_qkv, tp); + + if (attention_mlas_supported) { + ComputeAttentionProbs( + static_cast(attention_probs), Q, k, total_key_lengths->Data(), + batch_size, sequence_length, parameters.total_sequence_length, + past_buffer_sequence_length, present_buffer_sequence_length, head_size, + past_key->Data(), present_key->MutableData(), past_present_share_buffer, packed_qkv, + block_row_indices->Data(), block_col_indices->Data(), parameters, tp, allocator); + + ComputeVxAttentionScore( + output->MutableData(), static_cast(attention_probs), v, + total_key_lengths->Data(), + batch_size, sequence_length, parameters.total_sequence_length, + past_buffer_sequence_length, present_buffer_sequence_length, head_size, parameters.hidden_size, + past_value->Data(), present_value->MutableData(), past_present_share_buffer, packed_qkv, tp, allocator); + } else { + ComputeAttentionProbs( + static_cast(attention_probs), Q, k, total_key_lengths->Data(), + batch_size, sequence_length, parameters.total_sequence_length, + past_buffer_sequence_length, present_buffer_sequence_length, head_size, + past_key->Data(), present_key->MutableData(), past_present_share_buffer, packed_qkv, + block_row_indices->Data(), block_col_indices->Data(), parameters, tp, allocator); + + ComputeVxAttentionScore( + output->MutableData(), static_cast(attention_probs), v, + total_key_lengths->Data(), + batch_size, sequence_length, parameters.total_sequence_length, + past_buffer_sequence_length, present_buffer_sequence_length, head_size, parameters.hidden_size, + past_value->Data(), present_value->MutableData(), past_present_share_buffer, packed_qkv, tp, allocator); + } return Status::OK(); } @@ -100,9 +119,9 @@ class SparseAttentionBase { // Helper function to compute the attention probs. It does 2 things: // attention_probs(B, N, S, T) = 1/sqrt(H) x Q(B, N, S, H) x K'(B, N, T, H -> B, N, H, T) // attention_probs(B, N, S, T) = Softmax(attention_probs) - template + template void ComputeAttentionProbs( - T* attention_probs, // output buffer with size BxNxSxT + U* attention_probs, // output buffer with size BxNxSxT const T* Q, // query start pointer const T* K, // key start pointer const int32_t* total_key_lengths, // total key sequence lengths (past + new) @@ -119,7 +138,8 @@ class SparseAttentionBase { const int32_t* block_row_indices, // block row indices const int32_t* block_col_indices, // block column indices SparseAttentionParameters& parameters, // parameters - ThreadPool* tp) const { // thread pool + ThreadPool* tp, // thread pool + AllocatorPtr allocator) const { const bool is_prompt = (total_sequence_length == sequence_length); const ptrdiff_t packed_batch_stride = packed_qkv ? SafeInt(num_heads_ + 2 * kv_num_heads_) * sequence_length * head_size @@ -173,7 +193,7 @@ class SparseAttentionBase { const int total_seq_len = total_key_lengths[batch_index]; const ptrdiff_t output_offset = SafeInt(i) * sequence_length * total_sequence_length; - T* output = attention_probs + output_offset; + U* output = attention_probs + output_offset; const T* k; if (packed_qkv) { @@ -205,14 +225,34 @@ class SparseAttentionBase { DUMP_CPU_TENSOR("Q", q, sequence_length, head_size); DUMP_CPU_TENSOR("K", k, total_seq_len, head_size); - math::GemmEx(CblasNoTrans, CblasTrans, sequence_length, total_seq_len, head_size, alpha, q, - head_size, k, head_size, 0.0f /*bata*/, output, total_seq_len, - nullptr); + if constexpr (std::is_same::value) { + math::GemmEx(CblasNoTrans, CblasTrans, sequence_length, total_seq_len, head_size, alpha, q, + head_size, k, head_size, 0.0f /*bata*/, output, total_seq_len, + nullptr); + } else if constexpr (std::is_same::value) { + MlasGemm(CblasNoTrans, CblasTrans, sequence_length, total_seq_len, head_size, + q, head_size, k, head_size, output, total_seq_len, + MLFloat16(alpha).val, static_cast(0) /*beta*/, nullptr); + } else { + size_t bytes = static_cast(head_size) * (sequence_length + total_seq_len) * sizeof(float); + auto q_k_fp32 = allocator->Alloc(bytes); + BufferUniquePtr scratch_buffer(q_k_fp32, BufferDeleter(allocator)); + + float* q_fp32 = static_cast(q_k_fp32); + MlasConvertHalfToFloatBuffer(q, q_fp32, static_cast(head_size) * sequence_length); + + float* k_fp32 = q_fp32 + head_size * sequence_length; + MlasConvertHalfToFloatBuffer(k, k_fp32, static_cast(head_size) * total_seq_len); + + math::GemmEx(CblasNoTrans, CblasTrans, sequence_length, total_seq_len, head_size, + alpha, q_fp32, head_size, k_fp32, head_size, 0.0f /*bata*/, + output, total_seq_len, nullptr); + } DUMP_CPU_TENSOR("QK", output, sequence_length, total_seq_len); // Compute Softmax for causal and output result in place. - T* output_softmax = output; + U* output_softmax = output; int layout_id = head_index % parameters.num_sparse_layout; bool is_sparse_layout = layout_has_sparse[layout_id]; @@ -224,7 +264,11 @@ class SparseAttentionBase { int causal_length = past_seq_len + q_id + 1; ComputeAttentionSoftmaxInplace(output_softmax, 1, causal_length, nullptr); for (int remain_seq_id = causal_length; remain_seq_id < total_seq_len; remain_seq_id++) { - output_softmax[remain_seq_id] = 0.f; + if constexpr (std::is_same::value) { + output_softmax[remain_seq_id] = 0.f; + } else { + output_softmax[remain_seq_id] = MLFloat16::FromBits(static_cast(0)); + } } output_softmax += total_seq_len; } @@ -278,14 +322,23 @@ class SparseAttentionBase { // Update inline according to attention mask. if (has_sparse) { for (int s = 0; s < causal_length; s++) { - if (mask[s] == 0) - output_softmax[s] = std::numeric_limits::lowest(); + if (mask[s] == 0) { + if constexpr (std::is_same::value) { + output_softmax[s] = std::numeric_limits::lowest(); + } else { + output_softmax[s] = MLFloat16::FromBits(static_cast(0xFBFF)); + } + } } } ComputeAttentionSoftmaxInplace(output_softmax, 1, causal_length, nullptr); for (int remain_seq_id = causal_length; remain_seq_id < total_seq_len; remain_seq_id++) { - output_softmax[remain_seq_id] = 0.f; + if constexpr (std::is_same::value) { + output_softmax[remain_seq_id] = 0.f; + } else { + output_softmax[remain_seq_id] = MLFloat16::FromBits(static_cast(0)); + } } output_softmax += total_seq_len; @@ -299,9 +352,9 @@ class SparseAttentionBase { }); } - template + template void ComputeVxAttentionScore(T* output, // buffer for the result with size BxSxNxH - const T* attention_probs, // Softmax of Q*K' with size BxNxSxT + const U* attention_probs, // Softmax of Q*K' with size BxNxSxT const T* V, // v value with size BxN_kvxSxH const int32_t* total_key_lengths, // total sequence lengths int batch_size, // batch size @@ -315,7 +368,8 @@ class SparseAttentionBase { T* present_value, // present value only bool past_present_share_buffer, // whether past_key and present_key share the buffer bool packed_qkv, // whether Q, K, V are packed - ThreadPool* tp) const { + ThreadPool* tp, + AllocatorPtr allocator) const { const bool is_prompt = sequence_length == total_sequence_length; const ptrdiff_t packed_batch_stride = packed_qkv ? SafeInt(num_heads_ + 2 * kv_num_heads_) * sequence_length * head_size @@ -341,6 +395,13 @@ class SparseAttentionBase { unit_cost.bytes_stored += bytes_to_copy_value; } + size_t output_fp32_bytes = 0; + if constexpr (std::is_same::value && std::is_same::value) { + output_fp32_bytes = SafeInt(sequence_length) * batch_size * num_heads_ * head_size * sizeof(float); + } + auto output_fp32 = allocator->Alloc(output_fp32_bytes); + BufferUniquePtr scratch_buffer(output_fp32, BufferDeleter(allocator)); + DUMP_CPU_TENSOR_INIT(); ThreadPool::TryParallelFor( @@ -376,14 +437,42 @@ class SparseAttentionBase { DUMP_CPU_TENSOR("attention_probs", attention_probs + attention_probs_offset, sequence_length, total_seq_len); - math::GemmEx(CblasNoTrans, CblasNoTrans, sequence_length, head_size, total_seq_len, - 1.f, /*alpha*/ - attention_probs + attention_probs_offset, total_seq_len, v, - head_size, 0.0f /*beta*/, output_current, hidden_size, nullptr); + if constexpr (std::is_same::value) { + math::GemmEx(CblasNoTrans, CblasNoTrans, sequence_length, head_size, total_seq_len, + 1.f, /*alpha*/ + attention_probs + attention_probs_offset, total_seq_len, v, + head_size, 0.0f /*beta*/, output_current, hidden_size, nullptr); + } else if constexpr (std::is_same::value) { + MlasGemm(CblasNoTrans, CblasNoTrans, sequence_length, head_size, total_seq_len, + attention_probs + attention_probs_offset, total_seq_len, + v, head_size, output_current, hidden_size, + MLFloat16(1.0f).val, static_cast(0) /*beta*/, nullptr); + } else { + size_t bytes = static_cast(head_size) * total_seq_len * sizeof(float); + auto v_fp32 = allocator->Alloc(bytes); + BufferUniquePtr scratch_buffer(v_fp32, BufferDeleter(allocator)); + + float* v_fp32_ptr = static_cast(v_fp32); + MlasConvertHalfToFloatBuffer(v, v_fp32_ptr, static_cast(head_size) * total_seq_len); + + float* output_fp32_current = static_cast(output_fp32) + + (batch_index * sequence_length * num_heads_ + head_index) * head_size; + math::GemmEx(CblasNoTrans, CblasNoTrans, sequence_length, head_size, total_seq_len, + 1.f, /*alpha*/ attention_probs + attention_probs_offset, + total_seq_len, v_fp32_ptr, + head_size, 0.0f /*beta*/, output_fp32_current, + hidden_size, nullptr); + } DUMP_CPU_TENSOR("out", attention_probs + attention_probs_offset, sequence_length, head_size); } }); + + if constexpr (std::is_same::value && std::is_same::value) { + MlasConvertFloatToHalfBuffer(static_cast(output_fp32), + output, + SafeInt(sequence_length) * batch_size * num_heads_ * head_size); + } } }; From 373b9e2a23624ed89f1121aab8ebc6130bdf3c1d Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 24 Mar 2025 13:25:16 -0700 Subject: [PATCH 156/266] refactor mac CI pipelines (#24138) ### Description This PR refactors the mac CI pipeline: - Use composite action and reusable workflow to put together duplicated code - separate each EP --- .github/actions/macos-ci-setup/action.yml | 79 ++++ .github/workflows/mac.yml | 341 +++++------------- .../macos-ci-build-and-test-workflow.yml | 102 ++++++ .github/workflows/macos_coreml.yml | 51 --- 4 files changed, 269 insertions(+), 304 deletions(-) create mode 100644 .github/actions/macos-ci-setup/action.yml create mode 100644 .github/workflows/macos-ci-build-and-test-workflow.yml delete mode 100644 .github/workflows/macos_coreml.yml diff --git a/.github/actions/macos-ci-setup/action.yml b/.github/actions/macos-ci-setup/action.yml new file mode 100644 index 0000000000000..e170ccf50a0ac --- /dev/null +++ b/.github/actions/macos-ci-setup/action.yml @@ -0,0 +1,79 @@ +name: "macOS CI pipeline setup steps" +description: "Common setup steps for macOS CI pipelines" + +inputs: + platform_machine: + required: false + type: string + default: "arm64" + python_version: + required: false + type: string + default: "3.11" + node_version: + required: false + type: string + default: "20.x" + java_version: + required: false + type: string + default: "17" + xcode_version: + required: false + type: string + default: "16" + use_cache: + required: false + type: boolean + default: false + +runs: + using: "composite" + steps: + - name: Use Python + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python_version }} + + - name: Verify machine architecture + shell: python + run: | + import platform + print(f"Running on {platform.machine()}") + assert platform.machine().lower() == "${{ inputs.platform_machine}}", "This job expects to be run on an ${{ inputs.platform_machine}} machine." + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node_version }} + + - name: Install coreutils and ninja + shell: bash + run: brew install coreutils ninja + + - name: Install Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: ${{ inputs.java_version }} + + - name: Use Xcode ${{ inputs.xcode_version }} + shell: bash + run: | + XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ inputs.xcode_version }}.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: Export GitHub Actions cache environment variables + if: ${{ inputs.use_cache }} + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Install python dependencies + shell: bash + working-directory: ${{ github.workspace }} + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements-dev.txt diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 86b1cd5ee90e7..e2f45712f6f9f 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -3,12 +3,12 @@ name: "MacOS CI Pipeline" on: push: branches: - - main - - rel-* + - main + - rel-* pull_request: branches: - - main - - rel-* + - main + - rel-* workflow_dispatch: concurrency: @@ -19,182 +19,25 @@ env: python_version: 3.11 jobs: - MacOS_C_API_Packaging_CPU_x86_64: - runs-on: macos-13 - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: false - - - name: Use Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Use Node.js 20.x - uses: actions/setup-node@v4 - with: - node-version: '20.x' - - - name: Install Java 17 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '17' - architecture: x64 - - - name: Set version number variables for Unix - shell: bash - run: | - # Do not output ##vso[] commands with `set -x` or they may be parsed again and include a trailing quote. - set +x - - _OnnxRuntimeVersion=$(head -1 ${{ github.workspace }}/VERSION_NUMBER) - echo "OnnxRuntimeVersion=$_OnnxRuntimeVersion" - - _OnnxRuntimeGitCommitHash=$(git rev-parse HEAD) - echo "OnnxRuntimeGitCommitHash=$_OnnxRuntimeGitCommitHash" - - _OnnxRuntimeGitCommitHash=$(git rev-parse --short=8 HEAD) - echo "OnnxRuntimeGitCommitHashShort=$_OnnxRuntimeGitCommitHash" - working-directory: ${{ github.workspace }} - - - name: Use Xcode 14.3.1 - shell: bash - run: | - set -e -x - XCODE_DEVELOPER_DIR="/Applications/Xcode_14.3.1.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - name: Setup environment variables - shell: bash - run: | - set -e -x - export PATH=${{ github.workspace }}/installed/bin:$PATH - export ONNX_ML=1 - export CMAKE_ARGS="-DONNX_GEN_PB_TYPE_STUBS=ON -DONNX_WERROR=OFF" - python3 -m pip install -r '${{ github.workspace }}/tools/ci_build/github/linux/docker/scripts/requirements.txt' - - - name: Export GitHub Actions cache environment variables - uses: actions/github-script@v7 - with: - script: | - core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); - core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - - - name: Configure Build (build.py --update) - shell: bash - run: | - set -e -x - rm -rf ${{ github.workspace }}/Release - python3 ${{ github.workspace }}/tools/ci_build/build.py --update --build_objc --build_wheel --use_xnnpack --build_nodejs --build_java --use_coreml --use_webgpu --build_dir ${{ github.workspace }} --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --build_shared_lib --config Release --use_vcpkg --use_vcpkg_ms_internal_asset_cache - - - name: Build (build.py --build) - shell: bash - run: | - set -e -x - python3 ${{ github.workspace }}/tools/ci_build/build.py --build --build_objc --build_wheel --use_xnnpack --build_nodejs --build_java --use_coreml --use_webgpu --build_dir ${{ github.workspace }} --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --build_shared_lib --config Release --use_vcpkg --use_vcpkg_ms_internal_asset_cache - - - name: Install - shell: bash - run: | - set -e -x - cd ${{ github.workspace }}/Release - make install DESTDIR=${{ github.workspace }}/installed - - - name: Running Tests (build.py --test) - shell: bash - run: | - set -e -x - python3 ${{ github.workspace }}/tools/ci_build/build.py --test --build_objc --build_wheel --use_xnnpack --build_nodejs --build_java --use_coreml --use_webgpu --build_dir ${{ github.workspace }} --skip_submodule_sync --parallel --use_binskim_compliant_compile_flags --build_shared_lib --config Release --use_vcpkg --use_vcpkg_ms_internal_asset_cache - timeout-minutes: 300 - env: - MACOSX_DEPLOYMENT_TARGET: '13.3' - ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' - - ARM64-Xcode16: - runs-on: macos-15 - - env: - xcode_version: 16 - - timeout-minutes: 60 - - steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Verify ARM64 machine - shell: python - run: | - import platform - assert platform.machine() == "arm64", "This job expects to be run on an ARM64 machine." + cpu: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + coreml: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + use_coreml: true - - uses: actions/checkout@v4 + xnnpack: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + use_xnnpack: true - - name: Build and test - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --update \ - --build --parallel \ - --test \ - --build_shared_lib \ - --build_objc \ - --use_coreml \ - --use_xnnpack \ - --use_binskim_compliant_compile_flags + webgpu: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + use_webgpu: true - ARM64-Xcode16-webgpu: - runs-on: macos-15 - - env: - xcode_version: 16 - - timeout-minutes: 60 - - steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Verify ARM64 machine - shell: python - run: | - import platform - assert platform.machine() == "arm64", "This job expects to be run on an ARM64 machine." - - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - uses: actions/checkout@v4 - - - name: Build and test - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --update \ - --build --parallel \ - --test \ - --build_shared_lib \ - --build_nodejs \ - --use_webgpu \ - --use_binskim_compliant_compile_flags - - ARM64-Xcode16-targeting-iphonesimulator: + iphone_simulator: runs-on: macos-15 env: @@ -207,41 +50,34 @@ jobs: timeout-minutes: 90 steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Verify ARM64 machine - shell: python - run: | - import platform - assert platform.machine() == "arm64", "This job expects to be run on an ARM64 machine." - - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - uses: actions/checkout@v4 - - - name: Build for iphonesimulator ${{ matrix.target_arch }} - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --update \ - --build --parallel \ - --test \ - --build_apple_framework \ - --use_xcode \ - --use_coreml \ - --use_xnnpack \ - --use_binskim_compliant_compile_flags \ - --ios \ - --apple_deploy_target=15.1 \ - --apple_sysroot=iphonesimulator \ - --osx_arch=${{ matrix.target_arch }} + - name: Checkout code + uses: actions/checkout@v4 + + - name: macOS CI pipeline prepare steps + uses: ./.github/actions/macos-ci-setup + with: + platform_machine: "arm64" + python_version: ${{ env.python_version }} + xcode_version: ${{ env.xcode_version }} + use_cache: false + + - name: Build for iphonesimulator ${{ matrix.target_arch }} + shell: bash + run: | + python ./tools/ci_build/build.py \ + --build_dir ./build \ + --update \ + --build --parallel \ + --test \ + --build_apple_framework \ + --use_xcode \ + --use_coreml \ + --use_xnnpack \ + --use_binskim_compliant_compile_flags \ + --ios \ + --apple_deploy_target=15.1 \ + --apple_sysroot=iphonesimulator \ + --osx_arch=${{ matrix.target_arch }} Objective-C-StaticAnalysis: runs-on: macos-14 @@ -252,45 +88,44 @@ jobs: timeout-minutes: 30 steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - uses: actions/checkout@v4 - - - name: Generate compile_commands.json and ONNX protobuf files - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --cmake_generator "Unix Makefiles" \ - --config Debug \ - --build_shared_lib \ - --use_coreml \ - --build_objc \ - --enable_training_apis \ - --cmake_extra_defines CMAKE_EXPORT_COMPILE_COMMANDS=ON \ - --use_binskim_compliant_compile_flags \ - --update \ - --build --parallel \ - --target onnx_proto - - - name: Analyze Objective-C/C++ source code - shell: bash - run: | - CLANG_TIDY_CHECKS="-*,clang-analyzer-*" - - "$(brew --prefix llvm@15)/bin/clang-tidy" \ - -p=./build/Debug \ - --checks="${CLANG_TIDY_CHECKS}" \ - --warnings-as-errors="${CLANG_TIDY_CHECKS}" \ - --header-filter="objectivec/include|objectivec|onnxruntime/core" \ - ./objectivec/*.mm \ - ./onnxruntime/core/platform/apple/logging/apple_log_sink.mm \ - ./onnxruntime/core/providers/coreml/model/*.mm + - name: Checkout code + uses: actions/checkout@v4 + + - name: macOS CI pipeline prepare steps + uses: ./.github/actions/macos-ci-setup + with: + platform_machine: "arm64" + python_version: ${{ env.python_version }} + xcode_version: ${{ env.xcode_version }} + use_cache: false + + - name: Generate compile_commands.json and ONNX protobuf files + shell: bash + run: | + python ./tools/ci_build/build.py \ + --build_dir ./build \ + --cmake_generator "Unix Makefiles" \ + --config Debug \ + --build_shared_lib \ + --use_coreml \ + --build_objc \ + --enable_training_apis \ + --cmake_extra_defines CMAKE_EXPORT_COMPILE_COMMANDS=ON \ + --use_binskim_compliant_compile_flags \ + --update \ + --build --parallel \ + --target onnx_proto + + - name: Analyze Objective-C/C++ source code + shell: bash + run: | + CLANG_TIDY_CHECKS="-*,clang-analyzer-*" + + "$(brew --prefix llvm@15)/bin/clang-tidy" \ + -p=./build/Debug \ + --checks="${CLANG_TIDY_CHECKS}" \ + --warnings-as-errors="${CLANG_TIDY_CHECKS}" \ + --header-filter="objectivec/include|objectivec|onnxruntime/core" \ + ./objectivec/*.mm \ + ./onnxruntime/core/platform/apple/logging/apple_log_sink.mm \ + ./onnxruntime/core/providers/coreml/model/*.mm diff --git a/.github/workflows/macos-ci-build-and-test-workflow.yml b/.github/workflows/macos-ci-build-and-test-workflow.yml new file mode 100644 index 0000000000000..2258891b8697e --- /dev/null +++ b/.github/workflows/macos-ci-build-and-test-workflow.yml @@ -0,0 +1,102 @@ +name: "macOS CI Reusable Workflow for build and test" +description: "This is a reusable workflow for macOS CI pipelines to build and test" + +on: + workflow_call: + inputs: + use_webgpu: + required: false + type: boolean + default: false + use_xnnpack: + required: false + type: boolean + default: false + use_coreml: + required: false + type: boolean + default: false + python_version: + required: false + type: string + default: "3.11" + +jobs: + build-and-test: + strategy: + matrix: + platform_machine: ["x86_64", "arm64"] + build_config: ["Debug", "Release"] + include: + - platform_machine: "x86_64" + runs_on: "macos-13" + xcode_version: "14.3.1" + - platform_machine: "arm64" + runs_on: "macos-15" + xcode_version: "16" + + runs-on: ${{ matrix.runs_on }} + env: + build_flags: > + --build_dir ./build + --skip_submodule_sync + --parallel + --use_binskim_compliant_compile_flags + --build_shared_lib + --build_nodejs + --build_objc + --build_java + --build_wheel + ${{ inputs.use_webgpu && '--use_webgpu' || '' }} + ${{ inputs.use_xnnpack && '--use_xnnpack' || '' }} + ${{ inputs.use_coreml && '--use_coreml' || '' }} + --use_vcpkg --use_vcpkg_ms_internal_asset_cache + --config ${{ matrix.build_config }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: macOS CI pipeline prepare steps + uses: ./.github/actions/macos-ci-setup + with: + platform_machine: ${{ matrix.platform_machine }} + python_version: ${{ inputs.python_version }} + xcode_version: ${{ matrix.xcode_version }} + use_cache: true + + - name: Setup environment variables + shell: bash + run: | + set -e -x + export PATH=${{ github.workspace }}/build/installed/bin:$PATH + export ONNX_ML=1 + export CMAKE_ARGS="-DONNX_GEN_PB_TYPE_STUBS=ON -DONNX_WERROR=OFF" + python -m pip install -r '${{ github.workspace }}/tools/ci_build/github/linux/docker/scripts/requirements.txt' + + - name: Configure Build (build.py --update) + shell: bash + working-directory: ${{ github.workspace }} + run: | + rm -rf ${{ github.workspace }}/build/${{ matrix.build_config }} + python ./tools/ci_build/build.py --update ${{ env.build_flags }} + + - name: Build (build.py --build) + shell: bash + working-directory: ${{ github.workspace }} + run: | + python ./tools/ci_build/build.py --build ${{ env.build_flags }} + + - name: Install + shell: bash + run: | + set -e -x + rm -rf ${{ github.workspace }}/build/installed + cd ${{ github.workspace }}/build/${{ matrix.build_config }} + make install DESTDIR=${{ github.workspace }}/build/installed + + - name: Running Tests (build.py --test) + shell: bash + working-directory: ${{ github.workspace }} + run: | + python ./tools/ci_build/build.py --test ${{ env.build_flags }} diff --git a/.github/workflows/macos_coreml.yml b/.github/workflows/macos_coreml.yml deleted file mode 100644 index f0acbd54a3fb1..0000000000000 --- a/.github/workflows/macos_coreml.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: "CoreML CI Pipeline" - -on: - push: - branches: [ main, 'rel-*'] - pull_request: - branches: [ main ] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build_with_coreml: - runs-on: macos-13 - strategy: - matrix: - use_coreml: [true, false] - - env: - MACOSX_DEPLOYMENT_TARGET: '13.3' - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install coreutils and ninja - run: brew install coreutils ninja - - - name: Use Xcode 14.3.1 - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_14.3.1.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - name: Export GitHub Actions cache environment variables - uses: actions/github-script@v7 - with: - script: | - core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); - core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - - - name: CoreML EP, Build and Test on macOS - run: | - python3 tools/ci_build/build.py \ - --build_dir build \ - --skip_submodule_sync \ - --cmake_generator=Ninja \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags \ - --build_shared_lib \ - --config Debug \ - ${{ matrix.use_coreml && '--use_coreml' || '' }} \ No newline at end of file From 5244d68b1feda419955081e49079c9464a30f233 Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Mon, 24 Mar 2025 16:05:40 -0700 Subject: [PATCH 157/266] Address Windows CUDA build issue (#24149) ### Description Create a separate template overloads to address Windows Debug build warning 'unreachable code'. --- .../contrib_ops/cuda/bert/attention_qk.cu | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu b/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu index b81783377936f..3f02a441da73e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_qk.cu @@ -37,26 +37,17 @@ Status CopyQK(cudaStream_t stream, const int qk_size, const T* input, QK* output) { - if constexpr (std::is_same::value) { - CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(output, input, qk_size * sizeof(QK), cudaMemcpyDeviceToDevice, stream)); - return Status::OK(); - } - const bool half2float = std::is_same::value && std::is_same::value; - const bool float2half = std::is_same::value && std::is_same::value; - ORT_ENFORCE(half2float || float2half); + constexpr const bool half2float = std::is_same::value && std::is_same::value; + constexpr const bool float2half = std::is_same::value && std::is_same::value; + static_assert(half2float || float2half, "This function supports either or "); - int block_size = 256; + constexpr const int block_size = 256; int num_blocks = (qk_size + block_size - 1) / block_size; ConvertAndCopyQK<<>>(qk_size, input, output); return CUDA_CALL(cudaGetLastError()); } -template Status CopyQK(cudaStream_t stream, - const int qk_size, - const float* input, - float* output); - template Status CopyQK(cudaStream_t stream, const int qk_size, const float* input, @@ -67,10 +58,23 @@ template Status CopyQK(cudaStream_t stream, const half* input, float* output); -template Status CopyQK(cudaStream_t stream, - const int qk_size, - const half* input, - half* output); +template <> +Status CopyQK(cudaStream_t stream, + const int qk_size, + const float* input, + float* output) { + CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(output, input, qk_size * sizeof(float), cudaMemcpyDeviceToDevice, stream)); + return Status::OK(); +} + +template <> +Status CopyQK(cudaStream_t stream, + const int qk_size, + const half* input, + half* output) { + CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(output, input, qk_size * sizeof(half), cudaMemcpyDeviceToDevice, stream)); + return Status::OK(); +} } // namespace cuda } // namespace contrib From e03631ee528c84dde47f5289752c556ec3725b4c Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 24 Mar 2025 16:10:40 -0700 Subject: [PATCH 158/266] [webgpu] add option to perserve device and enable in unittest (#24115) ### Description This PR introduced a new WebGPU EP option `preserveDevice`. Before this change, a WebGPU device will be destroyed when no inference session uses it. The destroy of a WebGPU device will cleanup both buffer cache and shader cache. After this option is introduced, when the option is ON (default value is OFF), the device will no longer be destroyed and will be always keep alive. This is helpful in 2 scenarios: - A server that will be always on - unittest so that bugs of incorrect shader cache may be detected. (thanks to @qjia7 for the suggestion) --- .../contrib_ops/webgpu/bert/rotary_embedding.cc | 2 +- .../providers/webgpu/reduction/reduction_ops.cc | 8 +++++++- .../core/providers/webgpu/webgpu_context.cc | 4 ++-- onnxruntime/core/providers/webgpu/webgpu_context.h | 6 ++++-- .../providers/webgpu/webgpu_provider_factory.cc | 14 ++++++++++++++ .../providers/webgpu/webgpu_provider_options.h | 5 +++++ onnxruntime/test/util/default_providers.cc | 4 ++++ 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc index b33084d60cec3..8f316cfae80e9 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc @@ -100,7 +100,7 @@ Status RotaryEmbedding::ComputeInternal(onnxruntime::webgpu::ComputeContext& con program .CacheHint(interleaved_) - .AddInputs({{input, ProgramTensorMetadataDependency::Rank}, + .AddInputs({{input, ProgramTensorMetadataDependency::TypeAndRank}, {position_ids, ProgramTensorMetadataDependency::Rank}, {cos_cache, ProgramTensorMetadataDependency::Rank}, {sin_cache, ProgramTensorMetadataDependency::Rank}}) diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index 11fa30c798809..8f2619b6cb2b6 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -247,7 +247,13 @@ Status ReduceKernel::ComputeInternal(ComputeContext& context) program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}); } - program.CacheHint(is_input_empty) + // TODO: the ReduceKernel class is designed to use `keepdims_`, `noop_with_empty_axes_` and input axes as uniform variables, + // but the current implementation does not work without them in cache key. + // This is a temporary workaround to make it work. We should fix this in the future. + program.CacheHint(keepdims_, + noop_with_empty_axes_, + select_last_index_, + absl::StrJoin(input_axes, ",")) .AddOutput({context.Output(0, output_shape), ProgramTensorMetadataDependency::TypeAndRank}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) .AddUniformVariables({{static_cast(output_size)}, diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 82ba00f8d09e7..9234aab58dd99 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -768,7 +768,7 @@ WebGpuContext& WebGpuContextFactory::CreateContext(const WebGpuContextConfig& co auto it = contexts_.find(context_id); if (it == contexts_.end()) { GSL_SUPPRESS(r.11) - auto context = std::unique_ptr(new WebGpuContext(instance, device, config.validation_mode)); + auto context = std::unique_ptr(new WebGpuContext(instance, device, config.validation_mode, config.preserve_device)); it = contexts_.emplace(context_id, WebGpuContextFactory::WebGpuContextInfo{std::move(context), 0}).first; } else if (context_id != 0) { ORT_ENFORCE(it->second.context->instance_.Get() == instance && @@ -794,7 +794,7 @@ void WebGpuContextFactory::ReleaseContext(int context_id) { auto it = contexts_.find(context_id); ORT_ENFORCE(it != contexts_.end(), "WebGPU EP context ID ", context_id, " is not found."); - if (--it->second.ref_count == 0) { + if (--it->second.ref_count == 0 && !it->second.context->preserve_device_) { contexts_.erase(it); } } diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index a221bbcec95c3..96f5a0cebc5c1 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -32,6 +32,7 @@ struct WebGpuContextConfig { WGPUDevice device; const void* dawn_proc_table; ValidationMode validation_mode; + bool preserve_device; }; struct WebGpuBufferCacheConfig { @@ -152,8 +153,8 @@ class WebGpuContext final { AtPasses }; - WebGpuContext(WGPUInstance instance, WGPUDevice device, webgpu::ValidationMode validation_mode) - : instance_{instance}, device_{device}, validation_mode_{validation_mode}, query_type_{TimestampQueryType::None} {} + WebGpuContext(WGPUInstance instance, WGPUDevice device, webgpu::ValidationMode validation_mode, bool preserve_device) + : instance_{instance}, device_{device}, validation_mode_{validation_mode}, query_type_{TimestampQueryType::None}, preserve_device_{preserve_device} {} ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(WebGpuContext); std::vector GetEnabledAdapterToggles() const; @@ -229,6 +230,7 @@ class WebGpuContext final { uint64_t gpu_timestamp_offset_ = 0; bool is_profiling_ = false; + bool preserve_device_; #if defined(ENABLE_PIX_FOR_WEBGPU_EP) std::unique_ptr pix_frame_generator_ = nullptr; diff --git a/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc b/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc index 1d779152f91f3..d6812b2d0704d 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc @@ -143,12 +143,25 @@ std::shared_ptr WebGpuProviderFactoryCreator::Create( } } + std::string preserve_device_str; + bool preserve_device = false; + if (config_options.TryGetConfigEntry(kPreserveDevice, preserve_device_str)) { + if (preserve_device_str == kPreserveDevice_ON) { + preserve_device = true; + } else if (preserve_device_str == kPreserveDevice_OFF) { + preserve_device = false; + } else { + ORT_THROW("Invalid preserve device: ", preserve_device_str); + } + } + webgpu::WebGpuContextConfig context_config{ context_id, reinterpret_cast(webgpu_instance), reinterpret_cast(webgpu_device), reinterpret_cast(dawn_proc_table), validation_mode, + preserve_device, }; LOGS_DEFAULT(VERBOSE) << "WebGPU EP Device ID: " << context_id; @@ -156,6 +169,7 @@ std::shared_ptr WebGpuProviderFactoryCreator::Create( LOGS_DEFAULT(VERBOSE) << "WebGPU EP WGPUDevice: " << webgpu_device; LOGS_DEFAULT(VERBOSE) << "WebGPU EP DawnProcTable: " << dawn_proc_table; LOGS_DEFAULT(VERBOSE) << "WebGPU EP ValidationMode: " << validation_mode; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP PreserveDevice: " << preserve_device; // // STEP.3 - prepare parameters for WebGPU context initialization. diff --git a/onnxruntime/core/providers/webgpu/webgpu_provider_options.h b/onnxruntime/core/providers/webgpu/webgpu_provider_options.h index 1cf316f4304e5..fcfd6774f8ab8 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_provider_options.h +++ b/onnxruntime/core/providers/webgpu/webgpu_provider_options.h @@ -30,6 +30,8 @@ constexpr const char* kValidationMode = "WebGPU:validationMode"; constexpr const char* kForceCpuNodeNames = "WebGPU:forceCpuNodeNames"; constexpr const char* kEnablePIXCapture = "WebGPU:enablePIXCapture"; +constexpr const char* kPreserveDevice = "WebGPU:preserveDevice"; + // The following are the possible values for the provider options. constexpr const char* kDawnBackendType_D3D12 = "D3D12"; @@ -44,6 +46,9 @@ constexpr const char* kEnableGraphCapture_OFF = "0"; constexpr const char* kEnablePIXCapture_ON = "1"; constexpr const char* kEnablePIXCapture_OFF = "0"; +constexpr const char* kPreserveDevice_ON = "1"; +constexpr const char* kPreserveDevice_OFF = "0"; + constexpr const char* kBufferCacheMode_Disabled = "disabled"; constexpr const char* kBufferCacheMode_LazyRelease = "lazyRelease"; constexpr const char* kBufferCacheMode_Simple = "simple"; diff --git a/onnxruntime/test/util/default_providers.cc b/onnxruntime/test/util/default_providers.cc index c1564997c42b8..83fb548968d77 100644 --- a/onnxruntime/test/util/default_providers.cc +++ b/onnxruntime/test/util/default_providers.cc @@ -303,6 +303,10 @@ std::unique_ptr DefaultWebGpuExecutionProvider() { ORT_ENFORCE(config_options.AddConfigEntry(webgpu::options::kStorageBufferCacheMode, webgpu::options::kBufferCacheMode_Disabled) .IsOK()); + // Disable device auto collect + ORT_ENFORCE(config_options.AddConfigEntry(webgpu::options::kPreserveDevice, + webgpu::options::kPreserveDevice_ON) + .IsOK()); return WebGpuProviderFactoryCreator::Create(config_options)->CreateProvider(); #else return nullptr; From 78d91cdd439d9c67247c3eaafa59815b6b312225 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 24 Mar 2025 16:10:54 -0700 Subject: [PATCH 159/266] [js/web] allow bundler import condition for not bundling wasm (#24014) ### Description This gives a way for webapp developers to customize the bundler behavior regarding whether to bundle the wasm. To avoid treating ort-wasm-threaded-simd.jsep.mjs and ort-wasm-threaded-simd.jsep.wasm as dependencies during the process of bundler build, use import condition `onnxruntime-web-use-extern-wasm`. For webpack: ``` module.exports = { //... resolve: { conditionNames: ['onnxruntime-web-use-extern-wasm', 'import', 'module'], }, }; ``` For esbuild: ``` await esbuild.build({ //... conditions: ['onnxruntime-web-use-extern-wasm', 'import', 'module'], }) ``` For rollup: ``` import { nodeResolve } from '@rollup/plugin-node-resolve'; export default { //... plugins: [nodeResolve({ exportConditions: ['onnxruntime-web-use-extern-wasm', 'import', 'module', 'development|production'] })] }; ``` ### Motivation and Context - #24009 --- js/web/package.json | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/js/web/package.json b/js/web/package.json index b95d78e404cb0..af02453b0870a 100644 --- a/js/web/package.json +++ b/js/web/package.json @@ -72,15 +72,24 @@ "import": "./dist/ort.node.min.mjs", "require": "./dist/ort.node.min.js" }, - "import": "./dist/ort.bundle.min.mjs", + "import": { + "onnxruntime-web-use-extern-wasm": "./dist/ort.min.mjs", + "default": "./dist/ort.bundle.min.mjs" + }, "require": "./dist/ort.min.js" }, "./all": { - "import": "./dist/ort.all.bundle.min.mjs", + "import": { + "onnxruntime-web-use-extern-wasm": "./dist/ort.all.min.mjs", + "default": "./dist/ort.all.bundle.min.mjs" + }, "require": "./dist/ort.all.min.js" }, "./wasm": { - "import": "./dist/ort.wasm.bundle.min.mjs", + "import": { + "onnxruntime-web-use-extern-wasm": "./dist/ort.wasm.min.mjs", + "default": "./dist/ort.wasm.bundle.min.mjs" + }, "require": "./dist/ort.wasm.min.js" }, "./webgl": { @@ -88,7 +97,10 @@ "require": "./dist/ort.webgl.min.js" }, "./webgpu": { - "import": "./dist/ort.webgpu.bundle.min.mjs", + "import": { + "onnxruntime-web-use-extern-wasm": "./dist/ort.webgpu.min.mjs", + "default": "./dist/ort.webgpu.bundle.min.mjs" + }, "require": "./dist/ort.webgpu.min.js" } }, From 618aef7ec92d3e30ac692f769b5ddb6ed52ce1c6 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 24 Mar 2025 16:11:10 -0700 Subject: [PATCH 160/266] [js] Add API for accessing metadata of a model's input/output (#23937) ### Description Add API for accessing metadata of a model's input/output. Currently, The implementation is only applied to web assembly backend and nodejs binding. For webgl, there is so far no plan to implement this API; for react-native, the implementation will be done later and is not included in this PR. #### Example usage: ```js const mySession = await ort.InferenceSession.create( ... ); console.log(`there are ${mySession.inputMetadata.length} inputs:`); for (let i = 0; i < mySession.inputMetadata.length; i++) { let info; if (mySession.inputMetadata[i].isTensor) { info = `tensor: ${mySession.inputMetadata[i].type}, shape: ${mySession.inputMetadata[i].shape}`; } else { info = `non-tensor`; } console.log(`input ${i}: ${mySession.inputMetadata[i].name}: ${info}`); } ``` possible output: ``` there are 1 inputs: input 0: input: tensor: float32, shape: [batch, 3, 224, 224] ``` Resolves: - #22682 - #22949 --- js/.eslintrc.js | 3 +- js/common/lib/backend.ts | 3 + js/common/lib/inference-session-impl.ts | 8 ++ js/common/lib/inference-session.ts | 65 +++++++++-- js/node/lib/backend.ts | 81 ++++++++++++- js/node/lib/binding.ts | 11 +- js/node/src/inference_session_wrap.cc | 58 +++++----- js/node/src/inference_session_wrap.h | 19 +--- js/node/test/test-main.ts | 1 + js/node/test/unittests/lib/model-metadata.ts | 86 ++++++++++++++ js/react_native/lib/backend.ts | 7 ++ js/web/lib/backend-wasm.ts | 2 +- .../lib/onnxjs/session-handler-inference.ts | 8 ++ js/web/lib/wasm/proxy-messages.ts | 8 +- js/web/lib/wasm/session-handler-inference.ts | 11 +- js/web/lib/wasm/wasm-core-impl.ts | 80 +++++++++++-- js/web/lib/wasm/wasm-types.ts | 8 +- js/web/test/test-runner.ts | 5 +- .../backends/wasm/test-model-metadata.ts | 86 ++++++++++++++ js/web/test/unittests/index.ts | 2 + onnxruntime/wasm/api.cc | 107 ++++++++++++++++++ onnxruntime/wasm/api.h | 18 ++- 22 files changed, 586 insertions(+), 91 deletions(-) create mode 100644 js/node/test/unittests/lib/model-metadata.ts create mode 100644 js/web/test/unittests/backends/wasm/test-model-metadata.ts diff --git a/js/.eslintrc.js b/js/.eslintrc.js index 462e417df1d66..f20adcb0eaa52 100644 --- a/js/.eslintrc.js +++ b/js/.eslintrc.js @@ -185,10 +185,9 @@ module.exports = { '_OrtCreateTensor', '_OrtEndProfiling', '_OrtFree', - '_OrtGetInputName', '_OrtGetInputOutputCount', + '_OrtGetInputOutputMetadata', '_OrtGetLastError', - '_OrtGetOutputName', '_OrtGetTensorData', '_OrtInit', '_OrtReleaseBinding', diff --git a/js/common/lib/backend.ts b/js/common/lib/backend.ts index e63f9c6c9147f..9b7c1db219188 100644 --- a/js/common/lib/backend.ts +++ b/js/common/lib/backend.ts @@ -23,6 +23,9 @@ interface SessionHandler { readonly inputNames: readonly string[]; readonly outputNames: readonly string[]; + + readonly inputMetadata: readonly InferenceSession.ValueMetadata[]; + readonly outputMetadata: readonly InferenceSession.ValueMetadata[]; } /** diff --git a/js/common/lib/inference-session-impl.ts b/js/common/lib/inference-session-impl.ts index d47ed7a331045..797dba8b94089 100644 --- a/js/common/lib/inference-session-impl.ts +++ b/js/common/lib/inference-session-impl.ts @@ -225,5 +225,13 @@ export class InferenceSession implements InferenceSessionInterface { return this.handler.outputNames; } + get inputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] { + return this.handler.inputMetadata; + } + + get outputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] { + return this.handler.outputMetadata; + } + private handler: InferenceSessionHandler; } diff --git a/js/common/lib/inference-session.ts b/js/common/lib/inference-session.ts index 26784be41ca7c..330d4121475ec 100644 --- a/js/common/lib/inference-session.ts +++ b/js/common/lib/inference-session.ts @@ -4,6 +4,7 @@ import { InferenceSession as InferenceSessionImpl } from './inference-session-impl.js'; import { OnnxModelOptions } from './onnx-model.js'; import { OnnxValue, OnnxValueDataLocation } from './onnx-value.js'; +import type { Tensor } from './tensor.js'; import { TryGetGlobalType } from './type-helper.js'; /* eslint-disable @typescript-eslint/no-redeclare */ @@ -430,11 +431,53 @@ export declare namespace InferenceSession { // #region value metadata - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface ValueMetadata { - // TBD + /** + * The common part of the value metadata type for both tensor and non-tensor values. + */ + export interface ValueMetadataBase { + /** + * The name of the specified input or output. + */ + readonly name: string; } + /** + * Represents the metadata of a non-tensor value. + */ + export interface NonTensorValueMetadata extends ValueMetadataBase { + /** + * Get a value indicating whether the value is a tensor. + */ + readonly isTensor: false; + } + + /** + * Represents the metadata of a tensor value. + */ + export interface TensorValueMetadata extends ValueMetadataBase { + /** + * Get a value indicating whether the value is a tensor. + */ + readonly isTensor: true; + /** + * Get the data type of the tensor. + */ + readonly type: Tensor.Type; + /** + * Get the shape of the tensor. + * + * If the shape is not defined, the value will an empty array. Otherwise, it will be an array representing the shape + * of the tensor. Each element in the array can be a number or a string. If the element is a number, it represents + * the corresponding dimension size. If the element is a string, it represents a symbolic dimension. + */ + readonly shape: ReadonlyArray; + } + + /** + * Represents the metadata of a value. + */ + export type ValueMetadata = NonTensorValueMetadata | TensorValueMetadata; + // #endregion } @@ -505,15 +548,15 @@ export interface InferenceSession { */ readonly outputNames: readonly string[]; - // /** - // * Get input metadata of the loaded model. - // */ - // readonly inputMetadata: ReadonlyArray>; + /** + * Get input metadata of the loaded model. + */ + readonly inputMetadata: readonly InferenceSession.ValueMetadata[]; - // /** - // * Get output metadata of the loaded model. - // */ - // readonly outputMetadata: ReadonlyArray>; + /** + * Get output metadata of the loaded model. + */ + readonly outputMetadata: readonly InferenceSession.ValueMetadata[]; // #endregion } diff --git a/js/node/lib/backend.ts b/js/node/lib/backend.ts index 004a3c890a7e4..bea9debcfdd4d 100644 --- a/js/node/lib/backend.ts +++ b/js/node/lib/backend.ts @@ -5,6 +5,32 @@ import { Backend, InferenceSession, InferenceSessionHandler, SessionHandler } fr import { Binding, binding, initOrt } from './binding'; +const dataTypeStrings = [ + undefined, // 0 + 'float32', + 'uint8', + 'int8', + 'uint16', + 'int16', + 'int32', + 'int64', + 'string', + 'bool', + 'float16', + 'float64', + 'uint32', + 'uint64', + undefined, // 14 + undefined, // 15 + undefined, // 16 + undefined, // 17 + undefined, // 18 + undefined, // 19 + undefined, // 20 + 'uint4', + 'int4', +] as const; + class OnnxruntimeSessionHandler implements InferenceSessionHandler { #inferenceSession: Binding.InferenceSession; @@ -17,8 +43,56 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { } else { this.#inferenceSession.loadModel(pathOrBuffer.buffer, pathOrBuffer.byteOffset, pathOrBuffer.byteLength, options); } - this.inputNames = this.#inferenceSession.inputNames; - this.outputNames = this.#inferenceSession.outputNames; + + // prepare input/output names and metadata + this.inputNames = []; + this.outputNames = []; + this.inputMetadata = []; + this.outputMetadata = []; + + // this function takes raw metadata from binding and returns a tuple of the following 2 items: + // - an array of string representing names + // - an array of converted InferenceSession.ValueMetadata + const fillNamesAndMetadata = ( + rawMetadata: readonly Binding.ValueMetadata[], + ): [names: string[], metadata: InferenceSession.ValueMetadata[]] => { + const names: string[] = []; + const metadata: InferenceSession.ValueMetadata[] = []; + + for (const m of rawMetadata) { + names.push(m.name); + if (!m.isTensor) { + metadata.push({ name: m.name, isTensor: false }); + } else { + const type = dataTypeStrings[m.type]; + if (type === undefined) { + throw new Error(`Unsupported data type: ${m.type}`); + } + const shape: Array = []; + for (let i = 0; i < m.shape.length; ++i) { + const dim = m.shape[i]; + if (dim === -1) { + shape.push(m.symbolicDimensions[i]); + } else if (dim >= 0) { + shape.push(dim); + } else { + throw new Error(`Invalid dimension: ${dim}`); + } + } + metadata.push({ + name: m.name, + isTensor: m.isTensor, + type, + shape, + }); + } + } + + return [names, metadata]; + }; + + [this.inputNames, this.inputMetadata] = fillNamesAndMetadata(this.#inferenceSession.inputMetadata); + [this.outputNames, this.outputMetadata] = fillNamesAndMetadata(this.#inferenceSession.outputMetadata); } async dispose(): Promise { @@ -28,6 +102,9 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { readonly inputNames: string[]; readonly outputNames: string[]; + readonly inputMetadata: InferenceSession.ValueMetadata[]; + readonly outputMetadata: InferenceSession.ValueMetadata[]; + startProfiling(): void { // startProfiling is a no-op. // diff --git a/js/node/lib/binding.ts b/js/node/lib/binding.ts index 56203f5a5ca02..ed133734ce66a 100644 --- a/js/node/lib/binding.ts +++ b/js/node/lib/binding.ts @@ -19,12 +19,19 @@ type RunOptions = InferenceSession.RunOptions; * Binding exports a simple synchronized inference session object wrap. */ export declare namespace Binding { + export interface ValueMetadata { + name: string; + isTensor: boolean; + symbolicDimensions: string[]; + shape: number[]; + type: number; + } export interface InferenceSession { loadModel(modelPath: string, options: SessionOptions): void; loadModel(buffer: ArrayBuffer, byteOffset: number, byteLength: number, options: SessionOptions): void; - readonly inputNames: string[]; - readonly outputNames: string[]; + readonly inputMetadata: ValueMetadata[]; + readonly outputMetadata: ValueMetadata[]; run(feeds: FeedsType, fetches: FetchesType, options: RunOptions): ReturnType; diff --git a/js/node/src/inference_session_wrap.cc b/js/node/src/inference_session_wrap.cc index 04ab71dc48ec2..5512b418b5cfb 100644 --- a/js/node/src/inference_session_wrap.cc +++ b/js/node/src/inference_session_wrap.cc @@ -34,8 +34,8 @@ Napi::Object InferenceSessionWrap::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("run", &InferenceSessionWrap::Run), InstanceMethod("dispose", &InferenceSessionWrap::Dispose), InstanceMethod("endProfiling", &InferenceSessionWrap::EndProfiling), - InstanceAccessor("inputNames", &InferenceSessionWrap::GetInputNames, nullptr, napi_default, nullptr), - InstanceAccessor("outputNames", &InferenceSessionWrap::GetOutputNames, nullptr, napi_default, nullptr)}); + InstanceAccessor("inputMetadata", &InferenceSessionWrap::GetMetadata, nullptr, napi_default, reinterpret_cast(true)), + InstanceAccessor("outputMetadata", &InferenceSessionWrap::GetMetadata, nullptr, napi_default, reinterpret_cast(false))}); wrappedSessionConstructor = Napi::Persistent(func); wrappedSessionConstructor.SuppressDestruct(); @@ -120,27 +120,17 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { size_t count = session_->GetInputCount(); inputNames_.reserve(count); for (size_t i = 0; i < count; i++) { - auto inp_name = session_->GetInputNameAllocated(i, allocator); - inputNames_.emplace_back(inp_name.get()); - auto typeInfo = session_->GetInputTypeInfo(i); - auto onnxType = typeInfo.GetONNXType(); - inputTypes_.emplace_back(onnxType); - inputTensorElementDataTypes_.emplace_back(onnxType == ONNX_TYPE_TENSOR - ? typeInfo.GetTensorTypeAndShapeInfo().GetElementType() - : ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED); + auto input_name = session_->GetInputNameAllocated(i, allocator); + inputNames_.emplace_back(input_name.get()); + inputTypes_.push_back(session_->GetInputTypeInfo(i)); } count = session_->GetOutputCount(); outputNames_.reserve(count); for (size_t i = 0; i < count; i++) { - auto out_name = session_->GetOutputNameAllocated(i, allocator); - outputNames_.emplace_back(out_name.get()); - auto typeInfo = session_->GetOutputTypeInfo(i); - auto onnxType = typeInfo.GetONNXType(); - outputTypes_.emplace_back(onnxType); - outputTensorElementDataTypes_.emplace_back(onnxType == ONNX_TYPE_TENSOR - ? typeInfo.GetTensorTypeAndShapeInfo().GetElementType() - : ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED); + auto output_name = session_->GetOutputNameAllocated(i, allocator); + outputNames_.emplace_back(output_name.get()); + outputTypes_.push_back(session_->GetOutputTypeInfo(i)); } // cache preferred output locations @@ -157,22 +147,32 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { return env.Undefined(); } -Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo& info) { +Napi::Value InferenceSessionWrap::GetMetadata(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); Napi::EscapableHandleScope scope(env); - return scope.Escape(CreateNapiArrayFrom(env, inputNames_)); -} - -Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); - ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); - - Napi::EscapableHandleScope scope(env); - return scope.Escape(CreateNapiArrayFrom(env, outputNames_)); + auto& names = info.Data() != nullptr ? inputNames_ : outputNames_; + auto& types = info.Data() != nullptr ? inputTypes_ : outputTypes_; + auto array = Napi::Array::New(env, types.size()); + for (uint32_t i = 0; i < types.size(); i++) { + Napi::Object obj = Napi::Object::New(env); + obj.Set("name", names[i]); + auto& typeInfo = types[i]; + if (typeInfo.GetONNXType() == ONNX_TYPE_TENSOR) { + obj.Set("isTensor", true); + + auto tensorInfo = typeInfo.GetTensorTypeAndShapeInfo(); + obj.Set("type", static_cast>(tensorInfo.GetElementType())); + obj.Set("symbolicDimensions", CreateNapiArrayFrom(env, tensorInfo.GetSymbolicDimensions())); + obj.Set("shape", CreateNapiArrayFrom(env, tensorInfo.GetShape())); + } else { + obj.Set("isTensor", false); + } + array.Set(i, Napi::Value::From(env, obj)); + } + return scope.Escape(array); } Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { diff --git a/js/node/src/inference_session_wrap.h b/js/node/src/inference_session_wrap.h index 0b3dd1178c807..776cdc0d3b51e 100644 --- a/js/node/src/inference_session_wrap.h +++ b/js/node/src/inference_session_wrap.h @@ -45,19 +45,12 @@ class InferenceSessionWrap : public Napi::ObjectWrap { // following functions have to be called after model is loaded. /** - * [sync] get input names. + * [sync] get metadata of the model's inputs or outputs. * @param nothing - * @returns a string array. + * @returns an array of objects with keys: name, isTensor, type, symbolicDimensions, shape * @throw nothing */ - Napi::Value GetInputNames(const Napi::CallbackInfo& info); - /** - * [sync] get output names. - * @param nothing - * @returns a string array. - * @throw nothing - */ - Napi::Value GetOutputNames(const Napi::CallbackInfo& info); + Napi::Value GetMetadata(const Napi::CallbackInfo& info); /** * [sync] run the model. @@ -98,11 +91,9 @@ class InferenceSessionWrap : public Napi::ObjectWrap { // input/output metadata std::vector inputNames_; - std::vector inputTypes_; - std::vector inputTensorElementDataTypes_; + std::vector inputTypes_; std::vector outputNames_; - std::vector outputTypes_; - std::vector outputTensorElementDataTypes_; + std::vector outputTypes_; // preferred output locations std::vector preferredOutputLocations_; diff --git a/js/node/test/test-main.ts b/js/node/test/test-main.ts index fc792179d3373..6e7905a24711a 100644 --- a/js/node/test/test-main.ts +++ b/js/node/test/test-main.ts @@ -15,6 +15,7 @@ warmup(); // unittests require('./unittests/lib/index'); require('./unittests/lib/inference-session'); +require('./unittests/lib/model-metadata'); require('./unittests/lib/tensor'); // E2E tests diff --git a/js/node/test/unittests/lib/model-metadata.ts b/js/node/test/unittests/lib/model-metadata.ts new file mode 100644 index 0000000000000..e58c86d39a742 --- /dev/null +++ b/js/node/test/unittests/lib/model-metadata.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as assert from 'assert'; +import { InferenceSession } from 'onnxruntime-common'; + +const ONNX_MODEL_TEST_ABS_NO_SHAPE = Uint8Array.from([ + 8, 9, 58, 73, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 15, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 4, 10, 2, + 8, 1, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, 66, 4, 10, 0, 16, 21, +]); + +const ONNX_MODEL_TEST_ABS_SYMBOL = Uint8Array.from([ + 8, 9, 58, 105, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 47, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 36, 10, + 34, 8, 1, 18, 30, 10, 13, 18, 11, 95, 105, 110, 112, 117, 116, 95, 48, 95, 100, 48, 10, 13, 18, 11, 95, 105, 110, 112, + 117, 116, 95, 48, 95, 100, 49, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, 66, 4, 10, 0, + 16, 21, +]); + +const ONNX_MODEL_TEST_ABS_STATIC = Uint8Array.from([ + 8, 9, 58, 83, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 25, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 14, 10, + 12, 8, 1, 18, 8, 10, 2, 8, 2, 10, 2, 8, 4, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, + 66, 4, 10, 0, 16, 21, +]); + +const testModelMetadata = async ( + model: Uint8Array, + expectedInputNames: string[], + expectedOutputNames: string[], + expectedInputMetadata: InferenceSession.ValueMetadata[], + expectedOutputMetadata: InferenceSession.ValueMetadata[], +) => { + const session = await InferenceSession.create(model); + assert.deepStrictEqual(session.inputNames, expectedInputNames); + assert.deepStrictEqual(session.outputNames, expectedOutputNames); + assert.deepStrictEqual(session.inputMetadata, expectedInputMetadata); + assert.deepStrictEqual(session.outputMetadata, expectedOutputMetadata); +}; + +describe('#UnitTest# - test model input/output metadata', () => { + it('model input/output with no shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_NO_SHAPE, + ['input_0'], + ['output_0'], + [{ name: 'input_0', isTensor: true, type: 'float32', shape: [] }], + [{ name: 'output_0', isTensor: true, type: 'float32', shape: [] }], + ); + }); + + it('model input/output with symbol shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_SYMBOL, + ['input_0'], + ['output_0'], + [ + { + name: 'input_0', + isTensor: true, + type: 'float32', + shape: ['_input_0_d0', '_input_0_d1'], + }, + ], + [ + { + name: 'output_0', + isTensor: true, + type: 'float32', + shape: ['_input_0_d0', '_input_0_d1'], + }, + ], + ); + }); + + it('model input/output with static shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_STATIC, + ['input_0'], + ['output_0'], + [{ name: 'input_0', isTensor: true, type: 'float32', shape: [2, 4] }], + [{ name: 'output_0', isTensor: true, type: 'float32', shape: [2, 4] }], + ); + }); +}); diff --git a/js/react_native/lib/backend.ts b/js/react_native/lib/backend.ts index 854a7ffd9a6ab..edc28c2e43de9 100644 --- a/js/react_native/lib/backend.ts +++ b/js/react_native/lib/backend.ts @@ -66,6 +66,13 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { inputNames: string[]; outputNames: string[]; + get inputMetadata(): readonly InferenceSession.ValueMetadata[] { + throw new Error('Getting model metadata is currently not implemented for react-native backend.'); + } + get outputMetadata(): readonly InferenceSession.ValueMetadata[] { + throw new Error('Getting model metadata is currently not implemented for react-native backend.'); + } + constructor(pathOrBuffer: string | Uint8Array) { this.#inferenceSession = binding; this.#pathOrBuffer = pathOrBuffer; diff --git a/js/web/lib/backend-wasm.ts b/js/web/lib/backend-wasm.ts index 72b51d565896a..5e5f4804aed92 100644 --- a/js/web/lib/backend-wasm.ts +++ b/js/web/lib/backend-wasm.ts @@ -88,7 +88,7 @@ export class OnnxruntimeWebAssemblyBackend implements Backend { ): Promise { const handler = new OnnxruntimeWebAssemblySessionHandler(); await handler.loadModel(pathOrBuffer, options); - return Promise.resolve(handler); + return handler; } } diff --git a/js/web/lib/onnxjs/session-handler-inference.ts b/js/web/lib/onnxjs/session-handler-inference.ts index c1c2576971840..f13ee7a56c78a 100644 --- a/js/web/lib/onnxjs/session-handler-inference.ts +++ b/js/web/lib/onnxjs/session-handler-inference.ts @@ -12,6 +12,14 @@ export class OnnxjsSessionHandler implements InferenceSessionHandler { this.outputNames = this.session.outputNames; } + get inputMetadata(): readonly InferenceSession.ValueMetadata[] { + throw new Error('Getting model metadata is not supported in webgl backend.'); + } + + get outputMetadata(): readonly InferenceSession.ValueMetadata[] { + throw new Error('Getting model metadata is not supported in webgl backend.'); + } + async dispose(): Promise {} inputNames: readonly string[]; outputNames: readonly string[]; diff --git a/js/web/lib/wasm/proxy-messages.ts b/js/web/lib/wasm/proxy-messages.ts index 559f319a10f66..2584203d4503b 100644 --- a/js/web/lib/wasm/proxy-messages.ts +++ b/js/web/lib/wasm/proxy-messages.ts @@ -46,7 +46,13 @@ export type UnserializableTensorMetadata = */ export type TensorMetadata = SerializableTensorMetadata | UnserializableTensorMetadata; -export type SerializableSessionMetadata = [sessionHandle: number, inputNames: string[], outputNames: string[]]; +export type SerializableSessionMetadata = [ + sessionHandle: number, + inputNames: string[], + outputNames: string[], + inputMetadata: InferenceSession.ValueMetadata[], + outputMetadata: InferenceSession.ValueMetadata[], +]; export type SerializableInternalBuffer = [bufferOffset: number, bufferLength: number]; diff --git a/js/web/lib/wasm/session-handler-inference.ts b/js/web/lib/wasm/session-handler-inference.ts index c19043cc3637f..1fa2216b57219 100644 --- a/js/web/lib/wasm/session-handler-inference.ts +++ b/js/web/lib/wasm/session-handler-inference.ts @@ -57,8 +57,10 @@ export const decodeTensorMetadata = (tensor: TensorMetadata): Tensor => { export class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHandler { private sessionId: number; - inputNames: string[]; - outputNames: string[]; + inputNames: readonly string[]; + outputNames: readonly string[]; + inputMetadata: readonly InferenceSession.ValueMetadata[]; + outputMetadata: readonly InferenceSession.ValueMetadata[]; async fetchModelAndCopyToWasmMemory(path: string): Promise { // fetch model from url and move to wasm heap. @@ -82,7 +84,10 @@ export class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHan model = pathOrBuffer; } - [this.sessionId, this.inputNames, this.outputNames] = await createSession(model, options); + [this.sessionId, this.inputNames, this.outputNames, this.inputMetadata, this.outputMetadata] = await createSession( + model, + options, + ); TRACE_FUNC_END(); } diff --git a/js/web/lib/wasm/wasm-core-impl.ts b/js/web/lib/wasm/wasm-core-impl.ts index bb532e0fbae74..8dd643293937b 100644 --- a/js/web/lib/wasm/wasm-core-impl.ts +++ b/js/web/lib/wasm/wasm-core-impl.ts @@ -229,6 +229,49 @@ const getSessionInputOutputCount = (sessionHandle: number): [number, number] => } }; +const getSessionInputOutputMetadata = ( + sessionHandle: number, + index: number, +): [nameOffset: number, elementType: number, dims?: Array] => { + const wasm = getInstance(); + const stack = wasm.stackSave(); + let metadataOffset = 0; + try { + const ptrSize = wasm.PTR_SIZE; + const dataOffset = wasm.stackAlloc(2 * ptrSize); + const errorCode = wasm._OrtGetInputOutputMetadata(sessionHandle, index, dataOffset, dataOffset + ptrSize); + if (errorCode !== 0) { + checkLastError("Can't get session input/output metadata."); + } + const nameOffset = Number(wasm.getValue(dataOffset, '*')); + metadataOffset = Number(wasm.getValue(dataOffset + ptrSize, '*')); + // get element type + const elementType = wasm.HEAP32[metadataOffset / 4]; + if (elementType === 0) { + return [nameOffset, 0]; // non-tensor + } + + // get dims count + const dimsCount = wasm.HEAPU32[metadataOffset / 4 + 1]; + // get dims + const dims: Array = []; + for (let i = 0; i < dimsCount; i++) { + const symbolicDimNameOffset = Number(wasm.getValue(metadataOffset + 8 + i * ptrSize, '*')); + dims.push( + symbolicDimNameOffset !== 0 + ? wasm.UTF8ToString(symbolicDimNameOffset) + : Number(wasm.getValue(metadataOffset + 8 + (i + dimsCount) * ptrSize, '*')), + ); + } + return [nameOffset, elementType, dims]; + } finally { + wasm.stackRestore(stack); + if (metadataOffset !== 0) { + wasm._OrtFree(metadataOffset); + } + } +}; + /** * allocate the memory and memcpy the external buffer. * @@ -341,23 +384,36 @@ export const createSession = async ( const inputNames = []; const outputNames = []; + const inputMetadata: InferenceSession.ValueMetadata[] = []; + const outputMetadata: InferenceSession.ValueMetadata[] = []; const outputPreferredLocations: SupportedTensorDataLocationForInputOutput[] = []; for (let i = 0; i < inputCount; i++) { - const name = wasm._OrtGetInputName(sessionHandle, i); - if (name === 0) { + const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i); + if (nameOffset === 0) { checkLastError("Can't get an input name."); } - inputNamesUTF8Encoded.push(name); - inputNames.push(wasm.UTF8ToString(name)); + inputNamesUTF8Encoded.push(nameOffset); + const name = wasm.UTF8ToString(nameOffset); + inputNames.push(name); + inputMetadata.push( + elementType === 0 + ? { name, isTensor: false } + : { name, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! }, + ); } for (let i = 0; i < outputCount; i++) { - const name = wasm._OrtGetOutputName(sessionHandle, i); - if (name === 0) { + const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i + inputCount); + if (nameOffset === 0) { checkLastError("Can't get an output name."); } - outputNamesUTF8Encoded.push(name); - const nameString = wasm.UTF8ToString(name); + outputNamesUTF8Encoded.push(nameOffset); + const nameString = wasm.UTF8ToString(nameOffset); outputNames.push(nameString); + outputMetadata.push( + elementType === 0 + ? { name: nameString, isTensor: false } + : { name: nameString, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! }, + ); if (!BUILD_DEFS.DISABLE_JSEP) { if (enableGraphCapture && options?.preferredOutputLocation === undefined) { @@ -403,7 +459,7 @@ export const createSession = async ( enableGraphCapture, false, ]); - return [sessionHandle, inputNames, outputNames]; + return [sessionHandle, inputNames, outputNames, inputMetadata, outputMetadata]; } catch (e) { inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); @@ -470,6 +526,7 @@ export const prepareInputOutputTensor = async ( tensorHandles: number[], allocs: number[], sessionId: number, + tensorNameUTF8Encoded: number, index: number, enableGraphCapture = false, ): Promise => { @@ -543,8 +600,7 @@ export const prepareInputOutputTensor = async ( } else { const isGraphInput = wasm.webnnIsGraphInput; if (dataType !== 'string' && isGraphInput) { - const tensorNameUTF8 = wasm._OrtGetInputName(sessionId, index); - const tensorName = wasm.UTF8ToString(tensorNameUTF8); + const tensorName = wasm.UTF8ToString(tensorNameUTF8Encoded); // Promote the tensor to 'ml-tensor' if it is a graph input. if (isGraphInput(sessionId, tensorName)) { const dataTypeEnum = tensorDataTypeStringToEnum(dataType); @@ -644,6 +700,7 @@ export const run = async ( inputTensorHandles, inputOutputAllocs, sessionId, + inputNamesUTF8Encoded[inputIndices[i]], inputIndices[i], enableGraphCapture, ); @@ -656,6 +713,7 @@ export const run = async ( outputTensorHandles, inputOutputAllocs, sessionId, + outputNamesUTF8Encoded[outputIndices[i]], inputCount + outputIndices[i], enableGraphCapture, ); diff --git a/js/web/lib/wasm/wasm-types.ts b/js/web/lib/wasm/wasm-types.ts index 752bac28d7efb..b2ca8480f1546 100644 --- a/js/web/lib/wasm/wasm-types.ts +++ b/js/web/lib/wasm/wasm-types.ts @@ -327,8 +327,12 @@ export interface OrtInferenceAPIs { _OrtCreateSession(dataOffset: number, dataLength: number, sessionOptionsHandle: number): Promise; _OrtReleaseSession(sessionHandle: number): number; _OrtGetInputOutputCount(sessionHandle: number, inputCountOffset: number, outputCountOffset: number): number; - _OrtGetInputName(sessionHandle: number, index: number): number; - _OrtGetOutputName(sessionHandle: number, index: number): number; + _OrtGetInputOutputMetadata( + sessionHandle: number, + index: number, + namePtrOffset: number, + metadataPtrOffset: number, + ): number; _OrtFree(stringHandle: number): number; diff --git a/js/web/test/test-runner.ts b/js/web/test/test-runner.ts index 5de39535a5c07..6fbce114093c0 100644 --- a/js/web/test/test-runner.ts +++ b/js/web/test/test-runner.ts @@ -1016,8 +1016,9 @@ export class ProtoOpTestContext { // check if all test cases have the same shape for each inputs if ( test.cases.some((testCase) => - testCase.inputs!.some((input: Test.TensorValue, i) => - TensorResultValidator.integerEqual(input.dims, (test.cases[0].inputs![i] as Test.TensorValue).dims), + testCase.inputs!.some( + (input: Test.TensorValue, i) => + !TensorResultValidator.integerEqual(input.dims, (test.cases[0].inputs![i] as Test.TensorValue).dims), ), ) ) { diff --git a/js/web/test/unittests/backends/wasm/test-model-metadata.ts b/js/web/test/unittests/backends/wasm/test-model-metadata.ts new file mode 100644 index 0000000000000..9b70686633f27 --- /dev/null +++ b/js/web/test/unittests/backends/wasm/test-model-metadata.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { expect } from 'chai'; +import { InferenceSession } from 'onnxruntime-common'; + +const ONNX_MODEL_TEST_ABS_NO_SHAPE = Uint8Array.from([ + 8, 9, 58, 73, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 15, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 4, 10, 2, + 8, 1, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, 66, 4, 10, 0, 16, 21, +]); + +const ONNX_MODEL_TEST_ABS_SYMBOL = Uint8Array.from([ + 8, 9, 58, 105, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 47, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 36, 10, + 34, 8, 1, 18, 30, 10, 13, 18, 11, 95, 105, 110, 112, 117, 116, 95, 48, 95, 100, 48, 10, 13, 18, 11, 95, 105, 110, 112, + 117, 116, 95, 48, 95, 100, 49, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, 66, 4, 10, 0, + 16, 21, +]); + +const ONNX_MODEL_TEST_ABS_STATIC = Uint8Array.from([ + 8, 9, 58, 83, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 25, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 14, 10, + 12, 8, 1, 18, 8, 10, 2, 8, 2, 10, 2, 8, 4, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, + 66, 4, 10, 0, 16, 21, +]); + +const testModelMetadata = async ( + model: Uint8Array, + expectedInputNames: string[], + expectedOutputNames: string[], + expectedInputMetadata: InferenceSession.ValueMetadata[], + expectedOutputMetadata: InferenceSession.ValueMetadata[], +) => { + const session = await InferenceSession.create(model); + expect(session.inputNames).to.deep.equal(expectedInputNames); + expect(session.outputNames).to.deep.equal(expectedOutputNames); + expect(session.inputMetadata).to.deep.equal(expectedInputMetadata); + expect(session.outputMetadata).to.deep.equal(expectedOutputMetadata); +}; + +describe('#UnitTest# - wasm - test model input/output metadata', () => { + it('model input/output with no shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_NO_SHAPE, + ['input_0'], + ['output_0'], + [{ name: 'input_0', isTensor: true, type: 'float32', shape: [] }], + [{ name: 'output_0', isTensor: true, type: 'float32', shape: [] }], + ); + }); + + it('model input/output with symbol shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_SYMBOL, + ['input_0'], + ['output_0'], + [ + { + name: 'input_0', + isTensor: true, + type: 'float32', + shape: ['_input_0_d0', '_input_0_d1'], + }, + ], + [ + { + name: 'output_0', + isTensor: true, + type: 'float32', + shape: ['_input_0_d0', '_input_0_d1'], + }, + ], + ); + }); + + it('model input/output with static shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_STATIC, + ['input_0'], + ['output_0'], + [{ name: 'input_0', isTensor: true, type: 'float32', shape: [2, 4] }], + [{ name: 'output_0', isTensor: true, type: 'float32', shape: [2, 4] }], + ); + }); +}); diff --git a/js/web/test/unittests/index.ts b/js/web/test/unittests/index.ts index 4a0b155ecc80b..b68681f4977c0 100644 --- a/js/web/test/unittests/index.ts +++ b/js/web/test/unittests/index.ts @@ -11,4 +11,6 @@ if (typeof window !== 'undefined') { require('./backends/webgl/test-matmul-packed'); } +require('./backends/wasm/test-model-metadata'); + require('./opset'); diff --git a/onnxruntime/wasm/api.cc b/onnxruntime/wasm/api.cc index 1ad35b51bb1c1..147eab7116d94 100644 --- a/onnxruntime/wasm/api.cc +++ b/onnxruntime/wasm/api.cc @@ -223,6 +223,113 @@ int OrtGetInputOutputCount(OrtSession* session, size_t* input_count, size_t* out return ORT_OK; } +int OrtGetInputOutputMetadata(ort_session_handle_t session, size_t index, char** name_cstr_ptr, void** type_info_ptr) { + OrtAllocator* allocator = nullptr; + RETURN_ERROR_CODE_IF_ERROR(GetAllocatorWithDefaultOptions, &allocator); + + size_t input_count, output_count; + int error_code = OrtGetInputOutputCount(session, &input_count, &output_count); + if (error_code != ORT_OK) { + return error_code; + } + + if (index >= input_count + output_count) { + std::ostringstream ostr; + ostr << "Invalid index: " << index << ", input count: " << input_count << ", output count: " << output_count; + return CheckStatus(Ort::GetApi().CreateStatus(ORT_INVALID_ARGUMENT, ostr.str().c_str())); + } + + char* name_cstr; + if (index < input_count) { + RETURN_ERROR_CODE_IF_ERROR(SessionGetInputName, session, index, allocator, &name_cstr); + } else { + RETURN_ERROR_CODE_IF_ERROR(SessionGetOutputName, session, index - input_count, allocator, &name_cstr); + } + REGISTER_AUTO_RELEASE_BUFFER(char, name_cstr, allocator); + + OrtTypeInfo* type_info; + if (index < input_count) { + RETURN_ERROR_CODE_IF_ERROR(SessionGetInputTypeInfo, session, index, &type_info); + } else { + RETURN_ERROR_CODE_IF_ERROR(SessionGetOutputTypeInfo, session, index - input_count, &type_info); + } + REGISTER_AUTO_RELEASE_HANDLE(TypeInfo, type_info); + + const OrtTensorTypeAndShapeInfo* tensor_info; + RETURN_ERROR_CODE_IF_ERROR(CastTypeInfoToTensorInfo, type_info, &tensor_info); + + size_t type_info_size = 4; + ONNXTensorElementDataType element_type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + size_t dim_count = 0; + if (tensor_info != nullptr) { + RETURN_ERROR_CODE_IF_ERROR(GetTensorElementType, tensor_info, &element_type); + RETURN_ERROR_CODE_IF_ERROR(GetDimensionsCount, tensor_info, &dim_count); + + // byte [0, 4): [i32] element type + // byte [4, 8): [u32] dimension count + // byte [8, 8 + dim_count * ptr_size): [ptr] symbolic dimension names for dim[0], dim[1], ..., dim[dim_count - 1] + // byte [8 + dim_count * ptr_size, 8 + dim_count * ptr_size * 2): [size_t] dimension values for dim[0], dim[1], ..., dim[dim_count - 1] + // from byte 8 + dim_count * ptr_size * 2: optional string copies for symbolic dimension names + type_info_size = 8 + dim_count * (sizeof(size_t) * 2); + } + + std::vector dim_values(dim_count); + std::vector dim_params(dim_count); + std::vector dim_params_str_len(dim_count); + if (dim_count > 0) { + size_t str_len_total = 0; + RETURN_ERROR_CODE_IF_ERROR(GetDimensions, tensor_info, dim_values.data(), dim_count); + RETURN_ERROR_CODE_IF_ERROR(GetSymbolicDimensions, tensor_info, dim_params.data(), dim_count); + for (size_t i = 0; i < dim_count; ++i) { + size_t str_size = dim_params[i] ? strlen(dim_params[i]) : 0; + if (str_size > 0) { + str_len_total += str_size + 1; + dim_params_str_len[i] = str_size + 1; + } else { + dim_params_str_len[i] = 0; + } + } + type_info_size += str_len_total; + } + + uint8_t* type_info_buffer = reinterpret_cast(allocator->Alloc(allocator, type_info_size)); + // write to buffer @ byte [0, 4) + int32_t* p_type_info_element_type = reinterpret_cast(type_info_buffer); + *p_type_info_element_type = static_cast(element_type); + + if (tensor_info != nullptr) { + // write to buffer @ byte [4, 8) + uint32_t* p_type_info_dim_count = reinterpret_cast(type_info_buffer + 4); + *p_type_info_dim_count = static_cast(dim_count); + + if (dim_count > 0) { + // write to buffer @ byte [8, 8 + dim_count * ptr_size) + const char** p_dim_params = reinterpret_cast(type_info_buffer + 8); + char* p_str_copy_dest = reinterpret_cast(type_info_buffer + 8 + dim_count * sizeof(size_t) * 2); + for (size_t i = 0; i < dim_count; ++i) { + if (dim_params_str_len[i] > 0) { + p_dim_params[i] = p_str_copy_dest; + memcpy(p_str_copy_dest, dim_params[i], dim_params_str_len[i]); + p_str_copy_dest += dim_params_str_len[i]; + } else { + p_dim_params[i] = nullptr; + } + } + + // write to buffer @ byte [8 + dim_count * ptr_size, 8 + dim_count * ptr_size + dim_count * 4 + dim_count * 4) + size_t* p_dim_values = reinterpret_cast(type_info_buffer + 8 + dim_count * sizeof(size_t)); + for (size_t i = 0; i < dim_count; ++i) { + p_dim_values[i] = static_cast(dim_values[i]); + } + } + } + + UNREGISTER_AUTO_RELEASE(name_cstr); + *name_cstr_ptr = name_cstr; + *type_info_ptr = type_info_buffer; + return ORT_OK; +} + char* OrtGetInputName(OrtSession* session, size_t index) { OrtAllocator* allocator = nullptr; RETURN_NULLPTR_IF_ERROR(GetAllocatorWithDefaultOptions, &allocator); diff --git a/onnxruntime/wasm/api.h b/onnxruntime/wasm/api.h index 9ff1eb55ecedc..c488c16f4a60c 100644 --- a/onnxruntime/wasm/api.h +++ b/onnxruntime/wasm/api.h @@ -145,21 +145,17 @@ int EMSCRIPTEN_KEEPALIVE OrtGetInputOutputCount(ort_session_handle_t session, size_t* output_count); /** - * get the model's input name. + * get the metadata of the specified input or output of the model. * @param session handle of the specified session - * @param index the input index - * @returns a pointer to a buffer which contains C-style string. Caller must release the C style string after use by + * @param index the input index or output index. index should be in range [0, input_count + output_count). if the index + * is in range [0, input_count), it's an input index. otherwise, it's an output index. + * @param name_cstr_ptr [out] a pointer to a buffer which contains C-style string of the name of the input or output. Caller must release the C style string after use by * calling OrtFree(). - */ -char* EMSCRIPTEN_KEEPALIVE OrtGetInputName(ort_session_handle_t session, size_t index); -/** - * get the model's output name. - * @param session handle of the specified session - * @param index the output index - * @returns a pointer to a buffer which contains C-style string. Caller must release the C style string after use by + * @param type_info_ptr [out] a pointer to a buffer which contains the type information of the input or output. Caller must release the buffer after use by * calling OrtFree(). + * @returns ORT error code. If not zero, call OrtGetLastError() to get detailed error message. */ -char* EMSCRIPTEN_KEEPALIVE OrtGetOutputName(ort_session_handle_t session, size_t index); +int EMSCRIPTEN_KEEPALIVE OrtGetInputOutputMetadata(ort_session_handle_t session, size_t index, char** name_cstr_ptr, void** type_info_ptr); /** * free the specified buffer. From afaf4a5e63dc689d99a01e768d9dc923af04c60c Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 24 Mar 2025 17:14:31 -0700 Subject: [PATCH 161/266] add cache "onnxnodetests" for node tests (#24150) ### Description add cache "onnxnodetests" for node tests This fixes the random download network error for onnx node tests data. ### Motivation and Context --- .github/workflows/macos-ci-build-and-test-workflow.yml | 6 ++++++ .github/workflows/windows_cuda.yml | 8 +++++++- .github/workflows/windows_webgpu.yml | 8 +++++++- .github/workflows/windows_x64_debug_build_x64_debug.yml | 8 +++++++- .../workflows/windows_x64_release_build_x64_release.yml | 6 ++++++ .../windows_x64_release_dnnl_build_x64_release.yml | 8 +++++++- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-ci-build-and-test-workflow.yml b/.github/workflows/macos-ci-build-and-test-workflow.yml index 2258891b8697e..a387541488621 100644 --- a/.github/workflows/macos-ci-build-and-test-workflow.yml +++ b/.github/workflows/macos-ci-build-and-test-workflow.yml @@ -65,6 +65,12 @@ jobs: xcode_version: ${{ matrix.xcode_version }} use_cache: true + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + - name: Setup environment variables shell: bash run: | diff --git a/.github/workflows/windows_cuda.yml b/.github/workflows/windows_cuda.yml index d26ee0a2b766e..a36f0c3142d7d 100644 --- a/.github/workflows/windows_cuda.yml +++ b/.github/workflows/windows_cuda.yml @@ -65,6 +65,12 @@ jobs: java-version: '17' architecture: x64 + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + - name: API Documentation Check and generate run: | set ORT_DOXY_SRC=${{ github.workspace }} @@ -132,4 +138,4 @@ jobs: DocUpdateNeeded: false ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' AZCOPY_AUTO_LOGIN_TYPE: MSI - AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 \ No newline at end of file + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 diff --git a/.github/workflows/windows_webgpu.yml b/.github/workflows/windows_webgpu.yml index 7b8415c223e0f..908f28ae174d3 100644 --- a/.github/workflows/windows_webgpu.yml +++ b/.github/workflows/windows_webgpu.yml @@ -91,6 +91,12 @@ jobs: shell: cmd working-directory: ${{ github.workspace }} + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: @@ -259,4 +265,4 @@ jobs: - name: Validate C# native delegates run: python tools\ValidateNativeDelegateAttributes.py shell: cmd - working-directory: ${{ github.workspace }}\csharp \ No newline at end of file + working-directory: ${{ github.workspace }}\csharp diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml index b8d1bdf228261..2508bb2079119 100644 --- a/.github/workflows/windows_x64_debug_build_x64_debug.yml +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -75,6 +75,12 @@ jobs: run: | nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\Debug -ConfigFile ${{ github.workspace }}\NuGet.config + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: @@ -126,4 +132,4 @@ jobs: env: OrtPackageId: Microsoft.ML.OnnxRuntime OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' \ No newline at end of file + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_build_x64_release.yml b/.github/workflows/windows_x64_release_build_x64_release.yml index c0e8fb24bc615..58a94c2f2208a 100644 --- a/.github/workflows/windows_x64_release_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_build_x64_release.yml @@ -75,6 +75,12 @@ jobs: run: | nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: diff --git a/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml b/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml index 2ac7a4a646eb0..5b45f040c990b 100644 --- a/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml @@ -75,6 +75,12 @@ jobs: run: | nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: @@ -122,4 +128,4 @@ jobs: env: OrtPackageId: Microsoft.ML.OnnxRuntime OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' \ No newline at end of file + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' From ce65e253fafde91359d2e01121f12114329f252d Mon Sep 17 00:00:00 2001 From: vraspar Date: Mon, 24 Mar 2025 23:04:28 -0700 Subject: [PATCH 162/266] [Native WebGPU] Add Matmul (#24046) ### Description Add Native Matmul (`MatMulNaive`, `MatMulPacked` and `MatMulPackedVec4` ) ### Motivation and Context --- .../core/providers/webgpu/math/matmul.cc | 228 +++++++++++++ .../core/providers/webgpu/math/matmul.h | 47 +++ .../providers/webgpu/math/matmul_packed.cc | 303 ++++++++++++++++++ .../providers/webgpu/math/matmul_packed.h | 45 +++ .../core/providers/webgpu/math/matmul_utils.h | 40 +++ .../webgpu/webgpu_execution_provider.cc | 4 +- .../core/providers/webgpu/webgpu_utils.h | 15 + .../test/providers/cpu/math/matmul_test.cc | 133 +++++++- 8 files changed, 812 insertions(+), 3 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/math/matmul.cc create mode 100644 onnxruntime/core/providers/webgpu/math/matmul.h create mode 100644 onnxruntime/core/providers/webgpu/math/matmul_packed.cc create mode 100644 onnxruntime/core/providers/webgpu/math/matmul_packed.h create mode 100644 onnxruntime/core/providers/webgpu/math/matmul_utils.h diff --git a/onnxruntime/core/providers/webgpu/math/matmul.cc b/onnxruntime/core/providers/webgpu/math/matmul.cc new file mode 100644 index 0000000000000..9b447d5fdb59a --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/matmul.cc @@ -0,0 +1,228 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/math/matmul.h" +#include "core/common/inlined_containers.h" +#include "core/providers/cpu/tensor/utils.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +#include "core/providers/webgpu/data_transfer.h" +namespace onnxruntime { +namespace webgpu { + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + MatMul, + kOnnxDomain, + 1, 12, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()), + MatMul); + +ONNX_OPERATOR_KERNEL_EX( + MatMul, + kOnnxDomain, + 13, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()), + MatMul); + +static std::string CalcResult(int64_t components, int64_t a_components, int64_t output_number) { + std::ostringstream oss; + oss << "var a_data: a_value_t;\n"; + for (int i = 0; i < a_components; ++i) { + oss << "let b_data" << i << " = b[(b_offset + (k + " << i << ") * uniforms.N + col) / " << components << "];\n"; + } + for (int i = 0; i < output_number; ++i) { + oss << "a_data = a[(a_offset + (row + " << i << ") * uniforms.K + k) / " << a_components << "];\n"; + + for (int j = 0; j < a_components; j++) { + oss << "values[" << i << "] = fma(b_value_t(a_data" << (a_components == 1 ? "" : "[" + std::to_string(j) + "]") << "), b_data" << j << ", values[" << i << "]);\n"; + } + } + return oss.str(); +} + +Status MatMulNaiveProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& a = shader.AddInput("a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | + ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& b = shader.AddInput("b", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | + ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + + std::string process_bias; + if (has_bias_) { + shader.AddInput("bias", ShaderUsage::UseUniform); + process_bias = "value += output_value_t(bias[row + i]);"; + } + + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | + ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& batch_dims = shader.AddIndices("batch_dims"); + + int a_components = a.NumComponents(); + int components = b.NumComponents(); // components of N + + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "let col = (global_idx % (uniforms.N / " << components << ")) * " << components << ";\n" + << "var index1 = global_idx / (uniforms.N / " << components << ");\n" + << "let stride1 = uniforms.M / " << output_number_ << ";\n" + << "let row = (index1 % stride1) * " << output_number_ << ";\n" + << "let batch = index1 / stride1;\n"; + if (output_rank_ != 2) { + shader.MainFunctionBody() << "let batch_indices = " << batch_dims.OffsetToIndices("batch") << ";\n"; + } + shader.MainFunctionBody() << "var a_indices: a_indices_t;\n" + << ConvertOutputBatchIndicesToInputBatchIndices("a", a, a.Rank() - 2, batch_dims.Rank(), "batch_indices") + << a.IndicesSet("a_indices", a.Rank() - 2, 0) << "\n" + << a.IndicesSet("a_indices", a.Rank() - 1, 0) << "\n" + << "let a_offset = " << a.IndicesToOffset("a_indices") << "*" << a_components << ";\n" + << "var b_indices: b_indices_t;\n" + << ConvertOutputBatchIndicesToInputBatchIndices("b", b, b.Rank() - 2, batch_dims.Rank(), "batch_indices") + << b.IndicesSet("b_indices", b.Rank() - 2, 0) << "\n" + << b.IndicesSet("b_indices", b.Rank() - 1, 0) << "\n" + << "let b_offset = " << b.IndicesToOffset("b_indices") << " * " << components << ";\n" + << "var values: array;\n" + << "for (var k: u32 = 0u; k < uniforms.K; k = k + " << a_components << ") {\n" + << CalcResult(components, a_components, output_number_) << "\n" + << "}\n" + << "for (var i = 0u; i < " << output_number_ << "u; i++) {\n" + << " var value = values[i];\n" + << process_bias << "\n" + << " let cur_indices = output_indices_t(batch, row + i, col/ " << components << ");\n" + << " let offset = " << output.IndicesToOffset("cur_indices") << ";\n" + << output.SetByOffset("offset", "value") + << "}\n"; + + return Status::OK(); +} + +Status MatMul::ComputeInternal(ComputeContext& context) const { + // calculate output shape + MatMulComputeHelper helper; + const auto* a = context.Input(0); + const auto* b = context.Input(1); + + ORT_RETURN_IF_ERROR(helper.Compute(a->Shape(), b->Shape())); + auto* output_tensor = context.Output(0, helper.OutputShape()); + bool has_bias = context.InputCount() > 2; + + if (helper.N() < 8 && helper.K() < 8) { // call MatMulNaiveProgram + + const uint32_t m = narrow(helper.M()); // left matrix first dimension + const uint32_t n = narrow(helper.N()); // right matrix second dimension + const uint32_t k = narrow(helper.K()); // right matrix first dimension + + const auto components = GetMaxComponents(n); + const auto a_components = GetMaxComponents(k); + + const auto output_number = GetMaxComponents(m); + uint32_t output_size = narrow(helper.OutputShape().Size() / components / output_number); + + const size_t output_rank = helper.OutputShape().NumDimensions(); + TensorShape outer_dims = output_rank > 2 ? helper.OutputShape().Slice(0, output_rank - 2) : TensorShape({}); + const int64_t batch_size = outer_dims.Size(); + + const int64_t a_rows = a->Shape().NumDimensions() > 1 ? a->Shape()[a->Shape().NumDimensions() - 2] : 1; + TensorShape output_shape_shader({batch_size, a_rows, helper.N() / components}); + + MatMulNaiveProgram program{output_rank, output_number, has_bias}; + + program + .CacheHint(std::to_string(components), std::to_string(a_components), std::to_string(output_number)) + .AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, a_components}, + {b, ProgramTensorMetadataDependency::TypeAndRank, components}}); + + if (has_bias) { + const auto* bias = context.Input(2); + program.AddInput({bias, ProgramTensorMetadataDependency::Rank, 1}); + } + program + .AddOutputs({{output_tensor, ProgramTensorMetadataDependency::None, output_shape_shader, components}}) + .SetDispatchGroupSize((output_size + 63) / 64) // Integer ceiling division + .AddIndices(outer_dims) + .AddUniformVariables({{output_size}, {m}, {n}, {k}}); + + return context.RunProgram(program); + } + + int64_t batchA = a->Shape().SizeToDimension(a->Shape().NumDimensions() - 2); + int64_t batchB = b->Shape().SizeToDimension(b->Shape().NumDimensions() - 2); + + TensorShape a_shape = a->Shape(); + TensorShape b_shape = b->Shape(); + TensorShape output_shape = helper.OutputShape(); + + const int64_t dim_output_outer = output_shape[output_shape.NumDimensions() - 2]; + // check if A is batch of vector (bach is not 1, M is 1) and B is a matrix (batch is 1) + if (batchA != 1 && dim_output_outer == 1 && batchB == 1) { + // optimization for batched vector matrix multiplication + // dimensions of A: [1,`batchA`,K] + TensorShapeVector dims_a = {1, batchA, helper.K()}; + // dimensions of B: [1,K,N] + TensorShapeVector dims_b = {1, helper.K(), helper.N()}; + + a_shape = TensorShape(dims_a); + b_shape = TensorShape(dims_b); + output_shape = {1, batchA, helper.N()}; + } + + // helpful dimension variables + TensorShape outer_dims_a = a_shape.NumDimensions() > 2 + ? a_shape.Slice(0, a_shape.NumDimensions() - 2) + : TensorShape({}); + + TensorShape outer_dims_b = b_shape.NumDimensions() > 2 + ? b_shape.Slice(0, b_shape.NumDimensions() - 2) + : TensorShape({}); + + TensorShape outer_dims = output_shape.NumDimensions() > 2 + ? output_shape.Slice(0, output_shape.NumDimensions() - 2) + : TensorShape({}); + + const int64_t batch_size = outer_dims.Size(); + + // Get dimensions for matrix multiplication from TensorShape + const int32_t dim_a_outer = narrow(a_shape[a_shape.NumDimensions() - 2]); // left matrix second dimension + const int32_t dim_inner = narrow(a_shape[a_shape.NumDimensions() - 1]); // left matrix first dimension + const int32_t dim_b_outer = narrow(b_shape[b_shape.NumDimensions() - 1]); // right matrix first dimension + + const bool is_vec4 = dim_inner % 4 == 0 && dim_b_outer % 4 == 0; + + InlinedVector elements_per_thread = dim_a_outer <= 8 + ? InlinedVector({4, 1, 1}) + : InlinedVector({4, 4, 1}); + + const uint32_t dispatch_x = narrow((dim_b_outer + MATMUL_PACKED_WORKGROUP_SIZE_X * elements_per_thread[0] - 1) / + (MATMUL_PACKED_WORKGROUP_SIZE_X * elements_per_thread[0])); + const uint32_t dispatch_y = narrow((dim_a_outer + MATMUL_PACKED_WORKGROUP_SIZE_Y * elements_per_thread[1] - 1) / + (MATMUL_PACKED_WORKGROUP_SIZE_Y * elements_per_thread[1])); + const uint32_t dispatch_z = narrow((static_cast(batch_size) + MATMUL_PACKED_WORKGROUP_SIZE_Z * elements_per_thread[2] - 1) / + (MATMUL_PACKED_WORKGROUP_SIZE_Z * elements_per_thread[2])); + + const int components = is_vec4 ? 4 : 1; + const TensorShape a_shape_temp = CreateMatMulIntermediateShape(outer_dims_a, dim_a_outer, dim_inner, components); + const TensorShape b_shape_temp = CreateMatMulIntermediateShape(outer_dims_b, dim_inner, dim_b_outer, components); + const TensorShape output_shape_temp = TensorShape({batch_size, dim_a_outer, dim_b_outer / components}); + + MatMulProgram program{has_bias, is_vec4, elements_per_thread}; + program + .CacheHint(absl::StrJoin(elements_per_thread, "-"), std::to_string(is_vec4)) + .AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, a_shape_temp, components}, + {b, ProgramTensorMetadataDependency::TypeAndRank, b_shape_temp, components}}) + .AddOutputs({{output_tensor, ProgramTensorMetadataDependency::Rank, output_shape_temp, components}}) + .AddUniformVariables({{dim_a_outer}, {dim_b_outer}, {dim_inner}}) + .AddIndices(outer_dims) + .SetDispatchGroupSize(dispatch_x, dispatch_y, dispatch_z) + .SetWorkgroupSize(MATMUL_PACKED_WORKGROUP_SIZE_X, MATMUL_PACKED_WORKGROUP_SIZE_Y, MATMUL_PACKED_WORKGROUP_SIZE_Z); + + if (has_bias) { + const auto* bias = context.Input(2); + program.AddInput({bias, ProgramTensorMetadataDependency::Rank, 1}); + } + return context.RunProgram(program); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/math/matmul.h b/onnxruntime/core/providers/webgpu/math/matmul.h new file mode 100644 index 0000000000000..789e824383189 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/matmul.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/cpu/math/matmul_helper.h" +#include "core/providers/webgpu/math/matmul_utils.h" +#include "core/providers/webgpu/math/matmul_packed.h" +#include "core/providers/webgpu/webgpu_utils.h" + +namespace onnxruntime { +namespace webgpu { + +class MatMul final : public WebGpuKernel { + public: + MatMul(const OpKernelInfo& info) : WebGpuKernel{info} {} + + Status ComputeInternal(ComputeContext& context) const override; + + constexpr static uint32_t MATMUL_PACKED_WORKGROUP_SIZE_X = 8; + constexpr static uint32_t MATMUL_PACKED_WORKGROUP_SIZE_Y = 8; + constexpr static uint32_t MATMUL_PACKED_WORKGROUP_SIZE_Z = 1; +}; + +class MatMulNaiveProgram final : public Program { + public: + MatMulNaiveProgram(const size_t output_rank, int64_t output_number, bool has_bias) + : Program{"MatMulNaive"}, output_rank_(output_rank), output_number_(output_number), has_bias_{has_bias} { + } + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"output_size", ProgramUniformVariableDataType::Uint32}, + {"M", ProgramUniformVariableDataType::Uint32}, + {"N", ProgramUniformVariableDataType::Uint32}, + {"K", ProgramUniformVariableDataType::Uint32}); + + private: + const size_t output_rank_; + const int64_t output_number_; + const bool has_bias_; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/math/matmul_packed.cc b/onnxruntime/core/providers/webgpu/math/matmul_packed.cc new file mode 100644 index 0000000000000..2e5cff923f442 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/matmul_packed.cc @@ -0,0 +1,303 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/math/matmul_packed.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_utils.h" + +namespace onnxruntime { +namespace webgpu { + +void MatMulProgram::MatMulReadWriteFnSource(ShaderHelper& shader, + const ShaderVariableHelper& a, + const ShaderVariableHelper& b, + const ShaderVariableHelper& output, + const ShaderIndicesHelper& batch_dims) const { + int components = is_vec4_ ? 4 : 1; + const std::string data_type = "a_element_t"; + const std::string type_string = MakeScalarOrVectorType(components, data_type); + + // Add the mm_readA function + shader.AdditionalImplementation() + << "fn mm_readA(batch: i32, row: i32, colIn: i32, batch_indices: batch_dims_indices_t) -> " << type_string << " {\n" + << " var value = " << type_string << "(0.0);\n" + << " let col = colIn * " << components << ";\n" + << " if(row < uniforms.dim_a_outer && col < uniforms.dim_inner) {\n" + << " var a_indices: a_indices_t;\n" + << ConvertOutputBatchIndicesToInputBatchIndices("a", a, a.Rank() - 2, batch_dims.Rank(), "batch_indices") + << a.IndicesSet("a_indices", a.Rank() - 2, "u32(row)") << "\n" + << a.IndicesSet("a_indices", a.Rank() - 1, "u32(colIn)") << "\n" + << " value = " << a.GetByIndices("a_indices") << ";\n" + << " }\n" + << " return value;\n" + << "}\n\n"; + + // Add the mm_readB function + shader.AdditionalImplementation() + << "fn mm_readB(batch: i32, row: i32, colIn: i32, batch_indices: batch_dims_indices_t) -> " << type_string << " {\n" + << " var value = " << type_string << "(0.0);\n" + << " let col = colIn * " << components << ";\n" + << " if(row < uniforms.dim_inner && col < uniforms.dim_b_outer) {\n" + << " var b_indices: b_indices_t;\n" + << ConvertOutputBatchIndicesToInputBatchIndices("b", b, b.Rank() - 2, batch_dims.Rank(), "batch_indices") + << b.IndicesSet("b_indices", b.Rank() - 2, "u32(row)") << "\n" + << b.IndicesSet("b_indices", b.Rank() - 1, "u32(colIn)") << "\n" + << " value = " << b.GetByIndices("b_indices") << ";\n" + << " }\n" + << " return value;\n" + << "}\n\n"; + + // Add the mm_write function + shader.AdditionalImplementation() + << "fn mm_write(batch: i32, row: i32, colIn: i32, valueIn: " << type_string << ") {\n" + << " let col = colIn * " << components << ";\n" + << " if (row < uniforms.dim_a_outer && col < uniforms.dim_b_outer) {\n" + << " var value = valueIn;\n" + << " let coords = vec3(batch, row, colIn);\n"; + + if (has_bias_) { + shader.AdditionalImplementation() << " value = value + " << type_string << "(bias[row]);\n"; + } + + shader.AdditionalImplementation() + << output.SetByIndices("vec3(coords)", "value") << "\n" + << " }\n" + << "}\n\n"; +} + +Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, + const ShaderIndicesHelper& batch_dims, + const InlinedVector& elements_per_thread, + uint32_t workgroup_size_x, + uint32_t workgroup_size_y) { + // elements per thread + const auto elements_per_thread_x = elements_per_thread[0]; + const auto elements_per_thread_y = elements_per_thread[1]; + const decltype(elements_per_thread_x) tile_inner = 32; + + const auto tile_a_outer = workgroup_size_y * elements_per_thread_y; + const auto tile_b_outer = workgroup_size_x * elements_per_thread_x; + const auto tile_a_width = tile_inner; + + const auto tile_a_height = tile_a_outer; + const auto inner_elements_size = tile_a_width / workgroup_size_x; + const auto row_per_thread_b = tile_inner / workgroup_size_y; + + const std::string data_type = "a_element_t"; + + if (!((inner_elements_size == 3 || inner_elements_size == 4) && + tile_a_width % workgroup_size_x == 0 && + tile_inner % workgroup_size_y == 0 && + elements_per_thread_x == 4)) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "Invalid matrix multiplication configuration inner_elements_size: ", inner_elements_size, + " must be 3 or 4. tile_a_width: ", tile_a_width, " must be divisible by WorkgroupSizeX: ", + workgroup_size_x, ". tile_inner: ", tile_inner, " must be divisible by WorkgroupSizeY: ", + workgroup_size_y, ". elements_per_thread_x: ", elements_per_thread_x, " must be 4."); + } + + shader.AdditionalImplementation() + << "var mm_Asub: array, " << tile_a_width / inner_elements_size << ">, " << tile_a_height << ">;\n" + << "var mm_Bsub: array, " << tile_b_outer / elements_per_thread_x << ">, " << tile_inner << ">;\n" + << "const rowPerThread = " << elements_per_thread_y << ";\n" + << "const colPerThread = " << elements_per_thread_x << ";\n" + << "const innerElementSize = " << inner_elements_size << ";\n" + << "const tileInner = " << tile_inner << ";\n"; + + shader.MainFunctionBody() + << " let localRow = i32(local_id.y);\n" + << " let tileRow = localRow * rowPerThread;\n" + << " let tileCol = i32(local_id.x);\n" + << " let globalRow = i32(global_id.y) * rowPerThread;\n" + << " let globalCol = i32(global_id.x);\n" + << " let batch = i32(global_id.z);\n" + << " let batchIndices = " << batch_dims.OffsetToIndices("u32(batch)") << ";\n" + << " let globalRowStart = i32(workgroup_id.y) * " << tile_a_outer << ";\n" + << " let num_tiles = (uniforms.dim_inner - 1) / tileInner + 1;\n" + << " var kStart = 0;\n" + << " var acc: array, rowPerThread>;\n"; + + // Loop over shared dimension. + shader.MainFunctionBody() + << " let tileRowB = localRow * " << row_per_thread_b << ";\n" + << " for (var t = 0; t < num_tiles; t = t + 1) {\n"; + + // Load one tile of A into local memory. + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" + << " let inputRow = tileRow + innerRow;\n" + << " let inputCol = tileCol;\n" + << " mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRow + innerRow, kStart / innerElementSize + inputCol, batchIndices);\n" + << " }\n"; + + // Load one tile of B into local memory. + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < " << row_per_thread_b << "; innerRow = innerRow + 1) {\n" + << " let inputRow = tileRowB + innerRow;\n" + << " let inputCol = tileCol;\n" + << " mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol, batchIndices);\n" + << " }\n" + << " kStart = kStart + tileInner;\n" + << " workgroupBarrier();\n"; + + // Compute acc values for a single thread. + shader.MainFunctionBody() + << " for (var k = 0; k < tileInner / innerElementSize; k = k + 1) {\n" + << " let BCached0 = mm_Bsub[k * innerElementSize][tileCol];\n" + << " let BCached1 = mm_Bsub[k * innerElementSize + 1][tileCol];\n" + << " let BCached2 = mm_Bsub[k * innerElementSize + 2][tileCol];\n"; + + if (inner_elements_size != 3) { + shader.MainFunctionBody() << " let BCached3 = mm_Bsub[k * innerElementSize + 3][tileCol];\n"; + } + + shader.MainFunctionBody() + << " for (var i = 0; i < rowPerThread; i = i + 1) {\n" + << " let ACached = mm_Asub[tileRow + i][k];\n" + << " acc[i] = BCached0 * ACached.x + acc[i];\n" + << " acc[i] = BCached1 * ACached.y + acc[i];\n" + << " acc[i] = BCached2 * ACached.z + acc[i];\n" + << " " << (inner_elements_size == 3 ? "" : "acc[i] = BCached3 * ACached.w + acc[i];") << "\n" + << " }\n"; + + shader.MainFunctionBody() << " workgroupBarrier();\n" + << " }\n"; // main for loop + + // Write the results to the output buffer + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" + << " mm_write(batch, globalRow + innerRow, globalCol, acc[innerRow]);\n" + << " }\n" + << "}\n"; + + return Status::OK(); +} + +Status MatMulProgram::MakeMatMulPackedSource(ShaderHelper& shader, const ShaderIndicesHelper& batch_dims, + const InlinedVector& elements_per_thread, + uint32_t workgroup_size_x, + uint32_t workgroup_size_y) { + const auto elements_per_thread_x = elements_per_thread[0]; + const auto elements_per_thread_y = elements_per_thread[1]; + const decltype(elements_per_thread_x) tile_inner = 32; + + const auto tile_a_outer = workgroup_size_y * elements_per_thread_y; + const auto tile_b_outer = workgroup_size_x * elements_per_thread_x; + const auto tile_a_width = tile_inner; + const auto tile_a_height = tile_a_outer; + + if (!(tile_a_height % workgroup_size_y == 0 && tile_a_width % workgroup_size_x == 0 && tile_inner % workgroup_size_y == 0)) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "tile_a_height: ", tile_a_height, " must be divisible by WorkgroupSizeY: ", workgroup_size_y, + ", tile_a_width: ", tile_a_width, " must be divisible by WorkgroupSizeX: ", workgroup_size_x, + ", tile_inner: ", tile_inner, " must be divisible by WorkgroupSizeY: ", workgroup_size_y); + } + + const std::string data_type = "a_element_t"; + + const auto row_per_thread_a = tile_a_height / workgroup_size_y; + const auto col_per_thread_a = tile_a_width / workgroup_size_x; + const auto row_per_thread_b = tile_inner / workgroup_size_y; + + shader.AdditionalImplementation() + << "var mm_Asub: array, " << tile_a_height << ">;\n" + << "var mm_Bsub: array, " << tile_inner << ">;\n" + << "const rowPerThread = " << elements_per_thread_y << ";\n" + << "const colPerThread = " << elements_per_thread_x << ";\n" + << "const tileInner = " << tile_inner << ";\n"; + + shader.MainFunctionBody() << " let batch = i32(global_id.z);\n" + << " let batchIndices = " << batch_dims.OffsetToIndices("u32(batch)") << ";\n" + << " let num_tiles = (uniforms.dim_inner - 1) / tileInner + 1;\n" + << " var kStart = 0;\n" + << " var acc: array, rowPerThread>;\n"; + + shader.MainFunctionBody() + << "let tileRow = i32(local_id.y) * rowPerThread;\n" + << "let tileCol = i32(local_id.x) * colPerThread;\n" + << "let globalRow = i32(global_id.y) * rowPerThread;\n" + << "let globalCol = i32(global_id.x) * colPerThread;\n" + << "let globalRowStart = i32(workgroup_id.y) * " << tile_a_outer << ";\n" + << "let tileRowA = i32(local_id.y) * " << row_per_thread_a << ";\n" + << "let tileColA = i32(local_id.x) * " << col_per_thread_a << ";\n" + << "let tileRowB = i32(local_id.y) * " << row_per_thread_b << ";\n"; + + // Loop over shared dimension. + shader.MainFunctionBody() + << "for (var t = 0; t < num_tiles; t = t + 1) {\n"; + + // Load one tile of A into local memory. + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < " << row_per_thread_a << "; innerRow = innerRow + 1) {\n" + << " for (var innerCol = 0; innerCol < " << col_per_thread_a << "; innerCol = innerCol + 1) {\n" + << " let inputRow = tileRowA + innerRow;\n" + << " let inputCol = tileColA + innerCol;\n" + << " mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRowStart + inputRow, kStart + inputCol, batchIndices);\n" + << " }\n" + << " }\n"; + + // Load one tile of B into local memory. + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < " << row_per_thread_b << "; innerRow = innerRow + 1) {\n" + << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" + << " let inputRow = tileRowB + innerRow;\n" + << " let inputCol = tileCol + innerCol;\n" + << " mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol + innerCol, batchIndices);\n" + << " }\n" + << " }\n" + << " kStart = kStart + tileInner;\n" + << " workgroupBarrier();\n"; + + // Compute acc values for a single thread. + shader.MainFunctionBody() + << "var BCached: array<" << data_type << ", colPerThread>;\n" + << " for (var k = 0; k < tileInner; k = k + 1) {\n" + << " for (var inner = 0; inner < colPerThread; inner = inner + 1) {\n" + << " BCached[inner] = mm_Bsub[k][tileCol + inner];\n" + << " }\n" + << " for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" + << " let ACached = mm_Asub[tileRow + innerRow][k];\n" + << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" + << " acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol];\n" + << " }\n" + << " }\n" + << " }\n" + << " workgroupBarrier();\n" + << "}\n"; + + // Write the results to the output buffer + shader.MainFunctionBody() + << "for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" + << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" + << " mm_write(batch, globalRow + innerRow, globalCol + innerCol, acc[innerRow][innerCol]);\n" + << " }\n" + << "}\n"; + + return Status::OK(); +} + +Status MatMulProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& a = shader.AddInput("a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& b = shader.AddInput("b", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& batch_dims = shader.AddIndices("batch_dims", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias); + + if (has_bias_) { + shader.AddInput("bias", ShaderUsage::UseUniform); + } + + // declare the read and write functions + MatMulReadWriteFnSource(shader, a, b, output, batch_dims); + + // generate the main function + if (is_vec4_) { + ORT_RETURN_IF_ERROR(MakeMatMulPackedVec4Source(shader, batch_dims, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY())); + } else { + ORT_RETURN_IF_ERROR(MakeMatMulPackedSource(shader, batch_dims, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY())); + } + return Status::OK(); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/math/matmul_packed.h b/onnxruntime/core/providers/webgpu/math/matmul_packed.h new file mode 100644 index 0000000000000..ea76468944066 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/matmul_packed.h @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/math/matmul_utils.h" + +namespace onnxruntime { +namespace webgpu { +class MatMulProgram final : public Program { + public: + MatMulProgram(bool bias, bool is_vec4, const gsl::span& elements_per_thread) : Program{"MatMul"}, + has_bias_{bias}, + is_vec4_{is_vec4}, + elements_per_thread_(elements_per_thread.begin(), elements_per_thread.end()) {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"dim_a_outer", ProgramUniformVariableDataType::Int32}, + {"dim_b_outer", ProgramUniformVariableDataType::Int32}, + {"dim_inner", ProgramUniformVariableDataType::Int32}); + + static Status MakeMatMulPackedVec4Source(ShaderHelper& shader, + const ShaderIndicesHelper& batch_dims, + const InlinedVector& elements_per_thread, + uint32_t workgroup_size_x, + uint32_t workgroup_size_y); + static Status MakeMatMulPackedSource(ShaderHelper& shader, + const ShaderIndicesHelper& batch_dims, + const InlinedVector& elements_per_thread, + uint32_t workgroup_size_x, + uint32_t workgroup_size_y); + + private: + const bool has_bias_; + const bool is_vec4_; + const InlinedVector elements_per_thread_; + + void MatMulReadWriteFnSource(ShaderHelper& shader, const ShaderVariableHelper& a, const ShaderVariableHelper& b, const ShaderVariableHelper& output, const ShaderIndicesHelper& batch_dims) const; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/math/matmul_utils.h b/onnxruntime/core/providers/webgpu/math/matmul_utils.h new file mode 100644 index 0000000000000..bcd9c1b24a9bf --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/matmul_utils.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/inlined_containers.h" +#include "core/providers/cpu/tensor/utils.h" +#include "core/providers/webgpu/shader_helper.h" + +namespace onnxruntime { +namespace webgpu { + +// Helper that creates a new TensorShape for the intermediate result of MatMul +// The new shape is created by appending the two dimensions dim1 and dim2 / components to the original shape +inline TensorShape CreateMatMulIntermediateShape(const TensorShape& shape, const int64_t dim1, const int64_t dim2, const int components) { + TensorShapeVector shape_vec = shape.AsShapeVector(); + shape_vec.push_back(dim1); + shape_vec.push_back(dim2 / components); + return TensorShape(shape_vec); +} + +// Helper that convert output batch indices to input batch indices using only the rank and +// the shape information in uniform +inline std::string ConvertOutputBatchIndicesToInputBatchIndices(const std::string& name, const ShaderVariableHelper& input, int input_batch_rank, int output_batch_rank, const std::string& batch_indices) { + std::ostringstream oss; + const std::string input_shape = "uniforms." + name + "_shape"; + const std::string input_indices = name + "_indices"; + int extending_input_rank = output_batch_rank - input_batch_rank; + for (int i = 0; i < input_batch_rank; ++i) { + oss << "if (" << GetElementAt(input_shape, i, input.Rank()) << " != 1) {\n" + << input.IndicesSet(input_indices, i, GetElementAt(batch_indices, i + extending_input_rank, output_batch_rank)) << "\n" + << "} else {\n" + << input.IndicesSet(input_indices, i, 0) << "\n" + << "}\n"; + } + return oss.str(); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 874607988773b..15166df54e40c 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -621,8 +621,8 @@ std::unique_ptr RegisterKernels() { // BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/core/providers/webgpu/webgpu_utils.h b/onnxruntime/core/providers/webgpu/webgpu_utils.h index eb25a9bd5386e..5f6f18f34b7f5 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_utils.h +++ b/onnxruntime/core/providers/webgpu/webgpu_utils.h @@ -29,5 +29,20 @@ inline std::string SumVector(std::string x, int components) { } } +inline std::string MakeScalarOrVectorType(int components, std::string_view data_type) { + switch (components) { + case 1: + return std::string{data_type}; + case 2: + return MakeStringWithClassicLocale("vec2<", data_type, ">"); + case 3: + return MakeStringWithClassicLocale("vec3<", data_type, ">"); + case 4: + return MakeStringWithClassicLocale("vec4<", data_type, ">"); + default: + ORT_THROW("Unsupported number of components: ", components); + } +} + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/test/providers/cpu/math/matmul_test.cc b/onnxruntime/test/providers/cpu/math/matmul_test.cc index dd8cbed15e5ef..504e645738344 100644 --- a/onnxruntime/test/providers/cpu/math/matmul_test.cc +++ b/onnxruntime/test/providers/cpu/math/matmul_test.cc @@ -158,6 +158,112 @@ std::vector> GenerateTestCases() { // clang-format on })}); +#ifdef USE_WEBGPU + test_cases.push_back( + {"test 3D tensors with M = 1", + {6, 1, 8}, + {1, 8, 3}, + {6, 1, 3}, + real_expected_vals({ + // clang-format off + 420, 448, 476, + 1092, 1184, 1276, + 1764, 1920, 2076, + 2436, 2656, 2876, + 3108, 3392, 3676, + 3780, 4128, 4476, + // clang-format on + })}); + + test_cases.push_back( + {"test 4D tensors with M = 1", + {2, 3, 1, 8}, + {1, 1, 8, 3}, + {2, 3, 1, 3}, + real_expected_vals({420, 448, 476, 1092, 1184, 1276, 1764, 1920, 2076, 2436, 2656, 2876, 3108, 3392, 3676, 3780, 4128, 4476})}); + + test_cases.push_back( + {"test 4D tensors", + {2, 3, 4, 3}, + {2, 3, 3, 5}, + {2, 3, 4, 5}, + real_expected_vals({ + // clang-format off + 25, 28, 31, 34, 37, 70, 82, 94, 106, 118, 115, 136, 157, 178, 199, 160, 190, 220, + 250, 280, 790, 829, 868, 907, 946, 970, 1018, 1066, 1114, 1162, 1150, 1207, 1264, + 1321, 1378, 1330, 1396, 1462, 1528, 1594, 2635, 2710, 2785, 2860, 2935, 2950, 3034, + 3118, 3202, 3286, 3265, 3358, 3451, 3544, 3637, 3580, 3682, 3784, 3886, 3988, 5560, + 5671, 5782, 5893, 6004, 6010, 6130, 6250, 6370, 6490, 6460, 6589, 6718, 6847, 6976, + 6910, 7048, 7186, 7324, 7462, 9565, 9712, 9859, 10006, 10153, 10150, 10306, 10462, + 10618, 10774, 10735, 10900, 11065, 11230, 11395, 11320, 11494, 11668, 11842, 12016, + 14650, 14833, 15016, 15199, 15382, 15370, 15562, 15754, 15946, 16138, 16090, 16291, + 16492, 16693, 16894, 16810, 17020, 17230, 17440, 17650 + // clang-format on + })}); + + // Test case: multiplies 2D broadcasted to 4D tensors + test_cases.push_back( + {"test 2D broadcasted to 4D tensors", + {2, 4}, + {4, 3, 2, 4, 2}, + {4, 3, 2, 2, 2}, + real_expected_vals({ + // clang-format off + 28, 34, 76, 98, 76, 82, 252, 274, 124, 130, 428, 450, 172, 178, 604, 626, + 220, 226, 780, 802, 268, 274, 956, 978, 316, 322, 1132, 1154, 364, 370, + 1308, 1330, 412, 418, 1484, 1506, 460, 466, 1660, 1682, 508, 514, 1836, + 1858, 556, 562, 2012, 2034, 604, 610, 2188, 2210, 652, 658, 2364, 2386, + 700, 706, 2540, 2562, 748, 754, 2716, 2738, 796, 802, 2892, 2914, 844, + 850, 3068, 3090, 892, 898, 3244, 3266, 940, 946, 3420, 3442, 988, 994, + 3596, 3618, 1036, 1042, 3772, 3794, 1084, 1090, 3948, 3970, 1132, 1138, + 4124, 4146 + // clang-format on + })}); + + // Test case: multiplies 4D broadcasted to 5D tensors + test_cases.push_back( + {"test 4D broadcasted to 5D tensors", + {3, 1, 2, 4}, + {4, 3, 2, 4, 2}, + {4, 3, 2, 2, 2}, + real_expected_vals({ + // clang-format off + 28, 34, 76, 98, 76, 82, 252, 274, 732, 770, 1036, 1090, 1036, 1074, 1468, + 1522, 2460, 2530, 3020, 3106, 3020, 3090, 3708, 3794, 316, 322, 1132, + 1154, 364, 370, 1308, 1330, 2556, 2594, 3628, 3682, 2860, 2898, 4060, + 4114, 5820, 5890, 7148, 7234, 6380, 6450, 7836, 7922, 604, 610, 2188, + 2210, 652, 658, 2364, 2386, 4380, 4418, 6220, 6274, 4684, 4722, 6652, + 6706, 9180, 9250, 11276, 11362, 9740, 9810, 11964, 12050, 892, 898, 3244, + 3266, 940, 946, 3420, 3442, 6204, 6242, 8812, 8866, 6508, 6546, 9244, + 9298, 12540, 12610, 15404, 15490, 13100, 13170, 16092, 16178 + + // clang-format on + })}); + + // Test case: same ranks different broadcast small 1 + test_cases.push_back( + {"test same ranks different broadcast small 1", + {2, 1, 2, 2}, + {1, 2, 2, 1}, + {2, 2, 2, 1}, + real_expected_vals({1, 3, 3, 13, 5, 7, 23, 33})}); + + // Test case: same ranks different broadcast larger 0 + test_cases.push_back( + {"test same ranks different broadcast larger 0", + {1, 2, 2, 8}, + {2, 1, 8, 1}, + {2, 2, 2, 1}, + real_expected_vals({140, 364, 588, 812, 364, 1100, 1836, 2572})}); + + // Test case: same ranks different broadcast larger 1 + test_cases.push_back( + {"test same ranks different broadcast larger 1", + {2, 1, 2, 8}, + {1, 2, 8, 1}, + {2, 2, 2, 1}, + real_expected_vals({140, 364, 364, 1100, 588, 812, 1836, 2572})}); +#endif return test_cases; } @@ -189,6 +295,17 @@ void RunMatMulTest(int32_t opset_version, bool is_a_constant, bool is_b_constant excluded_providers.insert(kNnapiExecutionProvider); } + // TODO:: Change MatMulNaive Shader to support these test cases webgpu + std::unordered_set webgpu_excluded_test_cases{ + "test left 1D", + "test right 1D", + "test 2D empty input"}; + + // if test in webgpu_excluded_test_cases, add webgpu to excluded_providers + if (webgpu_excluded_test_cases.find(t.name) != webgpu_excluded_test_cases.end()) { + excluded_providers.insert(kWebGpuExecutionProvider); + } + test.ConfigExcludeEps(excluded_providers) .Config(run_with_tunable_op) .RunWithConfig(); @@ -234,10 +351,18 @@ TEST(MathOpTest, MatMulDoubleType) { } TEST(MathOpTest, MatMulInt32Type) { + // Webgpu does not support int32 matmul + if (DefaultWebGpuExecutionProvider().get() != nullptr) { + GTEST_SKIP() << "Skipping because of the following error: Webgpu does not support int32 matmul"; + } RunMatMulTest(9); } TEST(MathOpTest, MatMulUint32Type) { + // Webgpu does not support uint32 matmul + if (DefaultWebGpuExecutionProvider().get() != nullptr) { + GTEST_SKIP() << "Skipping because of the following error: Webgpu does not support uint32 matmul"; + } RunMatMulTest(9); } @@ -263,16 +388,22 @@ void RunMatMulZeroKTest() { // No special case is implemented. test.ConfigExcludeEps({kCoreMLExecutionProvider, kNnapiExecutionProvider, kDmlExecutionProvider, kDnnlExecutionProvider, kQnnExecutionProvider, - kOpenVINOExecutionProvider}) + kOpenVINOExecutionProvider, kWebGpuExecutionProvider}) .Config(run_with_tunable_op) .RunWithConfig(); } TEST(MathOpTest, MatMulZeroKFloatType) { + if (DefaultWebGpuExecutionProvider().get() != nullptr) { + GTEST_SKIP() << "Skipping because of the following error: Webgpu does not support zero-sized tensor"; + } RunMatMulZeroKTest(); } TEST(MathOpTest, MatMulZeroKInt32Type) { + if (DefaultWebGpuExecutionProvider().get() != nullptr) { + GTEST_SKIP() << "Skipping because of the following error: Webgpu does not support zero-sized tensor"; + } RunMatMulZeroKTest(); } From bb005b9362049cb049937ed7b497afb5e50a6b9a Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Tue, 25 Mar 2025 07:42:01 -0700 Subject: [PATCH 163/266] Upgrade Big Model pipeline CUDA from 11.8 to 12.x (#24156) ### Description Big model pipeline are still using cuda 11.8. This update the pipeline to use cuda 12.x. ### Motivation and Context --- .../azure-pipelines/bigmodels-ci-pipeline.yml | 27 ++++++++++--------- .../Dockerfile.package_ubuntu_2204_gpu_ffmpeg | 6 ++--- .../Dockerfile.package_ubuntu_2204_gpu_opencv | 6 ++--- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml index cbf70f32996db..f4658f3a22c33 100644 --- a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml @@ -41,11 +41,11 @@ parameters: variables: - name: docker_base_image - value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20250124.1 + value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 - name: linux_trt_version - value: 10.3.0.26-1.cuda11.8 + value: 10.9.0.34-1.cuda12.8 - name: Repository - value: 'onnxruntimecuda11manylinuxbuild' + value: 'onnxruntimecuda12manylinuxbuild' stages: - stage: Build_Onnxruntime_Cuda @@ -93,6 +93,7 @@ stages: $(Repository) \ /bin/bash -c ' set -ex; \ + ls /usr/local/; \ PATH=/opt/python/cp310-cp310/bin:$PATH /opt/python/cp310-cp310/bin/python3 /onnxruntime_src/tools/ci_build/build.py \ --build_dir /build --cmake_generator Ninja \ --config Release --update --build \ @@ -100,9 +101,9 @@ stages: --build_shared_lib \ --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ --build_wheel \ - --enable_onnx_tests --use_cuda --cuda_version=11.8 --cuda_home=/usr/local/cuda-11.8 --cudnn_home=/usr/local/cuda-11.8 \ + --enable_onnx_tests --use_cuda --cuda_version=12.2 --cuda_home=/usr/local/cuda-12.2 --cudnn_home=/usr/local/cuda-12.2 \ --enable_cuda_profiling \ - --enable_pybind --build_java \ + --enable_pybind \ --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=75;86" ' workingDirectory: $(Build.SourcesDirectory) @@ -164,7 +165,7 @@ stages: DockerBuildArgs: " --build-arg BUILD_UID=$( id -u ) " - Repository: onnxruntimeubuntupackagestest_cuda11 + Repository: onnxruntimeubuntupackagestest_cuda12 UseImageCacheContainerRegistry: false - task: Cache@2 @@ -182,14 +183,14 @@ stages: -v $(Build.BinariesDirectory)/Release:/Release \ -v $(STABLE_DIFFUSION_MODEL_CACHE):/model_cache:rw \ -v $(GenerateImage_DIR):/images:rw \ - onnxruntimeubuntupackagestest_cuda11 \ + onnxruntimeubuntupackagestest_cuda12 \ bash -c ' \ set -ex; \ python3 --version; \ python3 -m pip install --upgrade pip; \ python3 -m pip install /Release/*.whl; \ pushd /workspace/onnxruntime/python/tools/transformers/models/stable_diffusion; \ - python3 -m pip install -r requirements/cuda11/requirements.txt; \ + python3 -m pip install -r requirements/cuda12/requirements.txt; \ python3 -m pip install numpy==1.22.2; \ python3 -m pip install --upgrade polygraphy onnx-graphsurgeon ; \ echo Generate an image guided by a text prompt; \ @@ -221,7 +222,7 @@ stages: - script: | docker run -e SYSTEM_COLLECTIONURI --rm --gpus all -v $PWD:/workspace \ -v $(CLIP_MODEL_CACHE):/model_cache:rw \ - onnxruntimeubuntupackagestest_cuda11 \ + onnxruntimeubuntupackagestest_cuda12 \ bash -c ' set -x; \ python3 --version; \ @@ -248,7 +249,7 @@ stages: - script: | docker run -e SYSTEM_COLLECTIONURI --rm --gpus all -v $PWD:/workspace \ -v $(CLIP_MODEL_CACHE):/model_cache:rw \ - onnxruntimeubuntupackagestest_cuda11 \ + onnxruntimeubuntupackagestest_cuda12 \ bash -c ' set -ex; \ python3 --version; \ @@ -445,7 +446,7 @@ stages: popd ; \ python3 -m pip install /ort-artifact/*.whl ; \ python3 -m pip uninstall -y torch ; \ - python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu118 ; \ + python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu124 ; \ python3 -m models.whisper.convert_to_onnx -m openai/whisper-tiny --output wtiny-fp32-cpu-hf --precision fp32 --provider cpu --overwrite --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk ; \ python3 -m models.whisper.convert_to_onnx -m openai/whisper-tiny --output wtiny-fp32-cpu-hf --precision fp32 --provider cpu --overwrite --use_external_data_format --optimize_onnx ; \ python3 -m models.whisper.convert_to_onnx -m openai/whisper-tiny --output wtiny-fp32-cpu-hf --precision fp32 --provider cpu --overwrite --use_external_data_format --optimize_onnx --no_beam_search_op --output_cross_qk --separate_encoder_and_decoder_init ; \ @@ -489,7 +490,7 @@ stages: popd ; \ python3 -m pip install /ort-artifact/*.whl ; \ python3 -m pip uninstall -y torch ; \ - python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu118 ; \ + python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu124 ; \ python3 -m models.whisper.convert_to_onnx -m /whisper_large_v3 --output whisperlargev3 --use_external_data_format ; \ popd ; \ ' @@ -510,7 +511,7 @@ stages: popd ; \ python3 -m pip install /ort-artifact/*.whl ; \ python3 -m pip uninstall -y torch ; \ - python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu118 ; \ + python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu124 ; \ ls whisperlargev3; \ export LD_LIBRARY_PATH=/tmp/ompffmpeg:${LD_LIBRARY_PATH}; \ ffmpeg -version; \ diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg index 5cbfe70331803..bf3b50880a252 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_ffmpeg @@ -5,8 +5,8 @@ # Dockerfile to run ONNXRuntime with TensorRT integration # Build base image with required system packages -ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 -ARG TRT_VERSION=10.9.0.34-1+cuda11.8 +ARG BASEIMAGE=nvidia/cuda:12.8.1-cudnn-devel-ubuntu22.04 +ARG TRT_VERSION=10.9.0.34-1+cuda12.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION @@ -28,7 +28,7 @@ RUN apt-get install -y --no-install-recommends \ RUN pip install --upgrade pip # Install TensorRT -RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ +RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/7fa2af80.pub &&\ apt-get update &&\ apt-get install -y \ libnvinfer-dev=${TRT_VERSION} \ diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv index 4baf4b0bb0010..c6931147f96f9 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2204_gpu_opencv @@ -5,8 +5,8 @@ # Dockerfile to run ONNXRuntime with TensorRT integration # Build base image with required system packages -ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 -ARG TRT_VERSION=10.9.0.34-1+cuda11.8 +ARG BASEIMAGE=nvidia/cuda:12.8.1-cudnn-devel-ubuntu22.04 +ARG TRT_VERSION=10.9.0.34-1+cuda12.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION @@ -30,7 +30,7 @@ RUN apt-get install -y --no-install-recommends \ RUN pip install --upgrade pip # Install TensorRT -RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ +RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/7fa2af80.pub &&\ apt-get update &&\ apt-get install -y \ libnvinfer-dev=${TRT_VERSION} \ From de502c89fdffdb31b2179935c46efb08b44d9aae Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Tue, 25 Mar 2025 07:44:21 -0700 Subject: [PATCH 164/266] Proper Error Message when fp16 model is used for Beam Search in CPU (#24151) ### Description Show proper error message when fp16 model is used for Beam Search in CPU. Before: ``` 2025-02-15 20:15:02.999160115 [E:onnxruntime:, sequential_executor.cc:516 ExecuteKernel] Non-zero status code returned while running BeamSearch node. Name:'beam_search' Status Message: bad_function_call ``` After: ``` onnxruntime.capi.onnxruntime_pybind11_state.RuntimeException: [ONNXRuntimeError] : 6 : RUNTIME_EXCEPTION : Non-zero status code returned while running BeamSearch node. Name:'beam_search' Status Message: onnxruntime/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc:309 virtual onnxruntime::common::Status onnxruntime::contrib::transformers::BeamSearch::Compute(onnxruntime::OpKernelContext*) const BeamSearch does not support float16 model on CPU execution provider. Use float32 model or CUDA execution provider instead. ``` ### Motivation and Context https://github.com/microsoft/onnxruntime/issues/23728 --- .../cpu/transformers/beam_search.cc | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc b/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc index 7962662ff6088..885827fb09e7e 100644 --- a/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc +++ b/onnxruntime/contrib_ops/cpu/transformers/beam_search.cc @@ -68,6 +68,10 @@ REGISTER_KERNEL_TYPED(float) namespace transformers { +constexpr const char* kBeamSearchNotSupportFp16InCpu = + "BeamSearch does not support float16 model on CPU execution provider. " + "Use float32 model or CUDA execution provider instead."; + void BeamSearch::Init(const OpKernelInfo& info) { parameters_->ParseFromAttributes(info); @@ -215,6 +219,8 @@ Status BeamSearch::Compute(OpKernelContext* ctx) const { // Make a copy of parameters since we will update it based on inputs later BeamSearchParameters parameters = *parameters_; + const bool is_cpu_provider = ctx->GetComputeStream() == nullptr; + if (parameters.model_type == IGenerationParameters::kModelTypeGpt) { if (!gpt_subgraph_->IsOutputFloat16()) { // Output float32 BeamSearchGpt impl{ @@ -240,6 +246,10 @@ Status BeamSearch::Compute(OpKernelContext* ctx) const { return impl.Execute(init_run_decoder_feeds_fetches_manager_, *decoder_feeds_fetches_manager_); } else { // Output float16 + if (is_cpu_provider) { + ORT_THROW(kBeamSearchNotSupportFp16InCpu); + } + BeamSearchGpt impl{ *ctx_internal, has_init_decoder_ ? init_run_decoder_session_state : nullptr, @@ -256,6 +266,7 @@ Status BeamSearch::Compute(OpKernelContext* ctx) const { device_copy_int32_func_, update_gpt_feeds_fp16_func_, create_beam_scorer_func_}; + #ifdef USE_CUDA ORT_RETURN_IF_ERROR(impl.InitializeCuda(reorder_past_state_func_, cuda_device_prop_, cuda_device_arch_)); #endif @@ -294,6 +305,10 @@ Status BeamSearch::Compute(OpKernelContext* ctx) const { return impl.Execute(*encoder_feeds_fetches_manager_, *decoder_feeds_fetches_manager_); } else { + if (is_cpu_provider) { + ORT_THROW(kBeamSearchNotSupportFp16InCpu); + } + BeamSearchT5 impl{ *ctx_internal, *encoder_session_state, *decoder_session_state, *t5_encoder_subgraph_, *t5_decoder_subgraph_, thread_pool, ctx->GetComputeStream(), dumper_, parameters, @@ -309,6 +324,7 @@ Status BeamSearch::Compute(OpKernelContext* ctx) const { expand_buffer_float_func_, expand_buffer_float16_func_, create_beam_scorer_func_}; + #ifdef USE_CUDA ORT_RETURN_IF_ERROR(impl.InitializeCuda(reorder_past_state_func_, init_cache_indir_func_, cuda_device_prop_, cuda_device_arch_)); #endif @@ -346,6 +362,10 @@ Status BeamSearch::Compute(OpKernelContext* ctx) const { return impl.Execute(*encoder_feeds_fetches_manager_, *decoder_feeds_fetches_manager_); } else { + if (is_cpu_provider) { + ORT_THROW(kBeamSearchNotSupportFp16InCpu); + } + BeamSearchWhisper impl{ *ctx_internal, *encoder_session_state, *decoder_session_state, *whisper_encoder_subgraph_, *whisper_decoder_subgraph_, thread_pool, ctx->GetComputeStream(), dumper_, parameters, From a4b8f11cca62cfff51dbc08e49c1d2c797dca8f4 Mon Sep 17 00:00:00 2001 From: David Fan <30608893+jiafatom@users.noreply.github.com> Date: Tue, 25 Mar 2025 08:43:02 -0700 Subject: [PATCH 165/266] Change type len from int to size_t (#24157) ### Description As titled. ### Motivation and Context We have the last MatMul in phi-4-mini onnx which is b_shape = {3072, 200064} packed_b_size = MlasGemmPackBSize(N, K); it is `3072*200064*sizeof(float)=2458386432` This is larger than 2,147,483,647, it is out of the int boundary on a 32-bit system. Then len is negative. So we change the type to size_t, and the model can be loaded successfully after the change. --- .../framework/model_metadef_id_generator.cc | 6 ++--- onnxruntime/core/framework/murmurhash3.cc | 24 +++++++++---------- onnxruntime/core/framework/murmurhash3.h | 5 ++-- .../core/framework/prepacked_weights.cc | 4 ++-- .../core/framework/resource_accountant.cc | 2 +- onnxruntime/core/providers/cann/cann_utils.cc | 2 +- .../provider_bridge_provider.cc | 2 +- .../shared_library/provider_interfaces.h | 2 +- .../tensorrt_execution_provider_helper.cc | 2 +- .../tensorrt_execution_provider_utils.h | 2 +- .../core/session/provider_bridge_ort.cc | 2 +- 11 files changed, 27 insertions(+), 26 deletions(-) diff --git a/onnxruntime/core/framework/model_metadef_id_generator.cc b/onnxruntime/core/framework/model_metadef_id_generator.cc index 4a35052d159a0..2d55aa8360bd2 100644 --- a/onnxruntime/core/framework/model_metadef_id_generator.cc +++ b/onnxruntime/core/framework/model_metadef_id_generator.cc @@ -28,7 +28,7 @@ int ModelMetadefIdGenerator::GenerateId(const onnxruntime::GraphViewer& graph_vi // hash the bytes in the Graph instance. we can't just use the address as a new Graph instance may use // the same memory (unit tests prove this can occur). the raw bytes of the Graph instance should be a unique // fingerprint for the instance that can use used as the key to the hash of the model path/contents. - MurmurHash3::x86_128(&main_graph, gsl::narrow_cast(sizeof(Graph)), instance_hash[0], &instance_hash); + MurmurHash3::x86_128(&main_graph, sizeof(Graph), instance_hash[0], &instance_hash); HashValue graph_instance_hash = instance_hash[0] | (uint64_t(instance_hash[1]) << 32); // if we've already hashed this main graph instance use the cached value @@ -42,10 +42,10 @@ int ModelMetadefIdGenerator::GenerateId(const onnxruntime::GraphViewer& graph_vi // this may not be available if the model was loaded from a stream or in-memory bytes const auto model_path_str = main_graph.ModelPath().string(); if (!model_path_str.empty()) { - MurmurHash3::x86_128(model_path_str.data(), gsl::narrow_cast(model_path_str.size()), hash[0], &hash); + MurmurHash3::x86_128(model_path_str.data(), model_path_str.size(), hash[0], &hash); } else { auto hash_str = [&hash](const std::string& str) { - MurmurHash3::x86_128(str.data(), gsl::narrow_cast(str.size()), hash[0], &hash); + MurmurHash3::x86_128(str.data(), str.size(), hash[0], &hash); }; // fingerprint the main graph by hashing graph inputs and the ordered outputs from each node diff --git a/onnxruntime/core/framework/murmurhash3.cc b/onnxruntime/core/framework/murmurhash3.cc index 802f0a4c58a6d..c984767932a3b 100644 --- a/onnxruntime/core/framework/murmurhash3.cc +++ b/onnxruntime/core/framework/murmurhash3.cc @@ -59,7 +59,7 @@ inline uint64_t rotl64(uint64_t x, int8_t r) { // // Changes to support big-endian from https://github.com/explosion/murmurhash/pull/27/ // were manually applied to original murmurhash3 source code. -ORT_FORCEINLINE uint32_t getblock32(const uint32_t* p, int i) { +ORT_FORCEINLINE uint32_t getblock32(const uint32_t* p, ptrdiff_t i) { if constexpr (onnxruntime::endian::native == onnxruntime::endian::little) { return p[i]; } else { @@ -71,7 +71,7 @@ ORT_FORCEINLINE uint32_t getblock32(const uint32_t* p, int i) { } } -ORT_FORCEINLINE uint64_t getblock64(const uint64_t* p, int i) { +ORT_FORCEINLINE uint64_t getblock64(const uint64_t* p, ptrdiff_t i) { if constexpr (onnxruntime::endian::native == onnxruntime::endian::little) { return p[i]; } else { @@ -115,10 +115,10 @@ ORT_FORCEINLINE constexpr uint64_t fmix64(uint64_t k) { //----------------------------------------------------------------------------- namespace onnxruntime { -void MurmurHash3::x86_32(const void* key, int len, +void MurmurHash3::x86_32(const void* key, size_t len, uint32_t seed, void* out) { const uint8_t* data = (const uint8_t*)key; - const int nblocks = len / 4; + const auto nblocks = static_cast(len / 4U); uint32_t h1 = seed; @@ -128,9 +128,9 @@ void MurmurHash3::x86_32(const void* key, int len, //---------- // body - const uint32_t* blocks = (const uint32_t*)(data + static_cast(nblocks) * 4); + const uint32_t* blocks = (const uint32_t*)(data + nblocks * 4); - for (int i = -nblocks; i; i++) { + for (auto i = -nblocks; i; i++) { uint32_t k1 = getblock32(blocks, i); k1 *= c1; @@ -145,7 +145,7 @@ void MurmurHash3::x86_32(const void* key, int len, //---------- // tail - const uint8_t* tail = (const uint8_t*)(data + static_cast(nblocks) * 4); + const uint8_t* tail = (const uint8_t*)(data + nblocks * 4); uint32_t k1 = 0; @@ -176,9 +176,9 @@ void MurmurHash3::x86_32(const void* key, int len, //----------------------------------------------------------------------------- -void MurmurHash3::x86_128(const void* key, int len, uint32_t seed, void* out) { +void MurmurHash3::x86_128(const void* key, size_t len, uint32_t seed, void* out) { const uint8_t* data = (const uint8_t*)key; - const int nblocks = len / 16; + const auto nblocks = static_cast(len / 16U); uint32_t h1 = seed; uint32_t h2 = seed; @@ -193,9 +193,9 @@ void MurmurHash3::x86_128(const void* key, int len, uint32_t seed, void* out) { //---------- // body - const uint32_t* blocks = (const uint32_t*)(data + static_cast(nblocks) * 16); + const uint32_t* blocks = (const uint32_t*)(data + nblocks * 16); - for (int i = -nblocks; i; i++) { + for (auto i = -nblocks; i; i++) { uint32_t k1 = getblock32(blocks, i * 4 + 0); uint32_t k2 = getblock32(blocks, i * 4 + 1); uint32_t k3 = getblock32(blocks, i * 4 + 2); @@ -241,7 +241,7 @@ void MurmurHash3::x86_128(const void* key, int len, uint32_t seed, void* out) { //---------- // tail - const uint8_t* tail = (const uint8_t*)(data + static_cast(nblocks) * 16); + const uint8_t* tail = (const uint8_t*)(data + nblocks * 16); uint32_t k1 = 0; uint32_t k2 = 0; diff --git a/onnxruntime/core/framework/murmurhash3.h b/onnxruntime/core/framework/murmurhash3.h index ab86a3e591adf..ddba725bb2a37 100644 --- a/onnxruntime/core/framework/murmurhash3.h +++ b/onnxruntime/core/framework/murmurhash3.h @@ -4,13 +4,14 @@ #pragma once #include +#include namespace onnxruntime { struct MurmurHash3 { // generate 32-bit hash from input and write to 'out' - static void x86_32(const void* key, int len, uint32_t seed, void* out); + static void x86_32(const void* key, size_t len, uint32_t seed, void* out); // generate 128-bit hash from input and write to 'out'. - static void x86_128(const void* key, int len, uint32_t seed, void* out); + static void x86_128(const void* key, size_t len, uint32_t seed, void* out); }; } // namespace onnxruntime diff --git a/onnxruntime/core/framework/prepacked_weights.cc b/onnxruntime/core/framework/prepacked_weights.cc index 6aee164dcf104..460b43f2888ab 100644 --- a/onnxruntime/core/framework/prepacked_weights.cc +++ b/onnxruntime/core/framework/prepacked_weights.cc @@ -11,14 +11,14 @@ HashValue PrePackedWeights::GetHash() const { uint32_t hash[4] = {0, 0, 0, 0}; - auto hash_int8_t_buffer = [&hash](void* data, int len) { MurmurHash3::x86_128(data, len, hash[0], &hash); }; + auto hash_int8_t_buffer = [&hash](void* data, size_t len) { MurmurHash3::x86_128(data, len, hash[0], &hash); }; ORT_ENFORCE(buffers_.size() == buffer_sizes_.size()); for (size_t iter = 0; iter < buffers_.size(); ++iter) { // some pre-packed buffers may be null if they were just "place-holders" occupying an index // in the "buffers_" vector if (buffers_[iter].get() != nullptr) { - hash_int8_t_buffer(buffers_[iter].get(), static_cast(buffer_sizes_[iter])); + hash_int8_t_buffer(buffers_[iter].get(), buffer_sizes_[iter]); } } diff --git a/onnxruntime/core/framework/resource_accountant.cc b/onnxruntime/core/framework/resource_accountant.cc index b1bf9aa6d120b..0665cc1951e60 100644 --- a/onnxruntime/core/framework/resource_accountant.cc +++ b/onnxruntime/core/framework/resource_accountant.cc @@ -204,7 +204,7 @@ std::string IResourceAccountant::MakeUniqueNodeName(const Node& node) { uint32_t hash[4] = {0, 0, 0, 0}; auto hash_str = [&hash](const std::string& str) { - MurmurHash3::x86_128(str.data(), narrow(str.size()), hash[0], &hash); + MurmurHash3::x86_128(str.data(), str.size(), hash[0], &hash); }; const auto& node_name = (node.Name().empty()) ? node.OpType() : node.Name(); diff --git a/onnxruntime/core/providers/cann/cann_utils.cc b/onnxruntime/core/providers/cann/cann_utils.cc index 95d7a462ca9d9..5b3f9e6731b34 100644 --- a/onnxruntime/core/providers/cann/cann_utils.cc +++ b/onnxruntime/core/providers/cann/cann_utils.cc @@ -220,7 +220,7 @@ bool FileExist(const std::string& file_name) { void GenerateHashValue(const std::string string, HashValue& hash_value) { uint32_t hash[4] = {0, 0, 0, 0}; - MurmurHash3::x86_128(string.data(), gsl::narrow_cast(string.size()), hash[0], &hash); + MurmurHash3::x86_128(string.data(), string.size(), hash[0], &hash); hash_value = hash[0] | (uint64_t(hash[1]) << 32); } diff --git a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc index 90fd36ea29956..0d01215efaa14 100644 --- a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc +++ b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc @@ -775,7 +775,7 @@ std::unique_ptr CreateModel(const GraphViewer& graph_viewer, const loggin } // namespace cann #endif -void MurmurHash3::x86_128(const void* key, int len, uint32_t seed, void* out) { +void MurmurHash3::x86_128(const void* key, size_t len, uint32_t seed, void* out) { return g_host->MurmurHash3__x86_128(key, len, seed, out); } diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index 83d615c1bde0a..9d5e16caa361d 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -1288,7 +1288,7 @@ struct ProviderHost { virtual std::unique_ptr cann__CreateModel(const GraphViewer& graph_viewer, const logging::Logger& logger) = 0; #endif - virtual void MurmurHash3__x86_128(const void* key, int len, uint32_t seed, void* out) = 0; + virtual void MurmurHash3__x86_128(const void* key, size_t len, uint32_t seed, void* out) = 0; #ifdef _WIN32 virtual std::string ToUTF8String(const std::wstring& s) = 0; diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc index 71674f7c9c557..b99cb4f52ed59 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_helper.cc @@ -15,7 +15,7 @@ std::string GetUniqueGraphName(const Graph& graph) { uint32_t hash[4] = {0, 0, 0, 0}; auto hash_str = [&hash](const std::string& str) { - MurmurHash3::x86_128(str.data(), gsl::narrow_cast(str.size()), hash[0], &hash); + MurmurHash3::x86_128(str.data(), str.size(), hash[0], &hash); }; // Hash all nodes' name diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_utils.h b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_utils.h index 5a7b135fd92cd..dcf3673a004e4 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_utils.h +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_utils.h @@ -533,7 +533,7 @@ HashValue TRTGenerateId(const GraphViewer& graph_viewer, std::string trt_version uint32_t hash[4] = {0, 0, 0, 0}; auto hash_str = [&hash](const std::string& str) { - MurmurHash3::x86_128(str.data(), gsl::narrow_cast(str.size()), hash[0], &hash); + MurmurHash3::x86_128(str.data(), str.size(), hash[0], &hash); }; // Use the model's file name instead of the entire path to avoid cache regeneration if path changes diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index e46236f4ca11c..5fd197d7a798b 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -1636,7 +1636,7 @@ struct ProviderHostImpl : ProviderHost { } #endif - void MurmurHash3__x86_128(const void* key, int len, uint32_t seed, void* out) override { + void MurmurHash3__x86_128(const void* key, size_t len, uint32_t seed, void* out) override { MurmurHash3::x86_128(key, len, seed, out); } From a8fb78684966de8327244763008455a4fd778c0b Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 25 Mar 2025 12:49:04 -0400 Subject: [PATCH 166/266] Limit the Pipeline ability to build cuda 11 (#24073) ### Description Limit the Pipeline ability to build cuda 11. However, refernce to CUDA 11 is not complety removed in this PR. Will keep thme incase we decided to support both cuda 13 and cuda 12 in the future. ### Motivation and Context --- .github/ISSUE_TEMPLATE/03-mobile.yml | 2 +- .github/ISSUE_TEMPLATE/05-performance.yml | 2 +- .github/ISSUE_TEMPLATE/06-training.yml | 2 +- .github/ISSUE_TEMPLATE/08-general.yml | 2 +- js/node/script/install.js | 1 - .../tools/tensorrt/perf/build/build_image.py | 1 - .../models/stable_diffusion/README.md | 20 +--- .../c-api-noopenmp-packaging-pipelines.yml | 10 +- .../cuda-packaging-pipeline.yml | 1 - .../azure-pipelines/linux-gpu-ci-pipeline.yml | 1 - .../linux-gpu-tensorrt-ci-pipeline.yml | 1 - ...-gpu-tensorrt-cuda-minimal-ci-pipeline.yml | 1 - ...linux-gpu-tensorrt-daily-perf-pipeline.yml | 1 - .../azure-pipelines/post-merge-jobs.yml | 1 - .../py-cuda-alt-package-test-pipeline.yml | 57 --------- .../py-cuda-alt-packaging-pipeline.yml | 60 ---------- .../jobs/py-linux-cuda-package-test-job.yml | 3 +- .../nuget-linux-cuda-packaging-stage.yml | 2 +- .../stages/py-gpu-packaging-stage.yml | 1 - .../stages/py-linux-gpu-stage.yml | 7 +- .../stages/py-win-gpu-stage.yml | 3 +- .../templates/jobs/set-winenv.yml | 24 ++-- .../py-packaging-linux-test-cuda.yml | 7 +- ...-gpu-tensorrt-cuda-minimal-ci-pipeline.yml | 1 - ...ckerfile.package_ubi8_cuda11_8_tensorrt8_6 | 46 -------- .../docker/Dockerfile.package_ubuntu_2004_gpu | 4 +- .../Dockerfile.ubuntu_cuda11_tensorrt10 | 109 ------------------ .../x86_64/default/cuda11/Dockerfile | 45 -------- .../default/cuda11/scripts/install_deps.sh | 56 --------- .../inference/x86_64/python/cuda/Dockerfile | 45 -------- .../python/cuda/scripts/install_centos.sh | 18 --- 31 files changed, 33 insertions(+), 501 deletions(-) delete mode 100644 tools/ci_build/github/azure-pipelines/py-cuda-alt-package-test-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/py-cuda-alt-packaging-pipeline.yml delete mode 100644 tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda11_8_tensorrt8_6 delete mode 100644 tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 delete mode 100644 tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/Dockerfile delete mode 100755 tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/scripts/install_deps.sh delete mode 100644 tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile delete mode 100755 tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh diff --git a/.github/ISSUE_TEMPLATE/03-mobile.yml b/.github/ISSUE_TEMPLATE/03-mobile.yml index 7c6de5aad523d..07bb40ff94a2e 100644 --- a/.github/ISSUE_TEMPLATE/03-mobile.yml +++ b/.github/ISSUE_TEMPLATE/03-mobile.yml @@ -131,6 +131,6 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false diff --git a/.github/ISSUE_TEMPLATE/05-performance.yml b/.github/ISSUE_TEMPLATE/05-performance.yml index da0e6c7ada7a7..5d678033f6a42 100644 --- a/.github/ISSUE_TEMPLATE/05-performance.yml +++ b/.github/ISSUE_TEMPLATE/05-performance.yml @@ -127,7 +127,7 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false - type: textarea diff --git a/.github/ISSUE_TEMPLATE/06-training.yml b/.github/ISSUE_TEMPLATE/06-training.yml index 790d64dac0051..fec2ab3a1b285 100644 --- a/.github/ISSUE_TEMPLATE/06-training.yml +++ b/.github/ISSUE_TEMPLATE/06-training.yml @@ -72,6 +72,6 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false diff --git a/.github/ISSUE_TEMPLATE/08-general.yml b/.github/ISSUE_TEMPLATE/08-general.yml index 241be0044fe7d..53269c240429f 100644 --- a/.github/ISSUE_TEMPLATE/08-general.yml +++ b/.github/ISSUE_TEMPLATE/08-general.yml @@ -125,6 +125,6 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false diff --git a/js/node/script/install.js b/js/node/script/install.js index 7fdaeb9586278..d406da3591eec 100644 --- a/js/node/script/install.js +++ b/js/node/script/install.js @@ -9,7 +9,6 @@ // The purpose of this script is to download the required binaries for the platform and architecture. // Currently, most of the binaries are already bundled in the package, except for the following: -// - Linux/x64/CUDA 11 // - Linux/x64/CUDA 12 // // The CUDA binaries are not bundled because they are too large to be allowed in the npm registry. Instead, they are diff --git a/onnxruntime/python/tools/tensorrt/perf/build/build_image.py b/onnxruntime/python/tools/tensorrt/perf/build/build_image.py index 3e913094628c3..a4fbc21b43c85 100644 --- a/onnxruntime/python/tools/tensorrt/perf/build/build_image.py +++ b/onnxruntime/python/tools/tensorrt/perf/build/build_image.py @@ -16,7 +16,6 @@ import sys TRT_DOCKER_FILES = { - "10.9_cuda11.8_cudnn8": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10", "10.9_cuda12.8_cudnn9": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10", "BIN": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin", } diff --git a/onnxruntime/python/tools/transformers/models/stable_diffusion/README.md b/onnxruntime/python/tools/transformers/models/stable_diffusion/README.md index dc83f4dc220f0..2506ffe8a3f50 100644 --- a/onnxruntime/python/tools/transformers/models/stable_diffusion/README.md +++ b/onnxruntime/python/tools/transformers/models/stable_diffusion/README.md @@ -143,29 +143,11 @@ conda activate py310 ### Setup Environment (CUDA) without docker -First, we need install CUDA 11.8 or 12.x, [cuDNN](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html), and [TensorRT](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html) in the machine. +First, we need install CUDA 12.x, [cuDNN](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html), and [TensorRT](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html) in the machine. The verison of CuDNN can be found in https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#requirements. The version of TensorRT can be found in https://onnxruntime.ai/docs/execution-providers/TensorRT-ExecutionProvider.html#requirements. -#### CUDA 11.8: - -In the Conda environment, install PyTorch 2.1 up to 2.3.1, and other required packages like the following: -``` -pip install torch>=2.1,<2.4 --index-url https://download.pytorch.org/whl/cu118 -pip install --upgrade polygraphy onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com -pip install -r requirements/cuda11/requirements.txt -``` - -For Windows, install nvtx like the following: -``` -conda install -c conda-forge nvtx -``` - -We cannot directly `pip install tensorrt` for CUDA 11. Follow https://github.com/NVIDIA/TensorRT/issues/2773 to install TensorRT for CUDA 11 in Linux. - -For Windows, pip install the tensorrt wheel in the downloaded TensorRT zip file instead. Like `pip install tensorrt-8.6.1.6.windows10.x86_64.cuda-11.8\tensorrt-8.6.1.6\python\tensorrt-8.6.1-cp310-none-win_amd64.whl`. - #### CUDA 12.*: The official package of onnxruntime-gpu 1.19.x is built for CUDA 12.x. You can install it and other python packages like the following: ``` diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index 4a5ba81943b40..71c3edfaee8bd 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -76,12 +76,12 @@ variables: - name: ReleaseVersionSuffix value: '' - name: win_trt_version - value: 11.8 + value: 12.2 - name: win_trt_home - value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda11 }} + value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda12 }} - name: win_cuda_home - value: $(Agent.TempDirectory)\v11.8 + value: $(Agent.TempDirectory)\v12.2 stages: - template: stages/set_packaging_variables_stage.yml @@ -110,13 +110,13 @@ stages: - template: stages/java-cuda-packaging-stage.yml parameters: - CudaVersion: 11.8 + CudaVersion: 12.2 SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - template: stages/nuget-combine-cuda-stage.yml parameters: - CudaVersion: 11.8 + CudaVersion: 12.2 RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} win_trt_home: ${{ variables.win_trt_home }} diff --git a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml index 6eb1e858a812b..83d41f23d9de2 100644 --- a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml @@ -50,7 +50,6 @@ parameters: type: string default: '12.2' values: - - 11.8 - 12.2 variables: diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml index 665b7435eed66..492bada97acc9 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml @@ -33,7 +33,6 @@ parameters: type: string default: '12.2' values: - - 11.8 - 12.2 - name: SpecificArtifact diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml index dd5288ab3a436..c6eabed7c5b4a 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml @@ -33,7 +33,6 @@ parameters: type: string default: '12.2' values: - - 11.8 - 12.2 variables: diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-cuda-minimal-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-cuda-minimal-ci-pipeline.yml index ad9d9bfc4b5e5..0ec05909b846f 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-cuda-minimal-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-cuda-minimal-ci-pipeline.yml @@ -33,7 +33,6 @@ parameters: type: string default: '12.2' values: - - 11.8 - 12.2 variables: diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml index 2dc597fcb2351..ac9153e1b4887 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml @@ -10,7 +10,6 @@ parameters: type: string default: 10.9_cuda12.8_cudnn9 values: - - 10.9_cuda11.8_cudnn8 - 10.9_cuda12.8_cudnn9 - BIN diff --git a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml index 78c07c28d6f4e..2cecedb401724 100644 --- a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml +++ b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml @@ -4,7 +4,6 @@ parameters: type: string default: '12.2' values: - - 11.8 - 12.2 variables: diff --git a/tools/ci_build/github/azure-pipelines/py-cuda-alt-package-test-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-cuda-alt-package-test-pipeline.yml deleted file mode 100644 index 960b59f93bee0..0000000000000 --- a/tools/ci_build/github/azure-pipelines/py-cuda-alt-package-test-pipeline.yml +++ /dev/null @@ -1,57 +0,0 @@ -resources: - pipelines: - - pipeline: build - source: 'Python CUDA ALT Packaging Pipeline' - trigger: true - branch: main # branch to pick the artifact, Used only for manual triggered pipeline runs for testing the pipeline itself - -stages: - # ****The following Stage depend on all previous tags. *** - # GPU resources are very limited, - # To utilize gpu resource more efficiently, run GPU job only after all cpus jobs succeed - - stage: Linux_Test_CUDA_Alt_x86_64_stage - dependsOn: - jobs: - - template: templates/py-packaging-linux-test-cuda.yml - parameters: - arch: 'x86_64' - machine_pool: 'Onnxruntime-Linux-GPU' - python_wheel_suffix: '_gpu' - timeout: 480 - docker_base_image: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20250124.1 - cuda_version: '11.8' - - - stage: Republish_Wheels - dependsOn: - jobs: - - job: Python_Publishing_GPU - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' - steps: - - checkout: none - - download: build - displayName: 'Download Pipeline Artifact - onnxruntime_gpu' - artifact: 'onnxruntime_gpu' - patterns: '*.whl' - - download: build - displayName: 'Download Pipeline Artifact - Win GPU 3.10' - artifact: 'win_gpu_wheel_3.10' - patterns: '*.whl' - - download: build - displayName: 'Download Pipeline Artifact - Win GPU 3.11' - artifact: 'win_gpu_wheel_3.11' - patterns: '*.whl' - - download: build - displayName: 'Download Pipeline Artifact - Win GPU 3.12' - artifact: 'win_gpu_wheel_3.12' - patterns: '*.whl' - - download: build - displayName: 'Download Pipeline Artifact - Win GPU 3.13' - artifact: 'win_gpu_wheel_3.13' - patterns: '*.whl' - - - script: find $(Pipeline.Workspace) -name \*win_amd64.whl -exec mv {} $(Pipeline.Workspace)/build/onnxruntime_gpu \; - displayName: 'Merge files together' - - - publish: $(Pipeline.Workspace)/build/onnxruntime_gpu - artifact: whl - displayName: Republish artifacts \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/py-cuda-alt-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-cuda-alt-packaging-pipeline.yml deleted file mode 100644 index b4870db90a755..0000000000000 --- a/tools/ci_build/github/azure-pipelines/py-cuda-alt-packaging-pipeline.yml +++ /dev/null @@ -1,60 +0,0 @@ -trigger: none -resources: - repositories: - - repository: 1esPipelines - type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release -parameters: - - name: enable_linux_cuda - type: boolean - default: true - - - name: enable_windows_cuda - type: boolean - default: true - - - name: cmake_build_type - type: string - default: 'Release' - values: - - Debug - - Release - - RelWithDebInfo - - MinSizeRel -extends: - # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. - # For non-production pipelines, use "Unofficial" as defined below. - # For productions pipelines, use "Official". - template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines - parameters: - sdl: - componentgovernance: - ignoreDirectories: '$(Build.Repository.LocalPath)/cmake/external/emsdk/upstream/emscripten/tests,$(Build.Repository.LocalPath)/cmake/external/onnx/third_party/benchmark,$(Build.Repository.LocalPath)/cmake/external/onnx/third_party/pybind11,$(Build.Repository.LocalPath)/cmake/external/onnx/third_party/pybind11/tests,$(Build.Repository.LocalPath)/cmake/external/onnxruntime-extensions,$(Build.Repository.LocalPath)/js/react_native/e2e/node_modules,$(Build.Repository.LocalPath)/js/node_modules,$(Build.Repository.LocalPath)/onnxruntime-inference-examples,$(Build.SourcesDirectory)/cmake/external/emsdk/upstream/emscripten/tests,$(Build.SourcesDirectory)/cmake/external/onnx/third_party/benchmark,$(Build.SourcesDirectory)/cmake/external/onnx/third_party/pybind11,$(Build.SourcesDirectory)/cmake/external/onnx/third_party/pybind11/tests,$(Build.SourcesDirectory)/cmake/external/onnxruntime-extensions,$(Build.SourcesDirectory)/js/react_native/e2e/node_modules,$(Build.SourcesDirectory)/js/node_modules,$(Build.SourcesDirectory)/onnxruntime-inference-examples,$(Build.BinariesDirectory)' - alertWarningLevel: High - failOnAlert: false - verbosity: Normal - timeout: 3600 - tsa: - enabled: true - codeSignValidation: - enabled: true - break: true - policheck: - enabled: true - exclusionsFile: '$(Build.SourcesDirectory)\tools\ci_build\policheck_exclusions.xml' - codeql: - compiled: - enabled: false - justificationForDisabling: 'CodeQL is taking nearly 4 hours resulting in timeouts in our production pipelines' - pool: - name: 'onnxruntime-Win-CPU-2022' # Name of your hosted pool - os: windows # OS of the image. This value cannot be a variable. Allowed values: windows, linux, macOS - - stages: - - template: stages/py-gpu-packaging-stage.yml - parameters: - enable_linux_cuda: ${{ parameters.enable_linux_cuda }} - enable_windows_cuda: ${{ parameters.enable_windows_cuda }} - cmake_build_type: ${{ parameters.cmake_build_type }} - cuda_version: '11.8' diff --git a/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml b/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml index 85366ffc28b3a..49d65b10b393c 100644 --- a/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml +++ b/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml @@ -2,9 +2,8 @@ parameters: - name: CudaVersion displayName: 'CUDA version' type: string - default: '11.8' + default: '12.2' values: - - 11.8 - 12.2 - name: machine_pool type: string diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml index 06576ac05569e..b1d0625c3b11b 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml @@ -1,7 +1,7 @@ parameters: - name: CudaVersion type: string - default: '11.8' + default: '12.2' - name: buildJava type: boolean - name: buildNodejs diff --git a/tools/ci_build/github/azure-pipelines/stages/py-gpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-gpu-packaging-stage.yml index 362c2a3d74083..eea9b672eef3d 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-gpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-gpu-packaging-stage.yml @@ -36,7 +36,6 @@ parameters: displayName: 'CUDA version. Windows Only.' default: '12.2' values: - - 11.8 - 12.2 - name: PythonVersions diff --git a/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml index 60b2e04e82136..17eb10fae7eb2 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml @@ -22,9 +22,8 @@ parameters: - name: cuda_version type: string - default: '11.8' + default: '12.2' values: - - 11.8 - 12.2 stages: @@ -67,8 +66,8 @@ stages: - template: ../templates/get-docker-image-steps.yml parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda + Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12 DockerBuildArgs: "--build-arg BASEIMAGE=${{ parameters.docker_base_image }} --build-arg TRT_VERSION=${{ variables.trt_version }} --build-arg BUILD_UID=$( id -u )" Repository: onnxruntimecuda${{ replace(parameters.cuda_version, '.', '') }}xtrt86build${{ parameters.arch }} diff --git a/tools/ci_build/github/azure-pipelines/stages/py-win-gpu-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-win-gpu-stage.yml index 32004366fb947..fe2b85976d38b 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-win-gpu-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-win-gpu-stage.yml @@ -19,9 +19,8 @@ parameters: default: '' - name: CudaVersion type: string - default: '11.8' + default: '12.2' values: - - 11.8 - 12.2 - name: cmake_build_type diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml index 142b76ee43b99..96436883fb8b8 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml @@ -10,12 +10,12 @@ parameters: - name: PrimaryCUDAVersion type: string default: '12.2' - - name: SecondaryCUDAVersion - type: string - default: '11.8' - - name: win_trt_folder_cuda11 - type: string - default: 'TensorRT-10.9.0.34.Windows10.x86_64.cuda-11.8' +# - name: SecondaryCUDAVersion +# type: string +# default: '11.8' +# - name: win_trt_folder_cuda11 +# type: string +# default: 'TensorRT-10.9.0.34.Windows10.x86_64.cuda-11.8' - name: win_trt_folder_cuda12 type: string default: 'TensorRT-10.9.0.34.Windows10.x86_64.cuda-12.8' @@ -25,16 +25,16 @@ steps: - powershell: | azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v${{ parameters.PrimaryCUDAVersion }}" $(Agent.TempDirectory) displayName: 'Download Primary CUDA SDK v${{ parameters.PrimaryCUDAVersion }}' - - powershell: | - azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v${{ parameters.SecondaryCUDAVersion }}" $(Agent.TempDirectory) - displayName: 'Download Secondary CUDA SDK v${{ parameters.SecondaryCUDAVersion }}' +# - powershell: | +# azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v${{ parameters.SecondaryCUDAVersion }}" $(Agent.TempDirectory) +# displayName: 'Download Secondary CUDA SDK v${{ parameters.SecondaryCUDAVersion }}' - ${{ if eq(parameters.DownloadTRT, 'true') }}: - powershell: | azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/${{ parameters.win_trt_folder_cuda12 }}" $(Agent.TempDirectory) displayName: 'Download ${{ parameters.win_trt_folder_cuda12 }}' - - powershell: | - azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/${{ parameters.win_trt_folder_cuda11 }}" $(Agent.TempDirectory) - displayName: 'Download ${{ parameters.win_trt_folder_cuda11 }}' +# - powershell: | +# azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/${{ parameters.win_trt_folder_cuda11 }}" $(Agent.TempDirectory) +# displayName: 'Download ${{ parameters.win_trt_folder_cuda11 }}' - task: BatchScript@1 displayName: 'setup env' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml index e7c702042b441..96ff9943dc178 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml @@ -18,9 +18,8 @@ parameters: - name: cuda_version type: string - default: '11.8' + default: '12.2' values: - - 11.8 - 12.2 # TODO: Ideally it should fetch information from the build that triggers it @@ -91,8 +90,8 @@ jobs: - template: get-docker-image-steps.yml parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda + Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12 DockerBuildArgs: "--build-arg BASEIMAGE=${{ parameters.docker_base_image }} --build-arg TRT_VERSION=${{ variables.trt_version }} --build-arg BUILD_UID=$( id -u )" Repository: onnxruntimecuda${{ replace(parameters.cuda_version, '.', '') }}xtrt86build${{ parameters.arch }} diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-cuda-minimal-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-cuda-minimal-ci-pipeline.yml index c68ba01485db2..c12bb3552920c 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-cuda-minimal-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-cuda-minimal-ci-pipeline.yml @@ -33,7 +33,6 @@ parameters: type: string default: '12.2' values: - - 11.8 - 12.2 variables: diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda11_8_tensorrt8_6 b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda11_8_tensorrt8_6 deleted file mode 100644 index 9de88d1664b82..0000000000000 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda11_8_tensorrt8_6 +++ /dev/null @@ -1,46 +0,0 @@ -# -------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -# -------------------------------------------------------------- -# Dockerfile to Test ONNX Runtime on UBI8 with CUDA 11.8 and TensorRT 8.6 - -# Build base image with required system packages -ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubi8 -ARG TRT_VERSION=8.6.1.6-1.cuda11.8 -FROM $BASEIMAGE AS base -ARG TRT_VERSION -ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/src/tensorrt/bin:${PATH} - -RUN dnf install -y bash wget &&\ - dnf clean dbcache - -# Install python3 -RUN dnf install -y \ - python3.10 \ - python310-pip \ - python310-wheel &&\ - cd /usr/local/bin &&\ - ln -s /usr/bin/python3 python3.10 &&\ - ln -s /usr/bin/pip3 pip3.10; - -RUN pip3 install --upgrade pip -RUN pip3 install setuptools>=68.2.2 - -# Install TensorRT -RUN dnf install -y libnvinfer8 libnvonnxparsers8 libnvparsers8 libnvinfer-plugin8 libnvinfer-lean8 libnvinfer-vc-plugin8 libnvinfer-dispatch8 -RUN dnf downgrade -y libnvinfer8-${TRT_VERSION} libnvinfer8-${TRT_VERSION} libnvonnxparsers8-${TRT_VERSION} libnvparsers8-${TRT_VERSION} libnvinfer-plugin8-${TRT_VERSION} libnvinfer-lean8-${TRT_VERSION} libnvinfer-vc-plugin8-${TRT_VERSION} libnvinfer-dispatch8-${TRT_VERSION} &&\ - dnf install -y dnf-plugin-versionlock &&\ - dnf versionlock libnvinfer8 libnvonnxparsers8 libnvparsers8 libnvinfer-plugin8 libnvinfer-lean8 libnvinfer-vc-plugin8 libnvinfer-dispatch8 -RUN dnf clean dbcache - - -ADD scripts /tmp/scripts -RUN cd /tmp/scripts && /tmp/scripts/install_dotnet.sh && /tmp/scripts/install_java.sh && rm -rf /tmp/scripts - -# Build final image from base. -FROM base as final -ARG BUILD_USER=onnxruntimedev -ARG BUILD_UID=1000 -RUN adduser --uid $BUILD_UID $BUILD_USER -WORKDIR /home/$BUILD_USER -USER $BUILD_USER diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu index 9b392fa0e3a68..8a84b9b940306 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu @@ -5,8 +5,8 @@ # Dockerfile to run ONNXRuntime with TensorRT integration # Build base image with required system packages -ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04 -ARG TRT_VERSION=10.9.0.34-1+cuda11.8 +ARG BASEIMAGE=nvidia/cuda:12.2.2-cudnn8-devel-ubuntu20.04 +ARG TRT_VERSION=10.9.0.34-1+cuda12.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 deleted file mode 100644 index f68f488a9d8b8..0000000000000 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 +++ /dev/null @@ -1,109 +0,0 @@ -# -------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -# -------------------------------------------------------------- -# Dockerfile to run ONNXRuntime with TensorRT integration - -# Build base image with required system packages -FROM nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 AS base - -# The local directory into which to build and install CMAKE -ARG ONNXRUNTIME_LOCAL_CODE_DIR=/code - -ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/src/tensorrt/bin:${ONNXRUNTIME_LOCAL_CODE_DIR}/cmake-3.31.5-linux-x86_64/bin:/opt/miniconda/bin:${PATH} -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update &&\ - apt-get install -y sudo git bash unattended-upgrades wget -RUN unattended-upgrade - -# Install python3 -RUN apt-get install -y --no-install-recommends \ - python3 \ - python3-pip \ - python3-dev \ - python3-wheel &&\ - cd /usr/local/bin &&\ - ln -s /usr/bin/python3 python &&\ - ln -s /usr/bin/pip3 pip; - -RUN pip install --upgrade pip -RUN pip install psutil setuptools>=68.2.2 - -# Install TensorRT -RUN TRT_VERSION="10.9.0.34-1+cuda11.8" &&\ - apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ - apt-get update &&\ - apt-get install -y \ - libnvinfer-dev=${TRT_VERSION} \ - libnvinfer-dispatch-dev=${TRT_VERSION} \ - libnvinfer-dispatch10=${TRT_VERSION} \ - libnvinfer-headers-dev=${TRT_VERSION} \ - libnvinfer-headers-plugin-dev=${TRT_VERSION} \ - libnvinfer-lean-dev=${TRT_VERSION} \ - libnvinfer-lean10=${TRT_VERSION} \ - libnvinfer-plugin-dev=${TRT_VERSION} \ - libnvinfer-plugin10=${TRT_VERSION} \ - libnvinfer-vc-plugin-dev=${TRT_VERSION} \ - libnvinfer-vc-plugin10=${TRT_VERSION} \ - libnvinfer10=${TRT_VERSION} \ - libnvonnxparsers-dev=${TRT_VERSION} \ - libnvonnxparsers10=${TRT_VERSION} \ - tensorrt-dev=${TRT_VERSION} \ - libnvinfer-bin=${TRT_VERSION} - -# Compile trtexec if not installed -RUN if [ ! -d /usr/src/tensorrt/bin ] || [ ! -f /usr/src/tensorrt/bin/trtexec ]; then \ - cd /usr/src/tensorrt/samples/trtexec && make; \ - fi - -# Install Valgrind -RUN apt-get install -y valgrind - -# Build final image from base. Builds ORT. -FROM base AS final -ARG BUILD_USER=onnxruntimedev -ARG BUILD_UID=1000 -RUN adduser --gecos 'onnxruntime Build User' --disabled-password $BUILD_USER --uid $BUILD_UID -USER $BUILD_USER - -# ONNX Runtime arguments - -# URL to the github repo from which to clone ORT. -ARG ONNXRUNTIME_REPO=https://github.com/Microsoft/onnxruntime - -# The local directory into which to clone ORT. -ARG ONNXRUNTIME_LOCAL_CODE_DIR=/code - -# The git branch of ORT to checkout and build. -ARG ONNXRUNTIME_BRANCH=main - -# Optional. The specific commit to pull and build from. If not set, the latest commit is used. -ARG ONNXRUNTIME_COMMIT_ID - -# The supported CUDA architecture -ARG CMAKE_CUDA_ARCHITECTURES=75 - -WORKDIR ${ONNXRUNTIME_LOCAL_CODE_DIR} - -# Clone ORT repository with branch -RUN git clone --single-branch --branch ${ONNXRUNTIME_BRANCH} --recursive ${ONNXRUNTIME_REPO} onnxruntime &&\ - /bin/sh onnxruntime/dockerfiles/scripts/install_common_deps.sh - -WORKDIR ${ONNXRUNTIME_LOCAL_CODE_DIR}/onnxruntime - -# Reset to a specific commit if specified by build args. -RUN if [ -z "$ONNXRUNTIME_COMMIT_ID" ] ; then echo "Building branch ${ONNXRUNTIME_BRANCH}" ;\ - else echo "Building branch ${ONNXRUNTIME_BRANCH} @ commit ${ONNXRUNTIME_COMMIT_ID}" &&\ - git reset --hard ${ONNXRUNTIME_COMMIT_ID} && git submodule update --recursive ; fi - -# Build ORT -ENV CUDA_MODULE_LOADING="LAZY" -ARG PARSER_CONFIG="" -RUN /bin/sh build.sh ${PARSER_CONFIG} --parallel --build_shared_lib --cuda_home /usr/local/cuda --cudnn_home /usr/lib/x86_64-linux-gnu/ --use_tensorrt --tensorrt_home /usr/lib/x86_64-linux-gnu/ --config Release --build_wheel --skip_tests --skip_submodule_sync --cmake_extra_defines '"CMAKE_CUDA_ARCHITECTURES='${CMAKE_CUDA_ARCHITECTURES}'"' - -# Switch to root to continue following steps of CI -USER root - -# Intall ORT wheel -RUN pip install ${ONNXRUNTIME_LOCAL_CODE_DIR}/onnxruntime/build/Linux/Release/dist/*.whl diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/Dockerfile b/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/Dockerfile deleted file mode 100644 index 24287fd34d3ea..0000000000000 --- a/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -# This file is used by Zip-Nuget Packaging NoContribOps Pipeline,Zip-Nuget-Java Packaging Pipeline -FROM onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11_dotnet:20250124.1 - -ARG TRT_VERSION -#Install TensorRT only if TRT_VERSION is not empty -RUN if [ -n "$TRT_VERSION" ]; then \ - echo "TRT_VERSION is $TRT_VERSION" && \ - dnf -y install \ - libnvinfer10-${TRT_VERSION} \ - libnvinfer-headers-devel-${TRT_VERSION} \ - libnvinfer-devel-${TRT_VERSION} \ - libnvinfer-lean10-${TRT_VERSION} \ - libnvonnxparsers10-${TRT_VERSION} \ - libnvonnxparsers-devel-${TRT_VERSION} \ - libnvinfer-dispatch10-${TRT_VERSION} \ - libnvinfer-plugin10-${TRT_VERSION} \ - libnvinfer-vc-plugin10-${TRT_VERSION} \ - libnvinfer-bin-${TRT_VERSION} \ - libnvinfer-plugin10-${TRT_VERSION} \ - libnvinfer-plugin-devel-${TRT_VERSION} \ - libnvinfer-vc-plugin-devel-${TRT_VERSION} \ - libnvinfer-lean-devel-${TRT_VERSION} \ - libnvinfer-dispatch-devel-${TRT_VERSION} \ - libnvinfer-headers-plugin-devel-${TRT_VERSION} && \ - dnf clean dbcache ; \ -else \ - echo "TRT_VERSION is none skipping Tensor RT Installation" ; \ -fi - -ENV PATH=/usr/lib/jvm/msopenjdk-17/bin:$PATH -ENV LANG=en_US.UTF-8 -ENV LC_ALL=en_US.UTF-8 -ENV JAVA_HOME=/usr/lib/jvm/msopenjdk-17 -ENV CUDAHOSTCXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++ -ADD scripts /tmp/scripts -RUN cd /tmp/scripts && /tmp/scripts/install_deps.sh && rm -rf /tmp/scripts - -ARG BUILD_UID=1001 -ARG BUILD_USER=onnxruntimedev -RUN adduser --uid $BUILD_UID $BUILD_USER -WORKDIR /home/$BUILD_USER -USER $BUILD_USER diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/scripts/install_deps.sh b/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/scripts/install_deps.sh deleted file mode 100755 index e98429946f4b3..0000000000000 --- a/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/scripts/install_deps.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -set -e -x - -# Download a file from internet -function GetFile { - local uri=$1 - local path=$2 - local force=${3:-false} - local download_retries=${4:-5} - local retry_wait_time_seconds=${5:-30} - - if [[ -f $path ]]; then - if [[ $force = false ]]; then - echo "File '$path' already exists. Skipping download" - return 0 - else - rm -rf $path - fi - fi - - if [[ -f $uri ]]; then - echo "'$uri' is a file path, copying file to '$path'" - cp $uri $path - return $? - fi - - echo "Downloading $uri" - # Use aria2c if available, otherwise use curl - if command -v aria2c > /dev/null; then - aria2c -q -d $(dirname $path) -o $(basename $path) "$uri" - else - curl "$uri" -sSL --retry $download_retries --retry-delay $retry_wait_time_seconds --create-dirs -o "$path" --fail - fi - - return $? -} -mkdir -p /tmp/src - -cd /tmp/src - - -echo "Installing Node.js" -CPU_ARCH=`uname -m` -if [[ "$CPU_ARCH" = "x86_64" ]]; then - NODEJS_ARCH=x64 -elif [[ "$CPU_ARCH" = "aarch64" ]]; then - NODEJS_ARCH=arm64 -else - NODEJS_ARCH=$CPU_ARCH -fi -# The EOL for nodejs v18.17.1 LTS is April 2025 -GetFile https://nodejs.org/dist/v18.17.1/node-v18.17.1-linux-${NODEJS_ARCH}.tar.gz /tmp/src/node-v18.17.1-linux-${NODEJS_ARCH}.tar.gz -tar --strip 1 -xf /tmp/src/node-v18.17.1-linux-${NODEJS_ARCH}.tar.gz -C /usr - -cd / -rm -rf /tmp/src diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile deleted file mode 100644 index d1df74e2a4506..0000000000000 --- a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# The default ARGs are for cuda 11.8 with cudnn8, TensorRT is optional -# Please overwrite BASEIMAGE, TRT_VERSION and other arguments with -# --docker-build-args ' --build-arg BASEIMAGE=other_base_image --build-arg TRT_VERSION=other_trt_version etc...' -# for other cuda version and TRT version -ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubi8 - -FROM $BASEIMAGE -ARG TRT_VERSION=10.9.0.34-1.cuda11.8 - -#Install TensorRT only if TRT_VERSION is not empty -RUN if [ -n "${TRT_VERSION}" ]; then \ - echo "TRT_VERSION is $TRT_VERSION" && \ - dnf -y install \ - libnvinfer10-${TRT_VERSION} \ - libnvinfer-headers-devel-${TRT_VERSION} \ - libnvinfer-devel-${TRT_VERSION} \ - libnvinfer-lean10-${TRT_VERSION} \ - libnvonnxparsers10-${TRT_VERSION} \ - libnvonnxparsers-devel-${TRT_VERSION} \ - libnvinfer-dispatch10-${TRT_VERSION} \ - libnvinfer-plugin10-${TRT_VERSION} \ - libnvinfer-vc-plugin10-${TRT_VERSION} \ - libnvinfer-bin-${TRT_VERSION} \ - libnvinfer-plugin10-${TRT_VERSION} \ - libnvinfer-plugin-devel-${TRT_VERSION} \ - libnvinfer-vc-plugin-devel-${TRT_VERSION} \ - libnvinfer-lean-devel-${TRT_VERSION} \ - libnvinfer-dispatch-devel-${TRT_VERSION} \ - libnvinfer-headers-plugin-devel-${TRT_VERSION} && \ - dnf clean dbcache ; \ -else \ - echo "TRT_VERSION is x${TRT_VERSION} skipping Tensor RT Installation" ; \ -fi - -ENV PATH=/usr/local/cuda/bin:$PATH -ENV CUDA_MODULE_LOADING="LAZY" - -ADD scripts /tmp/scripts -RUN cd /tmp/scripts && /tmp/scripts/install_centos.sh && rm -rf /tmp/scripts - -ARG BUILD_UID=1001 -ARG BUILD_USER=onnxruntimedev -RUN adduser --uid $BUILD_UID $BUILD_USER -WORKDIR /home/$BUILD_USER -USER $BUILD_USER diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh deleted file mode 100755 index d0b58ed28b8c9..0000000000000 --- a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -e - -os_major_version=$(tr -dc '0-9.' < /etc/redhat-release |cut -d \. -f1) - -echo "installing for os major version : $os_major_version" -dnf install -y glibc-langpack-\* -yum install -y which redhat-lsb-core expat-devel tar unzip zlib-devel make bzip2 bzip2-devel perl-IPC-Cmd openssl-devel wget - -echo "installing rapidjson for AzureEP" -wget https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz -tar zxvf v1.1.0.tar.gz -cd rapidjson-1.1.0 -mkdir build -cd build -cmake .. -cmake --install . -cd ../.. From 868066778376bd2f6091b008c7330b6c14b41e79 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Tue, 25 Mar 2025 10:43:54 -0700 Subject: [PATCH 167/266] Move Linux CPU CI pipeline to Github Actions (#24154) ### Description Move the x64 part of "Linux CPU CI pipeline" to Github Actions --- .github/workflows/linux_ci.yml | 162 ++++++++++++ .../azure-pipelines/linux-ci-pipeline.yml | 238 ------------------ 2 files changed, 162 insertions(+), 238 deletions(-) create mode 100644 .github/workflows/linux_ci.yml diff --git a/.github/workflows/linux_ci.yml b/.github/workflows/linux_ci.yml new file mode 100644 index 0000000000000..26a6125ca92a1 --- /dev/null +++ b/.github/workflows/linux_ci.yml @@ -0,0 +1,162 @@ +# This workflow builds and tests the ONNX Runtime for Linux in both Debug and Release configurations. +# It uses a Docker container to provide a consistent build environment. +# +# The workflow consists of two jobs: +# - build-debug: Builds and tests the Debug configuration. +# - Uses the 'Debug' build configuration. +# - Enables AddressSanitizer for memory error detection. +# - Builds and runs tests. +# - build-release: Builds and tests the Release configuration. +# - Uses the 'Release' build configuration. +# - Includes additional flags for release builds: +# - --use_binskim_compliant_compile_flags +# - --build_wheel +# - --build_csharp +# - --enable_transformers_tool_test +# - --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON +# - Builds and runs tests. +# +# The two jobs run in parallel to reduce the overall build time. +# Both jobs use the same Docker image, built in a separate step. + +name: Linux CI + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main, 'rel-*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + linux-cpu-asan-debug: # Job for building and testing the Debug configuration + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + permissions: + actions: read + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python 3.x + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Build Docker Image + uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.1 + with: + Dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + Repository: 'onnxruntimecpubuildcentos8x64' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for context + + - name: Create .onnx directory + run: mkdir -p $HOME/.onnx + + # Build and Test ONNX Runtime in Docker (Debug) + - name: Build and Test ONNX Runtime in Docker (Debug) + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: 0 + NIGHTLY_BUILD: 1 # Assuming you want nightly build for both Debug and Release + run: | + docker run --rm \ + --volume /data/onnx:/data/onnx:ro \ + --volume /data/models:/data/models:ro \ + --volume ${{ github.workspace }}:/onnxruntime_src \ + --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ + -w /onnxruntime_src \ + -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ + -e NIGHTLY_BUILD \ + onnxruntimecpubuildcentos8x64 \ + /bin/bash -c 'set -ex; \ + # Build with Debug configuration and AddressSanitizer enabled + python3 tools/ci_build/build.py \ + --build_dir build/Debug --cmake_generator Ninja \ + --config Debug \ + --skip_submodule_sync \ + --build_shared_lib \ + --parallel \ + --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ + --enable_onnx_tests \ + --enable_address_sanitizer \ + --update --build; + # Run tests with Debug configuration + python3 tools/ci_build/build.py \ + --build_dir build/Debug --cmake_generator Ninja \ + --config Debug \ + --skip_submodule_sync \ + --build_shared_lib \ + --parallel \ + --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ + --enable_onnx_tests \ + --enable_address_sanitizer \ + --test;' + + linux-cpu-release: # Job for building and testing the Release configuration + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + permissions: + actions: read + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python 3.x + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Build Docker Image + uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.1 + with: + Dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + Repository: 'onnxruntimecpubuild' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for context + + - name: Create .onnx directory + run: mkdir -p $HOME/.onnx + # Build and Test ONNX Runtime in Docker (Release) + - name: Build and Test ONNX Runtime in Docker (Release) + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: 0 + NIGHTLY_BUILD: 1 + run: | + docker run --rm \ + --volume /data/onnx:/data/onnx:ro \ + --volume /data/models:/data/models:ro \ + --volume ${{ github.workspace }}:/onnxruntime_src \ + --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ + -w /onnxruntime_src \ + -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ + -e NIGHTLY_BUILD \ + onnxruntimecpubuild \ + /bin/bash -c 'set -ex; \ + # Build with Release configuration and additional flags for release builds + PATH=/opt/python/cp310-cp310/bin:$PATH python3 tools/ci_build/build.py \ + --build_dir build/Release --cmake_generator Ninja \ + --config Release \ + --skip_submodule_sync \ + --build_shared_lib \ + --parallel \ + --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ + --enable_onnx_tests \ + --use_binskim_compliant_compile_flags --build_wheel --build_csharp --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON \ + --update --build; + # Run tests with Release configuration + PATH=/opt/python/cp310-cp310/bin:$PATH python3 tools/ci_build/build.py \ + --build_dir build/Release --cmake_generator Ninja \ + --config Release \ + --skip_submodule_sync \ + --build_shared_lib \ + --parallel \ + --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ + --enable_onnx_tests \ + --use_binskim_compliant_compile_flags --build_wheel --build_csharp --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON \ + --test;' \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml index c957bb3ade91a..17c5af6480308 100644 --- a/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml @@ -29,244 +29,6 @@ pr: #### end trigger #### stages: -- stage: x64 - dependsOn: [] - jobs: - - job: Linux_Debug - timeoutInMinutes: 180 - workspace: - clean: all - variables: - skipComponentGovernanceDetection: true - ORT_CACHE_DIR: $(Agent.TempDirectory)/ort_ccache - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - pool: onnxruntime-Ubuntu2204-AMD-CPU - steps: - - - checkout: self - clean: true - submodules: none - - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuildcentos8x64 - - - template: templates/linux-build-step-with-cache.yml - parameters: - WithCache: false - Today: $(TODAY) - AdditionalKey: onnxruntime_linux_debug_with_address_sanitizer - CacheDir: $(ORT_CACHE_DIR) - ChangeEveryCommit: true - BuildStep: - - task: CmdLine@2 - displayName: 'build' - inputs: - script: | - mkdir -p $HOME/.onnx - docker run -e SYSTEM_COLLECTIONURI --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume /data/models:/data/models:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY=0 \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - onnxruntimecpubuildcentos8x64 \ - /bin/bash -c 'set -ex; \ - python3 /onnxruntime_src/tools/ci_build/build.py \ - --build_dir /build --cmake_generator Ninja \ - --config Debug \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests --enable_address_sanitizer \ - --update --build; - python3 /onnxruntime_src/tools/ci_build/build.py \ - --build_dir /build --cmake_generator Ninja \ - --config Debug \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests --enable_address_sanitizer \ - --test; - ' - workingDirectory: $(Build.SourcesDirectory) - - - task: PublishTestResults@2 - displayName: 'Publish unit test results' - inputs: - testResultsFiles: '**/*.results.xml' - searchFolder: '$(Build.BinariesDirectory)' - testRunTitle: 'Unit Test Run' - condition: succeededOrFailed() - - - job: Linux_Release - timeoutInMinutes: 180 - workspace: - clean: all - variables: - skipComponentGovernanceDetection: true - ORT_CACHE_DIR: $(Agent.TempDirectory)/ort_ccache - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - pool: onnxruntime-Ubuntu2204-AMD-CPU - steps: - - - checkout: self - clean: true - submodules: none - - - task: DownloadPackage@1 - displayName: 'Download ARM64 GCC' - inputs: - packageType: upack - feed: '/7424c8e4-5c62-490e-95c4-79446f31017c' - definition: 'gcc_aarch64_linux_gnu_host_x86_64' - version: 13.2.1 - downloadPath: $(Build.BinariesDirectory)/gcc - - - task: DownloadPackage@1 - displayName: 'Download ARM32 GCC' - inputs: - packageType: upack - feed: '/7424c8e4-5c62-490e-95c4-79446f31017c' - definition: 'gcc_aarch32_linux_gnu_host_x86_64' - version: 13.2.1 - downloadPath: $(Build.BinariesDirectory)/gcc - - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu - Context: tools/ci_build/github/linux/docker/ - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuild - - - script: | - set -e -x - # ARM64 build - mkdir -p $(Build.BinariesDirectory)/gccbin - tar -Jxf $(Build.BinariesDirectory)/gcc/arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz --strip=1 -C $(Build.BinariesDirectory)/gccbin - export PATH=$(Build.BinariesDirectory)/gccbin/bin:$PATH - mkdir $(Build.BinariesDirectory)/aarch64build - cd $(Build.BinariesDirectory)/aarch64build - cmake $(Build.SourcesDirectory)/cmake -Donnxruntime_ENABLE_CPUINFO=OFF -DPython_EXECUTABLE=/usr/bin/python3 -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=$(Build.SourcesDirectory)/cmake/linux_arm64_crosscompile_toolchain.cmake -G Ninja - ninja - rm -rf $(Build.BinariesDirectory)/aarch64build $(Build.BinariesDirectory)/gccbin - # ARM32 build - mkdir -p $(Build.BinariesDirectory)/gccbin - tar -Jxf $(Build.BinariesDirectory)/gcc/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz --strip=1 -C $(Build.BinariesDirectory)/gccbin - ls $(Build.BinariesDirectory)/gccbin/bin - mkdir $(Build.BinariesDirectory)/arm32build - cd $(Build.BinariesDirectory)/arm32build - cmake $(Build.SourcesDirectory)/cmake -Donnxruntime_ENABLE_CPUINFO=OFF -DPython_EXECUTABLE=/usr/bin/python3 -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=$(Build.SourcesDirectory)/cmake/linux_arm32_crosscompile_toolchain.cmake -G Ninja - ninja - rm -rf $(Build.BinariesDirectory)/arm32build $(Build.BinariesDirectory)/gccbin - displayName: Cross-compile for Linux ARM32 and ARM64 - - - template: templates/linux-build-step-with-cache.yml - parameters: - WithCache: true - Today: $(TODAY) - AdditionalKey: onnxruntime - CacheDir: $(ORT_CACHE_DIR) - ChangeEveryCommit: true - BuildStep: - - task: CmdLine@2 - displayName: 'build' - inputs: - script: | - mkdir -p $HOME/.onnx - docker run -e SYSTEM_COLLECTIONURI --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - --volume $(ORT_CACHE_DIR):/cache \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY=0 \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - -e CCACHE_DIR=/cache \ - onnxruntimecpubuild \ - /bin/bash -c ' - set -ex; \ - ccache -s; \ - PATH=/opt/python/cp310-cp310/bin:$PATH python /onnxruntime_src/tools/ci_build/build.py \ - --build_dir /build --cmake_generator Ninja \ - --config Release \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags \ - --build_wheel \ - --build_csharp \ - --enable_onnx_tests \ - --enable_transformers_tool_test \ - --use_cache \ - --update --build --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON; \ - ccache -sv; \ - ccache -z' - workingDirectory: $(Build.SourcesDirectory) - - - script: | - ln -s /data/models $(Build.BinariesDirectory)/models - displayName: link model dir - - - bash: | - mkdir -p $HOME/.onnx - docker run -e SYSTEM_COLLECTIONURI --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY=0 \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - onnxruntimecpubuild \ - /bin/bash -c " - set -ex; \ - pushd /onnxruntime_src/csharp; \ - dotnet restore /onnxruntime_src/csharp/OnnxRuntime.DesktopOnly.CSharp.sln; \ - dotnet build /onnxruntime_src/csharp/OnnxRuntime.DesktopOnly.CSharp.sln -c Release; \ - dotnet test /onnxruntime_src/csharp/OnnxRuntime.DesktopOnly.CSharp.sln -c Release -f net8.0 --no-build -l \"console;verbosity=normal\"; \ - popd - " - displayName: 'Dotnet build C# sln and Test' - - - bash: | - mkdir -p $HOME/.onnx - docker run -e SYSTEM_COLLECTIONURI --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY=0 \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - onnxruntimecpubuild \ - /bin/bash -c " - set -ex; \ - /bin/bash /onnxruntime_src/tools/scripts/python_test.sh /onnxruntime_src /build Release && \ - /bin/bash /onnxruntime_src/tools/scripts/symbolic_shape_infer_test.sh /build - " - displayName: 'Run Release tests and symbolic shape infer test' - - - template: templates/check_test_result.yml - parameters: - FileName: '$(Build.BinariesDirectory)/Release/onnxruntime_test_all.Release.results.xml' - - - task: PublishTestResults@2 - displayName: 'Publish unit test results' - inputs: - testResultsFiles: '**/*.results.xml' - searchFolder: '$(Build.BinariesDirectory)' - testRunTitle: 'Unit Test Run' - condition: succeededOrFailed() - - stage: arm64_build dependsOn: [] jobs: From d9c961ce9f4d338a6543efed5d90837de0165847 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 11:03:24 -0700 Subject: [PATCH 168/266] Bump vite from 6.2.1 to 6.2.3 in /js/web/test/e2e/exports/testcases/vite-default (#24167) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.1 to 6.2.3.
Release notes

Sourced from vite's releases.

v6.2.3

Please refer to CHANGELOG.md for details.

v6.2.2

Please refer to CHANGELOG.md for details.

Changelog

Sourced from vite's changelog.

6.2.3 (2025-03-24)

6.2.2 (2025-03-14)

  • fix: await client buildStart on top level buildStart (#19624) (b31faab), closes #19624
  • fix(css): inline css correctly for double quote use strict (#19590) (d0aa833), closes #19590
  • fix(deps): update all non-major dependencies (#19613) (363d691), closes #19613
  • fix(indexHtml): ensure correct URL when querying module graph (#19601) (dc5395a), closes #19601
  • fix(preview): use preview https config, not server (#19633) (98b3160), closes #19633
  • fix(ssr): use optional chaining to prevent "undefined is not an object" happening in `ssrRewriteStac (4309755), closes #19612
  • feat: show friendly error for malformed base (#19616) (2476391), closes #19616
  • feat(worker): show asset filename conflict warning (#19591) (367d968), closes #19591
  • chore: extend commit hash correctly when ambigious with a non-commit object (#19600) (89a6287), closes #19600
Commits
  • 16869d7 release: v6.2.3
  • f234b57 fix: fs raw query with query separators (#19702)
  • b12911e release: v6.2.2
  • 98b3160 fix(preview): use preview https config, not server (#19633)
  • b31faab fix: await client buildStart on top level buildStart (#19624)
  • dc5395a fix(indexHtml): ensure correct URL when querying module graph (#19601)
  • 2476391 feat: show friendly error for malformed base (#19616)
  • 4309755 fix(ssr): use optional chaining to prevent "undefined is not an object" happe...
  • 363d691 fix(deps): update all non-major dependencies (#19613)
  • d0aa833 fix(css): inline css correctly for double quote use strict (#19590)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vite&package-manager=npm_and_yarn&previous-version=6.2.1&new-version=6.2.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../e2e/exports/testcases/vite-default/package-lock.json | 8 ++++---- .../test/e2e/exports/testcases/vite-default/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json index ddb49f8e2f062..08c73d8e74beb 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json @@ -12,7 +12,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", - "vite": "^6.0.11" + "vite": "^6.2.3" } }, "node_modules/@babel/helper-string-parser": { @@ -1069,9 +1069,9 @@ } }, "node_modules/vite": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz", - "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", + "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/js/web/test/e2e/exports/testcases/vite-default/package.json b/js/web/test/e2e/exports/testcases/vite-default/package.json index 9e204875a1d01..4ef5b46691850 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package.json @@ -13,6 +13,6 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", - "vite": "^6.0.11" + "vite": "^6.2.3" } } From 1ef30446f4a8bc5bc889caade95aa41ecda63b93 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Tue, 25 Mar 2025 12:42:14 -0700 Subject: [PATCH 169/266] [onnxruntime_perf_test] Fix custom_allocator_ destruction order. (#24136) Move the allocator data member declaration before the `Ort::Value` container data members that might use the allocator so that the `Ort::Value` containers will be destroyed first. `custom_allocator_` may be used as the allocator for the `Ort::Value`s in `test_inputs_` and `outputs_`. The allocator shouldn't be destroyed before `Ort::Value`s allocated with it are freed. --- onnxruntime/test/perftest/ort_test_session.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/onnxruntime/test/perftest/ort_test_session.h b/onnxruntime/test/perftest/ort_test_session.h index d6580812da8f0..71f797b0d5a35 100644 --- a/onnxruntime/test/perftest/ort_test_session.h +++ b/onnxruntime/test/perftest/ort_test_session.h @@ -37,9 +37,10 @@ class OnnxRuntimeTestSession : public TestSession { Ort::Session session_{nullptr}; std::mt19937 rand_engine_; std::uniform_int_distribution dist_; - std::vector> test_inputs_; OrtAllocator* allocator_ = Ort::AllocatorWithDefaultOptions(); + // Note: custom_allocator_, if used, must outlive the `Ort::Value`s allocated with it in test_inputs_ and outputs_. Ort::Allocator custom_allocator_{nullptr}; + std::vector> test_inputs_; std::vector outputs_; std::vector output_names_; // The same size with output_names_. From 25b06f208a8dfadbb0534dfa7d1faa836eb98634 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 25 Mar 2025 14:54:18 -0700 Subject: [PATCH 170/266] Fix layout transformer for FusedConv (#24169) ### Description Fix layout transformer for FusedConv. The current layout transformer will transform `FusedConv` (kMSDomain) into `FusedConv` (kMSInternalNHWCDomain) if the EP wants channels_last. However, kMSInternalNHWCDomain uses OpType `Conv` for both Conv and FusedConv, so `FusedConv` (kMSInternalNHWCDomain) is invalid (unregistered op). This PR fixes this and allows layout transformer change `FusedConv` (kMSDomain) into `Conv` (kMSInternalNHWCDomain). ### Motivation and Context --- .../layout_transformation/layout_transformation.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc b/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc index 6f1d9d9c6611d..2754eebf75421 100644 --- a/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc +++ b/onnxruntime/core/optimizer/layout_transformation/layout_transformation.cc @@ -145,10 +145,14 @@ Status TransformLayoutForEP(Graph& graph, bool& modified, const IExecutionProvid } if (ConvertNodeLayout(*node)) { + // domain kMSInternalNHWCDomain uses OpType "Conv" for both Conv and FusedConv. + // So, change the OpType to "Conv" for FusedConv. + std::string_view op_type = node->OpType() == "FusedConv" ? "Conv" : node->OpType(); + // if already transformed then change the domain to kMSInternalNHWCDomain this way the EP // knows this op is in the expected format. if (node->GetAttributeIntDefault("channels_last", 0) == 1) { - SwapNodeOpTypeAndDomain(*api_graph, *node, node->OpType(), kMSInternalNHWCDomain); + SwapNodeOpTypeAndDomain(*api_graph, *node, op_type, kMSInternalNHWCDomain); // Changing the domain for the node requires creating a new node and replacing the old one // therefore set the modified flag. modified = true; @@ -175,7 +179,7 @@ Status TransformLayoutForEP(Graph& graph, bool& modified, const IExecutionProvid // Except for resize and convolution ops, all the other layout sensitive ops only require layout transformation // for 0th input and output. For resize, add the other relevant inputs which need conversion. For Conv - layout // transformer only converts layout for 0th input, weights should be handled by every EP. - if (node->OpType() == "Resize") { + if (op_type == "Resize") { // Older versions of resize have a bug where ROI and Scales cannot be made empty inputs. To handle this case, // we need to jump a few extra hoops to make sure its inputs are correctly handled. // @@ -205,7 +209,7 @@ Status TransformLayoutForEP(Graph& graph, bool& modified, const IExecutionProvid WrapTransposesAroundNode(*api_graph, *node, {&input_perm}, {&output_perm}); } - SwapNodeOpTypeAndDomain(*api_graph, *node, node->OpType(), kMSInternalNHWCDomain); + SwapNodeOpTypeAndDomain(*api_graph, *node, op_type, kMSInternalNHWCDomain); modified = true; } } From 1f6dc88164c4161b19f83eaca07548f2d5e3f790 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 25 Mar 2025 18:01:33 -0400 Subject: [PATCH 171/266] Migrate Zip-Nuget Package Pipeline to 1ES (#23609) Also, kleidail is disabled in MacOS and iOS packaging stage due to (#24152) (#24153) NuGet_Packaging_CPU is broken due to similar issue from #23923 ### Description Migrate [Zip-Nuget Package Pipeline](https://aiinfra.visualstudio.com/Lotus/_build?definitionId=940&_a=summary) to 1ES ### Motivation and Context ### Check list - [x] Issue with onnxruntime-Win-CPU-2022 - [x] [Spot Bug](https://aiinfra.visualstudio.com/Lotus/_build/results?buildId=697830&view=logs&j=6c6a898f-bbbb-5c72-8695-82b606149fa2&t=433f102b-5ed3-5fed-87a0-6107744ce9b1&l=81) --- ...ult_full_ios_framework_build_settings.json | 1 + .../c-api-noopenmp-packaging-pipelines.yml | 324 +++++++----------- .../nodejs/templates/test_linux.yml | 3 + .../nodejs/templates/test_macos.yml | 4 +- .../nuget/templates/dml-vs-2022.yml | 13 +- .../nuget/templates/test_macos.yml | 4 +- .../stages/nuget_dml_packaging_stage.yml | 99 ++++++ .../templates/android-java-api-aar-test.yml | 4 +- .../azure-pipelines/templates/c-api-cpu.yml | 84 +++-- .../templates/c-api-linux-cpu.yml | 1 + .../azure-pipelines/templates/compliance.yml | 36 -- .../templates/final-jar-testing.yml | 2 +- .../templates/mac-cpu-packaging-pipeline.yml | 160 ++++----- .../templates/mac-cpu-packaging-steps.yml | 7 +- .../templates/mac-cpu-packing-jobs.yml | 6 +- ...ifacts-package-and-publish-steps-posix.yml | 4 +- ...acts-package-and-publish-steps-windows.yml | 4 +- .../github/linux/python/requirements.txt | 1 - 18 files changed, 383 insertions(+), 374 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml delete mode 100644 tools/ci_build/github/azure-pipelines/templates/compliance.yml diff --git a/tools/ci_build/github/apple/default_full_ios_framework_build_settings.json b/tools/ci_build/github/apple/default_full_ios_framework_build_settings.json index 0fdc276ab5288..9658817d4409b 100644 --- a/tools/ci_build/github/apple/default_full_ios_framework_build_settings.json +++ b/tools/ci_build/github/apple/default_full_ios_framework_build_settings.json @@ -18,6 +18,7 @@ "--build_apple_framework", "--use_coreml", "--skip_tests", + "--no_kleidiai", "--cmake_extra_defines=onnxruntime_BUILD_UNIT_TESTS=OFF" ], "iphoneos": [ diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index 71c3edfaee8bd..ca78890720e9d 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -9,11 +9,6 @@ parameters: type: boolean default: false -- name: DoCompliance - displayName: Run Compliance Tasks? - type: boolean - default: true - - name: DoEsrp displayName: Run code sign tasks? Must be true if you are doing an ONNX Runtime release type: boolean @@ -70,6 +65,10 @@ resources: type: github endpoint: ort-examples name: microsoft/onnxruntime-inference-examples + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release variables: - template: templates/common-variables.yml @@ -82,208 +81,135 @@ variables: value: $(Agent.TempDirectory)\${{ variables.win_trt_folder_cuda12 }} - name: win_cuda_home value: $(Agent.TempDirectory)\v12.2 - -stages: -- template: stages/set_packaging_variables_stage.yml - parameters: - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - PreReleaseVersionSuffixString: ${{ parameters.PreReleaseVersionSuffixString }} - PreReleaseVersionSuffixNumber: ${{ parameters.PreReleaseVersionSuffixNumber }} - -- template: stages/download-java-tools-stage.yml - -- template: templates/c-api-cpu.yml +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - DoEsrp: ${{ parameters.DoEsrp }} - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - ${{ if eq(parameters.NugetPackageSuffix, 'NONE') }}: - OrtNugetPackageId: 'Microsoft.ML.OnnxRuntime' - ${{ else }}: - OrtNugetPackageId: 'Microsoft.ML.OnnxRuntime${{ parameters.NugetPackageSuffix }}' - AdditionalBuildFlags: '' - AdditionalWinBuildFlags: '--enable_onnx_tests --enable_wcos ${{parameters.AdditionalBuildFlag}}' - BuildVariant: 'default' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - QnnSDKVersion: ${{ parameters.QnnSdk }} - -- template: stages/java-cuda-packaging-stage.yml - parameters: - CudaVersion: 12.2 - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - -- template: stages/nuget-combine-cuda-stage.yml - parameters: - CudaVersion: 12.2 - RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} - UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} - win_trt_home: ${{ variables.win_trt_home }} - win_cuda_home: ${{ variables.win_cuda_home }} - DoEsrp: ${{ parameters.DoEsrp }} - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - buildJava: true - buildNodejs: true - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - -- template: nuget/templates/dml-vs-2022.yml - parameters: - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - ArtifactName: 'drop-nuget-dml' - StageName: 'Windows_CI_GPU_DML_Dev' - BuildCommand: --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --build_nodejs --cmake_generator "Visual Studio 17 2022" --use_vcpkg --use_vcpkg_ms_internal_asset_cache - BuildArch: 'x64' - msbuildArchitecture: 'amd64' - EnvSetupScript: 'setup_env.bat' - sln_platform: 'x64' - DoDebugBuild: 'false' - DoNugetPack: 'true' - DoCompliance: 'false' - DoEsrp: ${{ parameters.DoEsrp }} - NuPackScript: | - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /t:CreatePackage /p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML /p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} /p:CurrentData=$(BuildDate) /p:CurrentTime=$(BuildTime) - copy $(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) - mkdir $(Build.ArtifactStagingDirectory)\testdata - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\custom_op_library.* $(Build.ArtifactStagingDirectory)\testdata - -- template: nuget/templates/dml-vs-2022.yml - parameters: - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - ArtifactName: 'drop-win-dml-x86-zip' - StageName: 'Windows_CI_GPU_DML_Dev_x86' - BuildCommand: --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --cmake_generator "Visual Studio 17 2022" --use_vcpkg --use_vcpkg_ms_internal_asset_cache - BuildArch: 'x86' - EnvSetupScript: 'setup_env_x86.bat' - sln_platform: 'Win32' - DoDebugBuild: 'false' - DoNugetPack: 'true' - DoCompliance: ${{ parameters.DoCompliance }} - DoEsrp: ${{ parameters.DoEsrp }} - RunTests: 'false' - NuPackScript: | - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /p:TargetArchitecture=x86 /t:CreatePackage /p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML /p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} - cd $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\ - ren Microsoft.ML.OnnxRuntime.DirectML.* win-dml-x86.zip - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\win-dml-x86.zip $(Build.ArtifactStagingDirectory) - mkdir $(Build.ArtifactStagingDirectory)\testdata - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\custom_op_library.* $(Build.ArtifactStagingDirectory)\testdata - -- template: nuget/templates/dml-vs-2022.yml - parameters: - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - ArtifactName: 'drop-win-dml-arm64-zip' - StageName: 'Windows_CI_GPU_DML_Dev_arm64' - BuildCommand: --build_dir $(Build.BinariesDirectory) --arm64 --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --build_nodejs --cmake_generator "Visual Studio 17 2022" --use_vcpkg --use_vcpkg_ms_internal_asset_cache - BuildArch: 'x64' - EnvSetupScript: 'setup_env.bat' - sln_platform: 'arm64' - DoDebugBuild: 'false' - DoNugetPack: 'true' - DoCompliance: ${{ parameters.DoCompliance }} - DoEsrp: ${{ parameters.DoEsrp }} - RunTests: 'false' - NuPackScript: | - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /p:TargetArchitecture=arm64 /t:CreatePackage /p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML /p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} - cd $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\ - ren Microsoft.ML.OnnxRuntime.DirectML.* win-dml-arm64.zip - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\win-dml-arm64.zip $(Build.ArtifactStagingDirectory) - mkdir $(Build.ArtifactStagingDirectory)\testdata - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\custom_op_library.* $(Build.ArtifactStagingDirectory)\testdata - -- stage: NuGet_Packaging_DML - dependsOn: - - Windows_CI_GPU_DML_Dev - - Windows_CI_GPU_DML_Dev_x86 - - Windows_CI_GPU_DML_Dev_arm64 - condition: succeeded() - jobs: - - job: NuGet_Packaging_DML - workspace: - clean: all - pool: 'onnxruntime-Win2022-GPU-dml-A10' - steps: - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML' - inputs: - artifactName: 'drop-nuget-dml' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-dml' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML x86' - inputs: - artifactName: 'drop-win-dml-x86-zip' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-dml' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML arm64' - inputs: - artifactName: 'drop-win-dml-arm64-zip' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-dml' - - - script: | - pushd $(Build.BinariesDirectory)\nuget-artifact-dml - dir - powershell -Command "Invoke-WebRequest http://stahlworks.com/dev/unzip.exe -OutFile unzip.exe" - powershell -Command "Invoke-WebRequest http://stahlworks.com/dev/zip.exe -OutFile zip.exe" - set PATH=%CD%;%PATH% - SETLOCAL EnableDelayedExpansion - FOR /R %%i IN (*.nupkg) do ( - set filename=%%~ni - IF NOT "!filename:~25,7!"=="Managed" ( - rename %%~ni.nupkg %%~ni.zip - unzip %%~ni.zip -d %%~ni - del /Q %%~ni.zip - - unzip win-dml-x86.zip -d win-x86 - mkdir %%~ni\runtimes\win-x86 - mkdir %%~ni\runtimes\win-x86\native - - move win-x86\runtimes\win-x86\native\onnxruntime.dll %%~ni\runtimes\win-x86\native\onnxruntime.dll - move win-x86\runtimes\win-x86\native\onnxruntime.lib %%~ni\runtimes\win-x86\native\onnxruntime.lib - move win-x86\runtimes\win-x86\native\onnxruntime.pdb %%~ni\runtimes\win-x86\native\onnxruntime.pdb + sdl: + binskim: + enabled: true + analyzeTargetGlob: $(Build.ArtifactStagingDirectory)/**.dll + sourceAnalysisPool: "Onnxruntime-Win-CPU-2022" + sourceRepositoriesToScan: + exclude: + - repository: onnxruntime-inference-examples + spotBugs: + enabled: false + justificationForDisabling: "Getting ##[error]1. SpotBugs Error gdn.unknownFormatResult - File: spotbugs.xml, which indicates that SpotBugs found one or more errors, which are not handled by the Guardian right now." + + stages: + - template: stages/set_packaging_variables_stage.yml + parameters: + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + PreReleaseVersionSuffixString: ${{ parameters.PreReleaseVersionSuffixString }} + PreReleaseVersionSuffixNumber: ${{ parameters.PreReleaseVersionSuffixNumber }} - unzip win-dml-arm64.zip -d win-arm64 - mkdir %%~ni\runtimes\win-arm64 - mkdir %%~ni\runtimes\win-arm64\native + - template: stages/download-java-tools-stage.yml - move win-arm64\runtimes\win-arm64\native\onnxruntime.dll %%~ni\runtimes\win-arm64\native\onnxruntime.dll - move win-arm64\runtimes\win-arm64\native\onnxruntime.lib %%~ni\runtimes\win-arm64\native\onnxruntime.lib - move win-arm64\runtimes\win-arm64\native\onnxruntime.pdb %%~ni\runtimes\win-arm64\native\onnxruntime.pdb + - template: templates/c-api-cpu.yml + parameters: + RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} + DoEsrp: ${{ parameters.DoEsrp }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + ${{ if eq(parameters.NugetPackageSuffix, 'NONE') }}: + OrtNugetPackageId: 'Microsoft.ML.OnnxRuntime' + ${{ else }}: + OrtNugetPackageId: 'Microsoft.ML.OnnxRuntime${{ parameters.NugetPackageSuffix }}' + AdditionalBuildFlags: '' + AdditionalWinBuildFlags: '--enable_onnx_tests --enable_wcos ${{parameters.AdditionalBuildFlag}}' + BuildVariant: 'default' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + QnnSDKVersion: ${{ parameters.QnnSdk }} + is1ES: true + + - template: stages/java-cuda-packaging-stage.yml + parameters: + CudaVersion: 12.2 + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + - template: stages/nuget-combine-cuda-stage.yml + parameters: + CudaVersion: 12.2 + RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} + UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} + win_trt_home: ${{ variables.win_trt_home }} + win_cuda_home: ${{ variables.win_cuda_home }} + DoEsrp: ${{ parameters.DoEsrp }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + buildJava: true + buildNodejs: true + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} - pushd %%~ni - zip -r ..\%%~ni.zip . - popd - move %%~ni.zip %%~ni.nupkg - ) - ) - popd - copy $(Build.BinariesDirectory)\nuget-artifact-dml\Microsoft.ML.OnnxRuntime.DirectML*nupkg $(Build.ArtifactStagingDirectory) - displayName: 'Bundle DML NuGet and other binaries' - - template: templates/esrp_nuget.yml + - template: nuget/templates/dml-vs-2022.yml parameters: - DisplayName: 'ESRP - sign NuGet package' - FolderPath: '$(Build.ArtifactStagingDirectory)' + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + ArtifactName: 'drop-nuget-dml' + StageName: 'Windows_CI_GPU_DML_Dev' + BuildCommand: --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --build_nodejs --cmake_generator "Visual Studio 17 2022" --use_vcpkg --use_vcpkg_ms_internal_asset_cache + BuildArch: 'x64' + msbuildArchitecture: 'amd64' + EnvSetupScript: 'setup_env.bat' + sln_platform: 'x64' + DoDebugBuild: 'false' + DoNugetPack: 'true' DoEsrp: ${{ parameters.DoEsrp }} - - - template: templates/validate-package.yml + NuPackScript: | + msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /t:CreatePackage /p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML /p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} /p:CurrentData=$(BuildDate) /p:CurrentTime=$(BuildTime) + copy $(Build.SourcesDirectory)\csharp\src\Microsoft.ML.OnnxRuntime\bin\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) + copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) + mkdir $(Build.ArtifactStagingDirectory)\testdata + copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\custom_op_library.* $(Build.ArtifactStagingDirectory)\testdata + + - template: nuget/templates/dml-vs-2022.yml + parameters: + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + ArtifactName: 'drop-win-dml-x86-zip' + StageName: 'Windows_CI_GPU_DML_Dev_x86' + BuildCommand: --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --cmake_generator "Visual Studio 17 2022" --use_vcpkg --use_vcpkg_ms_internal_asset_cache + BuildArch: 'x86' + EnvSetupScript: 'setup_env_x86.bat' + sln_platform: 'Win32' + DoDebugBuild: 'false' + DoNugetPack: 'true' + DoEsrp: ${{ parameters.DoEsrp }} + RunTests: 'false' + NuPackScript: | + msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /p:TargetArchitecture=x86 /t:CreatePackage /p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML /p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} + cd $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\ + ren Microsoft.ML.OnnxRuntime.DirectML.* win-dml-x86.zip + copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\win-dml-x86.zip $(Build.ArtifactStagingDirectory) + mkdir $(Build.ArtifactStagingDirectory)\testdata + copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\custom_op_library.* $(Build.ArtifactStagingDirectory)\testdata + + - template: nuget/templates/dml-vs-2022.yml parameters: - PackageType: 'nuget' - PackagePath: '$(Build.ArtifactStagingDirectory)' - PackageName: 'Microsoft.ML.OnnxRuntime.DirectML*nupkg' - PlatformsSupported: 'win-x64,win-x86,win-arm64' - VerifyNugetSigning: ${{ parameters.DoEsrp }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + ArtifactName: 'drop-win-dml-arm64-zip' + StageName: 'Windows_CI_GPU_DML_Dev_arm64' + BuildCommand: --build_dir $(Build.BinariesDirectory) --arm64 --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --build_nodejs --cmake_generator "Visual Studio 17 2022" --use_vcpkg --use_vcpkg_ms_internal_asset_cache + BuildArch: 'x64' + EnvSetupScript: 'setup_env.bat' + sln_platform: 'arm64' + DoDebugBuild: 'false' + DoNugetPack: 'true' + DoEsrp: ${{ parameters.DoEsrp }} + RunTests: 'false' + NuPackScript: | + msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /p:TargetArchitecture=arm64 /t:CreatePackage /p:OrtPackageId=Microsoft.ML.OnnxRuntime.DirectML /p:IsReleaseBuild=${{ parameters.IsReleaseBuild }} + cd $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\ + ren Microsoft.ML.OnnxRuntime.DirectML.* win-dml-arm64.zip + copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\win-dml-arm64.zip $(Build.ArtifactStagingDirectory) + mkdir $(Build.ArtifactStagingDirectory)\testdata + copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\custom_op_library.* $(Build.ArtifactStagingDirectory)\testdata + - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline NuGet Artifact' - inputs: - artifactName: 'drop-signed-nuget-dml' - targetPath: '$(Build.ArtifactStagingDirectory)' - - template: templates/component-governance-component-detection-steps.yml + + - template: stages/nuget_dml_packaging_stage.yml parameters: - condition: 'succeeded' + DoEsrp: ${{ parameters.DoEsrp }} diff --git a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml index c4102f5ba2b49..c9d56c3474c3e 100644 --- a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml +++ b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_linux.yml @@ -19,4 +19,7 @@ stages: - name: OnnxRuntimeBuildDirectory value: '$(Build.BinariesDirectory)' steps: + - task: NodeTool@0 + inputs: + versionSpec: '20.x' - template: test.yml diff --git a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml index a2a0e3bcace9f..68b8f3ae90fa6 100644 --- a/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml +++ b/tools/ci_build/github/azure-pipelines/nodejs/templates/test_macos.yml @@ -11,7 +11,9 @@ stages: clean: all timeoutInMinutes: 120 pool: - vmImage: 'macOS-14' + name: 'Azure Pipelines' + image: 'macOS-14' + os: 'macOS' variables: - name: OnnxRuntimeBuildDirectory diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml index 8ab1eb2dd2fe4..fcae62b1f55f2 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml @@ -1,7 +1,6 @@ parameters: DoDebugBuild: 'true' # Unused. Use BuildConfigurations instead. - DoCompliance: 'false' BuildCommand: '' StageName: 'Windows_CI_Dev' DoNugetPack: 'false' @@ -144,7 +143,7 @@ stages: displayName: 'Create NuGet Package' failOnStderr: true - - task: PublishPipelineArtifact@0 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact: ${{ parameters.ArtifactName }}' inputs: artifactName: ${{ parameters.ArtifactName }} @@ -182,7 +181,7 @@ stages: workingDirectory: '$(Build.SourcesDirectory)\js\node' displayName: 'Create NPM Package' - - task: PublishPipelineArtifact@0 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact: ${{ parameters.ArtifactName }}' inputs: artifactName: ${{ parameters.ArtifactName }} @@ -208,17 +207,11 @@ stages: DisplayName: 'ESRP - Sign Node.js binding binaries' DoEsrp: ${{ parameters.DoEsrp }} Pattern: '*.node' - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: targetPath: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}' artifactName: 'drop-onnxruntime-nodejs-win-${{ parameters.sln_platform }}-dml' - - - ${{ if eq(parameters['DoCompliance'], 'true') }}: - - template: ../../templates/compliance.yml - parameters : - msbuildPlatform: ${{ parameters.sln_platform }} - - template: ../../templates/component-governance-component-detection-steps.yml parameters : condition : 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml index a6e38d0bc93f3..15746682d9137 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml @@ -11,7 +11,9 @@ stages: workspace: clean: all pool: - vmImage: 'macOS-14' + name: 'Azure Pipelines' + image: 'macOS-14' + os: 'macOS' variables: - name: OnnxRuntimeBuildDirectory diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml new file mode 100644 index 0000000000000..51ccef1cca6c8 --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml @@ -0,0 +1,99 @@ +parameters: +- name: DoEsrp + type: boolean + default: true + +stages: +- stage: NuGet_Packaging_DML + dependsOn: + - Windows_CI_GPU_DML_Dev + - Windows_CI_GPU_DML_Dev_x86 + - Windows_CI_GPU_DML_Dev_arm64 + condition: succeeded() + jobs: + - job: NuGet_Packaging_DML + workspace: + clean: all + pool: 'onnxruntime-Win2022-GPU-dml-A10' + steps: + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - NuGet DirectML' + inputs: + artifactName: 'drop-nuget-dml' + targetPath: '$(Build.BinariesDirectory)/nuget-artifact-dml' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - NuGet DirectML x86' + inputs: + artifactName: 'drop-win-dml-x86-zip' + targetPath: '$(Build.BinariesDirectory)/nuget-artifact-dml' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - NuGet DirectML arm64' + inputs: + artifactName: 'drop-win-dml-arm64-zip' + targetPath: '$(Build.BinariesDirectory)/nuget-artifact-dml' + + - script: | + pushd $(Build.BinariesDirectory)\nuget-artifact-dml + dir + powershell -Command "Invoke-WebRequest http://stahlworks.com/dev/unzip.exe -OutFile unzip.exe" + powershell -Command "Invoke-WebRequest http://stahlworks.com/dev/zip.exe -OutFile zip.exe" + set PATH=%CD%;%PATH% + SETLOCAL EnableDelayedExpansion + FOR /R %%i IN (*.nupkg) do ( + set filename=%%~ni + IF NOT "!filename:~25,7!"=="Managed" ( + rename %%~ni.nupkg %%~ni.zip + unzip %%~ni.zip -d %%~ni + del /Q %%~ni.zip + + unzip win-dml-x86.zip -d win-x86 + mkdir %%~ni\runtimes\win-x86 + mkdir %%~ni\runtimes\win-x86\native + + move win-x86\runtimes\win-x86\native\onnxruntime.dll %%~ni\runtimes\win-x86\native\onnxruntime.dll + move win-x86\runtimes\win-x86\native\onnxruntime.lib %%~ni\runtimes\win-x86\native\onnxruntime.lib + move win-x86\runtimes\win-x86\native\onnxruntime.pdb %%~ni\runtimes\win-x86\native\onnxruntime.pdb + + unzip win-dml-arm64.zip -d win-arm64 + mkdir %%~ni\runtimes\win-arm64 + mkdir %%~ni\runtimes\win-arm64\native + + move win-arm64\runtimes\win-arm64\native\onnxruntime.dll %%~ni\runtimes\win-arm64\native\onnxruntime.dll + move win-arm64\runtimes\win-arm64\native\onnxruntime.lib %%~ni\runtimes\win-arm64\native\onnxruntime.lib + move win-arm64\runtimes\win-arm64\native\onnxruntime.pdb %%~ni\runtimes\win-arm64\native\onnxruntime.pdb + + + pushd %%~ni + zip -r ..\%%~ni.zip . + popd + move %%~ni.zip %%~ni.nupkg + ) + ) + popd + copy $(Build.BinariesDirectory)\nuget-artifact-dml\Microsoft.ML.OnnxRuntime.DirectML*nupkg $(Build.ArtifactStagingDirectory) + displayName: 'Bundle DML NuGet and other binaries' + + - template: ../templates/esrp_nuget.yml + parameters: + DisplayName: 'ESRP - sign NuGet package' + FolderPath: '$(Build.ArtifactStagingDirectory)' + DoEsrp: ${{ parameters.DoEsrp }} + + - template: ../templates/validate-package.yml + parameters: + PackageType: 'nuget' + PackagePath: '$(Build.ArtifactStagingDirectory)' + PackageName: 'Microsoft.ML.OnnxRuntime.DirectML*nupkg' + PlatformsSupported: 'win-x64,win-x86,win-arm64' + VerifyNugetSigning: ${{ parameters.DoEsrp }} + + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline NuGet Artifact' + inputs: + artifactName: 'drop-signed-nuget-dml' + targetPath: '$(Build.ArtifactStagingDirectory)' + - template: ../templates/component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml index 7b257a4cdcdd5..925cb96cb270d 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml @@ -21,7 +21,9 @@ parameters: jobs: - job: Final_AAR_Testing_Android - pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + pool: + name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: linux workspace: clean: all variables: diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index d9b38e3eaba2e..b7cb5a51eada4 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -47,6 +47,11 @@ parameters: type: string default: 2.31.0.250130 +- name: is1ES + displayName: Is 1ES pipeline + type: boolean + default: false + stages: - template: linux-cpu-packaging-pipeline.yml parameters: @@ -75,6 +80,7 @@ stages: enable_code_sign: ${{ parameters.DoEsrp }} packageName: 'onnxruntime-android' ReleaseVersionSuffix: $(ReleaseVersionSuffix) + is1ES: ${{ parameters.is1ES }} - stage: Android_Java_API_AAR_Testing_Full dependsOn: Android_Java_API_AAR_Packaging_Full @@ -100,6 +106,7 @@ stages: packageName: 'onnxruntime-android-qnn' ReleaseVersionSuffix: $(ReleaseVersionSuffix) QnnSDKVersion: ${{ parameters.QnnSDKVersion }} + is1ES: ${{ parameters.is1ES }} - stage: Final_AAR_Testing_Android_QNN dependsOn: Android_Java_API_AAR_Packaging_QNN @@ -117,7 +124,10 @@ stages: workspace: clean: all pool: - vmImage: 'macOS-14' + name: 'Azure Pipelines' + image: 'macOS-14' + os: 'macOS' + timeoutInMinutes: 300 steps: - template: set-version-number-variables-step.yml @@ -146,9 +156,9 @@ stages: --mac_catalyst_enabled displayName: "Test Apple framework" - - task: PublishBuildArtifacts@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: - pathtoPublish: '$(Build.BinariesDirectory)/artifacts' + targetPath: '$(Build.BinariesDirectory)/artifacts' artifactName: 'onnxruntime-ios-full-xcframework' - template: component-governance-component-detection-steps.yml @@ -273,15 +283,15 @@ stages: SourceFolder: '$(Build.BinariesDirectory)\java-artifact\onnxruntime-java-win-x64' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact' inputs: targetPath: '$(Build.ArtifactStagingDirectory)' - artifact: 'onnxruntime-java' + artifactName: 'onnxruntime-java' - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' - stage: NuGet_Packaging_CPU dependsOn: @@ -303,8 +313,8 @@ stages: OrtPackageId: ${{ parameters.OrtNugetPackageId }} breakCodesignValidationInjection: ${{ parameters.DoEsrp }} ReleaseVersionSuffix: $[stageDependencies.Setup.Set_Variables.outputs['Set_Release_Version_Suffix.ReleaseVersionSuffix']] - BuildDate : $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Date.BuildDate']] - BuildTime : $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Time.BuildTime']] + BuildDate: $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Date.BuildDate']] + BuildTime: $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Time.BuildTime']] steps: - checkout: self @@ -375,7 +385,7 @@ stages: BuildId: ${{ parameters.BuildId }} - script: | - dir + dir workingDirectory: '$(Build.BinariesDirectory)/nuget-artifact' displayName: 'List artifacts' @@ -389,7 +399,7 @@ stages: filePath: $(Build.SourcesDirectory)\tools\ci_build\github\windows\extract_nuget_files.ps1 - script: | - mklink /D /J models C:\local\models + mklink /D /J models C:\local\models workingDirectory: '$(Build.BinariesDirectory)' displayName: 'Create models link' - task: NuGetToolInstaller@0 @@ -479,7 +489,7 @@ stages: PlatformsSupported: 'win-x64,win-x86,linux-x64,linux-arm64,osx-x64' VerifyNugetSigning: false - - task: PublishPipelineArtifact@0 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline NuGet Artifact' inputs: artifactName: 'drop-signed-nuget-CPU' @@ -496,8 +506,8 @@ stages: workingDirectory: '$(Build.SourcesDirectory)\csharp' - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' - stage: Nodejs_Packaging @@ -528,11 +538,11 @@ stages: submodules: true - script: | - echo.>>.gitattributes - echo /js/** text=auto eol=lf>>.gitattributes - rd /s /q js - git checkout -- js/** - git checkout -- .gitattributes + echo.>>.gitattributes + echo /js/** text=auto eol=lf>>.gitattributes + rd /s /q js + git checkout -- js/** + git checkout -- .gitattributes workingDirectory: '$(Build.SourcesDirectory)' displayName: 'Testing: force EOL to lf on windows for /js/**' @@ -641,20 +651,20 @@ stages: filePath: $(Build.SourcesDirectory)\tools\ci_build\github\windows\extract_nuget_files.ps1 - script: | - dir + dir workingDirectory: '$(Build.BinariesDirectory)/nuget-artifact' displayName: 'List artifacts' - script: | - npm ci + npm ci workingDirectory: '$(Build.SourcesDirectory)/js' displayName: 'Install NPM packages /js' - script: | - npm ci + npm ci workingDirectory: '$(Build.SourcesDirectory)/js/common' displayName: 'Install NPM packages /js/common' - script: | - npm ci + npm ci workingDirectory: '$(Build.SourcesDirectory)/js/node' displayName: 'Install NPM packages /js/node' @@ -758,22 +768,22 @@ stages: Contents: 'onnxruntime-node-*.tgz' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - task: PublishPipelineArtifact@0 + - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish NPM packages files' inputs: artifactName: 'NPM_packages' targetPath: '$(Build.ArtifactStagingDirectory)' - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' + parameters: + condition: 'succeeded' - template: ../nuget/templates/test_win.yml parameters: - AgentPool : 'onnxruntime-Win-CPU-2022' - Skipx86Tests : false - NugetPackageName : 'Microsoft.ML.OnnxRuntime' + AgentPool: 'onnxruntime-Win-CPU-2022' + Skipx86Tests: false + NugetPackageName: 'Microsoft.ML.OnnxRuntime' ArtifactSuffix: 'CPU' SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} @@ -787,30 +797,30 @@ stages: - template: ../nuget/templates/test_linux.yml parameters: - AgentPool : onnxruntime-Ubuntu2204-AMD-CPU - NugetPackageName : 'Microsoft.ML.OnnxRuntime' + AgentPool: onnxruntime-Ubuntu2204-AMD-CPU + NugetPackageName: 'Microsoft.ML.OnnxRuntime' ArtifactSuffix: 'CPU' SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - template: ../nuget/templates/test_macos.yml parameters: - AgentPool : macOS-14 + AgentPool: macOS-14 ArtifactSuffix: 'CPU' - template: ../nodejs/templates/test_win.yml parameters: - AgentPool : 'onnxruntime-Win-CPU-2022' - StageSuffix : 'Win_CPU_x64' + AgentPool: 'onnxruntime-Win-CPU-2022' + StageSuffix: 'Win_CPU_x64' - template: ../nodejs/templates/test_linux.yml parameters: - AgentPool : 'Azure-Pipelines-EO-Ubuntu-2004-aiinfra' - StageSuffix : 'Linux_CPU_x64' + AgentPool: 'onnxruntime-Ubuntu2204-AMD-CPU' + StageSuffix: 'Linux_CPU_x64' - template: ../nodejs/templates/test_macos.yml parameters: - StageSuffix : 'macOS_CPU_x64' + StageSuffix: 'macOS_CPU_x64' - template: final-jar-testing.yml parameters: diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml index e25ba88daa98a..3d2105bd07dbd 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml @@ -85,6 +85,7 @@ jobs: version: '$(OnnxRuntimeVersion)' libraryName: 'libonnxruntime.so' nativeLibraryName: 'libonnxruntime4j_jni.so' + is1ES: true - template: c-api-artifacts-package-and-publish-steps-posix.yml parameters: diff --git a/tools/ci_build/github/azure-pipelines/templates/compliance.yml b/tools/ci_build/github/azure-pipelines/templates/compliance.yml deleted file mode 100644 index cc451425be42a..0000000000000 --- a/tools/ci_build/github/azure-pipelines/templates/compliance.yml +++ /dev/null @@ -1,36 +0,0 @@ -parameters: -- name: msbuildPlatform - displayName: msbuildPlatform - type: string - default: x64 - -steps: -- task: CredScan@2 - displayName: 'Run CredScan' - inputs: - toolMajorVersion: V2 - debugMode: false - continueOnError: true - -- task: BinSkim@4 - displayName: 'Run BinSkim' - inputs: - AnalyzeTargetGlob: '+:file|$(Build.ArtifactStagingDirectory)\**\*.dll;-:file|$(Build.ArtifactStagingDirectory)\**\DirectML.dll' - continueOnError: true - -- task: SdtReport@2 - displayName: 'Create Security Analysis Report' - inputs: - SDLNativeRules: true - -- task: PublishSecurityAnalysisLogs@3 - displayName: 'Publish Security Analysis Logs' - continueOnError: true - -- task: TSAUpload@2 - displayName: 'TSA upload' - condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) - inputs: - GdnPublishTsaOnboard: false - GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - continueOnError: true diff --git a/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml b/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml index d893cac8ef358..900d15a1fa861 100644 --- a/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml +++ b/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml @@ -27,7 +27,7 @@ stages: ${{ if eq(parameters.OS, 'MacOS') }}: pool: name: 'Azure Pipelines' - image: macOS-13 + image: macOS-14 os: macOS ${{ if eq(parameters.OS, 'Linux') }}: pool: diff --git a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml index 8c725c1d6b9a0..a52932205f164 100644 --- a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml @@ -42,99 +42,101 @@ stages: - stage: MacOS_C_API_Packaging_CPU dependsOn: [] jobs: + - template: mac-cpu-packing-jobs.yml + parameters: + MacosArch: 'x86_64' + AllowReleasedOpsetOnly: ${{ parameters.AllowReleasedOpsetOnly }} + AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} + WithCache: ${{ parameters.WithCache }} + + - ${{ if eq(parameters.BuildForAllArchs, true) }}: - template: mac-cpu-packing-jobs.yml parameters: - MacosArch: 'x86_64' + MacosArch: 'arm64' + AllowReleasedOpsetOnly: ${{ parameters.AllowReleasedOpsetOnly }} + AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} + WithCache: ${{ parameters.WithCache }} + - template: mac-cpu-packing-jobs.yml + parameters: + MacosArch: 'universal2' AllowReleasedOpsetOnly: ${{ parameters.AllowReleasedOpsetOnly }} AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} WithCache: ${{ parameters.WithCache }} - - - ${{ if eq(parameters.BuildForAllArchs, true) }}: - - template: mac-cpu-packing-jobs.yml - parameters: - MacosArch: 'arm64' - AllowReleasedOpsetOnly: ${{ parameters.AllowReleasedOpsetOnly }} - AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} - WithCache: ${{ parameters.WithCache }} - - template: mac-cpu-packing-jobs.yml - parameters: - MacosArch: 'universal2' - AllowReleasedOpsetOnly: ${{ parameters.AllowReleasedOpsetOnly }} - AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} - WithCache: ${{ parameters.WithCache }} - stage: MacOS_C_API_Package_Publish dependsOn: MacOS_C_API_Packaging_CPU jobs: - - job: MacOS_C_API_Package_Publish - pool: - vmImage: 'macOS-14' - steps: - - checkout: none + - job: MacOS_C_API_Package_Publish + pool: + name: 'Azure Pipelines' + image: 'macOS-14' + os: 'macOS' + steps: + - checkout: none + - template: flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline onnxruntime-osx-x86_64' + ArtifactName: 'onnxruntime-osx-x86_64' + TargetPath: '$(Build.ArtifactStagingDirectory)' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + + - ${{ if eq(parameters.BuildForAllArchs, true) }}: - template: flex-downloadPipelineArtifact.yml parameters: - StepName: 'Download Pipeline onnxruntime-osx-x86_64' - ArtifactName: 'onnxruntime-osx-x86_64' + StepName: 'Download Pipeline onnxruntime-osx-arm64' + ArtifactName: 'onnxruntime-osx-arm64' + TargetPath: '$(Build.ArtifactStagingDirectory)' + SpecificArtifact: ${{ parameters.SpecificArtifact }} + BuildId: ${{ parameters.BuildId }} + - template: flex-downloadPipelineArtifact.yml + parameters: + StepName: 'Download Pipeline onnxruntime-osx-universal2' + ArtifactName: 'onnxruntime-osx-universal2' TargetPath: '$(Build.ArtifactStagingDirectory)' SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} - - ${{ if eq(parameters.BuildForAllArchs, true) }}: - - template: flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline onnxruntime-osx-arm64' - ArtifactName: 'onnxruntime-osx-arm64' - TargetPath: '$(Build.ArtifactStagingDirectory)' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - template: flex-downloadPipelineArtifact.yml - parameters: - StepName: 'Download Pipeline onnxruntime-osx-universal2' - ArtifactName: 'onnxruntime-osx-universal2' - TargetPath: '$(Build.ArtifactStagingDirectory)' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - - ${{ if eq(parameters.DoESRP, true)}}: - - script: | - pushd '$(Build.ArtifactStagingDirectory)' - find . '*.tgz' -exec tar -zxvf {} \; - rm -f *.tgz; - find . -type d -name 'onnxruntime-osx-*' -exec zip -FSr --symlinks {}.zip {} \; - find . -type d -name 'onnxruntime-osx-*' -exec rm -rf {} \; - ls -l - popd - displayName: tgz to zip - - template: mac-esrp-dylib.yml - parameters: - FolderPath: '$(Build.ArtifactStagingDirectory)' - DisplayName: 'ESRP - Sign Mac' - DoEsrp: true - Pattern: '*.zip' - - script: | - pushd '$(Build.ArtifactStagingDirectory)' - find . '*.zip' -exec unzip {} \; - rm -f *.zip; - find . -type d -name 'onnxruntime-osx-*' -exec tar -czf {}.tgz {} \; - find . -type d -name 'onnxruntime-osx-*' -exec rm -rf {} \; - ls -l - popd - displayName: zip to tgz - - bash: | - set -ex - mkdir -p $(Agent.TempDirectory)/macpackage - find $(Build.ArtifactStagingDirectory) -name "*.tgz" -exec tar -zxvf {} -C $(Agent.TempDirectory)/macpackage \; - find $(Agent.TempDirectory)/macpackage -name "*.dylib" -exec codesign -dvvv {} \; - find $(Agent.TempDirectory)/macpackage -name "*.dylib" -exec ls -l {} \; - rm -rf $(Agent.TempDirectory)/macpackage - displayName: 'Verify code signing' + - ${{ if eq(parameters.DoESRP, true)}}: + - script: | + pushd '$(Build.ArtifactStagingDirectory)' + find . '*.tgz' -exec tar -zxvf {} \; + rm -f *.tgz; + find . -type d -name 'onnxruntime-osx-*' -exec zip -FSr --symlinks {}.zip {} \; + find . -type d -name 'onnxruntime-osx-*' -exec rm -rf {} \; + ls -l + popd + displayName: tgz to zip + - template: mac-esrp-dylib.yml + parameters: + FolderPath: '$(Build.ArtifactStagingDirectory)' + DisplayName: 'ESRP - Sign Mac' + DoEsrp: true + Pattern: '*.zip' + - script: | + pushd '$(Build.ArtifactStagingDirectory)' + find . '*.zip' -exec unzip {} \; + rm -f *.zip; + find . -type d -name 'onnxruntime-osx-*' -exec tar -czf {}.tgz {} \; + find . -type d -name 'onnxruntime-osx-*' -exec rm -rf {} \; + ls -l + popd + displayName: zip to tgz + - bash: | + set -ex + mkdir -p $(Agent.TempDirectory)/macpackage + find $(Build.ArtifactStagingDirectory) -name "*.tgz" -exec tar -zxvf {} -C $(Agent.TempDirectory)/macpackage \; + find $(Agent.TempDirectory)/macpackage -name "*.dylib" -exec codesign -dvvv {} \; + find $(Agent.TempDirectory)/macpackage -name "*.dylib" -exec ls -l {} \; + rm -rf $(Agent.TempDirectory)/macpackage + displayName: 'Verify code signing' - - task: PublishPipelineArtifact@1 - inputs: - targetPath: '$(Build.ArtifactStagingDirectory)' - artifact: 'onnxruntime-osx' - condition: 'succeededOrFailed()' + - task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)' + artifactName: 'onnxruntime-osx' + condition: 'succeededOrFailed()' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-steps.yml b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-steps.yml index 5b94b2da8a096..9a8264a288582 100644 --- a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-steps.yml @@ -83,8 +83,10 @@ steps: displayName: 'Copy libcustom_op_library.dylib to ArtifactStagingDirectory' condition: and(succeeded(), eq('${{ parameters.MacosArch }}', 'x86_64')) -- publish: '$(Build.ArtifactStagingDirectory)' - artifact: 'onnxruntime-osx-${{ parameters.MacosArch }}' +- task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)' + artifactName: 'onnxruntime-osx-${{ parameters.MacosArch }}' - ${{ if eq(parameters.BuildJava, true) }}: - template: java-api-artifacts-package-and-publish-steps-posix.yml @@ -95,6 +97,7 @@ steps: version: '$(OnnxRuntimeVersion)' libraryName: 'libonnxruntime.dylib' nativeLibraryName: 'libonnxruntime4j_jni.dylib' + is1ES: true - ${{ if eq(parameters.BuildNodejs, true) }}: - template: nodejs-artifacts-package-and-publish-steps-posix.yml diff --git a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml index c7ae7bb3a0026..bcc336e65d6ad 100644 --- a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml +++ b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packing-jobs.yml @@ -37,7 +37,9 @@ jobs: PROTO_CACHE_DIR: $(Pipeline.Workspace)/ccache_proto ORT_CACHE_DIR: $(Pipeline.Workspace)/ccache_ort pool: - vmImage: 'macOS-14' + name: "Azure Pipelines" + image: 'macOS-14' + os: macOS timeoutInMinutes: 300 steps: - checkout: self @@ -75,7 +77,7 @@ jobs: - template: mac-cpu-packaging-steps.yml parameters: MacosArch: ${{ parameters.MacosArch }} - AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} --use_coreml --use_webgpu --cmake_extra_defines CMAKE_OSX_ARCHITECTURES="arm64;x86_64" + AdditionalBuildFlags: ${{ parameters.AdditionalBuildFlags }} --use_coreml --use_webgpu --no_kleidiai --cmake_extra_defines CMAKE_OSX_ARCHITECTURES="arm64;x86_64" BuildJava: false BuildNodejs: false WithCache: ${{ parameters.WithCache }} diff --git a/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-posix.yml b/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-posix.yml index 3a57982c52b1e..df4d3f95a47c7 100644 --- a/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-posix.yml +++ b/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-posix.yml @@ -10,7 +10,7 @@ parameters: default: '' steps: - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: - targetPath: '$(Build.SourcesDirectory)/js/node/bin/napi-v3/${{ parameters.os }}/${{ parameters.arch }}/onnxruntime_binding.node' + targetPath: '$(Build.SourcesDirectory)/js/node/bin/napi-v3/${{ parameters.os }}/${{ parameters.arch }}' artifactName: '${{parameters.artifactName}}' diff --git a/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-windows.yml b/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-windows.yml index 0bc067034b2fc..5286ae6c49142 100644 --- a/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-windows.yml +++ b/tools/ci_build/github/azure-pipelines/templates/nodejs-artifacts-package-and-publish-steps-windows.yml @@ -22,7 +22,7 @@ steps: DoEsrp: ${{parameters.DoEsrp}} Pattern: '*.node' - - task: PublishPipelineArtifact@1 + - task: 1ES.PublishPipelineArtifact@1 inputs: - targetPath: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.arch }}\onnxruntime_binding.node' + targetPath: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.arch }}' artifactName: '${{parameters.artifactName}}' diff --git a/tools/ci_build/github/linux/python/requirements.txt b/tools/ci_build/github/linux/python/requirements.txt index 36b30ed6d3d12..42e5c3d18840f 100644 --- a/tools/ci_build/github/linux/python/requirements.txt +++ b/tools/ci_build/github/linux/python/requirements.txt @@ -1,7 +1,6 @@ numpy==2.1.2 mypy pytest -setuptools>=68.2.2 wheel onnx==1.17.0 ; python_version < '3.13' protobuf==4.21.12 From 9dbfee91ca9c2ba2074d19805bb6dedccedbcfe3 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Tue, 25 Mar 2025 15:14:10 -0700 Subject: [PATCH 172/266] Update the min GCC version (#24148) ### Description Update the min supported GCC version to 11.1. ### Motivation and Context In order to utilize new CPU instructions, we need to use new compilers. For example, our MLAS code needs bfloat16 support for arm, which requires GCC version >=10. And some other code requires GCC version >=11.1. Also, our CI pipelines only tests the code with GCC 11,12 and 14. Therefore this PR increase the min GCC version to 11.1. Will update it to 12 once we deprecate CUDA 11 pipelines --- cmake/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 560d1cd423083..30123fc066f1e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -55,10 +55,6 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose build type: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() -if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 9) - message(FATAL_ERROR "GCC version must be greater than or equal to 9") -endif() - # Options option(onnxruntime_USE_VCPKG "Build with the vcpkg package manager" OFF) option(onnxruntime_RUN_ONNX_TESTS "Enable ONNX Compatibility Testing" OFF) @@ -259,6 +255,11 @@ option(onnxruntime_USE_OPENVINO_INTERFACE "Build ONNXRuntime shared lib which is option(onnxruntime_USE_VITISAI_INTERFACE "Build ONNXRuntime shared lib which is compatible with Vitis-AI EP interface" OFF) option(onnxruntime_USE_QNN_INTERFACE "Build ONNXRuntime shared lib which is compatible with QNN EP interface" OFF) + +if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 11.1) + message(FATAL_ERROR "GCC version must be greater than or equal to 11.1") +endif() + # ENABLE_TRAINING includes all training functionality # The following 2 entry points # 1. ORTModule From 2a800d1e4f6a9ac4a8727e1b6b943de0ea492fb5 Mon Sep 17 00:00:00 2001 From: George Wu Date: Tue, 25 Mar 2025 22:14:36 -0700 Subject: [PATCH 173/266] [QNN EP] ARM64EC python package remove --vcpkg in build (#24174) --use_vcpkg option seems to be causing problems for --arm64ec python packages (onnxruntime-qnn) session creation crashes for packages built with --use_vcpkg. the released onnxruntime-qnn 1.21.0 python wheel for x64 (arm64ec) has this issue. removing --use_vcpkg while the issue is debugged in parallel. we plan to release a 1.21.1 onnxruntime-qnn x64 python wheel without --use_vcpkg to address the crash. https://github.com/microsoft/onnxruntime/issues/24082 --- .../github/azure-pipelines/templates/py-win-arm64ec-qnn.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml index 24321d2a3e1ec..ee70742256a15 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml @@ -91,7 +91,7 @@ jobs: --use_qnn --qnn_home $(QnnSDKRootDir) --enable_pybind - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --update --arm64ec + --parallel --update --arm64ec $(TelemetryOption) ${{ parameters.BUILD_PY_PARAMETERS }} workingDirectory: '$(Build.BinariesDirectory)' From a8673c6e1d57173ad6c59e6adc494d0852c3887d Mon Sep 17 00:00:00 2001 From: Xiaofei Han <107654914+xiaofeihan1@users.noreply.github.com> Date: Wed, 26 Mar 2025 13:18:18 +0800 Subject: [PATCH 174/266] [WebGPU EP] Add GEMM implementation (#24023) Increases operator GEMM for WebGPU ep. --------- Co-authored-by: Xiaofei Han Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- .../core/providers/webgpu/math/gemm.cc | 236 ++++++++++++++++++ onnxruntime/core/providers/webgpu/math/gemm.h | 66 +++++ .../webgpu/webgpu_execution_provider.cc | 8 +- 3 files changed, 306 insertions(+), 4 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/math/gemm.cc create mode 100644 onnxruntime/core/providers/webgpu/math/gemm.h diff --git a/onnxruntime/core/providers/webgpu/math/gemm.cc b/onnxruntime/core/providers/webgpu/math/gemm.cc new file mode 100644 index 0000000000000..4057b63f0c65d --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/gemm.cc @@ -0,0 +1,236 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/math/gemm.h" + +#include + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" + +namespace onnxruntime { +namespace webgpu { + +#define WEBGPU_GEMM_VERSIONED_KERNEL(start, end) \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX( \ + Gemm, \ + kOnnxDomain, \ + start, \ + end, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T", WebGpuSupportedNumberTypes()), \ + Gemm); + +#define WEBGPU_GEMM_KERNEL(version) \ + ONNX_OPERATOR_KERNEL_EX( \ + Gemm, \ + kOnnxDomain, \ + version, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T", WebGpuSupportedNumberTypes()), \ + Gemm); + +WEBGPU_GEMM_VERSIONED_KERNEL(7, 8) +WEBGPU_GEMM_VERSIONED_KERNEL(9, 10) +WEBGPU_GEMM_VERSIONED_KERNEL(11, 12) +WEBGPU_GEMM_KERNEL(13) + +Status GemmProgram::GenerateShaderCode(ShaderHelper& shader) const { + const uint32_t TILE_SIZE = 16; + + // Add shared memory arrays + shader.AdditionalImplementation() << "var tile_a: array, " << TILE_SIZE << ">;\n" + << "var tile_b: array, " << TILE_SIZE << ">;\n\n"; + + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + + shader.MainFunctionBody() << " var value = output_value_t(0);\n\n" + << " let tile_col_start = (workgroup_idx % uniforms.num_tile_n) * " << TILE_SIZE << "u;\n" + << " let tile_row_start = (workgroup_idx / uniforms.num_tile_n) * " << TILE_SIZE << "u;\n"; + + // When A or B is empty, we don't bind A and B. Because WebGPU doesn't support binding a zero-sized buffer. + if (need_handle_matmul_) { + const ShaderVariableHelper& A = shader.AddInput("A", ShaderUsage::UseUniform); + const ShaderVariableHelper& B = shader.AddInput("B", ShaderUsage::UseUniform); + + shader.MainFunctionBody() + << " let num_tiles = (uniforms.K - 1u) / " << TILE_SIZE << "u + 1u;\n" + << " var k_start = 0u;\n" + << " for (var t = 0u; t < num_tiles; t = t + 1u) {\n"; + + // Fill workgroup shared memory + if (transA_ && transB_) { + shader.MainFunctionBody() << " var col = tile_row_start + local_id.x;\n" + << " var row = k_start + local_id.y;\n" + << " if (col < uniforms.M && row < uniforms.K) {\n" + << " tile_a[local_id.y][local_id.x] = " << A.GetByOffset("row * uniforms.M + col") << ";\n" + << " } else {\n" + << " tile_a[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n\n" + << " col = k_start + local_id.x;\n" + << " row = tile_col_start + local_id.y;\n" + << " if (col < uniforms.K && row < uniforms.N) {\n" + << " tile_b[local_id.y][local_id.x] = " << B.GetByOffset("row * uniforms.K + col") << ";\n" + << " } else {\n" + << " tile_b[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n"; + } else if (transA_ && !transB_) { + shader.MainFunctionBody() << " var col = tile_row_start + local_id.x;\n" + << " var row = k_start + local_id.y;\n" + << " if (col < uniforms.M && row < uniforms.K) {\n" + << " tile_a[local_id.y][local_id.x] = " << A.GetByOffset("row * uniforms.M + col") << ";\n" + << " } else {\n" + << " tile_a[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n\n" + << " col = tile_col_start + local_id.x;\n" + << " row = k_start + local_id.y;\n" + << " if (col < uniforms.N && row < uniforms.K) {\n" + << " tile_b[local_id.y][local_id.x] = " << B.GetByOffset("row * uniforms.N + col") << ";\n" + << " } else {\n" + << " tile_b[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n"; + } else if (!transA_ && transB_) { + shader.MainFunctionBody() << " var col = k_start + local_id.x;\n" + << " var row = tile_row_start + local_id.y;\n" + << " if (col < uniforms.K && row < uniforms.M) {\n" + << " tile_a[local_id.y][local_id.x] = " << A.GetByOffset("row * uniforms.K + col") << ";\n" + << " } else {\n" + << " tile_a[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n\n" + << " col = k_start + local_id.x;\n" + << " row = tile_col_start + local_id.y;\n" + << " if (col < uniforms.K && row < uniforms.N) {\n" + << " tile_b[local_id.y][local_id.x] = " << B.GetByOffset("row * uniforms.K + col") << ";\n" + << " } else {\n" + << " tile_b[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n"; + } else { + shader.MainFunctionBody() << " var col = k_start + local_id.x;\n" + << " var row = tile_row_start + local_id.y;\n" + << " if (col < uniforms.K && row < uniforms.M) {\n" + << " tile_a[local_id.y][local_id.x] = " << A.GetByOffset("row * uniforms.K + col") << ";\n" + << " } else {\n" + << " tile_a[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n\n" + << " col = tile_col_start + local_id.x;\n" + << " row = k_start + local_id.y;\n" + << " if (col < uniforms.N && row < uniforms.K) {\n" + << " tile_b[local_id.y][local_id.x] = " << B.GetByOffset("row * uniforms.N + col") << ";\n" + << " } else {\n" + << " tile_b[local_id.y][local_id.x] = output_value_t(0);\n" + << " }\n"; + } + + shader.MainFunctionBody() << " k_start = k_start + " << TILE_SIZE << "u;\n" + << " workgroupBarrier();\n\n" + << " for (var k = 0u; k < " << TILE_SIZE << "u; k = k + 1u) {\n"; + + if (transA_ && transB_) { + shader.MainFunctionBody() << " value = value + tile_a[k][local_id.y] * tile_b[local_id.x][k];\n"; + } else if (transA_ && !transB_) { + shader.MainFunctionBody() << " value = value + tile_a[k][local_id.y] * tile_b[k][local_id.x];\n"; + } else if (!transA_ && transB_) { + shader.MainFunctionBody() << " value = value + tile_a[local_id.y][k] * tile_b[local_id.x][k];\n"; + } else { + shader.MainFunctionBody() << " value = value + tile_a[local_id.y][k] * tile_b[k][local_id.x];\n"; + } + + shader.MainFunctionBody() << " }\n" + << " workgroupBarrier();\n" + << " }\n\n"; + } + + // Calculate Alpha + if (alpha_) { + shader.MainFunctionBody() << " value = value * output_value_t(uniforms.alpha);\n"; + } + + shader.MainFunctionBody() << " let m = tile_row_start + local_id.y;\n" + << " let n = tile_col_start + local_id.x;\n"; + + // Calculate Bias + if (need_handle_bias_) { + const ShaderVariableHelper& C = shader.AddInput("C", ShaderUsage::UseUniform); + shader.MainFunctionBody() << " value = value + output_value_t(uniforms.beta) * " + << C.GetByOffset(C.BroadcastedIndicesToOffset("vec2(m, n)", output)) << ";\n"; + } + + // Write output + shader.MainFunctionBody() << " if (m < uniforms.M && n < uniforms.N) {\n" + << " " << output.SetByOffset("m * uniforms.N + n", "value") << "\n" + << " }\n"; + + return Status::OK(); +} + +Status Gemm::ComputeInternal(ComputeContext& context) const { + const auto* A = context.Input(0); + const auto* B = context.Input(1); + const auto* C = context.Input(2); + + if (A == nullptr || B == nullptr) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Gemm requires input tensors A and B."); + } + + const auto& A_shape = A->Shape(); + const auto& B_shape = B->Shape(); + + if (A_shape.NumDimensions() != 2 || B_shape.NumDimensions() != 2) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input tensors A and B must be 2 dimensional."); + } + + uint32_t M = onnxruntime::narrow(transA_ ? A_shape[1] : A_shape[0]); + uint32_t K = onnxruntime::narrow(transA_ ? A_shape[0] : A_shape[1]); + uint32_t N = onnxruntime::narrow(transB_ ? B_shape[0] : B_shape[1]); + + if ((transA_ ? A_shape[0] : A_shape[1]) != (transB_ ? B_shape[1] : B_shape[0])) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Inner dimensions of A and B must match."); + } + + std::vector output_dims{M, N}; + auto* Y = context.Output(0, output_dims); + int64_t output_size = Y->Shape().Size(); + + if (output_size == 0) { + return Status::OK(); + } + + // WebGPU doesn't support binding a zero-sized buffer, so we need to check if A or B is empty. + bool need_handle_matmul = A_shape.Size() > 0 && B_shape.Size() > 0; + bool need_handle_bias = C && beta_; + + GemmProgram program{transA_, transB_, alpha_, need_handle_bias, need_handle_matmul}; + + if (need_handle_matmul) { + program.AddInputs({{A, ProgramTensorMetadataDependency::Type}, + {B, ProgramTensorMetadataDependency::Type}}); + } + + if (need_handle_bias) { + program.AddInput({C, ProgramTensorMetadataDependency::Rank}); + } + + const uint32_t TILE_SIZE = 16; + const uint32_t num_tile_n = (N + TILE_SIZE - 1) / TILE_SIZE; + const uint32_t num_tile_m = (M + TILE_SIZE - 1) / TILE_SIZE; + + program.CacheHint(alpha_, transA_, transB_) + .AddOutputs({{Y, ProgramTensorMetadataDependency::Type}}) + .SetDispatchGroupSize(num_tile_n * num_tile_m) + .SetWorkgroupSize(TILE_SIZE, TILE_SIZE) + .AddUniformVariables({ + {static_cast(num_tile_n)}, // num_tile_n + {static_cast(M)}, // M + {static_cast(N)}, // N + {static_cast(K)}, // K + {alpha_}, // alpha + {beta_} // beta + }); + + return context.RunProgram(program); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/math/gemm.h b/onnxruntime/core/providers/webgpu/math/gemm.h new file mode 100644 index 0000000000000..7fee1091de5f8 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/math/gemm.h @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/program.h" + +namespace onnxruntime { +namespace webgpu { + +class GemmProgram final : public Program { + public: + GemmProgram(bool transA, bool transB, float alpha, bool need_handle_bias, bool need_handle_matmul) + : Program{"Gemm"}, + transA_{transA}, + transB_{transB}, + alpha_{alpha}, + need_handle_bias_{need_handle_bias}, + need_handle_matmul_{need_handle_matmul} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( + {"num_tile_n", ProgramUniformVariableDataType::Uint32}, + {"M", ProgramUniformVariableDataType::Uint32}, + {"N", ProgramUniformVariableDataType::Uint32}, + {"K", ProgramUniformVariableDataType::Uint32}, + {"alpha", ProgramUniformVariableDataType::Float32}, + {"beta", ProgramUniformVariableDataType::Float32}); + + private: + bool transA_; + bool transB_; + float alpha_; + bool need_handle_bias_; + bool need_handle_matmul_; +}; + +class Gemm final : public WebGpuKernel { + public: + Gemm(const OpKernelInfo& info) : WebGpuKernel(info) { + int64_t transA_temp; + info.GetAttrOrDefault("transA", &transA_temp, static_cast(0)); + transA_ = transA_temp != 0; + + int64_t transB_temp; + info.GetAttrOrDefault("transB", &transB_temp, static_cast(0)); + transB_ = transB_temp != 0; + + info.GetAttrOrDefault("alpha", &alpha_, 1.0f); + info.GetAttrOrDefault("beta", &beta_, 1.0f); + } + + Status ComputeInternal(ComputeContext& context) const override; + + private: + bool transA_; + bool transB_; + float alpha_; + float beta_; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 15166df54e40c..4eddcfde1c0b7 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -617,10 +617,10 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, From 513e8de14453a4cc3ec339aa3d5375ba0a2058d8 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 25 Mar 2025 23:40:30 -0700 Subject: [PATCH 175/266] [wasm] remove --vcpkg in wasm build (#24179) ### Description There are slightly mismatch for the build flags for Web build pipeline when using vcpkg. A [fix](https://github.com/microsoft/onnxruntime/pull/24012) is on the way but for now we need to disable vcpkg for the next patch release. ### Motivation and Context --- .../ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index d7850153698e1..5e06fc47ea801 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -51,7 +51,7 @@ jobs: os: linux variables: buildArch: x64 - CommonBuildArgs: '--parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --config ${{ parameters.BuildConfig }} --skip_submodule_sync --build_wasm --enable_wasm_simd --enable_wasm_threads ${{ parameters.ExtraBuildArgs }}' + CommonBuildArgs: '--parallel --config ${{ parameters.BuildConfig }} --skip_submodule_sync --build_wasm --enable_wasm_simd --enable_wasm_threads ${{ parameters.ExtraBuildArgs }}' runCodesignValidationInjection: false TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] ORT_CACHE_DIR: $(Agent.TempDirectory)/ort_ccache From 32b376cd85aad888f71cc14b70176892f2a59709 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 26 Mar 2025 09:16:05 -0700 Subject: [PATCH 176/266] revise mac os pipeline to reduce the amount of jobs (#24177) ### Description - remove x86_64/Debug build in the matrix to reduce the amount of jobs - set max-parallel to 1 to avoid big backlogs (single PR will take longer but less traffic in the pipeine) --- .github/workflows/macos-ci-build-and-test-workflow.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/macos-ci-build-and-test-workflow.yml b/.github/workflows/macos-ci-build-and-test-workflow.yml index a387541488621..52a284a40488d 100644 --- a/.github/workflows/macos-ci-build-and-test-workflow.yml +++ b/.github/workflows/macos-ci-build-and-test-workflow.yml @@ -27,6 +27,11 @@ jobs: matrix: platform_machine: ["x86_64", "arm64"] build_config: ["Debug", "Release"] + exclude: + # we do not have enough resources to run all combinations + # Exclude x86_64 + Debug combination + - platform_machine: "x86_64" + build_config: "Debug" include: - platform_machine: "x86_64" runs_on: "macos-13" @@ -34,6 +39,7 @@ jobs: - platform_machine: "arm64" runs_on: "macos-15" xcode_version: "16" + max-parallel: 1 runs-on: ${{ matrix.runs_on }} env: From be1cfc4e2849dd3149be3ecbef4199805d9bc39f Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 26 Mar 2025 09:44:58 -0700 Subject: [PATCH 177/266] fix triggering for "Validate Gradle Wrapper" pipeline (#24181) ### Description currently it is triggered on every branch. --- .github/workflows/gradle-wrapper-validation.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index cf3bc598d02bb..9adae8c0d6854 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -3,7 +3,11 @@ # This workflow was copied from the link above. name: "Validate Gradle Wrapper" -on: [push, pull_request] +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main, 'rel-*'] jobs: validation: From 5d805c23f9b8acc4736b456e108f31a61bd9a857 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Wed, 26 Mar 2025 10:35:41 -0700 Subject: [PATCH 178/266] upgrade QNN to version 2.32.0.250228 (#23977) ### Description upgrade QNN to latest version 2.32.0.250228 --- onnxruntime/test/onnx/TestCase.cc | 2 ++ .../cpu/tensor/space_depth_ops_test.cc | 17 +++++------------ onnxruntime/test/providers/qnn/conv_test.cc | 12 ++++++++---- onnxruntime/test/providers/qnn/matmul_test.cpp | 8 +++++--- onnxruntime/test/providers/qnn/pad_op_test.cpp | 3 ++- onnxruntime/test/providers/qnn/resize_test.cc | 10 ++++++++-- .../test/providers/qnn/simple_op_htp_test.cc | 14 ++++++++++---- ...d-arm64-v8a-QNN-crosscompile-ci-pipeline.yml | 2 +- .../c-api-noopenmp-packaging-pipelines.yml | 2 +- .../custom-nuget-packaging-pipeline.yml | 2 +- .../azure-pipelines/linux-qnn-ci-pipeline.yml | 10 +++++----- .../azure-pipelines/py-packaging-pipeline.yml | 2 +- .../qnn-ep-nuget-packaging-pipeline.yml | 2 +- .../stages/py-cpu-packaging-stage.yml | 2 +- .../templates/android-java-api-aar-test.yml | 2 +- .../templates/android-java-api-aar.yml | 2 +- .../azure-pipelines/templates/c-api-cpu.yml | 2 +- .../templates/jobs/download_linux_qnn_sdk.yml | 2 +- .../templates/jobs/download_win_qnn_sdk.yml | 2 +- .../azure-pipelines/templates/py-linux-qnn.yml | 2 +- .../templates/py-win-arm64-qnn.yml | 2 +- .../templates/py-win-arm64ec-qnn.yml | 2 +- .../templates/py-win-x64-qnn.yml | 2 +- .../azure-pipelines/templates/qnn-ep-win.yml | 2 +- .../win-qnn-arm64-ci-pipeline.yml | 2 +- .../azure-pipelines/win-qnn-ci-pipeline.yml | 2 +- 26 files changed, 63 insertions(+), 49 deletions(-) diff --git a/onnxruntime/test/onnx/TestCase.cc b/onnxruntime/test/onnx/TestCase.cc index 3433a88515b53..024987ede0ce3 100644 --- a/onnxruntime/test/onnx/TestCase.cc +++ b/onnxruntime/test/onnx/TestCase.cc @@ -1410,6 +1410,8 @@ std::unique_ptr> GetBrokenTests(const std::string& provider broken_tests->insert({"convtranspose_1d", "Access violation 0xc000005 from call graphAddNode."}); broken_tests->insert({"convtranspose", "Access violation 0xc000005 from call graphAddNode."}); broken_tests->insert({"averagepool_2d_ceil", "result differs. expected 13.5 (41580000), got 0 (0)"}); + // Fails with QNN 2.32 + broken_tests->insert({"resize_upsample_scales_linear", "expected 1 (3f800000), got 0.25 (3e800000)"}); } #ifdef DISABLE_CONTRIB_OPS diff --git a/onnxruntime/test/providers/cpu/tensor/space_depth_ops_test.cc b/onnxruntime/test/providers/cpu/tensor/space_depth_ops_test.cc index d0620a794e4d5..a40b85b7754a3 100644 --- a/onnxruntime/test/providers/cpu/tensor/space_depth_ops_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/space_depth_ops_test.cc @@ -44,9 +44,7 @@ TEST(TensorOpTest, SpaceToDepthTest_1) { 3.1f, 3.3f}; test.AddOutput("output", {N, C * blocksize * blocksize, H / blocksize, W / blocksize}, result); - // TODO: Test is flaky on QNN EP (CPU backend). - // Re-enable when the QnnCPUBackendTests.DISABLED_SpaceToDepth_Flaky test is fixed. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kQnnExecutionProvider}); + test.Run(OpTester::ExpectResult::kExpectSuccess); } TEST(TensorOpTest, SpaceToDepthTest_1_double) { @@ -111,9 +109,7 @@ TEST(TensorOpTest, SpaceToDepthTest_2) { 88., 103., 106., 68., 71., 86., 89., 104., 107.}; test.AddOutput("output", {2, 27, 1, 2}, result); - // TODO: Test is flaky on QNN EP (CPU backend). - // Re-enable when the QnnCPUBackendTests.DISABLED_SpaceToDepth_Flaky2 test is fixed. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kQnnExecutionProvider}); + test.Run(OpTester::ExpectResult::kExpectSuccess); } TEST(TensorOpTest, SpaceToDepthTest_3) { @@ -327,8 +323,7 @@ TYPED_TEST(TensorOpTest, DepthToSpaceTest_3) { ORT_THROW("Type not supported"); } - // TODO: Test is flaky on QNN EP (CPU backend). - // Re-enable when the QnnCPUBackendTests.DISABLED_SpaceToDepth_Flaky test is fixed. + // type not supported by QNN EP: MLFloat16 and unsigned char test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kQnnExecutionProvider}); } @@ -392,8 +387,7 @@ TYPED_TEST(TensorOpTest, DepthToSpaceTest_4) { ORT_THROW("Type not supported"); } - // TODO: Test is flaky on QNN EP (CPU backend). - // Re-enable when the QnnCPUBackendTests.DISABLED_SpaceToDepth_Flaky2 test is fixed. + // type not supported by QNN EP: MLFloat16 and unsigned char test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kQnnExecutionProvider}); } @@ -439,8 +433,7 @@ TYPED_TEST(TensorOpTest, DepthToSpaceTest_5) { ORT_THROW("Type not supported"); } - // TODO: Test is flaky on QNN EP (CPU backend). - // Re-enable when the QnnCPUBackendTests.DISABLED_SpaceToDepth_Flaky2 test is fixed. + // type not supported by QNN EP: MLFloat16 and unsigned char test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kQnnExecutionProvider}); } diff --git a/onnxruntime/test/providers/qnn/conv_test.cc b/onnxruntime/test/providers/qnn/conv_test.cc index d12141fccc6dd..5562da10b5463 100644 --- a/onnxruntime/test/providers/qnn/conv_test.cc +++ b/onnxruntime/test/providers/qnn/conv_test.cc @@ -371,7 +371,8 @@ static void RunHTPConvOpPerChannelTest(const std::string& conv_op_type, const Te // Check that QNN compiles DQ -> Conv -> Q as a single unit. // Tests bias as a dynamic input. // TODO: Segfaults when calling graphFinalize(). v2.13 -TEST_F(QnnCPUBackendTests, DISABLED_Convf32_dynamic_bias) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, Convf32_dynamic_bias) { RunCPUConvOpTest("Conv", TestInputDef({1, 1, 3, 3}, false, 0.0f, 10.0f), // Random dynamic input TestInputDef({2, 1, 2, 2}, true, 0.0f, 1.0f), // Random static weights @@ -499,7 +500,8 @@ TEST_F(QnnCPUBackendTests, Convf32_AutoPadLower) { // Tests ConvTranspose's auto_pad value "SAME_LOWER" (compares to CPU EP). // 2.31 Exception from qnn_interface.graphAddNode // unknown file: error: SEH exception with code 0xc0000005 thrown in the test body -TEST_F(QnnCPUBackendTests, DISABLED_ConvTransposef32_AutoPadLower) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, ConvTransposef32_AutoPadLower) { RunCPUConvOpTest("ConvTranspose", TestInputDef({1, 1, 3, 3}, false, -3.0f, 3.0f), // Random dynamic input TestInputDef({1, 2, 2, 2}, false, -1.0f, 1.0f), // Random dynamic weights @@ -516,7 +518,8 @@ TEST_F(QnnCPUBackendTests, DISABLED_ConvTransposef32_AutoPadLower) { // Exception from graphFinalize // Exception thrown at 0x00007FFFB7651630 (QnnCpu.dll) in onnxruntime_test_all.exe: // 0xC0000005: Access violation reading location 0x0000000000000000. -TEST_F(QnnCPUBackendTests, DISABLED_ConvTranspose3D_f32_AutoPadLower) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, ConvTranspose3D_f32_AutoPadLower) { RunCPUConvOpTest("ConvTranspose", TestInputDef({1, 1, 3, 3, 3}, false, -3.0f, 3.0f), // Random dynamic input TestInputDef({1, 2, 2, 2, 2}, false, -1.0f, 1.0f), // Random dynamic weights @@ -642,7 +645,8 @@ TEST_F(QnnCPUBackendTests, ConvTranspose1Df32_StaticWeights_DefaultBias) { // Test 1D ConvTranspose with dynamic weights (implemented in QNN EP as 2D convolution with height of 1). // 2.31 Exception from qnn_interface.graphAddNode // unknown file: error: SEH exception with code 0xc0000005 thrown in the test body -TEST_F(QnnCPUBackendTests, DISABLED_ConvTranspose1Df32_DynamicWeights_DefaultBias) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, ConvTranspose1Df32_DynamicWeights_DefaultBias) { std::vector input_data = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; RunCPUConvOpTest("ConvTranspose", TestInputDef({1, 2, 4}, false, input_data), // Dynamic input diff --git a/onnxruntime/test/providers/qnn/matmul_test.cpp b/onnxruntime/test/providers/qnn/matmul_test.cpp index acc653d8bd459..5cf915e9a4729 100644 --- a/onnxruntime/test/providers/qnn/matmul_test.cpp +++ b/onnxruntime/test/providers/qnn/matmul_test.cpp @@ -136,7 +136,8 @@ template static void RunQDQMatMulOpTest(const std::vector& shape_0, const std::vector& shape_1, bool is_initializer_0, bool is_initializer_1, ExpectedEPNodeAssignment expected_ep_assignment = ExpectedEPNodeAssignment::All, - int opset = 21, bool use_contrib_qdq = false) { + int opset = 21, bool use_contrib_qdq = false, + QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; #if defined(_WIN32) provider_options["backend_path"] = "QnnHtp.dll"; @@ -159,7 +160,7 @@ static void RunQDQMatMulOpTest(const std::vector& shape_0, const std::v TestQDQModelAccuracy( BuildMatMulOpTestCase(input0_def, input1_def), BuildMatMulOpQDQTestCase(input0_def, input1_def, use_contrib_qdq), - provider_options, opset, expected_ep_assignment); + provider_options, opset, expected_ep_assignment, tolerance); } template @@ -279,7 +280,8 @@ TEST_F(QnnHTPBackendTests, MatMulOp_QDQ) { // RunQDQMatMulOpTest(shape_0, shape_1, is_initializer_0, is_initializer_1, expected_ep_assignment, opset, // use_contrib_qdq) RunQDQMatMulOpTest({2, 3}, {3, 2}, false, false); - RunQDQMatMulOpTest({2, 3}, {3, 2}, false, true); + RunQDQMatMulOpTest({2, 3}, {3, 2}, false, true, ExpectedEPNodeAssignment::All, 21, + false, QDQTolerance(0.008f)); RunQDQMatMulOpTest({2, 2, 3}, {3, 2}, true, false, ExpectedEPNodeAssignment::All, 18, true); RunQDQMatMulOpTest({2, 1, 3, 3}, {3, 3, 2}, false, true); diff --git a/onnxruntime/test/providers/qnn/pad_op_test.cpp b/onnxruntime/test/providers/qnn/pad_op_test.cpp index ae8c4428e242d..3497a9ceff664 100644 --- a/onnxruntime/test/providers/qnn/pad_op_test.cpp +++ b/onnxruntime/test/providers/qnn/pad_op_test.cpp @@ -180,7 +180,8 @@ TEST_F(QnnCPUBackendTests, Pad2dPadsNotIni) { // Pad reflect mode // Expected: contains 12 values, where each value and its corresponding value in 16-byte object <0C-00 00-00 00-00 00-00 40-01 23-05 EC-01 00-00> are an almost-equal pair // Actual: 16-byte object <0C-00 00-00 00-00 00-00 40-01 12-05 EC-01 00-00>, where the value pair (1.2, 0) at index #1 don't match, which is -1.2 from 1.2 -TEST_F(QnnCPUBackendTests, DISABLED_PadModeReflect) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, PadModeReflect) { bool has_constant_value = false; RunPadOpTest(TestInputDef({3, 2}, false, {1.0f, 1.2f, 2.3f, 3.4f, 4.5f, 5.6f}), TestInputDef({4}, true, {0, 1, 0, 0}), diff --git a/onnxruntime/test/providers/qnn/resize_test.cc b/onnxruntime/test/providers/qnn/resize_test.cc index 4964e593e9521..e1ac1d7889954 100644 --- a/onnxruntime/test/providers/qnn/resize_test.cc +++ b/onnxruntime/test/providers/qnn/resize_test.cc @@ -271,14 +271,20 @@ TEST_F(QnnCPUBackendTests, ResizeDownsampleNearestAlignCorners_rpf) { // Cpu tests that use the "linear" mode. // -TEST_F(QnnCPUBackendTests, Resize2xLinearHalfPixel) { +// accuracy issue since QNN 2.31 +// Expected: contains 240 values, where each value and its corresponding value in 16-byte object are an almost-equal pair +// Actual: 16-byte object , where the value pair (-10, -10.5084743) at index #0 don't match, which is -0.508474 from -10 +TEST_F(QnnCPUBackendTests, DISABLED_Resize2xLinearHalfPixel) { std::vector input_data = GetFloatDataInRange(-10.0f, 10.0f, 60); RunCPUResizeOpTest(TestInputDef({1, 3, 4, 5}, false, input_data), {1, 3, 8, 10}, "linear", "half_pixel", "", ExpectedEPNodeAssignment::All); } -TEST_F(QnnCPUBackendTests, Resize2xLinearHalfPixel_scales) { +// accuracy issue since QNN 2.31 +// Expected: contains 240 values, where each value and its corresponding value in 16-byte object are an almost-equal pair +// Actual: 16-byte object , where the value pair (-10, -10.5084743) at index #0 don't match, which is -0.508474 from -10 +TEST_F(QnnCPUBackendTests, DISABLED_Resize2xLinearHalfPixel_scales) { std::vector input_data = GetFloatDataInRange(-10.0f, 10.0f, 60); RunCPUResizeOpTestWithScales(TestInputDef({1, 3, 4, 5}, false, input_data), {1.0f, 1.0f, 2.0f, 2.0f}, "linear", "half_pixel", "", diff --git a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc index 5ce376f5c6063..2d7d034ac2ad6 100644 --- a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc @@ -49,7 +49,8 @@ static void RunOpTestOnCPU(const std::string& op_type, // index #2 don't match, which is -1.9 from 2 // // If/when fixed, enable QNN EP in cpu test TensorOpTest.SpaceToDepthTest_1 -TEST_F(QnnCPUBackendTests, DISABLED_SpaceToDepth_Flaky) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, SpaceToDepth_Flaky) { std::vector X = {0.0f, 0.1f, 0.2f, 0.3f, 1.0f, 1.1f, 1.2f, 1.3f, @@ -73,7 +74,8 @@ TEST_F(QnnCPUBackendTests, DISABLED_SpaceToDepth_Flaky) { // at index #2 don't match, which is -17 from 18 // // If/when fixed, enable QNN EP in cpu test TensorOpTest.SpaceToDepthTest_2 -TEST_F(QnnCPUBackendTests, DISABLED_SpaceToDepth_Flaky2) { +// fixed by QNN 2.32 +TEST_F(QnnCPUBackendTests, SpaceToDepth_Flaky2) { const std::vector X = { 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., @@ -1054,7 +1056,10 @@ TEST_F(QnnHTPBackendTests, GridSample_AlignCorners) { utils::MakeAttribute("mode", "bilinear"), utils::MakeAttribute("padding_mode", "zeros")}, 17, - ExpectedEPNodeAssignment::All); + ExpectedEPNodeAssignment::All, + kOnnxDomain, + false, + QDQTolerance(0.008f)); } // Test 16-bit QDQ GridSample with align corners @@ -1116,7 +1121,8 @@ TEST_F(QnnHTPBackendTests, GridSample_U16_Nearest) { // Expected val: 3.212885856628418 // QNN QDQ val: 3.1308119297027588 (err 0.08207392692565918) // CPU QDQ val: 3.2036216259002686 (err 0.0092642307281494141) -TEST_F(QnnHTPBackendTests, DISABLED_GridSample_ReflectionPaddingMode) { +// fixed by QNN 2.32 +TEST_F(QnnHTPBackendTests, GridSample_ReflectionPaddingMode) { RunQDQOpTest("GridSample", {TestInputDef({1, 1, 3, 2}, false, -10.0f, 10.0f), TestInputDef({1, 2, 4, 2}, false, -10.0f, 10.0f)}, diff --git a/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml index f403975f4efe6..18a14aa0ac075 100644 --- a/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml @@ -32,7 +32,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 jobs: - job: Build_QNN_EP diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index ca78890720e9d..17e841360efd0 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -57,7 +57,7 @@ parameters: - name: QnnSdk displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 resources: repositories: diff --git a/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml index 8aaaa0e85585a..4d3c3c831a621 100644 --- a/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml @@ -6,7 +6,7 @@ parameters: - name: QnnSdk displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: IsReleaseBuild displayName: Is a release build? Set it to true if you are doing an Onnx Runtime release. diff --git a/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml index f78dd44b49ec3..704860587459a 100644 --- a/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml @@ -33,7 +33,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 jobs: - job: Build_QNN_EP @@ -90,7 +90,7 @@ jobs: inputs: script: | ./build/Release/onnx_test_runner -e qnn \ - -v -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnCpu.so" \ + -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnCpu.so" \ cmake/external/onnx/onnx/backend/test/data/node - task: CmdLine@2 @@ -98,7 +98,7 @@ jobs: inputs: script: | ./build/Release/onnx_test_runner -e qnn \ - -v -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnCpu.so" \ + -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnCpu.so" \ /data/float32_models - task: CmdLine@2 @@ -106,7 +106,7 @@ jobs: inputs: script: | ./build/Release/onnx_test_runner -e qnn \ - -v -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnHtp.so" \ + -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnHtp.so" \ /data/qdq_models - task: CmdLine@2 @@ -114,5 +114,5 @@ jobs: inputs: script: | ./build/Release/onnx_test_runner -e qnn \ - -v -f -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnHtp.so" \ + -f -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnHtp.so" \ /data/qdq_models/mobilenetv2-1.0_add_transpose_quant diff --git a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml index 28ddd29ec63e6..41549287cd3ab 100644 --- a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml @@ -59,7 +59,7 @@ parameters: - name: qnn_sdk_version type: string displayName: 'QNN SDK version. Only for QNN packages.' - default: 2.31.0.250130 + default: 2.32.0.250228 trigger: none diff --git a/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml index cfca998e0f06c..fedabba9083e6 100644 --- a/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml @@ -2,7 +2,7 @@ parameters: - name: QnnSdk displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: build_config displayName: Build Configuration diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml index d64ee07aa2131..62657db41562d 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml @@ -59,7 +59,7 @@ parameters: - name: qnn_sdk_version type: string displayName: 'QNN SDK version. Only for QNN packages.' - default: 2.31.0.250130 + default: 2.32.0.250228 stages: - ${{ if eq(parameters.enable_windows_cpu, true) }}: diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml index 925cb96cb270d..2fbae07b897b8 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml @@ -17,7 +17,7 @@ parameters: - name: QnnSDKVersion displayName: QNN SDK Version type: string - default: '2.31.0.250130' + default: '2.32.0.250228' jobs: - job: Final_AAR_Testing_Android diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml index 2f891360c626a..f930101f34d05 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar.yml @@ -51,7 +51,7 @@ parameters: - name: QnnSDKVersion displayName: QNN SDK Version type: string - default: '2.31.0.250130' + default: '2.32.0.250228' - name: is1ES displayName: Is 1ES pipeline diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index b7cb5a51eada4..3228673d012ba 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -45,7 +45,7 @@ parameters: - name: QnnSDKVersion displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: is1ES displayName: Is 1ES pipeline diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml index da91080f34623..9ab308c440e21 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml @@ -1,7 +1,7 @@ parameters: - name: QnnSDKVersion type: string - default: '2.31.0.250130' + default: '2.32.0.250228' steps: - script: | diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml index 66793592a6be5..62399443dfd35 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml @@ -1,7 +1,7 @@ parameters: - name: QnnSDKVersion type: string - default: '2.31.0.250130' + default: '2.32.0.250228' steps: - powershell: | diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml index 8126cda449daa..73da992a121eb 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml @@ -26,7 +26,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: is1ES displayName: 'Whether the pipeline is running in 1ES' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml index 10ea7f6203bb1..b05d542376364 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml @@ -7,7 +7,7 @@ parameters: - name: QNN_SDK displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: ENV_SETUP_SCRIPT type: string diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml index ee70742256a15..ade5b110f3043 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml @@ -7,7 +7,7 @@ parameters: - name: QNN_SDK displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: ENV_SETUP_SCRIPT type: string diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml index 175b343e55d57..57361173b8880 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml @@ -7,7 +7,7 @@ parameters: - name: QNN_SDK displayName: QNN SDK Version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 - name: ENV_SETUP_SCRIPT type: string diff --git a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml index 3fa4799ec9c0e..0dca93b845caa 100644 --- a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml +++ b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml @@ -1,5 +1,5 @@ parameters: - QnnSdk: '2.31.0.250130' + QnnSdk: '2.32.0.250228' build_config: 'RelWithDebInfo' IsReleaseBuild: false DoEsrp: false diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml index 1c3d911fa7dbb..6ea497fab6a8a 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml @@ -33,7 +33,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 jobs: - job: 'BUILD_QNN_EP' diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml index faef469e010f6..01c44da39905a 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml @@ -33,7 +33,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.31.0.250130 + default: 2.32.0.250228 jobs: - job: 'BUILD_QNN_EP' From 24ece479d42f2e9ccf3920d667b38d66b544f791 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 26 Mar 2025 11:36:49 -0700 Subject: [PATCH 179/266] [JSEP] adjust edge case logic for scatternd (#24172) Fixes https://github.com/microsoft/onnxruntime/issues/24070 by explicitly restricting single-threaded, sequential execution in the case where `reduction=none && hasDuplicates`. --- js/web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts | 88 +++++++++++-------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts b/js/web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts index 7fd0c2ef42aff..ec1d23e4887d5 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts @@ -78,6 +78,36 @@ const atomicReductionSnippet = (reduction: string, ptr: string, v: string, type: } }; +const calcDataOffsetSnippet = (dataRank: number, parallel: boolean) => + `${ + dataRank === 1 + ? ` + let element_count_dim = uniforms.output_strides; + let dim_value = uniforms.output_shape;` + : ` + let element_count_dim = uniforms.output_strides[${parallel ? 'i - indices_start' : 'i'}]; + let dim_value = uniforms.output_shape[${parallel ? 'i - indices_start' : 'i'} + uniforms.last_index_dimension];` + } + + if (index >= 0) { + if (index >= i32(dim_value)) { + index = i32(dim_value - 1); + } + } else { + if (index < -i32(dim_value)) { + index = 0; + } else { + index += i32(dim_value); + } + } + data_offset += u32((u32(index) * element_count_dim));`; + +const updateElementsSnippet = (attributes: ScatterNDAttributes, outputTypeValue: ReductionType, parallel: boolean) => + `for (var i = 0u; i < uniforms.num_updates_elements; i++) { + let value = updates[uniforms.num_updates_elements * ${parallel ? 'global_idx' : 'idx'} + i]; + ${atomicReductionSnippet(attributes.reduction, 'output[data_offset + i]', 'value', outputTypeValue)} + }`; + const createScatterNDProgramInfo = (inputs: readonly TensorView[], attributes: ScatterNDAttributes): ProgramInfo => { const inputShape = inputs[0].dims; const indicesShape = inputs[1].dims; @@ -87,6 +117,7 @@ const createScatterNDProgramInfo = (inputs: readonly TensorView[], attributes: S const outputSize = Math.ceil(ShapeUtil.size(indicesShape) / components); const lastIndexDimension = indicesShape[indicesShape.length - 1]; const numUpdatesElements = ShapeUtil.sizeFromDimension(inputShape, lastIndexDimension); + const numIndicesElements = ShapeUtil.sizeFromDimension(indicesShape, 0) / lastIndexDimension; const programUniforms: ProgramUniform[] = [ { type: DataType.uint32, data: outputSize }, @@ -113,9 +144,8 @@ const createScatterNDProgramInfo = (inputs: readonly TensorView[], attributes: S ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} var hasDuplicates = false; if (${attributes.reduction === 'none'}) { - let n = ${ShapeUtil.size(indicesShape)}; - for (var i = 0; i < n; i = i + 1) { - for (var j = i + 1; j < n; j = j + 1) { + for (var i = 0; i < ${numIndicesElements}; i = i + 1) { + for (var j = i + 1; j < ${numIndicesElements}; j = j + 1) { var index_i = i32(indices[i].x); var index_j = i32(indices[j].x); if (index_i == index_j) { @@ -129,51 +159,31 @@ const createScatterNDProgramInfo = (inputs: readonly TensorView[], attributes: S } } - var data_offset = 0u; - var indices_start = uniforms.last_index_dimension * global_idx; if (${attributes.reduction === 'none'} && hasDuplicates) { if (global_idx != 0u) { return; } - indices_start = 0u; - } - let indices_end = indices_start + uniforms.last_index_dimension; - for (var i = indices_start; i < indices_end; i++) { - var index = i32(indices[i].x); - ${ - inputs[0].dims.length === 1 - ? ` - let element_count_dim = uniforms.output_strides; - let dim_value = uniforms.output_shape;` - : ` - let element_count_dim = uniforms.output_strides[i - indices_start]; - let dim_value = uniforms.output_shape[i - indices_start + uniforms.last_index_dimension];` - } - if (index >= 0) { - if (index >= i32(dim_value)) { - index = i32(dim_value - 1); - } - } else { - if (index < -i32(dim_value)) { - index = 0; - } else { - index += i32(dim_value); + // Process each index-update pair individually when duplicates exist + for (var idx = 0u; idx < ${numIndicesElements}u; idx++) { + var data_offset = 0u; + for (var i = 0u; i < uniforms.last_index_dimension; i++) { + var index = i32(indices[idx * uniforms.last_index_dimension + i].x); + ${calcDataOffsetSnippet(inputShape.length, false)} } + ${updateElementsSnippet(attributes, output.type.value as ReductionType, false)} } - data_offset += u32((u32(index) * element_count_dim)); + return; } - for (var i = 0u; i < uniforms.num_updates_elements; i++) { - let value = updates[uniforms.num_updates_elements * global_idx + i]; - ${atomicReductionSnippet( - attributes.reduction, - 'output[data_offset + i]', - 'value', - output.type.value as ReductionType, - )} + var data_offset = 0u; + var indices_start = uniforms.last_index_dimension * global_idx; + var indices_end = indices_start + uniforms.last_index_dimension; + for (var i = indices_start; i < indices_end; i++) { + var index = i32(indices[i].x); + ${calcDataOffsetSnippet(inputShape.length, true)} } - - }`; + ${updateElementsSnippet(attributes, output.type.value as ReductionType, true)} + }`; }; return { name: 'ScatterND', From 1f70fc25319fea9c25c3c19f5f93090dfe30721d Mon Sep 17 00:00:00 2001 From: Baiju Meswani Date: Wed, 26 Mar 2025 17:35:10 -0700 Subject: [PATCH 180/266] Make the custom nuget packaging pipeline 1ES commpliant. (#24191) --- .../custom-nuget-packaging-pipeline.yml | 240 ++++++++++-------- .../azure-pipelines/templates/qnn-ep-win.yml | 18 +- 2 files changed, 133 insertions(+), 125 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml index 4d3c3c831a621..a6ad823594917 100644 --- a/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/custom-nuget-packaging-pipeline.yml @@ -28,115 +28,131 @@ variables: ${{ if eq(parameters.CudaVersion, '12.2') }}: value: $(Agent.TempDirectory)\v12.2 -stages: - - template: templates/win-ci.yml - parameters: - ort_build_pool_name: 'onnxruntime-Win2022-GPU-A10' - DoCompliance: false - DoEsrp: true - stage_name_suffix: CUDA - buildArch: x64 - msbuildPlatform: x64 - packageName: x64-cuda - CudaVersion: ${{ parameters.CudaVersion }} - buildparameter: --use_cuda --cuda_home=${{ variables.win_cuda_home }} --enable_onnx_tests --enable_wcos --use_webgpu --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52-real;61-real;75-real;86-real;89-real;90-virtual" - runTests: false - buildJava: false - java_artifact_id: onnxruntime_gpu - UseIncreasedTimeoutForTests: false - SpecificArtifact: false - BuildId: '0' - - - template: templates/qnn-ep-win.yml - parameters: - qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' - QnnSdk: ${{ parameters.QnnSdk }} - IsReleaseBuild: ${{ parameters.IsReleaseBuild }} - DoEsrp: true - ArtifactName: 'drop-nuget-qnn-arm64' - # Add --use_webgpu to enable WebGPU - buildParameter: '--arm64' - buildPlatform: 'ARM64' - buildArch: 'ARM64' - StageName: 'OnnxRuntime_QNN_Nuget_Win_Arm64' - build_config: 'RelWithDebInfo' - Is1ES: false - PublishArchive: true - - - stage: NugetPackaging - dependsOn: [Windows_Packaging_CUDA, OnnxRuntime_QNN_Nuget_Win_Arm64] - jobs: - - job: CreateNugetPackage - pool: 'Onnxruntime-Win2022-GPU-A10' - timeoutInMinutes: 120 - steps: - - checkout: self - clean: true - submodules: none - - - task: UsePythonVersion@0 - inputs: - versionSpec: '3.12' - addToPath: true - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - managed nuget' - inputs: - artifactName: 'drop-nuget-qnn-arm64' - targetPath: '$(Build.BinariesDirectory)/managed-nuget' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - win-x64' - inputs: - artifactName: 'onnxruntime-win-x64-cuda' - targetPath: '$(Build.BinariesDirectory)/win-x64' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - win-arm64' - inputs: - artifactName: 'onnxruntime-win-ARM64-qnn' - targetPath: '$(Build.BinariesDirectory)/win-arm64' - - - task: PowerShell@2 - displayName: 'Extract Nuget Package Version' - inputs: - targetType: 'inline' - script: | - $nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/managed-nuget -Filter Microsoft.ML.OnnxRuntime.Managed.*.nupkg -Recurse) - $package_name = $nupkgs[0].Name - $version_length = $package_name.Length - "Microsoft.ML.OnnxRuntime.Managed.".Length - ".nupkg".Length - $package_version = $package_name.Substring("Microsoft.ML.OnnxRuntime.Managed.".Length, $version_length) - Write-Host "##vso[task.setvariable variable=package_version;]$package_version" - workingDirectory: $(Build.BinariesDirectory) - - - task: PowerShell@2 - displayName: 'Extract Archives' - inputs: - targetType: 'inline' - script: | - Expand-Archive -Path $(Build.BinariesDirectory)/win-x64/onnxruntime-win-x64-cuda*.zip -DestinationPath $(Build.BinariesDirectory)/win-x64 - Expand-Archive -Path $(Build.BinariesDirectory)/win-arm64/onnxruntime-win-ARM64-qnn*.zip -DestinationPath $(Build.BinariesDirectory)/win-arm64 - $win_x64 = (Get-ChildItem -Path $(Build.BinariesDirectory)/win-x64 -Filter onnxruntime-win-x64-cuda*)[0].FullName - $win_arm64 = (Get-ChildItem -Path $(Build.BinariesDirectory)/win-arm64 -Filter onnxruntime-win-ARM64-qnn*)[0].FullName - Write-Host "##vso[task.setvariable variable=win_x64;]$win_x64" - Write-Host "##vso[task.setvariable variable=win_arm64;]$win_arm64" - workingDirectory: $(Build.BinariesDirectory) - - - task: PythonScript@0 - displayName: 'Generate Nuget Package' - inputs: - scriptPath: '$(Build.SourcesDirectory)/tools/nuget/generate_nuspec_for_custom_nuget.py' - arguments: '--nuspec_path "$(Build.BinariesDirectory)/${{ parameters.PackageName }}.nuspec" --root_dir "$(Build.SourcesDirectory)" --commit_id "$(Build.SourceVersion)" --win_arm64 "$(win_arm64)" --win_x64 "$(win_x64)" --package_version "$(package_version)" --package_name "${{ parameters.PackageName }}"' - - - task: NuGetCommand@2 - displayName: 'Pack Nuget Package' - inputs: - command: 'pack' - packagesToPack: '$(Build.BinariesDirectory)/${{ parameters.PackageName }}.nuspec' - packDestination: $(Build.ArtifactStagingDirectory)\ - - - task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: Nuget' - inputs: - pathtoPublish: '$(Build.ArtifactStagingDirectory)' - artifactName: '${{ parameters.PackageName }}' +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + sdl: + sourceAnalysisPool: + name: onnxruntime-Win-CPU-2022 + os: windows + + stages: + - template: templates/win-ci.yml + parameters: + ort_build_pool_name: 'onnxruntime-Win2022-GPU-A10' + DoCompliance: false + DoEsrp: true + stage_name_suffix: CUDA + buildArch: x64 + msbuildPlatform: x64 + packageName: x64-cuda + CudaVersion: ${{ parameters.CudaVersion }} + buildparameter: --use_cuda --cuda_home=${{ variables.win_cuda_home }} --enable_onnx_tests --enable_wcos --use_webgpu --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52-real;61-real;75-real;86-real;89-real;90-virtual" + runTests: false + buildJava: false + java_artifact_id: onnxruntime_gpu + UseIncreasedTimeoutForTests: false + SpecificArtifact: false + BuildId: '0' + + - template: templates/qnn-ep-win.yml + parameters: + qnn_ep_build_pool_name: 'Onnxruntime-QNNEP-Windows-2022-CPU' + QnnSdk: ${{ parameters.QnnSdk }} + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + DoEsrp: true + ArtifactName: 'drop-nuget-qnn-arm64' + # Add --use_webgpu to enable WebGPU + buildParameter: '--arm64' + buildPlatform: 'ARM64' + buildArch: 'ARM64' + StageName: 'OnnxRuntime_QNN_Nuget_Win_Arm64' + build_config: 'RelWithDebInfo' + PublishArchive: true + + - stage: NugetPackaging + dependsOn: [Windows_Packaging_CUDA, OnnxRuntime_QNN_Nuget_Win_Arm64] + jobs: + - job: CreateNugetPackage + pool: 'Onnxruntime-Win2022-GPU-A10' + timeoutInMinutes: 120 + steps: + - checkout: self + clean: true + submodules: none + + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + addToPath: true + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - managed nuget' + inputs: + artifactName: 'drop-nuget-qnn-arm64' + targetPath: '$(Build.BinariesDirectory)/managed-nuget' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - win-x64' + inputs: + artifactName: 'onnxruntime-win-x64-cuda' + targetPath: '$(Build.BinariesDirectory)/win-x64' + + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact - win-arm64' + inputs: + artifactName: 'onnxruntime-win-ARM64-qnn' + targetPath: '$(Build.BinariesDirectory)/win-arm64' + + - task: PowerShell@2 + displayName: 'Extract Nuget Package Version' + inputs: + targetType: 'inline' + script: | + $nupkgs = (Get-ChildItem $(Build.BinariesDirectory)/managed-nuget -Filter Microsoft.ML.OnnxRuntime.Managed.*.nupkg -Recurse) + $package_name = $nupkgs[0].Name + $version_length = $package_name.Length - "Microsoft.ML.OnnxRuntime.Managed.".Length - ".nupkg".Length + $package_version = $package_name.Substring("Microsoft.ML.OnnxRuntime.Managed.".Length, $version_length) + Write-Host "##vso[task.setvariable variable=package_version;]$package_version" + workingDirectory: $(Build.BinariesDirectory) + + - task: PowerShell@2 + displayName: 'Extract Archives' + inputs: + targetType: 'inline' + script: | + Expand-Archive -Path $(Build.BinariesDirectory)/win-x64/onnxruntime-win-x64-cuda*.zip -DestinationPath $(Build.BinariesDirectory)/win-x64 + Expand-Archive -Path $(Build.BinariesDirectory)/win-arm64/onnxruntime-win-ARM64-qnn*.zip -DestinationPath $(Build.BinariesDirectory)/win-arm64 + $win_x64 = (Get-ChildItem -Path $(Build.BinariesDirectory)/win-x64 -Filter onnxruntime-win-x64-cuda*)[0].FullName + $win_arm64 = (Get-ChildItem -Path $(Build.BinariesDirectory)/win-arm64 -Filter onnxruntime-win-ARM64-qnn*)[0].FullName + Write-Host "##vso[task.setvariable variable=win_x64;]$win_x64" + Write-Host "##vso[task.setvariable variable=win_arm64;]$win_arm64" + workingDirectory: $(Build.BinariesDirectory) + + - task: PythonScript@0 + displayName: 'Generate Nuget Package' + inputs: + scriptPath: '$(Build.SourcesDirectory)/tools/nuget/generate_nuspec_for_custom_nuget.py' + arguments: '--nuspec_path "$(Build.BinariesDirectory)/${{ parameters.PackageName }}.nuspec" --root_dir "$(Build.SourcesDirectory)" --commit_id "$(Build.SourceVersion)" --win_arm64 "$(win_arm64)" --win_x64 "$(win_x64)" --package_version "$(package_version)" --package_name "${{ parameters.PackageName }}"' + + - task: NuGetCommand@2 + displayName: 'Pack Nuget Package' + inputs: + command: 'pack' + packagesToPack: '$(Build.BinariesDirectory)/${{ parameters.PackageName }}.nuspec' + packDestination: $(Build.ArtifactStagingDirectory)\ + + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Artifact: Nuget' + inputs: + artifactName: '${{ parameters.PackageName }}' + targetPath: '$(Build.ArtifactStagingDirectory)' diff --git a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml index 0dca93b845caa..a799d2eb44a20 100644 --- a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml +++ b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml @@ -10,7 +10,6 @@ parameters: buildPlatform: 'x64' buildArch: 'x64' StageName: 'OnnxRuntime_QNN_Nuget_Win_x64' - Is1ES: true PublishArchive: false stages: @@ -165,15 +164,8 @@ stages: Contents: '*.snupkg' TargetFolder: '$(Build.ArtifactStagingDirectory)' - - ${{ if eq(parameters.Is1ES, true) }}: - - task: 1ES.PublishPipelineArtifact@1 - displayName: 'Publish Pipeline x64 NuGet Artifact' - inputs: - artifactName: ${{ parameters.ArtifactName }} - targetPath: '$(Build.ArtifactStagingDirectory)' - - ${{ else }}: - - task: PublishPipelineArtifact@1 - displayName: 'Publish Pipeline x64 NuGet Artifact' - inputs: - artifactName: ${{ parameters.ArtifactName }} - targetPath: '$(Build.ArtifactStagingDirectory)' + - task: 1ES.PublishPipelineArtifact@1 + displayName: 'Publish Pipeline x64 NuGet Artifact' + inputs: + artifactName: ${{ parameters.ArtifactName }} + targetPath: '$(Build.ArtifactStagingDirectory)' From 4d13b70fe38208e7e47b6e01076fd1c9404a7449 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Thu, 27 Mar 2025 09:06:43 -0700 Subject: [PATCH 181/266] Disable KleidiAI in Python Packaging pipeline MacOS build (#24194) This is a workaround for a build error. See https://github.com/microsoft/onnxruntime/issues/24152. --- .../stages/py-cpu-packaging-stage.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml index 62657db41562d..5efdd3228e21e 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml @@ -232,7 +232,20 @@ stages: set -e -x export _PYTHON_HOST_PLATFORM=macosx-${{variables.MACOSX_DEPLOYMENT_TARGET}}-universal2 python3 -m pip install -r '$(Build.SourcesDirectory)/tools/ci_build/github/linux/docker/scripts/requirements.txt' - python3 $(Build.SourcesDirectory)/tools/ci_build/build.py --build_dir $(Build.BinariesDirectory) --use_coreml --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --config Release --build_wheel ${{ parameters.build_py_parameters }} --use_coreml --cmake_extra_defines CMAKE_OSX_ARCHITECTURES="arm64;x86_64" --update --build + # Note: There is a build error when we set CMAKE_OSX_ARCHITECTURES="arm64;x86_64" and KleidiAI is enabled. + # Disable KleidiAI as a workaround with --no_kleidiai. + # TODO Re-enable KleidiAI once https://github.com/microsoft/onnxruntime/issues/24152 is fixed. + python3 $(Build.SourcesDirectory)/tools/ci_build/build.py \ + --build_dir $(Build.BinariesDirectory) \ + --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ + --use_binskim_compliant_compile_flags \ + --config Release \ + --build_wheel \ + --use_coreml \ + --no_kleidiai \ + ${{ parameters.build_py_parameters }} \ + --cmake_extra_defines CMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + --update --skip_submodule_sync --build --parallel displayName: 'Command Line Script' - script: | From 041674adc8686a037204805e792f75668521e621 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 27 Mar 2025 13:12:43 -0400 Subject: [PATCH 182/266] Rolling back the python/cuda (#24170) ### Description ### Motivation and Context --- .../stages/py-linux-gpu-stage.yml | 4 +- .../py-packaging-linux-test-cuda.yml | 4 +- .../inference/x86_64/python/cuda/Dockerfile | 45 +++++++++++++++++++ .../python/cuda/scripts/install_centos.sh | 18 ++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile create mode 100755 tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh diff --git a/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml index 17eb10fae7eb2..715470eb9f012 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-linux-gpu-stage.yml @@ -66,8 +66,8 @@ stages: - template: ../templates/get-docker-image-steps.yml parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12 + Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda DockerBuildArgs: "--build-arg BASEIMAGE=${{ parameters.docker_base_image }} --build-arg TRT_VERSION=${{ variables.trt_version }} --build-arg BUILD_UID=$( id -u )" Repository: onnxruntimecuda${{ replace(parameters.cuda_version, '.', '') }}xtrt86build${{ parameters.arch }} diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml index 96ff9943dc178..a7760318c1618 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml @@ -90,8 +90,8 @@ jobs: - template: get-docker-image-steps.yml parameters: - Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12/Dockerfile - Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/default/cuda12 + Dockerfile: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/${{ parameters.arch }}/python/cuda DockerBuildArgs: "--build-arg BASEIMAGE=${{ parameters.docker_base_image }} --build-arg TRT_VERSION=${{ variables.trt_version }} --build-arg BUILD_UID=$( id -u )" Repository: onnxruntimecuda${{ replace(parameters.cuda_version, '.', '') }}xtrt86build${{ parameters.arch }} diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile new file mode 100644 index 0000000000000..d87870db0bca8 --- /dev/null +++ b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile @@ -0,0 +1,45 @@ +# The default ARGs are for cuda 11.8 with cudnn8, TensorRT is optional +# Please overwrite BASEIMAGE, TRT_VERSION and other arguments with +# --docker-build-args ' --build-arg BASEIMAGE=other_base_image --build-arg TRT_VERSION=other_trt_version etc...' +# for other cuda version and TRT version +ARG BASEIMAGE=nvidia/cuda:12.5.1-cudnn-devel-ubi8 + +FROM $BASEIMAGE +ARG TRT_VERSION=10.9.0.34-1.cuda12.8 + +#Install TensorRT only if TRT_VERSION is not empty +RUN if [ -n "${TRT_VERSION}" ]; then \ + echo "TRT_VERSION is $TRT_VERSION" && \ + dnf -y install \ + libnvinfer10-${TRT_VERSION} \ + libnvinfer-headers-devel-${TRT_VERSION} \ + libnvinfer-devel-${TRT_VERSION} \ + libnvinfer-lean10-${TRT_VERSION} \ + libnvonnxparsers10-${TRT_VERSION} \ + libnvonnxparsers-devel-${TRT_VERSION} \ + libnvinfer-dispatch10-${TRT_VERSION} \ + libnvinfer-plugin10-${TRT_VERSION} \ + libnvinfer-vc-plugin10-${TRT_VERSION} \ + libnvinfer-bin-${TRT_VERSION} \ + libnvinfer-plugin10-${TRT_VERSION} \ + libnvinfer-plugin-devel-${TRT_VERSION} \ + libnvinfer-vc-plugin-devel-${TRT_VERSION} \ + libnvinfer-lean-devel-${TRT_VERSION} \ + libnvinfer-dispatch-devel-${TRT_VERSION} \ + libnvinfer-headers-plugin-devel-${TRT_VERSION} && \ + dnf clean dbcache ; \ +else \ + echo "TRT_VERSION is x${TRT_VERSION} skipping Tensor RT Installation" ; \ +fi + +ENV PATH=/usr/local/cuda/bin:$PATH +ENV CUDA_MODULE_LOADING="LAZY" + +ADD scripts /tmp/scripts +RUN cd /tmp/scripts && /tmp/scripts/install_centos.sh && rm -rf /tmp/scripts + +ARG BUILD_UID=1001 +ARG BUILD_USER=onnxruntimedev +RUN adduser --uid $BUILD_UID $BUILD_USER +WORKDIR /home/$BUILD_USER +USER $BUILD_USER diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh new file mode 100755 index 0000000000000..d0b58ed28b8c9 --- /dev/null +++ b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/scripts/install_centos.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +os_major_version=$(tr -dc '0-9.' < /etc/redhat-release |cut -d \. -f1) + +echo "installing for os major version : $os_major_version" +dnf install -y glibc-langpack-\* +yum install -y which redhat-lsb-core expat-devel tar unzip zlib-devel make bzip2 bzip2-devel perl-IPC-Cmd openssl-devel wget + +echo "installing rapidjson for AzureEP" +wget https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz +tar zxvf v1.1.0.tar.gz +cd rapidjson-1.1.0 +mkdir build +cd build +cmake .. +cmake --install . +cd ../.. From 914be22e85f04b9ac1734d135f4599c5c12e95b0 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 27 Mar 2025 13:16:00 -0400 Subject: [PATCH 183/266] Remove all CG template from pipelines (#24193) ### Description Since we are adapting 1ES teamplate, we are remove the redundent CG steps from our pipelines ### Motivation and Context --- ...linux-gpu-tensorrt-daily-perf-pipeline.yml | 4 -- .../azure-pipelines/nodejs/templates/test.yml | 4 -- .../nuget/templates/dml-vs-2022.yml | 4 -- .../nuget/templates/test_linux.yml | 4 -- .../nuget/templates/test_macos.yml | 4 -- .../nuget/templates/test_win.yml | 4 -- .../stages/download-java-tools-stage.yml | 6 +-- .../stages/java-cuda-packaging-stage.yml | 11 ----- .../jobs/py-linux-cuda-package-test-job.yml | 3 -- .../stages/nuget-cuda-packaging-stage.yml | 4 -- .../nuget-linux-cuda-packaging-stage.yml | 10 ---- .../stages/nuget-win-cuda-packaging-stage.yml | 4 -- .../stages/nuget_dml_packaging_stage.yml | 5 +- .../stages/py-cpu-packaging-stage.yml | 10 ---- .../stages/set_packaging_variables_stage.yml | 6 --- .../templates/android-java-api-aar-test.yml | 4 -- .../azure-pipelines/templates/c-api-cpu.yml | 16 ++----- .../templates/c-api-linux-cpu.yml | 5 -- .../clean-agent-build-directory-step.yml | 3 -- ...t-governance-component-detection-steps.yml | 47 ------------------- .../explicitly-defined-final-tasks.yml | 3 -- .../templates/final-jar-testing.yml | 4 +- .../templates/linux-wasm-ci.yml | 3 -- .../templates/mac-cpu-packaging-pipeline.yml | 4 +- ...device-training-cpu-packaging-pipeline.yml | 4 -- .../templates/publish-nuget-steps.yml | 4 +- .../templates/py-linux-qnn.yml | 3 -- .../azure-pipelines/templates/py-linux.yml | 3 -- .../templates/py-win-arm64-qnn.yml | 3 -- .../templates/py-win-arm64ec-qnn.yml | 3 -- .../templates/py-win-x64-qnn.yml | 6 +-- .../github/azure-pipelines/templates/rocm.yml | 3 -- .../stages/mac-ios-packaging-build-stage.yml | 4 -- .../azure-pipelines/templates/win-ci.yml | 4 -- .../azure-pipelines/templates/win-wasm-ci.yml | 3 -- .../azure-pipelines/templates/win-web-ci.yml | 3 -- .../azure-pipelines/win-ci-fuzz-testing.yml | 4 -- .../win-gpu-reduce-op-ci-pipeline.yml | 4 -- 38 files changed, 10 insertions(+), 213 deletions(-) delete mode 100644 tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml index ac9153e1b4887..c00cbb06f26fd 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml @@ -191,8 +191,4 @@ jobs: pathtoPublish: '$(Build.SourcesDirectory)/Artifact' artifactName: 'result-$(Build.BuildNumber)' - - template: templates/component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' - - template: templates/clean-agent-build-directory-step.yml \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/nodejs/templates/test.yml b/tools/ci_build/github/azure-pipelines/nodejs/templates/test.yml index 9b2d7284cf342..28ece85428287 100644 --- a/tools/ci_build/github/azure-pipelines/nodejs/templates/test.yml +++ b/tools/ci_build/github/azure-pipelines/nodejs/templates/test.yml @@ -33,8 +33,4 @@ steps: node -p "require('onnxruntime-node')" workingDirectory: '$(Build.BinariesDirectory)/e2e_test' -- template: ../../templates/component-governance-component-detection-steps.yml - parameters : - condition : 'always' - - template: ../../templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml index fcae62b1f55f2..130bc330d53f7 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/dml-vs-2022.yml @@ -211,7 +211,3 @@ stages: inputs: targetPath: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}' artifactName: 'drop-onnxruntime-nodejs-win-${{ parameters.sln_platform }}-dml' - - - template: ../../templates/component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml index 26a6c685ffa66..ff598ce92ddb4 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml @@ -112,8 +112,4 @@ stages: IsReleaseBuild: $(IsReleaseBuild) PACKAGENAME: ${{ parameters.NugetPackageName }} - - template: ../../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'always' - - template: ../../templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml index 15746682d9137..5be0bfb7a3535 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_macos.yml @@ -53,8 +53,4 @@ stages: DisableMlOps: $(DisableMlOps) IsReleaseBuild: $(IsReleaseBuild) - - template: ../../templates/component-governance-component-detection-steps.yml - parameters : - condition : 'always' - - template: ../../templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_win.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_win.yml index 4842fcbd4dcfb..af2069a3512a5 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_win.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_win.yml @@ -118,8 +118,4 @@ stages: env: PACKAGENAME: ${{ parameters.NugetPackageName }} - - template: ../../templates/component-governance-component-detection-steps.yml - parameters : - condition : 'always' - - template: ../../templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml b/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml index 7e5237b32bce2..1cc3e2def327f 100644 --- a/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/download-java-tools-stage.yml @@ -23,8 +23,4 @@ stages: displayName: 'Publish Pipeline Java Tools Artifact' inputs: targetPath: '$(Agent.TempDirectory)/java-tools' - artifact: 'onnxruntime-java-tools' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' \ No newline at end of file + artifact: 'onnxruntime-java-tools' \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml index 6c3407c09d463..617c00b5fa592 100644 --- a/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/java-cuda-packaging-stage.yml @@ -79,9 +79,6 @@ stages: path: '$(Build.ArtifactStagingDirectory)' artifact: 'onnxruntime-java-gpu' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - job: Final_Jar_Testing_Windows_GPU dependsOn: Jar_Packaging_GPU @@ -127,10 +124,6 @@ stages: popd java -DUSE_CUDA=1 -jar junit-platform-console-standalone-1.6.2.jar -cp .;.\test;protobuf-java-3.21.7.jar;onnxruntime_gpu-$(OnnxRuntimeVersion).jar --scan-class-path --fail-if-no-tests --disable-banner workingDirectory: '$(Build.BinariesDirectory)\final-jar' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - job: Final_Jar_Testing_Linux_GPU dependsOn: Jar_Packaging_GPU @@ -182,7 +175,3 @@ stages: onnxruntimeubi8packagestest \ /bin/bash /onnxruntime_src/tools/ci_build/github/linux/java_linux_final_test.sh -r /build -v $(OnnxRuntimeVersion) displayName: 'Test' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml b/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml index 49d65b10b393c..4e42afe0da96e 100644 --- a/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml +++ b/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml @@ -113,6 +113,3 @@ jobs: targetType: filePath filePath: tools/ci_build/github/linux/run_python_dockertest.sh arguments: -d GPU -c ${{parameters.cmake_build_type}} -i onnxruntimecuda${{ replace(parameters.CudaVersion, '.', '') }}xtrt86buildx86_64 -u 12.2 - - template: ../../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml index 5c5b464fe24e2..84b6d30ee32ac 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-cuda-packaging-stage.yml @@ -204,10 +204,6 @@ stages: msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=Microsoft.ML.OnnxRuntime.Gpu' workingDirectory: '$(Build.SourcesDirectory)\csharp' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - - task: 1ES.PublishPipelineArtifact@1 displayName: 'Publish Pipeline NuGet Artifact' inputs: diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml index b1d0625c3b11b..8560817331475 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml @@ -59,9 +59,6 @@ stages: artifactNameNoVersionString: 'onnxruntime-linux-x64-cuda' libraryName: 'libonnxruntime.so.$(OnnxRuntimeVersion)' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - template: ../templates/clean-agent-build-directory-step.yml # Linux CUDA with TensorRT Packaging - job: Linux_C_API_Packaging_TensorRT @@ -130,10 +127,6 @@ stages: artifactNameNoVersionString: 'onnxruntime-linux-x64-tensorrt' libraryName: 'libonnxruntime.so.$(OnnxRuntimeVersion)' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - template: ../templates/clean-agent-build-directory-step.yml # Linux CUDA Combined Testing and Publishing - stage: Linux_Packaging_combined_CUDA @@ -230,6 +223,3 @@ stages: inputs: targetPath: '$(Build.ArtifactStagingDirectory)' artifactName: 'onnxruntime-linux-x64-gpu' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml index 53e4218ae6fd5..e5d15db5c062a 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-win-cuda-packaging-stage.yml @@ -160,7 +160,3 @@ stages: inputs: artifactName: 'onnxruntime-win-x64-gpu' targetPath: '$(Build.ArtifactStagingDirectory)' - - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml index 51ccef1cca6c8..093de22566a8b 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget_dml_packaging_stage.yml @@ -93,7 +93,4 @@ stages: displayName: 'Publish Pipeline NuGet Artifact' inputs: artifactName: 'drop-signed-nuget-dml' - targetPath: '$(Build.ArtifactStagingDirectory)' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' \ No newline at end of file + targetPath: '$(Build.ArtifactStagingDirectory)' \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml index 5efdd3228e21e..f5e827e277b40 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cpu-packaging-stage.yml @@ -186,11 +186,6 @@ stages: workingDirectory: '$(Build.BinariesDirectory)\${{ parameters.cmake_build_type }}\${{ parameters.cmake_build_type }}' displayName: 'Run Python Tests' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - - - ${{ if eq(parameters.enable_mac_cpu, true) }}: - stage: Python_Packaging_MacOS dependsOn: [] @@ -273,11 +268,6 @@ stages: artifactName: onnxruntime-macos-$(PythonVersion) targetPath: '$(Build.ArtifactStagingDirectory)' - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - - - ${{ if eq(parameters.enable_linux_arm, true) }}: - stage: Python_Packaging_Linux_ARM dependsOn: [] diff --git a/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml b/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml index 8013396018ffa..a1a983ee9ba20 100644 --- a/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/set_packaging_variables_stage.yml @@ -39,9 +39,6 @@ stages: echo "##vso[task.setvariable variable=BuildTime;isOutput=true]$hhmm" displayName: 'Set Start Time as Variable' name: Set_Build_Time - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - stage: Debug dependsOn: Setup @@ -59,6 +56,3 @@ stages: - bash: echo $(MyVar) - bash: echo $(BuildTime) - bash: echo $(BuildDate) - - template: ../templates/component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml index 2fbae07b897b8..f5c0cfa68c0c7 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-java-api-aar-test.yml @@ -110,7 +110,3 @@ jobs: env: BROWSERSTACK_ID: $(browserstack_username) BROWSERSTACK_TOKEN: $(browserstack_access_key) - - - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index 3228673d012ba..bb789edc1cf21 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -161,9 +161,7 @@ stages: targetPath: '$(Build.BinariesDirectory)/artifacts' artifactName: 'onnxruntime-ios-full-xcframework' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - template: win-ci.yml parameters: @@ -289,9 +287,7 @@ stages: targetPath: '$(Build.ArtifactStagingDirectory)' artifactName: 'onnxruntime-java' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - stage: NuGet_Packaging_CPU dependsOn: @@ -505,9 +501,7 @@ stages: msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=$(OrtPackageId)' workingDirectory: '$(Build.SourcesDirectory)\csharp' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - stage: Nodejs_Packaging @@ -774,9 +768,7 @@ stages: artifactName: 'NPM_packages' targetPath: '$(Build.ArtifactStagingDirectory)' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + - template: ../nuget/templates/test_win.yml diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml index 3d2105bd07dbd..cd2997cc389e9 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml @@ -100,8 +100,3 @@ jobs: arch: '${{parameters.OnnxruntimeNodejsBindingArch}}' os: 'linux' artifactName: 'drop-onnxruntime-nodejs-linux-${{parameters.OnnxruntimeArch}}' - - - ${{ if not(eq(parameters.OnnxruntimeNodejsBindingArch, 'arm64')) }}: - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/clean-agent-build-directory-step.yml b/tools/ci_build/github/azure-pipelines/templates/clean-agent-build-directory-step.yml index 8d6a097ae6dcb..e0a13540351a4 100644 --- a/tools/ci_build/github/azure-pipelines/templates/clean-agent-build-directory-step.yml +++ b/tools/ci_build/github/azure-pipelines/templates/clean-agent-build-directory-step.yml @@ -9,9 +9,6 @@ steps: testRunTitle: 'Unit Test Run' condition: succeededOrFailed() -- template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' - script: | diff --git a/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml b/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml deleted file mode 100644 index a5351a182b7a2..0000000000000 --- a/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml +++ /dev/null @@ -1,47 +0,0 @@ -# component detection for component governance checks -parameters: -- name: condition - type: string - default: 'succeeded' # could be 'ci_only', 'always', 'succeeded' - -steps: -- ${{ if eq(variables['System.TeamProject'], 'Lotus') }}: - - powershell: | - Remove-Item $(Build.BinariesDirectory)/* -Recurse -Force - displayName: 'Clean up build directory' - - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true - condition: - or(or(and(eq('${{parameters.condition}}', 'ci_only'), and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'Scheduled'))), - and(eq('${{parameters.condition}}', 'always'), always())), - and(eq('${{parameters.condition}}', 'succeeded'), succeeded())) - inputs: - # ignore unit tests in emscripten. emscripten unit tests are not used in onnxruntime build - # ignore onnx third_party directory. onnx third_party directory is not responsible for onnxruntime build - # ignore pybind11 third_party directory. pybind11 third_party directory is not responsible for onnxruntime build - # ignore pybind11 tests directory. pybind11 tests directory is not responsible for onnxruntime build - # ignore onnxruntime-extensions directory. onnxruntime-extensions directory is not responsible for onnxruntime build - # ignore react_native e2e node_modules directory. react_native e2e node_modules directory is generated by react_native e2e tests - # ignore js node_modules directory. js node_modules directory is generated by js tests - # ignore onnxruntime-inference-examples directory. onnxruntime-inference-examples directory is used for inference examples, not for onnxruntime package - # ignore BinariesDirectory. BinariesDirectory is used for build output, not for onnxruntime package - ignoreDirectories: - '$(Build.Repository.LocalPath)/cmake/external/emsdk/upstream/emscripten/tests, - $(Build.Repository.LocalPath)/cmake/external/onnx/third_party/benchmark, - $(Build.Repository.LocalPath)/cmake/external/onnx/third_party/pybind11, - $(Build.Repository.LocalPath)/cmake/external/onnx/third_party/pybind11/tests, - $(Build.Repository.LocalPath)/cmake/external/onnxruntime-extensions, - $(Build.Repository.LocalPath)/js/react_native/e2e/node_modules, - $(Build.Repository.LocalPath)/js/node_modules, - $(Build.Repository.LocalPath)/onnxruntime-inference-examples, - $(Build.SourcesDirectory)/cmake/external/emsdk/upstream/emscripten/tests, - $(Build.SourcesDirectory)/cmake/external/onnx/third_party/benchmark, - $(Build.SourcesDirectory)/cmake/external/onnx/third_party/pybind11, - $(Build.SourcesDirectory)/cmake/external/onnx/third_party/pybind11/tests, - $(Build.SourcesDirectory)/cmake/external/onnxruntime-extensions, - $(Build.SourcesDirectory)/js/react_native/e2e/node_modules, - $(Build.SourcesDirectory)/js/node_modules, - $(Build.SourcesDirectory)/onnxruntime-inference-examples, - $(Build.BinariesDirectory)' \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/templates/explicitly-defined-final-tasks.yml b/tools/ci_build/github/azure-pipelines/templates/explicitly-defined-final-tasks.yml index 047445027220a..fa0f5dde4d639 100644 --- a/tools/ci_build/github/azure-pipelines/templates/explicitly-defined-final-tasks.yml +++ b/tools/ci_build/github/azure-pipelines/templates/explicitly-defined-final-tasks.yml @@ -9,9 +9,6 @@ steps: testRunTitle: 'Unit Test Run' condition: succeededOrFailed() -- template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' - script: docker system df && docker system prune -a -f && docker system df displayName: Clean docker images diff --git a/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml b/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml index 900d15a1fa861..5d947b3c34ad7 100644 --- a/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml +++ b/tools/ci_build/github/azure-pipelines/templates/final-jar-testing.yml @@ -95,7 +95,5 @@ stages: - ${{ if eq(parameters['OS'], 'MacOS') }}: - template: use-xcode-version.yml - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index 5e06fc47ea801..0e60bf8e2e26d 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -184,6 +184,3 @@ jobs: searchFolder: '$(Build.BinariesDirectory)' testRunTitle: 'Unit Test Run' condition: and(succeededOrFailed(), eq('${{ parameters.BuildConfig }}', 'Debug')) - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml index a52932205f164..8fcdab437052c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/templates/mac-cpu-packaging-pipeline.yml @@ -137,6 +137,4 @@ stages: artifactName: 'onnxruntime-osx' condition: 'succeededOrFailed()' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + diff --git a/tools/ci_build/github/azure-pipelines/templates/ondevice-training-cpu-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/templates/ondevice-training-cpu-packaging-pipeline.yml index 48b033cad1afb..56f0a6aad7dd0 100644 --- a/tools/ci_build/github/azure-pipelines/templates/ondevice-training-cpu-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/templates/ondevice-training-cpu-packaging-pipeline.yml @@ -297,10 +297,6 @@ stages: msbuildArguments: '-t:Clean -p:OnnxRuntimeBuildDirectory="$(Build.BinariesDirectory)" -p:OrtPackageId=$(OrtPackageId)' workingDirectory: '$(Build.SourcesDirectory)\csharp' - - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' - - template: ../nuget/templates/test_win.yml parameters: diff --git a/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml b/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml index aa47294acac2b..2f7f3989e6055 100644 --- a/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/publish-nuget-steps.yml @@ -132,6 +132,4 @@ stages: publishVstsFeed: '2692857e-05ef-43b4-ba9c-ccf1c22c437c/7982ae20-ed19-4a35-a362-a96ac99897b7' allowPackageConflicts: true - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml index 73da992a121eb..f9d651c79d604 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml @@ -103,6 +103,3 @@ jobs: targetPath: '$(Build.BinariesDirectory)/dist' artifactName: onnxruntime-linux-qnn-x64 - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux.yml index 8d0c4334f4874..313d9c7fd2b1c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-linux.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux.yml @@ -126,6 +126,3 @@ jobs: - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml index b05d542376364..f5c597ab50af9 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml @@ -182,6 +182,3 @@ jobs: GdnPublishTsaOnboard: false GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml index ade5b110f3043..e8665d9d46d41 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml @@ -164,6 +164,3 @@ jobs: GdnPublishTsaOnboard: false GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml index 57361173b8880..8f910e8305b76 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml @@ -155,8 +155,4 @@ jobs: condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) inputs: GdnPublishTsaOnboard: false - GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' - - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' + GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' diff --git a/tools/ci_build/github/azure-pipelines/templates/rocm.yml b/tools/ci_build/github/azure-pipelines/templates/rocm.yml index 1debe9e98eedc..25d58ffe0b29e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/rocm.yml +++ b/tools/ci_build/github/azure-pipelines/templates/rocm.yml @@ -141,8 +141,5 @@ jobs: condition: and(ne(variables['ORT_DISABLE_PYTHON_PACKAGE_LOCAL_VERSION'], 'true'), and(succeeded(), eq(variables['DRY_RUN'], '0'))) displayName: 'Upload Rocm wheel to release repository' - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' - template: clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml index 90670858c8417..eeef3b96edd4c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml +++ b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml @@ -228,7 +228,3 @@ stages: set -e -x ls -R "$(Build.ArtifactStagingDirectory)" displayName: "List staged artifacts" - - - template: ../component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/win-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-ci.yml index e8a1395474634..da869f708418c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-ci.yml @@ -246,10 +246,6 @@ stages: SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' Contents: 'custom_op_library.dll' TargetFolder: '$(Build.ArtifactStagingDirectory)/testdata' - - - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' - ${{ if contains(parameters.ort_build_pool_name, 'GPU') }}: - stage: Windows_Packaging_${{ parameters.stage_name_suffix }}_Testing dependsOn: Windows_Packaging_${{ parameters.stage_name_suffix }} diff --git a/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml index ed1862b78505d..196ea0d7b9ea9 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml @@ -154,6 +154,3 @@ jobs: searchFolder: '$(Build.BinariesDirectory)' testRunTitle: 'Unit Test Run' condition: and(succeededOrFailed(), eq('${{ parameters.BuildConfig }}', 'Debug')) - - template: component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml index 4ae7423803ddf..fecbfc8657894 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-web-ci.yml @@ -307,6 +307,3 @@ jobs: displayName: 'Log Chrome processes (after test)' workingDirectory: '$(Agent.TempDirectory)\web\test' condition: always() - - template: component-governance-component-detection-steps.yml - parameters: - condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/win-ci-fuzz-testing.yml b/tools/ci_build/github/azure-pipelines/win-ci-fuzz-testing.yml index f02e760130ff4..093b4ee7ec50d 100644 --- a/tools/ci_build/github/azure-pipelines/win-ci-fuzz-testing.yml +++ b/tools/ci_build/github/azure-pipelines/win-ci-fuzz-testing.yml @@ -66,7 +66,3 @@ jobs: script: '$(Build.BinariesDirectory)\$(BuildConfig)\$(BuildConfig)\onnxruntime_security_fuzz.exe /t /f "$(Build.BinariesDirectory)\$(BuildConfig)\$(BuildConfig)\testdata\mnist.onnx" 1 m' workingDirectory: $(Build.BinariesDirectory)\$(BuildConfig)\$(BuildConfig) failOnStderr: false # Optional - - - template: templates/component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-reduce-op-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-reduce-op-ci-pipeline.yml index 211541a18546f..bf909ad0605fe 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-reduce-op-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-reduce-op-ci-pipeline.yml @@ -48,7 +48,3 @@ jobs: python $(Build.SourcesDirectory)\tools\ci_build\build.py --config $(BuildConfig) --build_dir $(Build.BinariesDirectory) --skip_submodule_sync --build_shared_lib --test --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --use_cuda --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=75" --include_ops_by_config="$(Build.SourcesDirectory)\onnxruntime\test\testdata\required_ops.config" workingDirectory: '$(Build.BinariesDirectory)\$(BuildConfig)\$(BuildConfig)' displayName: 'Run tests' - - - template: templates/component-governance-component-detection-steps.yml - parameters : - condition : 'succeeded' From bd00c39f36bcab79ce44f27042bb5112064aa367 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 10:19:18 -0700 Subject: [PATCH 184/266] Move Linux ARM64 CI pipeline and Linux DNNL CI pipeline to Github Actions (#24190) ### Description 1. Move Linux ARM64 CI pipeline and Linux DNNL CI pipeline to Github Actions 2. Refactor .github/workflows/linux_training.yml to use a template ### Motivation and Context --- .github/workflows/linux-dnnl.yml | 32 +++ .github/workflows/linux_ci.yml | 225 +++++++----------- .github/workflows/linux_training.yml | 55 ----- .github/workflows/reusable_linux_build.yml | 143 +++++++++++ onnxruntime/test/providers/cpu/model_tests.cc | 1 + .../azure-pipelines/linux-ci-pipeline.yml | 72 ------ .../linux-dnnl-ci-pipeline.yml | 84 ------- 7 files changed, 259 insertions(+), 353 deletions(-) create mode 100644 .github/workflows/linux-dnnl.yml delete mode 100644 .github/workflows/linux_training.yml create mode 100644 .github/workflows/reusable_linux_build.yml delete mode 100644 tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml diff --git a/.github/workflows/linux-dnnl.yml b/.github/workflows/linux-dnnl.yml new file mode 100644 index 0000000000000..9ef2efd9792df --- /dev/null +++ b/.github/workflows/linux-dnnl.yml @@ -0,0 +1,32 @@ +# This workflow builds and tests the ONNX Runtime for Linux for DNNL EP +# It leverages a reusable workflow (`reusable_linux_build.yml`) to handle the core build and test logic +# within Docker containers, ensuring a consistent environment. +# This file is very similar to linux_ci.yml, but much simpler + + +name: Linux CI + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main, 'rel-*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-linux-x64-release-dnnl: + name: Build Linux x64 Release (DNNL EP) + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + docker_image_repo: onnxruntimecpubuildpythonx64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --build_nuget --use_dnnl' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_ci.yml b/.github/workflows/linux_ci.yml index 26a6125ca92a1..c3986a098ea37 100644 --- a/.github/workflows/linux_ci.yml +++ b/.github/workflows/linux_ci.yml @@ -1,23 +1,21 @@ -# This workflow builds and tests the ONNX Runtime for Linux in both Debug and Release configurations. -# It uses a Docker container to provide a consistent build environment. +# This workflow builds and tests the ONNX Runtime for Linux on multiple architectures and configurations. +# It leverages a reusable workflow (`reusable_linux_build.yml`) to handle the core build and test logic +# within Docker containers, ensuring a consistent environment. # -# The workflow consists of two jobs: -# - build-debug: Builds and tests the Debug configuration. -# - Uses the 'Debug' build configuration. -# - Enables AddressSanitizer for memory error detection. -# - Builds and runs tests. -# - build-release: Builds and tests the Release configuration. -# - Uses the 'Release' build configuration. -# - Includes additional flags for release builds: -# - --use_binskim_compliant_compile_flags -# - --build_wheel -# - --build_csharp -# - --enable_transformers_tool_test -# - --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON -# - Builds and runs tests. +# The workflow consists of five parallel jobs targeting different combinations: +# - build-linux-x64-debug: Builds/tests Debug config on Linux x64 (AMD CPU pool), enables AddressSanitizer. +# - build-linux-x64-release: Builds/tests Release config on Linux x64 (AMD CPU pool), includes wheel/nuget/benchmark flags. +# - orttraining-linux-ci-pipeline: Builds/tests Release config with Training enabled (--enable_training) on Linux x64 (AMD CPU pool). +# - build-linux-arm64-debug: Builds/tests Debug config on Linux arm64 (ARM CPU pool); ASan is disabled due to excessive runtime. Includes wheel build. +# - build-linux-arm64-release: Builds/tests Release config on Linux arm64 (ARM CPU pool), includes wheel/benchmark flags. # -# The two jobs run in parallel to reduce the overall build time. -# Both jobs use the same Docker image, built in a separate step. +# Each job calls the reusable workflow, passing specific parameters: +# - target architecture (x64 or arm64) +# - build configuration (Debug or Release) +# - runner pool name +# - path to the appropriate Dockerfile +# - Docker image name for caching/use +# - configuration-specific build flags (e.g., --enable_address_sanitizer, --enable_training, --build_wheel) name: Linux CI @@ -32,131 +30,74 @@ concurrency: cancel-in-progress: true jobs: - linux-cpu-asan-debug: # Job for building and testing the Debug configuration - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] - permissions: - actions: read - contents: read + # --- x64 Builds --- + build-linux-x64-debug: + name: Build Linux x64 Debug (ASan) + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Debug + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + docker_image_repo: onnxruntimecpubuildcix64 + extra_build_flags: '--enable_address_sanitizer' + # python_path_prefix: '' # Default empty string is fine, no prefix needed + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Checkout code - uses: actions/checkout@v3 + build-linux-x64-release: + name: Build Linux x64 Release + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + docker_image_repo: onnxruntimecpubuildpythonx64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' # $ needs escaping in single quotes + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Set up Python 3.x - uses: actions/setup-python@v4 - with: - python-version: '3.x' + orttraining-linux-ci-pipeline: + name: Build Linux x64 Release with training + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + docker_image_repo: onnxruntimecpubuildpythonx64 # Shares image with standard x64 release + extra_build_flags: '--enable_training --use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' # $ needs escaping in single quotes + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Build Docker Image - uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.1 - with: - Dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile - Repository: 'onnxruntimecpubuildcentos8x64' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for context + # --- arm64 Builds --- + build-linux-arm64-debug: + name: Build Linux arm64 Debug + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-ARM-CPU" + build_config: Debug + architecture: arm64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile + docker_image_repo: onnxruntimecpubuildciaarch64 + # ASan disabled due to excessive runtime (>4hr). Includes wheel build for basic checks. + extra_build_flags: '--use_binskim_compliant_compile_flags --build_shared_lib' + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create .onnx directory - run: mkdir -p $HOME/.onnx - - # Build and Test ONNX Runtime in Docker (Debug) - - name: Build and Test ONNX Runtime in Docker (Debug) - env: - ALLOW_RELEASED_ONNX_OPSET_ONLY: 0 - NIGHTLY_BUILD: 1 # Assuming you want nightly build for both Debug and Release - run: | - docker run --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume /data/models:/data/models:ro \ - --volume ${{ github.workspace }}:/onnxruntime_src \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -w /onnxruntime_src \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ - -e NIGHTLY_BUILD \ - onnxruntimecpubuildcentos8x64 \ - /bin/bash -c 'set -ex; \ - # Build with Debug configuration and AddressSanitizer enabled - python3 tools/ci_build/build.py \ - --build_dir build/Debug --cmake_generator Ninja \ - --config Debug \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel \ - --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests \ - --enable_address_sanitizer \ - --update --build; - # Run tests with Debug configuration - python3 tools/ci_build/build.py \ - --build_dir build/Debug --cmake_generator Ninja \ - --config Debug \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel \ - --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests \ - --enable_address_sanitizer \ - --test;' - - linux-cpu-release: # Job for building and testing the Release configuration - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] - permissions: - actions: read - contents: read - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Python 3.x - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Build Docker Image - uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.1 - with: - Dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu - Repository: 'onnxruntimecpubuild' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for context - - - name: Create .onnx directory - run: mkdir -p $HOME/.onnx - # Build and Test ONNX Runtime in Docker (Release) - - name: Build and Test ONNX Runtime in Docker (Release) - env: - ALLOW_RELEASED_ONNX_OPSET_ONLY: 0 - NIGHTLY_BUILD: 1 - run: | - docker run --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume /data/models:/data/models:ro \ - --volume ${{ github.workspace }}:/onnxruntime_src \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -w /onnxruntime_src \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ - -e NIGHTLY_BUILD \ - onnxruntimecpubuild \ - /bin/bash -c 'set -ex; \ - # Build with Release configuration and additional flags for release builds - PATH=/opt/python/cp310-cp310/bin:$PATH python3 tools/ci_build/build.py \ - --build_dir build/Release --cmake_generator Ninja \ - --config Release \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel \ - --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests \ - --use_binskim_compliant_compile_flags --build_wheel --build_csharp --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON \ - --update --build; - # Run tests with Release configuration - PATH=/opt/python/cp310-cp310/bin:$PATH python3 tools/ci_build/build.py \ - --build_dir build/Release --cmake_generator Ninja \ - --config Release \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel \ - --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests \ - --use_binskim_compliant_compile_flags --build_wheel --build_csharp --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON \ - --test;' \ No newline at end of file + build-linux-arm64-release: + name: Build Linux arm64 Release + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-ARM-CPU" + build_config: Release + architecture: arm64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/Dockerfile + docker_image_repo: onnxruntimecpubuildpythonaarch64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' # $ needs escaping in single quotes + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_training.yml b/.github/workflows/linux_training.yml deleted file mode 100644 index d382cdf476283..0000000000000 --- a/.github/workflows/linux_training.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: orttraining-linux-ci-pipeline -on: - push: - branches: - - main - - rel-* - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - orttraining-linux-ci-pipeline: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] - permissions: - actions: read - contents: read - security-events: write - steps: - - uses: actions/checkout@v4 - - run: | - python3 -m pip install --user -r tools/ci_build/github/linux/python/requirements.txt - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - config-file: ./.github/codeql/codeql-config.yml - languages: 'cpp' - - run: | - set -e -x - rm -rf build - python3 tools/ci_build/build.py --build_dir build --config Release --enable_training --skip_submodule_sync --parallel --update --build - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:cpp" - output: sarif-results - upload: failure-only - - - name: filter-sarif - uses: advanced-security/filter-sarif@v1 - with: - patterns: | - +**/*.cc - +**/*.h - -tests/**/*.* - -build/**/*.* - input: sarif-results/cpp.sarif - output: sarif-results/cpp.sarif - - - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: sarif-results/cpp.sarif \ No newline at end of file diff --git a/.github/workflows/reusable_linux_build.yml b/.github/workflows/reusable_linux_build.yml new file mode 100644 index 0000000000000..cf5c34a064965 --- /dev/null +++ b/.github/workflows/reusable_linux_build.yml @@ -0,0 +1,143 @@ +name: Reusable Linux CPU Build and Test + +on: + workflow_call: + inputs: + pool_name: + description: 'The specific 1ES pool name (e.g., onnxruntime-github-Ubuntu2204-AMD-CPU)' + required: true + type: string + build_config: + description: 'Build configuration (Debug or Release)' + required: true + type: string + architecture: + description: 'Target architecture (x64 or arm64)' + required: true + type: string + dockerfile_path: + description: 'Path to the Dockerfile relative to the workspace root' + required: true + type: string + docker_image_repo: + description: 'Name for the Docker image repository' + required: true + type: string + extra_build_flags: + description: 'Additional flags for the build.py script' + required: false + type: string + default: '' + python_path_prefix: + description: 'Optional prefix to add to the PATH for python command (e.g., PATH=/opt/python/cp310-cp310/bin:$PATH)' + required: false + type: string + default: '' + python_version: + description: 'Python version to set up' + required: false + type: string + default: '3.x' # Use a sensible default + secrets: + GH_TOKEN: + description: 'GitHub token for accessing actions/packages' + required: true + +jobs: + build_and_test: + runs-on: + - self-hosted + - "1ES.Pool=${{ inputs.pool_name }}" + permissions: + contents: read + packages: read # Change to write when migrating to GHCR + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python ${{ inputs.python_version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python_version }} + + - name: Build Docker Image (${{ inputs.architecture }} / ${{ inputs.build_config }}) + uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.1 + with: + Dockerfile: ${{ github.workspace }}/${{ inputs.dockerfile_path }} + Repository: ${{ inputs.docker_image_repo }} + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + + - name: Create .onnx directory + run: mkdir -p $HOME/.onnx + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + # ------------- Main Build and Test Step ------------- + - name: Build and Test ONNX Runtime in Docker (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: build_test # Add an ID to potentially reference its outcome if needed, though `if: failure()` is simpler + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: 0 + NIGHTLY_BUILD: 1 + run: | + set -ex + # Construct the build command + BUILD_CMD="${{ inputs.python_path_prefix }} python3 tools/ci_build/build.py \ + --build_dir build/${{ inputs.build_config }} --cmake_generator Ninja \ + --config ${{ inputs.build_config }} \ + --skip_submodule_sync \ + --build_shared_lib \ + --parallel \ + --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ + --enable_onnx_tests \ + ${{ inputs.extra_build_flags }}" # Add extra flags here + + # Execute build + docker run --rm \ + --volume /data/onnx:/data/onnx:ro \ + --volume /data/models:/data/models:ro \ + --volume ${{ github.workspace }}:/onnxruntime_src \ + --volume ${{ runner.temp }}:/onnxruntime_src/build \ + --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ + -w /onnxruntime_src \ + -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ + -e NIGHTLY_BUILD \ + -e ACTIONS_RUNTIME_TOKEN \ + -e ACTIONS_CACHE_URL \ + -e RUNNER_TEMP=/onnxruntime_src/build \ + ${{ inputs.docker_image_repo }} \ + /bin/bash -c "${BUILD_CMD} --update --build" + + # Execute test (using the same base command but adding --test) + docker run --rm \ + --volume /data/onnx:/data/onnx:ro \ + --volume /data/models:/data/models:ro \ + --volume ${{ github.workspace }}:/onnxruntime_src \ + --volume ${{ runner.temp }}:/onnxruntime_src/build \ + --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ + -w /onnxruntime_src \ + -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ + -e NIGHTLY_BUILD \ + -e ACTIONS_RUNTIME_TOKEN \ + -e ACTIONS_CACHE_URL \ + -e RUNNER_TEMP=/onnxruntime_src/build \ + ${{ inputs.docker_image_repo }} \ + /bin/bash -c "${BUILD_CMD} --test" + # ------------- End Main Build and Test Step ------------- + + # ------------- Upload Log on Failure Step ------------- + - name: Upload VCPKG Manifest Install Log on Failure + if: failure() # This step only runs if the previous steps (like build_test) failed + uses: actions/upload-artifact@v4 + with: + name: vcpkg-manifest-install-log-${{ inputs.architecture }}-${{ inputs.build_config }} # Descriptive artifact name + # Use the exact path provided in the request + path: ${{ github.workspace }}/build/${{ inputs.build_config }}/${{ inputs.build_config }}/vcpkg-manifest-install.log + if-no-files-found: ignore + # ------------- End Upload Log on Failure Step ------------- diff --git a/onnxruntime/test/providers/cpu/model_tests.cc b/onnxruntime/test/providers/cpu/model_tests.cc index e3c86a137484f..fa6b8b7e2274d 100644 --- a/onnxruntime/test/providers/cpu/model_tests.cc +++ b/onnxruntime/test/providers/cpu/model_tests.cc @@ -619,6 +619,7 @@ ::std::vector<::std::basic_string> GetParameterStrings() { ORT_TSTR("resnet101v2"), ORT_TSTR("resnet101v2"), ORT_TSTR("vgg19"), + ORT_TSTR("dequantizelinear"), ORT_TSTR("tf_inception_resnet_v2"), ORT_TSTR("tf_inception_v1"), ORT_TSTR("tf_inception_v3"), diff --git a/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml deleted file mode 100644 index 17c5af6480308..0000000000000 --- a/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml +++ /dev/null @@ -1,72 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -stages: -- stage: arm64_build - dependsOn: [] - jobs: - - template: templates/py-linux.yml - parameters: - arch: 'aarch64' - machine_pool: 'onnxruntime-linux-ARM64-CPU-2019' - with_cache: true - cmake_build_type: Release - python_exe_path: '/opt/python/cp310-cp310/bin/python3.10' - -- stage: arm64_test - dependsOn: ['arm64_build'] - jobs: - - template: templates/py-packaging-linux-test-cpu.yml - parameters: - arch: 'aarch64' - ep: 'cpu' - machine_pool: 'onnxruntime-linux-ARM64-CPU-2019' - -- stage: arm64_build_xnnpack - dependsOn: [] - jobs: - - template: templates/py-linux.yml - parameters: - arch: 'aarch64' - machine_pool: 'onnxruntime-linux-ARM64-CPU-2019' - with_cache: true - cmake_build_type: Release - ep: 'XNNPack' - extra_build_arg: '--use_xnnpack' - python_exe_path: '/opt/python/cp310-cp310/bin/python3.10' - -- stage: arm64_test_xnnpack - dependsOn: ['arm64_build_xnnpack'] - jobs: - - template: templates/py-packaging-linux-test-cpu.yml - parameters: - arch: 'aarch64' - ep: 'XNNPack' - machine_pool: 'onnxruntime-linux-ARM64-CPU-2019' diff --git a/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml deleted file mode 100644 index eafab4829a8db..0000000000000 --- a/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml +++ /dev/null @@ -1,84 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### - -jobs: -- job: Linux_py_Wheels - timeoutInMinutes: 180 - variables: - skipComponentGovernanceDetection: true - workspace: - clean: all - pool: Linux-CPU-2019 - steps: - - checkout: self - clean: true - submodules: none - - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu - Context: tools/ci_build/github/linux/docker - DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" - Repository: onnxruntimecpubuild - - - task: CmdLine@2 - displayName: 'Build and test' - inputs: - script: | - mkdir -p $HOME/.onnx - docker run -e SYSTEM_COLLECTIONURI --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - onnxruntimecpubuild \ - bash -c 'PATH=/opt/python/cp310-cp310/bin:$PATH python /onnxruntime_src/tools/ci_build/build.py \ - --build_dir /build \ - --config Debug Release \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_pybind \ - --enable_onnx_tests \ - --build_java \ - --use_dnnl' - workingDirectory: $(Build.SourcesDirectory) - - - task: PublishTestResults@2 - displayName: 'Publish unit test results' - inputs: - testResultsFiles: '**/*.results.xml' - searchFolder: '$(Build.BinariesDirectory)' - testRunTitle: 'Unit Test Run' - condition: succeededOrFailed() - From 86b4c7897ed4bbb6f49eeff333121327910c1643 Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Fri, 28 Mar 2025 02:08:11 +0800 Subject: [PATCH 185/266] [webgpu-ep] Fix test_batchnorm_example (#24184) This fixes the missing component handling for the input and output variables in BatchNorm operator. --- .../core/providers/webgpu/nn/batch_norm.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/nn/batch_norm.cc b/onnxruntime/core/providers/webgpu/nn/batch_norm.cc index 687f8cb0c684b..ae4057bdea173 100644 --- a/onnxruntime/core/providers/webgpu/nn/batch_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/batch_norm.cc @@ -104,6 +104,7 @@ Status BatchNormalization::ComputeInternal(ComputeContext& context) con const TensorShape& input_shape = input_tensor->Shape(); size_t input_rank = input_shape.NumDimensions(); const int components = spatial_ ? ((input_shape[input_rank - 1] % 4 == 0) ? 4 : ((input_shape[input_rank - 1] % 2 == 0) ? 2 : 1)) : 1; + const int c_components = is_nhwc && input_rank > 1 ? components : 1; auto output_dims = input_shape.AsShapeVector(); TensorShape output_shape(output_dims); @@ -123,16 +124,17 @@ Status BatchNormalization::ComputeInternal(ComputeContext& context) con BatchNormalizationProgram program{epsilon_, spatial_, format_, static_cast(components)}; program - .AddInputs({{input_tensor, ProgramTensorMetadataDependency::TypeAndRank}, - {scale, ProgramTensorMetadataDependency::TypeAndRank}, - {B, ProgramTensorMetadataDependency::TypeAndRank}, - {input_mean, ProgramTensorMetadataDependency::TypeAndRank}, - {input_var, ProgramTensorMetadataDependency::TypeAndRank}}) - .AddOutputs({output_tensor}) + .CacheHint(epsilon_, spatial_, format_, components) + .AddInputs({{input_tensor, ProgramTensorMetadataDependency::TypeAndRank, components}, + {scale, ProgramTensorMetadataDependency::TypeAndRank, c_components}, + {B, ProgramTensorMetadataDependency::TypeAndRank, c_components}, + {input_mean, ProgramTensorMetadataDependency::TypeAndRank, c_components}, + {input_var, ProgramTensorMetadataDependency::TypeAndRank, c_components}}) + .AddOutputs({{output_tensor, ProgramTensorMetadataDependency::TypeAndRank, components}}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) .AddUniformVariables({{static_cast(output_size)}}); return context.RunProgram(program); } } // namespace webgpu -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime From 2656671064a83564ddf5766f3449c2406259c3ef Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 27 Mar 2025 11:11:41 -0700 Subject: [PATCH 186/266] Further reduce work load for Mac CI pipeline (#24197) ### Description Further reduce work load for Mac CI pipeline ### Motivation and Context --- .github/workflows/mac.yml | 12 ++++++++ .../macos-ci-build-and-test-workflow.yml | 29 +++++++++---------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index e2f45712f6f9f..8fcc53bbd9991 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -21,6 +21,12 @@ env: jobs: cpu: uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + # Only build arm64 for CPU + matrix_exclude: >- + [ + {"platform_machine": "x86_64"} + ] coreml: uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml @@ -31,6 +37,12 @@ jobs: uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml with: use_xnnpack: true + # only build arm64/Debug for XNNPack + matrix_exclude: >- + [ + {"platform_machine": "x86_64"}, + {"platform_machine": "arm64", "build_config": "Release"} + ] webgpu: uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml diff --git a/.github/workflows/macos-ci-build-and-test-workflow.yml b/.github/workflows/macos-ci-build-and-test-workflow.yml index 52a284a40488d..eb8d4ad76d964 100644 --- a/.github/workflows/macos-ci-build-and-test-workflow.yml +++ b/.github/workflows/macos-ci-build-and-test-workflow.yml @@ -20,6 +20,16 @@ on: required: false type: string default: "3.11" + matrix_exclude: + required: false + type: string + description: "JSON string specifying combinations to exclude from the matrix" + # we do not have enough resources to run all combinations + # Exclude x86_64 + Debug combination by default + default: >- + [ + {"platform_machine": "x86_64", "build_config": "Debug"} + ] jobs: build-and-test: @@ -27,21 +37,9 @@ jobs: matrix: platform_machine: ["x86_64", "arm64"] build_config: ["Debug", "Release"] - exclude: - # we do not have enough resources to run all combinations - # Exclude x86_64 + Debug combination - - platform_machine: "x86_64" - build_config: "Debug" - include: - - platform_machine: "x86_64" - runs_on: "macos-13" - xcode_version: "14.3.1" - - platform_machine: "arm64" - runs_on: "macos-15" - xcode_version: "16" - max-parallel: 1 + exclude: ${{ fromJSON(inputs.matrix_exclude) }} - runs-on: ${{ matrix.runs_on }} + runs-on: ${{ matrix.platform_machine == 'x86_64' && 'macos-13' || 'macos-15' }} env: build_flags: > --build_dir ./build @@ -58,6 +56,7 @@ jobs: ${{ inputs.use_coreml && '--use_coreml' || '' }} --use_vcpkg --use_vcpkg_ms_internal_asset_cache --config ${{ matrix.build_config }} + xcode_version: ${{ matrix.platform_machine == 'x86_64' && '14.3.1' || '16' }} steps: - name: Checkout code @@ -68,7 +67,7 @@ jobs: with: platform_machine: ${{ matrix.platform_machine }} python_version: ${{ inputs.python_version }} - xcode_version: ${{ matrix.xcode_version }} + xcode_version: ${{ env.xcode_version }} use_cache: true - uses: actions/cache@v3 From 64b0d071a7ce4f42495b663aec993d3e12fbc5d8 Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Thu, 27 Mar 2025 15:05:51 -0700 Subject: [PATCH 187/266] Generate unique names for SliceSplit fusion. (#24217) ### Description Generate unique name for fused Split nodes. ### Motivation and Context The bug is manifested when the model features more than one Slice to Split fusion patterns and the nodes of the graph are nameless. This addresses https://github.com/microsoft/onnxruntime/issues/24203. --- onnxruntime/core/optimizer/gather_fusion.cc | 3 ++- .../test/optimizer/graph_transform_test.cc | 12 ++++++++++++ onnxruntime/test/testdata/gh_issue_24203.onnx | Bin 0 -> 904 bytes 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 onnxruntime/test/testdata/gh_issue_24203.onnx diff --git a/onnxruntime/core/optimizer/gather_fusion.cc b/onnxruntime/core/optimizer/gather_fusion.cc index 2bde320786130..9732ec2587b2a 100644 --- a/onnxruntime/core/optimizer/gather_fusion.cc +++ b/onnxruntime/core/optimizer/gather_fusion.cc @@ -273,7 +273,8 @@ Status GatherSliceToSplitFusion::ApplyImpl(Graph& graph, bool& modified, int gra split_initializer_proto.add_dims(static_cast(split_values.size())); split_initializer_proto.mutable_int64_data()->Add(split_values.begin(), split_values.end()); NodeArg* split_initializer_arg = &graph_utils::AddInitializer(graph, split_initializer_proto); - Node& split_node = graph.AddNode(nodes_to_fuse[0].get().Name() + "/GatherSliceToSplitFusion/", "Split", "Split for Fused Gather nodes", + const auto split_node_name = graph.GenerateNodeName(nodes_to_fuse[0].get().Name() + "/GatherSliceToSplitFusion"); + Node& split_node = graph.AddNode(split_node_name, "Split", "Split for Fused Gather nodes", {graph.GetNodeArg(node_arg->Name()), split_initializer_arg}, split_outputs); split_node.AddAttribute("axis", axis); split_node.SetExecutionProviderType(nodes_to_fuse[0].get().GetExecutionProviderType()); diff --git a/onnxruntime/test/optimizer/graph_transform_test.cc b/onnxruntime/test/optimizer/graph_transform_test.cc index eeb5deb268c5a..a66964de17c72 100755 --- a/onnxruntime/test/optimizer/graph_transform_test.cc +++ b/onnxruntime/test/optimizer/graph_transform_test.cc @@ -7700,6 +7700,18 @@ TEST_F(GraphTransformationTests, GatherSliceToSplitFusion_AllSlice_GraphInput) { 1, pre_graph_checker, post_graph_checker)); } +TEST_F(GraphTransformationTests, GatherSliceToSplitFusion_AllSlice_GraphInput_gh_issue_24203) { + // https://github.com/microsoft/onnxruntime/issues/24203 + // This bug is manifested when the model features nameless nodes and there are more than one + // SliceToSplitFusion resulting in multiple Split nodes with the same name. + const PathString CUSTOM_OP_MODEL_URI = ORT_TSTR("testdata/gh_issue_24203.onnx"); + SessionOptions session_options; + session_options.graph_optimization_level = TransformerLevel::Level2; + InferenceSession session(session_options, GetEnvironment()); + ASSERT_STATUS_OK(session.Load(CUSTOM_OP_MODEL_URI)); + ASSERT_STATUS_OK(session.Initialize()); +} + TEST_F(GraphTransformationTests, GatherSliceToSplitFusion_Combined) { auto build_test_case = [&](ModelTestBuilder& builder) { auto* data_arg = builder.MakeInput({{144}}); diff --git a/onnxruntime/test/testdata/gh_issue_24203.onnx b/onnxruntime/test/testdata/gh_issue_24203.onnx new file mode 100644 index 0000000000000000000000000000000000000000..535b79f65cf700940493fb07841317a3dd59968d GIT binary patch literal 904 zcmdG3H`~gAqY=1plo;p4Bp?O=N*BpI literal 0 HcmV?d00001 From 259214768adc2545f570643c43e44d2de8e2bdd6 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 28 Mar 2025 07:33:48 -0700 Subject: [PATCH 188/266] Fix the pipeline that failed because of vcpkg (#24226) ### Description - Pin VCPKG version for Github Actions pipelines - Update NDK to 28 because cmake 4.0 dropped the support for NDK 27. - Disable vcpkg temporarily for 2 ADO pipelines. --- .../locate-vcvarsall-and-setup-env/action.yml | 27 ++++++++++++++++++- .github/workflows/android.yml | 4 +-- tools/android_custom_build/Dockerfile | 2 +- .../templates/use-android-ndk.yml | 2 +- .../win-gpu-doc-gen-ci-pipeline.yml | 2 +- .../azure-pipelines/win-qnn-ci-pipeline.yml | 2 +- 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.github/actions/locate-vcvarsall-and-setup-env/action.yml b/.github/actions/locate-vcvarsall-and-setup-env/action.yml index b1e09e7d17f9e..f652a98ed2fe5 100644 --- a/.github/actions/locate-vcvarsall-and-setup-env/action.yml +++ b/.github/actions/locate-vcvarsall-and-setup-env/action.yml @@ -12,6 +12,31 @@ outputs: runs: using: "composite" steps: + - name: Download ORT Actions Asset (v0.0.3) + uses: dsaltares/fetch-gh-release-asset@1.1.0 # Action to download assets + with: + repo: 'microsoft/onnxruntime-github-actions' # The repo containing the actions + version: 'tags/v0.0.3' # The specific tag/version to use + file: 'onnxruntime-actions-v0.0.3.zip' # The asset filename (matches release workflow output) + target: 'onnxruntime-actions.zip' # Local filename to save as + + - name: Unzip ORT Actions (Windows) + shell: pwsh + run: | + # Create a directory to hold them (-Force acts like -p, creates parents if needed) + New-Item -Path '.\.github\_downloaded_actions' -ItemType Directory -Force + # Unzip the archive to the target directory + Expand-Archive -Path '.\onnxruntime-actions.zip' -DestinationPath '.\.github\_downloaded_actions' -Force + Write-Host "Unzipped contents:" + # List the contents recursively (Windows equivalent of ls -lR) + Get-ChildItem -Path '.\.github\_downloaded_actions' -Recurse + + - name: Setup VCPKG + uses: ./.github/_downloaded_actions/setup-vcpkg + with: + vcpkg-version: '2025.03.19' + vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' + - name: Find vcvarsall.bat id: find-vcvarsall shell: python # Use Python shell @@ -60,4 +85,4 @@ runs: set > final_env.txt REM Call the Python script to update the GitHub Actions environment - python ${{ github.action_path }}\update_environment.py \ No newline at end of file + python ${{ github.action_path }}\update_environment.py diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 64c40946c49c5..0e06f8707da5f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -32,7 +32,7 @@ jobs: - name: Setup Android NDK uses: ./.github/actions/setup-android-ndk with: - ndk-version: 27.2.12479018 + ndk-version: 28.0.13004108 - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 @@ -101,7 +101,7 @@ jobs: - name: Setup Android NDK uses: ./.github/actions/setup-android-ndk with: - ndk-version: 27.2.12479018 + ndk-version: 28.0.13004108 - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 diff --git a/tools/android_custom_build/Dockerfile b/tools/android_custom_build/Dockerfile index cc8de631aacec..dddd8995ba7d1 100644 --- a/tools/android_custom_build/Dockerfile +++ b/tools/android_custom_build/Dockerfile @@ -55,7 +55,7 @@ WORKDIR /workspace # install Android SDK and tools ENV ANDROID_HOME=~/android-sdk -ENV NDK_VERSION=27.2.12479018 +ENV NDK_VERSION=28.0.13004108 ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/${NDK_VERSION} RUN aria2c -q -d /tmp -o cmdline-tools.zip \ diff --git a/tools/ci_build/github/azure-pipelines/templates/use-android-ndk.yml b/tools/ci_build/github/azure-pipelines/templates/use-android-ndk.yml index 50832d1bf1f8b..81a53499bfc98 100644 --- a/tools/ci_build/github/azure-pipelines/templates/use-android-ndk.yml +++ b/tools/ci_build/github/azure-pipelines/templates/use-android-ndk.yml @@ -3,7 +3,7 @@ parameters: - name: AndroidNdkVersion type: string - default: "27.2.12479018" # LTS version + default: "28.0.13004108" # LTS version steps: - bash: | diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml index 3b98eae952ed1..c20f4a2c1bd19 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml @@ -50,7 +50,7 @@ stages: additionalBuildFlags: >- --gen_doc validate --skip_tests --build_wheel --use_dml --use_cuda --cuda_home="$(Agent.TempDirectory)\v${{ parameters.CudaVersion }}" - --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF msbuildPlatform: x64 isX86: false diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml index 01c44da39905a..eea2af585595a 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml @@ -78,7 +78,7 @@ jobs: --build_dir $(Build.BinariesDirectory) --cmake_generator "Visual Studio 17 2022" --build_java - --build_shared_lib --use_vcpkg --use_vcpkg_ms_internal_asset_cache + --build_shared_lib --use_qnn $(QnnLibKind) --qnn_home $(QnnSDKRootDir) --use_binskim_compliant_compile_flags From c756e0abd755fc823417472f68028de58f06e5c3 Mon Sep 17 00:00:00 2001 From: Peishen Yan Date: Sat, 29 Mar 2025 00:59:45 +0800 Subject: [PATCH 189/266] Improve Shape Inference for GQA (#24143) ### Description For GroupQueryAttention op, if the input total_sequence_length is a constant, we can infer the shape of output present_key/present_value `(batch_size, kv_num_heads, present_sequence_length, head_size)`. https://github.com/microsoft/onnxruntime/blob/5ed900e9712ce2f02e40c15b945d18453d1960d8/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h#L185 We know that from CPU EP, `present_sequence_length = max(past_sequence_length, total_sequence_length)`, and `batch_size, kv_num_heads, head_size` are the same as past_key/past_value. This inference is very important for WebNN EP, because WebNN only supports GQA for `present_sequence_length == past_sequence_length` and requires static shape for graph compilation. ### Motivation and Context --- .../core/graph/contrib_ops/bert_defs.cc | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/onnxruntime/core/graph/contrib_ops/bert_defs.cc b/onnxruntime/core/graph/contrib_ops/bert_defs.cc index bdcc93692379a..abfd93e13ca3b 100644 --- a/onnxruntime/core/graph/contrib_ops/bert_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/bert_defs.cc @@ -309,6 +309,29 @@ void BaseGroupQueryAttentionTypeAndShapeInference(ONNX_NAMESPACE::InferenceConte // shape of present key/value is (batch_size, kv_num_heads, total_sequence_length, head_size) present_shape.mutable_dim(2)->set_dim_value(total_sequence_length); + updateOutputShape(ctx, 1, present_shape); + updateOutputShape(ctx, 2, present_shape); + } + } else if (use_max_past_present_buffer == -1) { + const auto* total_sequence_length_data = ctx.getInputData(6); + if (total_sequence_length_data != nullptr && past_dims[2].has_dim_value()) { + int64_t total_sequence_length_value = 0; + const auto& data = ParseData(total_sequence_length_data); + total_sequence_length_value = static_cast(data[0]); + + // present_sequence_length = max(past_sequence_length, total_sequence_length) + int64_t present_sequence_length = total_sequence_length_value > past_dims[2].dim_value() + ? total_sequence_length_value + : past_dims[2].dim_value(); + + ONNX_NAMESPACE::TensorShapeProto present_shape; + for (auto& dim : past_dims) { + *present_shape.add_dim() = dim; + } + + // shape of present key/value is (batch_size, kv_num_heads, present_sequence_length, head_size) + present_shape.mutable_dim(2)->set_dim_value(present_sequence_length); + updateOutputShape(ctx, 1, present_shape); updateOutputShape(ctx, 2, present_shape); } From 19d8d69c6692f43ed6e03bfa177aeb6548db5008 Mon Sep 17 00:00:00 2001 From: Caroline Zhu Date: Fri, 28 Mar 2025 10:59:55 -0700 Subject: [PATCH 190/266] Add React Native namespace back in for iOS (#24218) ### Description - adds react native namespace back in to the androidmanifest.xml ### Motivation and Context - reverses [this commit](https://github.com/microsoft/onnxruntime/commit/d8ed4da1dfee781919247d9ce001f246489c8f90) - missed [this comment](https://github.com/microsoft/onnxruntime/blob/2656671064a83564ddf5766f3449c2406259c3ef/js/react_native/android/build.gradle#L141) that explains that androidmanifest.xml is used for iOS while androidmanifestnew.xml is used for android --- js/react_native/android/src/main/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/react_native/android/src/main/AndroidManifest.xml b/js/react_native/android/src/main/AndroidManifest.xml index a2f47b6057db7..8713bb2c6b8cd 100644 --- a/js/react_native/android/src/main/AndroidManifest.xml +++ b/js/react_native/android/src/main/AndroidManifest.xml @@ -1,2 +1,3 @@ - + From 180ba8f849d08fff0f4e69eb410b6078e5ed4a69 Mon Sep 17 00:00:00 2001 From: liqun Fu Date: Fri, 28 Mar 2025 12:10:59 -0700 Subject: [PATCH 191/266] RoPE fp16 avx (#23772) ### Description RoPE to work with fp16 data types ### Motivation and Context this is need to improve GQA --------- Signed-off-by: liqunfu Signed-off-by: Liqun Fu Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- cmake/onnxruntime_mlas.cmake | 4 +- .../mlas/lib/rotary_embedding_kernel_avx2.cpp | 283 +++++++++- .../mlas/lib/rotary_embedding_kernel_avx2.h | 10 + .../lib/rotary_embedding_kernel_avx2_fp32.cpp | 166 ------ onnxruntime/test/mlas/bench/bench_rope.cpp | 34 +- onnxruntime/test/mlas/unittest/test_rope.cpp | 52 +- .../test/python/transformers/test_gqa_cpu.py | 489 +++++++++--------- 7 files changed, 592 insertions(+), 446 deletions(-) delete mode 100644 onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2_fp32.cpp diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index 9b468da44928e..98f2a9b099dad 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -192,7 +192,7 @@ function(setup_mlas_source_for_windows) ${mlas_platform_srcs_avx2} ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.h ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp - ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2_fp32.cpp + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp ${MLAS_SRC_DIR}/qgemm_kernel_amx.cpp ${MLAS_SRC_DIR}/qgemm_kernel_avx2.cpp ${MLAS_SRC_DIR}/qgemm_kernel_sse.cpp @@ -634,7 +634,7 @@ else() ${MLAS_SRC_DIR}/sqnbitgemm_kernel_avx2.cpp ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.h ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp - ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2_fp32.cpp + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp ) if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13.1 AND NOT(APPLE)) set(mlas_platform_srcs_avx2 diff --git a/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.cpp b/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.cpp index 7b6c49720853a..024e67d14a0d7 100644 --- a/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.cpp +++ b/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.cpp @@ -14,14 +14,295 @@ Module Name: --*/ + +#include + #include "rotary_embedding.h" #include "rotary_embedding_kernel_avx2.h" +namespace rope_avx2 { + +namespace { + +typedef __m256 float32x8_t; +static constexpr int32_t mask_buffer[16] = {-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0}; + +template +void +RopeKernel_Avx2_fp16_Impl( + const MLAS_FP16* input, + const MLAS_FP16* sin_data, + const MLAS_FP16* cos_data, + size_t dim, + MLAS_FP16* output +); + +float32x8_t +load_fp16_and_convert_to_fp32(const MLAS_FP16* input) +{ + __m128i fp16 = _mm_lddqu_si128(reinterpret_cast(input)); + return _mm256_cvtph_ps(fp16); +} + +void +convert_to_fp16_and_store(MLAS_FP16* dst_fp16, const __m256 output) +{ + __m128i fp16_chunk = _mm256_cvtps_ph(output, _MM_FROUND_TO_NEAREST_INT); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst_fp16), fp16_chunk); +} + +template <> +void +RopeKernel_Avx2_fp16_Impl( + const MLAS_FP16* input, + const MLAS_FP16* sin_data, + const MLAS_FP16* cos_data, + size_t dim, + MLAS_FP16* output +) +{ + // ?cast input -> const unsigned short* + const size_t half_dim = dim >> 1; + size_t i = 0, j = half_dim; + for (; i + 7 < half_dim; i += 8, j += 8) { + float32x8_t real = load_fp16_and_convert_to_fp32(input + i); + float32x8_t imag = load_fp16_and_convert_to_fp32(input + j); + float32x8_t sin_val = load_fp16_and_convert_to_fp32(sin_data + i); + float32x8_t cos_val = load_fp16_and_convert_to_fp32(cos_data + i); + // Compute Real and Imaginary output values + float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); + float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); + // Store back into non interleaved format + convert_to_fp16_and_store(output + i, real_out); + convert_to_fp16_and_store(output + j, imag_out); + } + for (; i < half_dim; i++, j++) { + float real = input[i].ToFloat(); + float imag = input[j].ToFloat(); + float sin_val = sin_data[i]; + float cos_val = cos_data[i]; + output[i] = MLAS_FP16(real * cos_val - imag * sin_val); + output[j] = MLAS_FP16(real * sin_val + imag * cos_val); + } +} + +template <> +void +RopeKernel_Avx2_fp16_Impl( + const MLAS_FP16* input, + const MLAS_FP16* sin_data, + const MLAS_FP16* cos_data, + size_t dim, + MLAS_FP16* output +) +{ + // ?cast input -> const unsigned short* + size_t i = 0; + for (; i + 15 < dim; i += 16) { + float32x8_t x0 = load_fp16_and_convert_to_fp32(input + i); + float32x8_t x1 = load_fp16_and_convert_to_fp32(input + i + 8); + float32x8_t real_s = _mm256_shuffle_ps(x0, x1, 0b10001000); + float32x8_t imag_s = _mm256_shuffle_ps(x0, x1, 0b11011101); + __m256i in_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); + float32x8_t real = _mm256_permutevar8x32_ps(real_s, in_mask_vec); + float32x8_t imag = _mm256_permutevar8x32_ps(imag_s, in_mask_vec); + float32x8_t sin_val = load_fp16_and_convert_to_fp32(sin_data + i / 2); + float32x8_t cos_val = load_fp16_and_convert_to_fp32(cos_data + i / 2); + // Compute Real and Imaginary output values + float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); + float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); + // Store back into interleaved format + __m256i out_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); + float32x8_t real_out_s = _mm256_permutevar8x32_ps(real_out, out_mask_vec); + float32x8_t imag_out_s = _mm256_permutevar8x32_ps(imag_out, out_mask_vec); + float32x8_t y0 = _mm256_unpacklo_ps(real_out_s, imag_out_s); + float32x8_t y1 = _mm256_unpackhi_ps(real_out_s, imag_out_s); + + // Store back into non interleaved format + convert_to_fp16_and_store(output + i, y0); + convert_to_fp16_and_store(output + i + 8, y1); + } + + for (; i < dim; i++) { + size_t cache_idx = i / 2; + bool sign = i & 1; + size_t j = sign ? i - 1 : i + 1; + + float output_data_i = input[i].ToFloat() * cos_data[cache_idx].ToFloat(); + float input_data_j = input[j].ToFloat(); + float sin_data_cache_idx = sin_data[cache_idx].ToFloat(); + if (sign) { + output_data_i += input_data_j * sin_data_cache_idx; + } else { + output_data_i -= input_data_j * sin_data_cache_idx; + } + output[i] = MLAS_FP16(output_data_i); + } +} + +template +void +RopeKernel_Avx2_fp32_Impl( + const float* input, + const float* sin_data, + const float* cos_data, + size_t dim, + float* output +); + +template <> +void +RopeKernel_Avx2_fp32_Impl( + const float* input, + const float* sin_data, + const float* cos_data, + size_t dim, + float* output +) { + const size_t half_dim = dim >> 1; + size_t i = 0, j = half_dim; + for (; i + 7 < half_dim; i += 8, j += 8) { + float32x8_t real = _mm256_loadu_ps(input + i); + float32x8_t imag = _mm256_loadu_ps(input + j); + float32x8_t sin_val = _mm256_loadu_ps(sin_data + i); + float32x8_t cos_val = _mm256_loadu_ps(cos_data + i); + //Compute Real and Imaginary output values + float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); + float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); + //Store back into non interleaved format + _mm256_storeu_ps(output + i, real_out); + _mm256_storeu_ps(output + j, imag_out); + } + if (half_dim - i != 0) { + size_t rem = half_dim - i; + const __m256i mask = _mm256_loadu_si256((const __m256i*)(mask_buffer + 8 - rem)); + //Use a mask to load the remaining input values + float32x8_t real = _mm256_maskload_ps(input + i, mask); + float32x8_t imag = _mm256_maskload_ps(input + j, mask); + float32x8_t sin_val = _mm256_maskload_ps(sin_data + i, mask); + float32x8_t cos_val = _mm256_maskload_ps(cos_data + i, mask); + //Compute Real and Imaginary output values + float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); + float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); + //Store back into non interleaved format + _mm256_maskstore_ps(output + i, mask, real_out); + _mm256_maskstore_ps(output + j, mask, imag_out); + } +} + +template <> +void +RopeKernel_Avx2_fp32_Impl( + const float* input, + const float* sin_data, + const float* cos_data, + size_t dim, + float* output +) { + size_t i = 0; + for (; i + 15 < dim; i += 16) { + float32x8_t x0 = _mm256_loadu_ps(input + i); + float32x8_t x1 = _mm256_loadu_ps(input + i + 8); + //Load imaginary and real values to separate non-interleaved vectors + float32x8_t real_s = _mm256_shuffle_ps(x0, x1, 0b10001000); + float32x8_t imag_s = _mm256_shuffle_ps(x0, x1, 0b11011101); + __m256i in_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); + float32x8_t real = _mm256_permutevar8x32_ps(real_s, in_mask_vec); + float32x8_t imag = _mm256_permutevar8x32_ps(imag_s, in_mask_vec); + float32x8_t sin_val = _mm256_loadu_ps(sin_data + i / 2); + float32x8_t cos_val = _mm256_loadu_ps(cos_data + i / 2); + //Compute Real and Imaginary output values + float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); + float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); + //Store back into interleaved format + __m256i out_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); + float32x8_t real_out_s = _mm256_permutevar8x32_ps(real_out, out_mask_vec); + float32x8_t imag_out_s = _mm256_permutevar8x32_ps(imag_out, out_mask_vec); + float32x8_t y0 = _mm256_unpacklo_ps(real_out_s, imag_out_s); + float32x8_t y1 = _mm256_unpackhi_ps(real_out_s, imag_out_s); + _mm256_storeu_ps(output + i, y0); + _mm256_storeu_ps(output + i + 8, y1); + } + if (dim - i != 0) { + size_t rem = dim - i; + const __m256i mask0 = _mm256_loadu_si256((const __m256i*)(mask_buffer + 8 - (rem>8?8:rem))); + const __m256i mask1 = _mm256_loadu_si256((const __m256i*)(mask_buffer + 8 - (rem>8?(rem-8):0))); + float32x8_t x0 = _mm256_maskload_ps(input + i, mask0); //Load the first set of data using mask + float32x8_t x1 = _mm256_maskload_ps(input + i + 8, mask1); //Load the reminder of data using a second mask + //Load imaginary and real values to separate non-interleaved vectors + float32x8_t real_s = _mm256_shuffle_ps(x0, x1, 0b10001000); + float32x8_t imag_s = _mm256_shuffle_ps(x0, x1, 0b11011101); + __m256i in_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); + float32x8_t real = _mm256_permutevar8x32_ps(real_s, in_mask_vec); + float32x8_t imag = _mm256_permutevar8x32_ps(imag_s, in_mask_vec); + float32x8_t sin_val = _mm256_loadu_ps(sin_data+ i / 2); + float32x8_t cos_val = _mm256_loadu_ps(cos_data + i / 2); + //Compute Real and Imaginary output values + float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); + float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); + //Store back into interleaved format + __m256i out_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); + float32x8_t real_out_s = _mm256_permutevar8x32_ps(real_out, out_mask_vec); + float32x8_t imag_out_s = _mm256_permutevar8x32_ps(imag_out, out_mask_vec); + float32x8_t y0 = _mm256_unpacklo_ps(real_out_s, imag_out_s); + float32x8_t y1 = _mm256_unpackhi_ps(real_out_s, imag_out_s); + _mm256_maskstore_ps(output + i, mask0, y0); + _mm256_maskstore_ps(output + i + 8, mask1, y1); + } +} + +} // rope_avx2 namespace + +void +RopeKernel_Avx2_fp32( + const float* input, + const float* sin_data, + const float* cos_data, + size_t dim, + bool interleaved, + float* output +) { + // real part and imaginary part must be paired + assert(dim % 2 == 0); + const auto* input_impl = reinterpret_cast(input); + const auto* sin_impl = reinterpret_cast(sin_data); + const auto* cos_impl = reinterpret_cast(cos_data); + auto* output_impl = reinterpret_cast(output); + + if (interleaved) { + RopeKernel_Avx2_fp32_Impl(input_impl, sin_impl, cos_impl, dim, output_impl); + } else { + RopeKernel_Avx2_fp32_Impl(input_impl, sin_impl, cos_impl, dim, output_impl); + } +} + +void +RopeKernel_Avx2_fp16( + const MLAS_FP16* input, + const MLAS_FP16* sin_data, + const MLAS_FP16* cos_data, + size_t dim, + bool interleaved, + MLAS_FP16* output +) +{ + // real part and imaginary part must be paired + assert(dim % 2 == 0); + + if (interleaved) { + RopeKernel_Avx2_fp16_Impl(input, sin_data, cos_data, dim, output); + } else { + RopeKernel_Avx2_fp16_Impl(input, sin_data, cos_data, dim, output); + } +} +} + // // Kernel dispatch structure definition. // const MLAS_ROPE_DISPATCH MlasRopeDispatchAvx2 = []() { MLAS_ROPE_DISPATCH d; - d.SRope = rope_avx2::RopeKernel_Avx2; + d.SRope = rope_avx2::RopeKernel_Avx2_fp32; + d.HRope = rope_avx2::RopeKernel_Avx2_fp16; return d; }(); diff --git a/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.h b/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.h index 18a2e11998644..c08833e114b9e 100644 --- a/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.h +++ b/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2.h @@ -34,4 +34,14 @@ RopeKernel_Avx2( float* output ); +void +RopeKernel_Avx2_fp16( + const MLAS_FP16* input, + const MLAS_FP16* sin_data, + const MLAS_FP16* cos_data, + size_t dim, + bool interleaved, + MLAS_FP16* output +); + } // namespace rope_avx2 diff --git a/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2_fp32.cpp b/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2_fp32.cpp deleted file mode 100644 index 7124b82606978..0000000000000 --- a/onnxruntime/core/mlas/lib/rotary_embedding_kernel_avx2_fp32.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - -Licensed under the MIT License. - -Module Name: - - rotary_embedding_kernel_avx2_fp32.cpp - -Abstract: - - This module implements the fp32 rotary embedding kernels using AVX2. - ---*/ - -#include - -#include "rotary_embedding.h" -#include "rotary_embedding_kernel_avx2.h" - -namespace rope_avx2 { - -namespace { - -typedef __m256 float32x8_t; - -template -void -RopeKernel_Avx2_Impl( - const float* input, - const float* sin_data, - const float* cos_data, - size_t dim, - float* output -); - -template <> -void -RopeKernel_Avx2_Impl( - const float* input, - const float* sin_data, - const float* cos_data, - size_t dim, - float* output -) { - const size_t half_dim = dim >> 1; - size_t i = 0, j = half_dim; - for (; i + 7 < half_dim; i += 8, j += 8) { - float32x8_t real = _mm256_loadu_ps(input + i); - float32x8_t imag = _mm256_loadu_ps(input + j); - float32x8_t sin_val = _mm256_loadu_ps(sin_data + i); - float32x8_t cos_val = _mm256_loadu_ps(cos_data + i); - //Compute Real and Imaginary output values - float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); - float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); - //Store back into non interleaved format - _mm256_storeu_ps(output + i, real_out); - _mm256_storeu_ps(output + j, imag_out); - } - if (half_dim - i != 0) { - size_t rem = half_dim - i; - static constexpr int32_t mask_buffer[16] = {-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0}; - const __m256i mask = _mm256_loadu_si256((const __m256i*)(mask_buffer + 8 - rem)); - //Use a mask to load the remaining input values - float32x8_t real = _mm256_maskload_ps(input + i, mask); - float32x8_t imag = _mm256_maskload_ps(input + j, mask); - float32x8_t sin_val = _mm256_maskload_ps(sin_data + i, mask); - float32x8_t cos_val = _mm256_maskload_ps(cos_data + i, mask); - //Compute Real and Imaginary output values - float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); - float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); - //Store back into non interleaved format - _mm256_maskstore_ps(output + i, mask, real_out); - _mm256_maskstore_ps(output + j, mask, imag_out); - } -} - -template <> -void -RopeKernel_Avx2_Impl( - const float* input, - const float* sin_data, - const float* cos_data, - size_t dim, - float* output -) { - size_t i = 0; - for (; i + 15 < dim; i += 16) { - float32x8_t x0 = _mm256_loadu_ps(input + i); - float32x8_t x1 = _mm256_loadu_ps(input + i + 8); - //Load imaginary and real values to separate non-interleaved vectors - float32x8_t real_s = _mm256_shuffle_ps(x0, x1, 0b10001000); - float32x8_t imag_s = _mm256_shuffle_ps(x0, x1, 0b11011101); - __m256i in_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); - float32x8_t real = _mm256_permutevar8x32_ps(real_s, in_mask_vec); - float32x8_t imag = _mm256_permutevar8x32_ps(imag_s, in_mask_vec); - float32x8_t sin_val = _mm256_loadu_ps(sin_data + i / 2); - float32x8_t cos_val = _mm256_loadu_ps(cos_data + i / 2); - //Compute Real and Imaginary output values - float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); - float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); - //Store back into interleaved format - __m256i out_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); - float32x8_t real_out_s = _mm256_permutevar8x32_ps(real_out, out_mask_vec); - float32x8_t imag_out_s = _mm256_permutevar8x32_ps(imag_out, out_mask_vec); - float32x8_t y0 = _mm256_unpacklo_ps(real_out_s, imag_out_s); - float32x8_t y1 = _mm256_unpackhi_ps(real_out_s, imag_out_s); - _mm256_storeu_ps(output + i, y0); - _mm256_storeu_ps(output + i + 8, y1); - } - if (dim - i != 0) { - size_t rem = dim - i; - static constexpr int32_t mask_buffer[16] = {-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0}; - const __m256i mask0 = _mm256_loadu_si256((const __m256i*)(mask_buffer + 8 - (rem>8?8:rem))); - const __m256i mask1 = _mm256_loadu_si256((const __m256i*)(mask_buffer + 8 - (rem>8?(rem-8):0))); - float32x8_t x0 = _mm256_maskload_ps(input + i, mask0); //Load the first set of data using mask - float32x8_t x1 = _mm256_maskload_ps(input + i + 8, mask1); //Load the reminder of data using a second mask - //Load imaginary and real values to separate non-interleaved vectors - float32x8_t real_s = _mm256_shuffle_ps(x0, x1, 0b10001000); - float32x8_t imag_s = _mm256_shuffle_ps(x0, x1, 0b11011101); - __m256i in_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); - float32x8_t real = _mm256_permutevar8x32_ps(real_s, in_mask_vec); - float32x8_t imag = _mm256_permutevar8x32_ps(imag_s, in_mask_vec); - float32x8_t sin_val = _mm256_loadu_ps(sin_data+ i / 2); - float32x8_t cos_val = _mm256_loadu_ps(cos_data + i / 2); - //Compute Real and Imaginary output values - float32x8_t real_out = _mm256_fmsub_ps(real, cos_val, _mm256_mul_ps(imag, sin_val)); - float32x8_t imag_out = _mm256_fmadd_ps(real, sin_val, _mm256_mul_ps(imag, cos_val)); - //Store back into interleaved format - __m256i out_mask_vec = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0); - float32x8_t real_out_s = _mm256_permutevar8x32_ps(real_out, out_mask_vec); - float32x8_t imag_out_s = _mm256_permutevar8x32_ps(imag_out, out_mask_vec); - float32x8_t y0 = _mm256_unpacklo_ps(real_out_s, imag_out_s); - float32x8_t y1 = _mm256_unpackhi_ps(real_out_s, imag_out_s); - _mm256_maskstore_ps(output + i, mask0, y0); - _mm256_maskstore_ps(output + i + 8, mask1, y1); - } -} - -} // namespace - -void -RopeKernel_Avx2( - const float* input, - const float* sin_data, - const float* cos_data, - size_t dim, - bool interleaved, - float* output -) { - // real part and imaginary part must be paired - assert(dim % 2 == 0); - const auto* input_impl = reinterpret_cast(input); - const auto* sin_impl = reinterpret_cast(sin_data); - const auto* cos_impl = reinterpret_cast(cos_data); - auto* output_impl = reinterpret_cast(output); - - if (interleaved) { - RopeKernel_Avx2_Impl(input_impl, sin_impl, cos_impl, dim, output_impl); - } else { - RopeKernel_Avx2_Impl(input_impl, sin_impl, cos_impl, dim, output_impl); - } -} - -} diff --git a/onnxruntime/test/mlas/bench/bench_rope.cpp b/onnxruntime/test/mlas/bench/bench_rope.cpp index 9103ba6424f65..b0630b9c8720b 100644 --- a/onnxruntime/test/mlas/bench/bench_rope.cpp +++ b/onnxruntime/test/mlas/bench/bench_rope.cpp @@ -4,42 +4,47 @@ #include "mlas.h" #include "benchmark/benchmark.h" #include "bench_util.h" +#include "core/framework/float16.h" -void RunRoPEBenchmark(size_t rotary_emb_dim, bool interleaved, benchmark::State& state) { - const float Pi = 2 * std::acos(0.0f); +using namespace onnxruntime; - std::vector input(rotary_emb_dim); +template +void RunRoPEBenchmark(size_t rotary_emb_dim, bool interleaved, benchmark::State& state) { + std::vector input(rotary_emb_dim); size_t table_len = interleaved ? rotary_emb_dim / 2 : rotary_emb_dim; - std::vector sin_data(table_len); - std::vector cos_data(table_len); - std::vector output_ref(rotary_emb_dim), output_impl(rotary_emb_dim); + std::vector sin_data(table_len); + std::vector cos_data(table_len); + std::vector output_ref(rotary_emb_dim), output_impl(rotary_emb_dim); for (size_t i = 0; i < rotary_emb_dim; ++i) { - input[i] = static_cast(i + 1); + input[i] = static_cast(i + 1.0f); } for (size_t i = 0; i < table_len; ++i) { - float theta = (float)i / 1000 * Pi; - sin_data[i] = std::sin(theta); - cos_data[i] = std::cos(theta); + // https://arxiv.org/pdf/2104.09864 section 3.4.3 + float theta_i = static_cast(pow(10000, -2.0f * i / rotary_emb_dim)); + sin_data[i] = static_cast(std::sin(theta_i)); + cos_data[i] = static_cast(std::cos(theta_i)); } // warm up run - MlasRotaryEmbedOneRow(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_impl[0]); + MlasRotaryEmbedOneRow(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_impl[0]); for (auto _ : state) { - MlasRotaryEmbedOneRow(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_impl[0]); + MlasRotaryEmbedOneRow(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_impl[0]); } } +template void RoPE(benchmark::State& state) { using onnxruntime::narrow; const auto rotary_emb_dim = narrow(state.range(0)); const auto interleaved = narrow(state.range(1)); - RunRoPEBenchmark(rotary_emb_dim, interleaved, state); + RunRoPEBenchmark(rotary_emb_dim, interleaved, state); } +template static void RoPEArgs(benchmark::internal::Benchmark* b) { b->ArgNames({"rotary_emb_dim", "interleaved"}); @@ -49,4 +54,5 @@ static void RoPEArgs(benchmark::internal::Benchmark* b) { }); } -BENCHMARK(RoPE)->Apply(RoPEArgs)->UseRealTime(); +BENCHMARK(RoPE)->Apply(RoPEArgs)->UseRealTime(); +BENCHMARK(RoPE)->Apply(RoPEArgs)->UseRealTime(); diff --git a/onnxruntime/test/mlas/unittest/test_rope.cpp b/onnxruntime/test/mlas/unittest/test_rope.cpp index 54087a933fd9e..516bc866459a8 100644 --- a/onnxruntime/test/mlas/unittest/test_rope.cpp +++ b/onnxruntime/test/mlas/unittest/test_rope.cpp @@ -16,31 +16,34 @@ Module Name: #include "test_util.h" #include "mlas.h" +#include "core/framework/float16.h" #include "core/mlas/lib/rotary_embedding.h" -class MlasRoPETest : public MlasTestBase { - const float Pi = 2 * std::acos(0.0f); +using namespace onnxruntime; +template +class MlasRoPETest : public MlasTestBase { public: void Test(size_t rotary_emb_dim, bool interleaved) { - std::vector input(rotary_emb_dim); + std::vector input(rotary_emb_dim); size_t table_len = interleaved ? rotary_emb_dim / 2 : rotary_emb_dim; - std::vector sin_data(table_len); - std::vector cos_data(table_len); - std::vector output_ref(rotary_emb_dim), output_impl(rotary_emb_dim); + std::vector sin_data(table_len); + std::vector cos_data(table_len); + std::vector output_ref(rotary_emb_dim), output_impl(rotary_emb_dim); for (size_t i = 0; i < rotary_emb_dim; ++i) { - input[i] = static_cast(i + 1); + input[i] = static_cast(i + 1.0f); } for (size_t i = 0; i < table_len; ++i) { - float theta = (float)i / 1000 * Pi; - sin_data[i] = std::sin(theta); - cos_data[i] = std::cos(theta); + // https://arxiv.org/pdf/2104.09864 section 3.4.3 + float theta_i = static_cast(pow(10000, -2.0f * i / rotary_emb_dim)); + sin_data[i] = static_cast(std::sin(theta_i)); + cos_data[i] = static_cast(std::cos(theta_i)); } // Call the function - MlasRotaryEmbedOneRow_FallBack(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_ref[0]); - MlasRotaryEmbedOneRow(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_impl[0]); + MlasRotaryEmbedOneRow_FallBack(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_ref[0]); + MlasRotaryEmbedOneRow(&input[0], &sin_data[0], &cos_data[0], rotary_emb_dim, interleaved, &output_impl[0]); for (size_t i = 0; i < rotary_emb_dim; i++) { ASSERT_TRUE(CloseEnough(output_impl[i], output_ref[i])) @@ -48,40 +51,49 @@ class MlasRoPETest : public MlasTestBase { << "rotary_emb_dim=" << rotary_emb_dim << ", interleaved=" << interleaved; } } - - public: }; // // Short Execute() test helper to register each test separately by all parameters. // -class RoPEShortExecuteTest : public MlasTestFixture { +template +class RoPEShortExecuteTest : public MlasTestFixture> { public: explicit RoPEShortExecuteTest(size_t rotary_emb_dim, bool interleaved) : rotary_emb_dim_(rotary_emb_dim), interleaved_(interleaved) {} void TestBody() override { - MlasTestFixture::mlas_tester->Test(rotary_emb_dim_, interleaved_); + MlasTestFixture>::mlas_tester->Test(rotary_emb_dim_, interleaved_); } static size_t RegisterSingleTest(size_t rotary_emb_dim, bool interleaved) { size_t tests_registered = 0; + std::string test_suite_name{"RoPE_"}; + if (std::is_same::value) { + test_suite_name += "fp32"; + } else if (std::is_same::value) { + test_suite_name += "fp16"; + } else { + ADD_FAILURE() << "Unknown type passed to test: " << test_suite_name; + return 0; // Return 0 since no test is registered + } + std::stringstream ss; ss << "/rotary_emb_dim" << rotary_emb_dim << "/interleaved" << interleaved; auto test_name = ss.str(); testing::RegisterTest( - "RoPE", + test_suite_name.c_str(), test_name.c_str(), nullptr, test_name.c_str(), __FILE__, __LINE__, // Important to use the fixture type as the return type here. - [=]() -> MlasTestFixture* { - return new RoPEShortExecuteTest(rotary_emb_dim, interleaved); + [=]() -> MlasTestFixture>* { + return new RoPEShortExecuteTest(rotary_emb_dim, interleaved); }); tests_registered += 1; @@ -116,7 +128,7 @@ class RoPEShortExecuteTest : public MlasTestFixture { // only test float RoPE with avx2 where RopeDispatch is assigned at this moment. #ifdef MLAS_TARGET_AMD64 static size_t RoPERegisterAllShortExecuteTests() { - return RoPEShortExecuteTest::RegisterShortExecuteTests(); + return RoPEShortExecuteTest::RegisterShortExecuteTests() + RoPEShortExecuteTest::RegisterShortExecuteTests(); } static UNUSED_VARIABLE bool added_to_main = AddTestRegister( diff --git a/onnxruntime/test/python/transformers/test_gqa_cpu.py b/onnxruntime/test/python/transformers/test_gqa_cpu.py index 1239affcc04de..461c243b82212 100644 --- a/onnxruntime/test/python/transformers/test_gqa_cpu.py +++ b/onnxruntime/test/python/transformers/test_gqa_cpu.py @@ -30,11 +30,12 @@ GREEN = "\033[32m" RESET = "\033[0m" -ORT_TYPE = TensorProto.FLOAT -TORCH_TYPE = torch.float16 if ORT_TYPE == TensorProto.FLOAT16 else torch.float32 -NUMPY_TYPE = numpy.float16 if ORT_TYPE == TensorProto.FLOAT16 else numpy.float32 -RTOL = 3e-2 if ORT_TYPE == TensorProto.FLOAT16 else 1e-3 -ATOL = RTOL +# These will now be set dynamically in tests +ORT_TYPE = None +TORCH_TYPE = None +NUMPY_TYPE = None +RTOL = None +ATOL = None class Formats: @@ -138,6 +139,7 @@ def forward(self, x, cos, sin, pos, interleaved): def create_group_query_attention_graph_prompt( config, + ort_type, past_kv_format=Formats.BSNH, share_buffer=True, local_window_size=-1, @@ -183,7 +185,7 @@ def create_group_query_attention_graph_prompt( graph_input = [ helper.make_tensor_value_info( "query", - ORT_TYPE, + ort_type, [ config.batch_size, config.q_sequence_length, @@ -209,7 +211,7 @@ def create_group_query_attention_graph_prompt( graph_input += [ helper.make_tensor_value_info( "key", - ORT_TYPE, + ort_type, [ config.batch_size, config.kv_sequence_length, @@ -218,7 +220,7 @@ def create_group_query_attention_graph_prompt( ), helper.make_tensor_value_info( "value", - ORT_TYPE, + ort_type, [ config.batch_size, config.kv_sequence_length, @@ -230,7 +232,7 @@ def create_group_query_attention_graph_prompt( graph_input += [ helper.make_tensor_value_info( "past_key", - ORT_TYPE, + ort_type, [ config.batch_size, past_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -240,7 +242,7 @@ def create_group_query_attention_graph_prompt( ), helper.make_tensor_value_info( "past_value", - ORT_TYPE, + ort_type, [ config.batch_size, past_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -253,7 +255,7 @@ def create_group_query_attention_graph_prompt( graph_input += [ helper.make_tensor_value_info( "cos_cache", - ORT_TYPE, + ort_type, [ config.buffer_sequence_length if share_buffer else config.kv_sequence_length, (math.floor(config.head_size / 16) * 16) // 2, @@ -261,7 +263,7 @@ def create_group_query_attention_graph_prompt( ), helper.make_tensor_value_info( "sin_cache", - ORT_TYPE, + ort_type, [ config.buffer_sequence_length if share_buffer else config.kv_sequence_length, (math.floor(config.head_size / 16) * 16) // 2, @@ -282,7 +284,7 @@ def create_group_query_attention_graph_prompt( graph_input += [ helper.make_tensor_value_info( "attention_bias", - ORT_TYPE, + ort_type, [config.batch_size, 1, config.kv_sequence_length, config.kv_sequence_length], ), ] @@ -290,12 +292,12 @@ def create_group_query_attention_graph_prompt( graph_output = [ helper.make_tensor_value_info( "output", - ORT_TYPE, + ort_type, [config.batch_size, config.q_sequence_length, config.num_heads * config.head_size], ), helper.make_tensor_value_info( "present_key", - ORT_TYPE, + ort_type, [ config.batch_size, present_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -305,7 +307,7 @@ def create_group_query_attention_graph_prompt( ), helper.make_tensor_value_info( "present_value", - ORT_TYPE, + ort_type, [ config.batch_size, present_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -315,7 +317,7 @@ def create_group_query_attention_graph_prompt( ), helper.make_tensor_value_info( "present_key", - ORT_TYPE, + ort_type, [ config.batch_size, config.kv_sequence_length if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -325,7 +327,7 @@ def create_group_query_attention_graph_prompt( ), helper.make_tensor_value_info( "present_value", - ORT_TYPE, + ort_type, [ config.batch_size, config.kv_sequence_length if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -349,6 +351,7 @@ def create_group_query_attention_graph_prompt( def create_group_query_attention_graph_past( config, + ort_type, past_kv_format=Formats.BSNH, share_buffer=True, local_window_size=-1, @@ -396,7 +399,7 @@ def create_group_query_attention_graph_past( graph_input = [ helper.make_tensor_value_info( "query", - ORT_TYPE, + ort_type, [ config.batch_size, config.sequence_length, @@ -409,7 +412,7 @@ def create_group_query_attention_graph_past( ), helper.make_tensor_value_info( "past_key", - ORT_TYPE, + ort_type, [ config.batch_size, past_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -419,7 +422,7 @@ def create_group_query_attention_graph_past( ), helper.make_tensor_value_info( "past_value", - ORT_TYPE, + ort_type, [ config.batch_size, past_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -442,7 +445,7 @@ def create_group_query_attention_graph_past( graph_input += [ helper.make_tensor_value_info( "key", - ORT_TYPE, + ort_type, [ config.batch_size, config.sequence_length, @@ -451,7 +454,7 @@ def create_group_query_attention_graph_past( ), helper.make_tensor_value_info( "value", - ORT_TYPE, + ort_type, [ config.batch_size, config.sequence_length, @@ -463,7 +466,7 @@ def create_group_query_attention_graph_past( graph_input += [ helper.make_tensor_value_info( "cos_cache", - ORT_TYPE, + ort_type, [ config.kv_sequence_length + (0 if share_buffer else config.sequence_length), (math.floor(config.head_size / 16) * 16) // 2, @@ -471,7 +474,7 @@ def create_group_query_attention_graph_past( ), helper.make_tensor_value_info( "sin_cache", - ORT_TYPE, + ort_type, [ config.kv_sequence_length + (0 if share_buffer else config.sequence_length), (math.floor(config.head_size / 16) * 16) // 2, @@ -490,7 +493,7 @@ def create_group_query_attention_graph_past( graph_input += [ helper.make_tensor_value_info( "attention_bias", - ORT_TYPE, + ort_type, [config.batch_size, 1, config.sequence_length, present_kv_seqlen], ), ] @@ -498,12 +501,12 @@ def create_group_query_attention_graph_past( graph_output = [ helper.make_tensor_value_info( "output", - ORT_TYPE, + ort_type, [config.batch_size, config.sequence_length, config.num_heads * config.head_size], ), helper.make_tensor_value_info( "present_key", - ORT_TYPE, + ort_type, [ config.batch_size, present_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -513,7 +516,7 @@ def create_group_query_attention_graph_past( ), helper.make_tensor_value_info( "present_value", - ORT_TYPE, + ort_type, [ config.batch_size, present_kv_seqlen if past_kv_format == Formats.BSNH else config.kv_num_heads, @@ -667,7 +670,7 @@ def dk_pad_fn(dk_unpad): ) -def create_inputs(config: Config, kv_packed=False, qkv_packed=True): +def create_inputs(config: Config, torch_type, kv_packed=False, qkv_packed=True): qkv = torch.randn( config.batch_size, config.sequence_length, @@ -675,7 +678,7 @@ def create_inputs(config: Config, kv_packed=False, qkv_packed=True): config.num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) key_padding_mask = generate_random_padding_mask( @@ -717,9 +720,12 @@ def gqa_prompt_func( rotary_interleaved=False, softcap=0.0, use_smooth_softmax=False, + ort_type=TensorProto.FLOAT16, + numpy_type=numpy.float16, ): onnx_model_str = create_group_query_attention_graph_prompt( config, + ort_type, past_kv_format, share_buffer, local_window_size=window_size, @@ -776,13 +782,13 @@ def gqa_prompt_func( io_binding.bind_cpu_input("query", ort_inputs["query"]) io_binding.bind_input( - "past_key", "cpu", 0, NUMPY_TYPE, ort_inputs["past_key"].shape(), ort_inputs["past_key"].data_ptr() + "past_key", "cpu", 0, numpy_type, ort_inputs["past_key"].shape(), ort_inputs["past_key"].data_ptr() ) io_binding.bind_input( "past_value", "cpu", 0, - NUMPY_TYPE, + numpy_type, ort_inputs["past_value"].shape(), ort_inputs["past_value"].data_ptr(), ) @@ -855,10 +861,13 @@ def gqa_past_func( rotary_interleaved=False, softcap=0.0, use_smooth_softmax=False, + ort_type=TensorProto.FLOAT16, + numpy_type=numpy.float16, ): assert seqlens_k is not None onnx_model_str = create_group_query_attention_graph_past( config, + ort_type, past_kv_format, share_buffer, local_window_size=window_size, @@ -916,13 +925,13 @@ def gqa_past_func( io_binding.bind_cpu_input("query", ort_inputs["query"]) io_binding.bind_input( - "past_key", "cpu", 0, NUMPY_TYPE, ort_inputs["past_key"].shape(), ort_inputs["past_key"].data_ptr() + "past_key", "cpu", 0, numpy_type, ort_inputs["past_key"].shape(), ort_inputs["past_key"].data_ptr() ) io_binding.bind_input( "past_value", "cpu", 0, - NUMPY_TYPE, + numpy_type, ort_inputs["past_value"].shape(), ort_inputs["past_value"].data_ptr(), ) @@ -1140,10 +1149,12 @@ def attention_qkvpacked_ref( ) -def get_custom_attention_bias(batch_size, sequence_length, total_seq_len, seqlens_k=None, past=False): +def get_custom_attention_bias( + batch_size, sequence_length, total_seq_len, seqlens_k=None, past=False, torch_type=torch.float16 +): if past: assert seqlens_k is not None - attention_bias = torch.zeros((batch_size, 1, sequence_length, total_seq_len), dtype=TORCH_TYPE) + attention_bias = torch.zeros((batch_size, 1, sequence_length, total_seq_len), dtype=torch_type) for b in range(batch_size): total_seq_len = seqlens_k[b] + 1 past_seq_len = total_seq_len - sequence_length @@ -1153,7 +1164,7 @@ def get_custom_attention_bias(batch_size, sequence_length, total_seq_len, seqlen for j in range(past_seq_len + i + 1, total_seq_len): attention_bias[b][0][i][j] = -5000 else: - attention_bias = torch.rand(batch_size, 1, sequence_length, total_seq_len, dtype=TORCH_TYPE) + attention_bias = torch.rand(batch_size, 1, sequence_length, total_seq_len, dtype=torch_type) attention_bias = torch.triu(attention_bias, diagonal=1) return attention_bias @@ -1177,6 +1188,9 @@ def get_custom_position_ids(batch_size, sequence_length, seqlens_k=None, past=Fa def parity_check_gqa_prompt( config, + torch_type, + numpy_type, + ort_type, causal=True, local=False, past_format=Formats.BSNH, @@ -1194,7 +1208,7 @@ def parity_check_gqa_prompt( config.num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) k = torch.randn( @@ -1203,17 +1217,16 @@ def parity_check_gqa_prompt( config.kv_num_heads if past_format == Formats.BSNH else config.buffer_sequence_length, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) - v = torch.randn( config.batch_size, config.buffer_sequence_length if past_format == Formats.BSNH else config.kv_num_heads, config.kv_num_heads if past_format == Formats.BSNH else config.buffer_sequence_length, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_k = torch.randn( @@ -1222,7 +1235,7 @@ def parity_check_gqa_prompt( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_v = torch.randn( @@ -1231,7 +1244,7 @@ def parity_check_gqa_prompt( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) @@ -1257,8 +1270,8 @@ def parity_check_gqa_prompt( rotary_fraction = 1.0 rotary_dim = math.floor(int(rotary_fraction * config.head_size) / 16) * 16 angle = torch.rand(config.buffer_sequence_length, rotary_dim // 2, device="cpu") * 2 * math.pi - cos = torch.cos(angle).to(dtype=TORCH_TYPE) - sin = torch.sin(angle).to(dtype=TORCH_TYPE) + cos = torch.cos(angle).to(dtype=torch_type) + sin = torch.sin(angle).to(dtype=torch_type) rot = LlamaMSRotaryEmbedding() q_ro = rot( q.clone(), cos.unsqueeze(0).unsqueeze(2), sin.unsqueeze(0).unsqueeze(2), rotary_seqlens, rotary_interleaved @@ -1281,20 +1294,24 @@ def parity_check_gqa_prompt( ) attention_bias = ( get_custom_attention_bias( - config.batch_size, config.kv_sequence_length, config.q_sequence_length, seqlens_k=None, past=False + config.batch_size, + config.kv_sequence_length, + config.q_sequence_length, + seqlens_k=None, + past=False, + torch_type=torch_type, ) if config.has_attention_bias else None ) - rearrange(torch.arange(config.kv_sequence_length, device="cpu"), "s -> 1 s") arange = rearrange(torch.arange(config.buffer_sequence_length, device="cpu"), "s -> 1 s") cache_seqlens_expanded = rearrange(cache_seqlens, "b -> b 1") kv_seqlens = torch.tensor([config.kv_sequence_length], device="cpu").repeat(config.batch_size) kv_seqlens_expanded = rearrange(kv_seqlens, "b -> b 1") update_mask = arange < kv_seqlens_expanded - k_cache_ref[update_mask] = rearrange(k_ro, "b s ... -> (b s) ...").to(dtype=TORCH_TYPE) - v_cache_ref[update_mask] = rearrange(new_v, "b s ... -> (b s) ...").to(dtype=TORCH_TYPE) + k_cache_ref[update_mask] = rearrange(k_ro, "b s ... -> (b s) ...").to(dtype=torch_type) + v_cache_ref[update_mask] = rearrange(new_v, "b s ... -> (b s) ...").to(dtype=torch_type) k_cache_rep = repeat(k_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded @@ -1338,6 +1355,8 @@ def parity_check_gqa_prompt( rotary_interleaved, softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) else: out, present_k, present_v = gqa_prompt_func( @@ -1358,17 +1377,19 @@ def parity_check_gqa_prompt( rotary_interleaved, softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.q_sequence_length, config.num_heads, config.head_size)) out = out.detach().cpu().numpy() # Make sure past-present buffer updating correctly - assert numpy.allclose(present_k, k_cache_ref.detach().cpu().numpy(), rtol=RTOL, atol=ATOL, equal_nan=True) - assert numpy.allclose(present_v, v_cache_ref.detach().cpu().numpy(), rtol=RTOL, atol=ATOL, equal_nan=True) + assert numpy.allclose(present_k, k_cache_ref.detach().cpu().numpy(), rtol=rtol, atol=atol, equal_nan=True) + assert numpy.allclose(present_v, v_cache_ref.detach().cpu().numpy(), rtol=rtol, atol=atol, equal_nan=True) # Compare results - all_close = numpy.allclose(out, out_ref, rtol=RTOL, atol=ATOL, equal_nan=True) + all_close = numpy.allclose(out, out_ref, rtol=rtol, atol=atol, equal_nan=True) correct = GREEN + "True" + RESET if all_close else RED + "False" + RESET print( "KV-buffer", @@ -1413,6 +1434,9 @@ def parity_check_gqa_prompt( def parity_check_gqa_prompt_no_buff( config, + torch_type, + numpy_type, + ort_type, causal=True, local=False, past_format=Formats.BSNH, @@ -1430,7 +1454,7 @@ def parity_check_gqa_prompt_no_buff( config.num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_k = torch.randn( @@ -1439,7 +1463,7 @@ def parity_check_gqa_prompt_no_buff( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_v = torch.randn( @@ -1448,7 +1472,7 @@ def parity_check_gqa_prompt_no_buff( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) @@ -1471,8 +1495,8 @@ def parity_check_gqa_prompt_no_buff( rotary_fraction = 1.0 rotary_dim = math.floor(int(rotary_fraction * config.head_size) / 16) * 16 angle = torch.rand(config.kv_sequence_length, rotary_dim // 2, device="cpu") * 2 * math.pi - cos = torch.cos(angle).to(dtype=TORCH_TYPE) - sin = torch.sin(angle).to(dtype=TORCH_TYPE) + cos = torch.cos(angle).to(dtype=torch_type) + sin = torch.sin(angle).to(dtype=torch_type) rot = LlamaMSRotaryEmbedding() q_ro = rot( q.clone(), cos.unsqueeze(0).unsqueeze(2), sin.unsqueeze(0).unsqueeze(2), rotary_seqlens, rotary_interleaved @@ -1496,7 +1520,12 @@ def parity_check_gqa_prompt_no_buff( ) attention_bias = ( get_custom_attention_bias( - config.batch_size, config.kv_sequence_length, config.q_sequence_length, seqlens_k=None, past=False + config.batch_size, + config.kv_sequence_length, + config.q_sequence_length, + seqlens_k=None, + past=False, + torch_type=torch_type, ) if config.has_attention_bias else None @@ -1547,6 +1576,8 @@ def parity_check_gqa_prompt_no_buff( rotary_interleaved, softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) else: out, present_k, present_v = gqa_prompt_func( @@ -1567,17 +1598,19 @@ def parity_check_gqa_prompt_no_buff( rotary_interleaved, softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.q_sequence_length, config.num_heads, config.head_size)) out = out.detach().cpu().numpy() # Make sure past-present buffer updating correctly - assert numpy.allclose(present_k, k_cache_ref.detach().cpu().numpy(), rtol=RTOL, atol=ATOL, equal_nan=True) - assert numpy.allclose(present_v, v_cache_ref.detach().cpu().numpy(), rtol=RTOL, atol=ATOL, equal_nan=True) + assert numpy.allclose(present_k, k_cache_ref.detach().cpu().numpy(), rtol=rtol, atol=atol, equal_nan=True) + assert numpy.allclose(present_v, v_cache_ref.detach().cpu().numpy(), rtol=rtol, atol=atol, equal_nan=True) # Compare results - all_close = numpy.allclose(out, out_ref, rtol=RTOL, atol=ATOL, equal_nan=True) + all_close = numpy.allclose(out, out_ref, rtol=rtol, atol=atol, equal_nan=True) correct = GREEN + "True" + RESET if all_close else RED + "False" + RESET print( "No buff", @@ -1622,6 +1655,9 @@ def parity_check_gqa_prompt_no_buff( def parity_check_gqa_past( config, + torch_type, + numpy_type, + ort_type, causal=True, local=False, past_format=Formats.BSNH, @@ -1639,7 +1675,7 @@ def parity_check_gqa_past( config.num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) k = torch.randn( @@ -1648,7 +1684,7 @@ def parity_check_gqa_past( config.kv_num_heads if past_format == Formats.BSNH else config.kv_sequence_length, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) v = torch.randn( @@ -1657,7 +1693,7 @@ def parity_check_gqa_past( config.kv_num_heads if past_format == Formats.BSNH else config.kv_sequence_length, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_k = torch.randn( @@ -1666,7 +1702,7 @@ def parity_check_gqa_past( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_v = torch.randn( @@ -1675,7 +1711,7 @@ def parity_check_gqa_past( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) @@ -1706,8 +1742,8 @@ def parity_check_gqa_past( rotary_fraction = 1.0 rotary_dim = math.floor(int(rotary_fraction * config.head_size) / 16) * 16 angle = torch.rand(config.kv_sequence_length, rotary_dim // 2, device="cpu") * 2 * math.pi - cos = torch.cos(angle).to(dtype=TORCH_TYPE) - sin = torch.sin(angle).to(dtype=TORCH_TYPE) + cos = torch.cos(angle).to(dtype=torch_type) + sin = torch.sin(angle).to(dtype=torch_type) rot = LlamaMSRotaryEmbedding() q_ro = rot( q.clone(), cos.unsqueeze(0).unsqueeze(2), sin.unsqueeze(0).unsqueeze(2), cache_seqlens, rotary_interleaved @@ -1728,8 +1764,8 @@ def parity_check_gqa_past( update_mask = torch.logical_and( cache_seqlens_expanded <= arange, arange < cache_seqlens_expanded + config.sequence_length ) - k_cache_ref[update_mask] = rearrange(k_ro, "b s ... -> (b s) ...") - v_cache_ref[update_mask] = rearrange(new_v, "b s ... -> (b s) ...") + k_cache_ref[update_mask] = rearrange(k_ro, "b s ... -> (b s) ...").to(dtype=torch_type) + v_cache_ref[update_mask] = rearrange(new_v, "b s ... -> (b s) ...").to(dtype=torch_type) k_cache_rep = repeat(k_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded + config.sequence_length @@ -1760,7 +1796,12 @@ def parity_check_gqa_past( ) attention_bias = ( get_custom_attention_bias( - config.batch_size, config.sequence_length, config.kv_sequence_length, seqlens_k=cache_seqlens, past=True + config.batch_size, + config.sequence_length, + config.kv_sequence_length, + seqlens_k=cache_seqlens, + past=True, + torch_type=torch_type, ) if config.has_attention_bias else None @@ -1787,6 +1828,8 @@ def parity_check_gqa_past( rotary_interleaved, softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) else: out, present_k, present_v = gqa_past_func( @@ -1807,17 +1850,19 @@ def parity_check_gqa_past( rotary_interleaved, softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) out = out.detach().cpu().numpy() # Make sure past-present buffer updating correctly - assert numpy.allclose(present_k, k_cache_ref.detach().cpu().numpy(), rtol=RTOL, atol=ATOL, equal_nan=True) - assert numpy.allclose(present_v, v_cache_ref.detach().cpu().numpy(), rtol=RTOL, atol=ATOL, equal_nan=True) + assert numpy.allclose(present_k, k_cache_ref.detach().cpu().numpy(), rtol=rtol, atol=atol, equal_nan=True) + assert numpy.allclose(present_v, v_cache_ref.detach().cpu().numpy(), rtol=rtol, atol=atol, equal_nan=True) # Compare results - all_close = numpy.allclose(out, out_ref, rtol=RTOL, atol=ATOL, equal_nan=True) + all_close = numpy.allclose(out, out_ref, rtol=rtol, atol=atol, equal_nan=True) correct = GREEN + "True" + RESET if all_close else RED + "False" + RESET print( "KV-buffer", @@ -1862,6 +1907,9 @@ def parity_check_gqa_past( def parity_check_gqa_past_no_buff( config, + torch_type, + numpy_type, + ort_type, causal=True, local=False, past_format=Formats.BSNH, @@ -1880,7 +1928,7 @@ def parity_check_gqa_past_no_buff( config.num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) k = torch.randn( @@ -1889,7 +1937,7 @@ def parity_check_gqa_past_no_buff( config.kv_num_heads if past_format == Formats.BSNH else config.kv_sequence_length, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) v = torch.randn( @@ -1898,7 +1946,7 @@ def parity_check_gqa_past_no_buff( config.kv_num_heads if past_format == Formats.BSNH else config.kv_sequence_length, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_k = torch.randn( @@ -1907,7 +1955,7 @@ def parity_check_gqa_past_no_buff( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) new_v = torch.randn( @@ -1916,7 +1964,7 @@ def parity_check_gqa_past_no_buff( config.kv_num_heads, config.head_size, device="cpu", - dtype=TORCH_TYPE, + dtype=torch_type, requires_grad=False, ) @@ -1952,8 +2000,8 @@ def parity_check_gqa_past_no_buff( angle = ( torch.rand(config.kv_sequence_length + config.sequence_length, rotary_dim // 2, device="cpu") * 2 * math.pi ) - cos = torch.cos(angle).to(dtype=TORCH_TYPE) - sin = torch.sin(angle).to(dtype=TORCH_TYPE) + cos = torch.cos(angle).to(dtype=torch_type) + sin = torch.sin(angle).to(dtype=torch_type) rot = LlamaMSRotaryEmbedding() q_ro = rot( q.clone(), cos.unsqueeze(0).unsqueeze(2), sin.unsqueeze(0).unsqueeze(2), cache_seqlens, rotary_interleaved @@ -1974,8 +2022,8 @@ def parity_check_gqa_past_no_buff( update_mask = torch.logical_and( cache_seqlens_expanded <= arange, arange < cache_seqlens_expanded + config.sequence_length ) - k_cache_ref[update_mask] = rearrange(k_ro, "b s ... -> (b s) ...") - v_cache_ref[update_mask] = rearrange(new_v, "b s ... -> (b s) ...") + k_cache_ref[update_mask] = rearrange(k_ro, "b s ... -> (b s) ...").to(dtype=torch_type) + v_cache_ref[update_mask] = rearrange(new_v, "b s ... -> (b s) ...").to(dtype=torch_type) k_cache_rep = repeat(k_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded + config.sequence_length @@ -2011,6 +2059,7 @@ def parity_check_gqa_past_no_buff( config.kv_sequence_length + config.sequence_length, seqlens_k=cache_seqlens, past=True, + torch_type=torch_type, ) if config.has_attention_bias else None @@ -2037,6 +2086,8 @@ def parity_check_gqa_past_no_buff( rotary_interleaved=rotary_interleaved, softcap=softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) else: out, present_k, present_v = gqa_past_func( @@ -2057,13 +2108,15 @@ def parity_check_gqa_past_no_buff( rotary_interleaved=rotary_interleaved, softcap=softcap, use_smooth_softmax=use_smooth_softmax, + ort_type=ort_type, + numpy_type=numpy_type, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) out = out.detach().cpu().numpy() # Compare results - all_close = numpy.allclose(out, out_ref, rtol=RTOL, atol=ATOL, equal_nan=True) + all_close = numpy.allclose(out, out_ref, rtol=rtol, atol=atol, equal_nan=True) correct = GREEN + "True" + RESET if all_close else RED + "False" + RESET print( "NO buff", @@ -2107,24 +2160,83 @@ def parity_check_gqa_past_no_buff( class TestGQA(unittest.TestCase): - def test_gqa_no_past(self): + def setUp(self): + # Define precision configurations + self.precision_configs = [ + { + "ort_type": TensorProto.FLOAT16, + "torch_type": torch.float16, + "numpy_type": numpy.float16, + "rtol": 1e-2, + "atol": 1e-2, + }, + { + "ort_type": TensorProto.FLOAT, + "torch_type": torch.float32, + "numpy_type": numpy.float32, + "rtol": 1e-5, + "atol": 1e-5, + }, + ] + + def run_test_config( + self, test_func, config_class, batches, seqs, num_h, h_sizes, pos_ids_attn_bias, additional_params=None + ): + if additional_params is None: + additional_params = {} + + random.seed(69) torch.manual_seed(69) + + for precision in self.precision_configs: + print( + f"\nRunning tests with precision: {'FLOAT16' if precision['ort_type'] == TensorProto.FLOAT16 else 'FLOAT32'}" + ) + for b in batches: + for s, s2 in seqs: + for n, n2 in num_h: + for h in h_sizes: + for local in [False, True]: + for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: + for packed in [False, True]: + for softcap in [0.0, 50.0]: + for use_smooth_softmax in [False, True]: + for has_pos, has_attn in pos_ids_attn_bias: + if config_class == PromptConfig: + config = config_class( + b, s, s2, s + s2 + 8, n, n2, h, has_pos, has_attn + ) + else: # Config + sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 + config = config_class(b, s, s2, sp, n, n2, h, has_pos, has_attn) + + params = { + "config": config, + "torch_type": precision["torch_type"], + "numpy_type": precision["numpy_type"], + "ort_type": precision["ort_type"], + "rtol": precision["rtol"], + "atol": precision["atol"], + "local": local, + "past_format": Formats.BNSH, + "rotary": rotary, + "rotary_interleaved": rotary_interleaved, + "packed": packed, + "softcap": softcap, + "use_smooth_softmax": use_smooth_softmax, + } + params.update(additional_params) + + all_close = test_func(**params) + self.assertTrue(all_close) + + def test_gqa_no_past(self): print("-------- TEST GQA NO PAST (PROMPT CASE) ---------") batches = [3] if pipeline_mode else [1, 3, 5] seqs = ( - [ - (127, 127), - (240, 240), - ] + [(127, 127), (240, 240)] if pipeline_mode - else [ - (127, 127), - (35, 35), - (2000, 2000), - (200, 200), - (240, 240), - (8000, 8000), - ] + else [(127, 127), (35, 35), (2000, 2000), (200, 200), (240, 240), (8000, 8000)] ) pos_ids_attn_bias = ( [(False, False), (True, True)] @@ -2133,50 +2245,13 @@ def test_gqa_no_past(self): ) num_h = [(32, 8)] if pipeline_mode else [(6, 6), (6, 3), (9, 9), (9, 3)] h_sizes = [128] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] - for b in batches: - for sq, skv in seqs: - for n, n2 in num_h: - for h in h_sizes: - for local in [False, True]: - for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: - for packed in [False, True]: - for softcap in [0.0, 50.0]: - for use_smooth_softmax in [False, True]: - for has_position_ids, has_attention_bias in pos_ids_attn_bias: - config = PromptConfig( - b, - sq, - skv, - sq + skv + 8, - n, - n2, - h, - has_position_ids, - has_attention_bias, - ) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_prompt( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_prompt_no_buff( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) + + # Test with buffer + self.run_test_config(parity_check_gqa_prompt, PromptConfig, batches, seqs, num_h, h_sizes, pos_ids_attn_bias) + # Test without buffer + self.run_test_config( + parity_check_gqa_prompt_no_buff, PromptConfig, batches, seqs, num_h, h_sizes, pos_ids_attn_bias + ) def test_gqa_past(self): print("-------- TEST GQA PAST (TOKEN GEN) ---------") @@ -2184,19 +2259,7 @@ def test_gqa_past(self): seqs = ( [(1, 128)] if pipeline_mode - else [ - (1, 128), - (1, 339), - (1, 1024), - (1, 5000), - (1, 800), - (1, 256), - (1, 799), - (1, 2048), - # (1, 128 * 512), - # (16, 128 * 512), - # (128, 128), - ] + else [(1, 128), (1, 339), (1, 1024), (1, 5000), (1, 800), (1, 256), (1, 799), (1, 2048)] ) pos_ids_attn_bias = ( [(False, False), (True, True)] @@ -2205,48 +2268,11 @@ def test_gqa_past(self): ) num_h = [(9, 3)] if pipeline_mode else [(6, 6), (6, 3), (9, 9), (9, 3)] h_sizes = [64] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] - random.seed(69) - for b in batches: - for s, s2 in seqs: - for n, n2 in num_h: - for h in h_sizes: - for local in [False, True]: - for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: - for packed in [False, True]: - for softcap in [0.0, 50.0]: - for use_smooth_softmax in [False, True]: - for has_position_ids, has_attention_bias in pos_ids_attn_bias: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config( - b, s, s2, sp, n, n2, h, has_position_ids, has_attention_bias - ) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_past( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_past_no_buff( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - softcap=softcap, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) + + # Test with buffer + self.run_test_config(parity_check_gqa_past, Config, batches, seqs, num_h, h_sizes, pos_ids_attn_bias) + # Test without buffer + self.run_test_config(parity_check_gqa_past_no_buff, Config, batches, seqs, num_h, h_sizes, pos_ids_attn_bias) def test_gqa_interactive_one_batch(self): print("-------- TEST GQA INTERACTIVE ---------") @@ -2254,19 +2280,7 @@ def test_gqa_interactive_one_batch(self): seqs = ( [(256, 2048)] if pipeline_mode - else [ - (1, 128), - (1, 339), - (1, 1024), - (1, 5000), - (1, 800), - (1, 256), - (1, 799), - (1, 2048), - # (1, 128 * 512), - # (16, 128 * 512), - # (128, 128), - ] + else [(1, 128), (1, 339), (1, 1024), (1, 5000), (1, 800), (1, 256), (1, 799), (1, 2048)] ) pos_ids_attn_bias = ( [(False, False), (True, True)] @@ -2275,39 +2289,28 @@ def test_gqa_interactive_one_batch(self): ) num_h = [(32, 8)] if pipeline_mode else [(6, 6), (6, 3), (9, 9), (9, 3)] h_sizes = [32] if pipeline_mode else [32, 40, 64, 80, 96, 128, 160, 192, 224, 256] - random.seed(69) - for b in batches: - for s, s2 in seqs: - for n, n2 in num_h: - for h in h_sizes: - for local in [False, True]: - for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: - for packed in [False, True]: - for has_position_ids, has_attention_bias in pos_ids_attn_bias: - config = Config(b, s, s2, -1, n, n2, h, has_position_ids, has_attention_bias) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_past( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_past_no_buff( - config, - local=local, - past_format=past_kv_format, - rtol=RTOL, - atol=ATOL, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) + + # Only test softcap=0.0 for interactive case as per original + self.run_test_config( + parity_check_gqa_past, + Config, + batches, + seqs, + num_h, + h_sizes, + pos_ids_attn_bias, + additional_params={"softcap": 0.0, "use_smooth_softmax": False}, + ) + self.run_test_config( + parity_check_gqa_past_no_buff, + Config, + batches, + seqs, + num_h, + h_sizes, + pos_ids_attn_bias, + additional_params={"softcap": 0.0, "use_smooth_softmax": False}, + ) if __name__ == "__main__": From f430dce9ba365b5b3fd2f67bb318fabb24154be6 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Fri, 28 Mar 2025 13:11:37 -0700 Subject: [PATCH 192/266] Migrate Linux GPU pipelines to Github Actions (#24232) --- .github/workflows/linux-dnnl.yml | 2 +- .github/workflows/linux_ci.yml | 6 +- .github/workflows/linux_cuda_ci.yml | 112 +++++++++ .github/workflows/linux_tensorrt_ci.yml | 112 +++++++++ .github/workflows/reusable_linux_build.yml | 188 +++++++++------ .../windows_x64_debug_build_x64_debug.yml | 14 +- onnxruntime/test/providers/base_tester.cc | 2 +- onnxruntime/test/providers/cpu/model_tests.cc | 4 +- .../azure-pipelines/linux-gpu-ci-pipeline.yml | 221 ------------------ .../linux-gpu-tensorrt-ci-pipeline.yml | 104 --------- 10 files changed, 366 insertions(+), 399 deletions(-) create mode 100644 .github/workflows/linux_cuda_ci.yml create mode 100644 .github/workflows/linux_tensorrt_ci.yml delete mode 100644 tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml delete mode 100644 tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml diff --git a/.github/workflows/linux-dnnl.yml b/.github/workflows/linux-dnnl.yml index 9ef2efd9792df..60720a1ac562f 100644 --- a/.github/workflows/linux-dnnl.yml +++ b/.github/workflows/linux-dnnl.yml @@ -27,6 +27,6 @@ jobs: dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu docker_image_repo: onnxruntimecpubuildpythonx64 extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --build_nuget --use_dnnl' - python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' secrets: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_ci.yml b/.github/workflows/linux_ci.yml index c3986a098ea37..2f2a97a00bb31 100644 --- a/.github/workflows/linux_ci.yml +++ b/.github/workflows/linux_ci.yml @@ -55,7 +55,7 @@ jobs: dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu docker_image_repo: onnxruntimecpubuildpythonx64 extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' - python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' # $ needs escaping in single quotes + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' # $ needs escaping in single quotes secrets: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -69,7 +69,7 @@ jobs: dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu docker_image_repo: onnxruntimecpubuildpythonx64 # Shares image with standard x64 release extra_build_flags: '--enable_training --use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' - python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' # $ needs escaping in single quotes + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' # $ needs escaping in single quotes secrets: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -98,6 +98,6 @@ jobs: dockerfile_path: tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/Dockerfile docker_image_repo: onnxruntimecpubuildpythonaarch64 extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' - python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:\$PATH' # $ needs escaping in single quotes + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' # $ needs escaping in single quotes secrets: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_cuda_ci.yml b/.github/workflows/linux_cuda_ci.yml new file mode 100644 index 0000000000000..d1001deb28bf0 --- /dev/null +++ b/.github/workflows/linux_cuda_ci.yml @@ -0,0 +1,112 @@ +name: Linux CUDA CI + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main, 'rel-*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-linux-cuda-x64-release: + name: Build Linux CUDA x64 Release + # This job runs on a CPU node using the reusable build workflow + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" # Build pool + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + docker_build_args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1' + docker_image_repo: onnxruntimecuda12manylinuxbuild + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cuda_version=12.2 --cuda_home=/usr/local/cuda-12.2 --cudnn_home=/usr/local/cuda-12.2 --enable_cuda_profiling --build_java --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=80 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' + run_tests: false # <<< Do not run tests in this job + upload_build_output: true # <<< Upload the build/Release directory + execution_providers: 'cuda' + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token for reusable workflow needs (e.g., docker build action) + + test-linux-cuda-x64-release: + name: Test Linux CUDA x64 Release + needs: build-linux-cuda-x64-release + runs-on: + - self-hosted + - "1ES.Pool=Onnxruntime-github-Linux-GPU-A100-WUS3" + permissions: + contents: read + packages: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download ORT Actions Asset (v0.0.2) + uses: dsaltares/fetch-gh-release-asset@1.1.0 + with: + repo: 'microsoft/onnxruntime-github-actions' + version: 'tags/v0.0.2' + file: 'onnxruntime-actions-v0.0.2.zip' + target: 'onnxruntime-actions.zip' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Unzip ORT Actions + run: | + mkdir -p ./.github/_downloaded_actions + unzip -q onnxruntime-actions.zip -d ./.github/_downloaded_actions + echo "Unzipped contents:" + ls -lR ./.github/_downloaded_actions + + # --- Build the Docker image needed for testing --- + - name: Build Docker Image for Testing + uses: ./.github/_downloaded_actions/build-docker-image # Use downloaded action + with: + Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + Repository: onnxruntimecuda12manylinuxbuild + DockerBuildArgs: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action + + # --- Download Build Artifact to Runner Temp Directory --- + - name: Download Build Artifact + uses: actions/download-artifact@v4 + with: + name: build-output-x64-Release # Must match the upload name + path: ${{ runner.temp }}/Release # Download contents into temp dir structure + + # --- Restore Permissions in the Temp Directory --- + - name: Restore Executable Permissions + if: success() # Only run if download succeeded + working-directory: ${{ runner.temp }}/Release + run: | + if [ -f perms.txt ]; then + echo "Restoring executable permissions in ${{ runner.temp }}/Release ..." + while IFS= read -r file; do + # Check relative path existence within the current directory + if [ -f "$file" ]; then + chmod +x "$file" + else + echo "Warning: File '$file' listed in perms.txt not found." + fi + done < perms.txt + echo "Permissions restored." + else + echo "Warning: perms.txt not found in artifact." + fi + + # --- Run Tests using the downloaded build --- + # The run-build-script-in-docker action mounts ${{ runner.temp }} to /onnxruntime_src/build + # So build.py --build_dir build/Release inside the container correctly finds the artifacts. + - name: Test ONNX Runtime + id: test_step + uses: ./.github/_downloaded_actions/run-build-script-in-docker # Use downloaded action + with: + docker_image: onnxruntimecuda12manylinuxbuild # Use the same image + build_config: Release + mode: 'test' # Set mode to test + execution_providers: 'cuda' + extra_build_flags: '--use_binskim_compliant_compile_flags --cuda_version=12.2 --cuda_home=/usr/local/cuda-12.2 --cudnn_home=/usr/local/cuda-12.2 --enable_cuda_profiling --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=80 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' diff --git a/.github/workflows/linux_tensorrt_ci.yml b/.github/workflows/linux_tensorrt_ci.yml new file mode 100644 index 0000000000000..0d3b7e532ebfb --- /dev/null +++ b/.github/workflows/linux_tensorrt_ci.yml @@ -0,0 +1,112 @@ +name: Linux TensorRT CI + +on: + push: + branches: [ main, 'rel-*'] + pull_request: + branches: [ main, 'rel-*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-linux-TensorRT-x64-release: + name: Build Linux TensorRT x64 Release + # This job runs on a CPU node using the reusable build workflow + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" # Build pool + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + docker_build_args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 --build-arg TRT_VERSION=10.9.0.34-1.cuda12.8 --network=host' + docker_image_repo: onnxruntimetensorrt86gpubuild + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cuda_version=12.2 --cuda_home=/usr/local/cuda-12.2 --cudnn_home=/usr/local/cuda-12.2 --use_tensorrt --tensorrt_home /usr --build_java --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=80 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' + run_tests: false # <<< Do not run tests in this job + upload_build_output: true # <<< Upload the build/Release directory + execution_providers: 'cuda tensorrt' + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token for reusable workflow needs (e.g., docker build action) + + test-linux-TensorRT-x64-release: + name: Test Linux TensorRT x64 Release + needs: build-linux-TensorRT-x64-release + runs-on: + - self-hosted + - "1ES.Pool=Onnxruntime-github-Linux-GPU-A100-WUS3" + permissions: + contents: read + packages: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download ORT Actions Asset (v0.0.2) + uses: dsaltares/fetch-gh-release-asset@1.1.0 + with: + repo: 'microsoft/onnxruntime-github-actions' + version: 'tags/v0.0.2' + file: 'onnxruntime-actions-v0.0.2.zip' + target: 'onnxruntime-actions.zip' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Unzip ORT Actions + run: | + mkdir -p ./.github/_downloaded_actions + unzip -q onnxruntime-actions.zip -d ./.github/_downloaded_actions + echo "Unzipped contents:" + ls -lR ./.github/_downloaded_actions + + # --- Build the Docker image needed for testing --- + - name: Build Docker Image for Testing + uses: ./.github/_downloaded_actions/build-docker-image # Use downloaded action + with: + Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + Repository: onnxruntimetensorrt86gpubuild + DockerBuildArgs: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 --build-arg TRT_VERSION=10.9.0.34-1.cuda12.8 --network=host' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action + + # --- Download Build Artifact to Runner Temp Directory --- + - name: Download Build Artifact + uses: actions/download-artifact@v4 + with: + name: build-output-x64-Release # Must match the upload name + path: ${{ runner.temp }}/Release # Download contents into temp dir structure + + # --- Restore Permissions in the Temp Directory --- + - name: Restore Executable Permissions + if: success() # Only run if download succeeded + working-directory: ${{ runner.temp }}/Release + run: | + if [ -f perms.txt ]; then + echo "Restoring executable permissions in ${{ runner.temp }}/Release ..." + while IFS= read -r file; do + # Check relative path existence within the current directory + if [ -f "$file" ]; then + chmod +x "$file" + else + echo "Warning: File '$file' listed in perms.txt not found." + fi + done < perms.txt + echo "Permissions restored." + else + echo "Warning: perms.txt not found in artifact." + fi + + # --- Run Tests using the downloaded build --- + # The run-build-script-in-docker action mounts ${{ runner.temp }} to /onnxruntime_src/build + # So build.py --build_dir build/Release inside the container correctly finds the artifacts. + - name: Test ONNX Runtime + id: test_step + uses: ./.github/_downloaded_actions/run-build-script-in-docker # Use downloaded action + with: + docker_image: onnxruntimetensorrt86gpubuild # Use the same image + build_config: Release + mode: 'test' # Set mode to test + execution_providers: 'cuda tensorrt' + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cuda_version=12.2 --cuda_home=/usr/local/cuda-12.2 --cudnn_home=/usr/local/cuda-12.2 --use_tensorrt --tensorrt_home /usr --build_java --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=80 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' diff --git a/.github/workflows/reusable_linux_build.yml b/.github/workflows/reusable_linux_build.yml index cf5c34a064965..a8d55b203bdca 100644 --- a/.github/workflows/reusable_linux_build.yml +++ b/.github/workflows/reusable_linux_build.yml @@ -1,4 +1,4 @@ -name: Reusable Linux CPU Build and Test +name: Reusable Linux CPU/GPU Build and Test on: workflow_call: @@ -23,8 +23,18 @@ on: description: 'Name for the Docker image repository' required: true type: string + docker_build_args: + description: 'Arguments to pass to the docker image build command' + required: false + type: string + default: '' + execution_providers: + description: 'Space-separated list of execution providers to enable (passed to build.py)' + required: false + type: string + default: '' extra_build_flags: - description: 'Additional flags for the build.py script' + description: 'Additional flags for the build.py script (appended after EP flags)' required: false type: string default: '' @@ -34,23 +44,33 @@ on: type: string default: '' python_version: - description: 'Python version to set up' + description: 'Python version to set up on the runner host' required: false type: string - default: '3.x' # Use a sensible default + default: '3.x' + run_tests: + description: 'Whether to execute the test suite after building' + required: false + type: boolean + default: true + upload_build_output: + description: 'Whether to upload the build output directory as an artifact (used when tests are skipped)' + required: false + type: boolean + default: false secrets: GH_TOKEN: description: 'GitHub token for accessing actions/packages' required: true jobs: - build_and_test: + build_test_pipeline: runs-on: - self-hosted - "1ES.Pool=${{ inputs.pool_name }}" permissions: contents: read - packages: read # Change to write when migrating to GHCR + packages: read steps: - name: Checkout code @@ -61,83 +81,119 @@ jobs: with: python-version: ${{ inputs.python_version }} + - name: Download ORT Actions Asset (v0.0.2) # <-- Adjust version as needed + uses: dsaltares/fetch-gh-release-asset@1.1.0 # Action to download assets + with: + repo: 'microsoft/onnxruntime-github-actions' # The repo containing the actions + version: 'tags/v0.0.2' # The specific tag/version to use + file: 'onnxruntime-actions-v0.0.2.zip' # The asset filename (matches release workflow output) + target: 'onnxruntime-actions.zip' # Local filename to save as + env: + # Use default token for public repos, provide PAT for private if necessary + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Unzip ORT Actions + run: | + mkdir -p ./.github/_downloaded_actions # Create a directory to hold them + unzip onnxruntime-actions.zip -d ./.github/_downloaded_actions + echo "Unzipped contents:" + ls -lR ./.github/_downloaded_actions # Verify structure + - name: Build Docker Image (${{ inputs.architecture }} / ${{ inputs.build_config }}) - uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.1 + uses: ./.github/_downloaded_actions/build-docker-image with: Dockerfile: ${{ github.workspace }}/${{ inputs.dockerfile_path }} Repository: ${{ inputs.docker_image_repo }} + DockerBuildArgs: ${{ inputs.docker_build_args }} env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - - name: Create .onnx directory - run: mkdir -p $HOME/.onnx - - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: script: | core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + # ------------- Update Step (CMake Generation) ------------- + - name: Generate Build Files (CMake) (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: update_step + uses: ./.github/_downloaded_actions/run-build-script-in-docker + with: + docker_image: ${{ inputs.docker_image_repo }} + build_config: ${{ inputs.build_config }} + mode: 'update' + execution_providers: ${{ inputs.execution_providers }} # Pass down EP list + extra_build_flags: ${{ inputs.extra_build_flags }} + python_path_prefix: ${{ inputs.python_path_prefix }} - # ------------- Main Build and Test Step ------------- - - name: Build and Test ONNX Runtime in Docker (${{ inputs.architecture }} / ${{ inputs.build_config }}) - id: build_test # Add an ID to potentially reference its outcome if needed, though `if: failure()` is simpler - env: - ALLOW_RELEASED_ONNX_OPSET_ONLY: 0 - NIGHTLY_BUILD: 1 - run: | - set -ex - # Construct the build command - BUILD_CMD="${{ inputs.python_path_prefix }} python3 tools/ci_build/build.py \ - --build_dir build/${{ inputs.build_config }} --cmake_generator Ninja \ - --config ${{ inputs.build_config }} \ - --skip_submodule_sync \ - --build_shared_lib \ - --parallel \ - --use_vcpkg --use_vcpkg_ms_internal_asset_cache \ - --enable_onnx_tests \ - ${{ inputs.extra_build_flags }}" # Add extra flags here + # ------------- Build Step (Compilation) ------------- + - name: Build ONNX Runtime (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: build_step + uses: ./.github/_downloaded_actions/run-build-script-in-docker + with: + docker_image: ${{ inputs.docker_image_repo }} + build_config: ${{ inputs.build_config }} + mode: 'build' + execution_providers: ${{ inputs.execution_providers }} # Pass down EP list + extra_build_flags: ${{ inputs.extra_build_flags }} + python_path_prefix: ${{ inputs.python_path_prefix }} - # Execute build - docker run --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume /data/models:/data/models:ro \ - --volume ${{ github.workspace }}:/onnxruntime_src \ - --volume ${{ runner.temp }}:/onnxruntime_src/build \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -w /onnxruntime_src \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ - -e NIGHTLY_BUILD \ - -e ACTIONS_RUNTIME_TOKEN \ - -e ACTIONS_CACHE_URL \ - -e RUNNER_TEMP=/onnxruntime_src/build \ - ${{ inputs.docker_image_repo }} \ - /bin/bash -c "${BUILD_CMD} --update --build" + # ------------- Test Step ------------- + - name: Test ONNX Runtime (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: test_step + if: inputs.run_tests == true + uses: ./.github/_downloaded_actions/run-build-script-in-docker + with: + docker_image: ${{ inputs.docker_image_repo }} + build_config: ${{ inputs.build_config }} + mode: 'test' + execution_providers: ${{ inputs.execution_providers }} # Pass down EP list + extra_build_flags: ${{ inputs.extra_build_flags }} + python_path_prefix: ${{ inputs.python_path_prefix }} + + # ------------- Prepare Artifact Step ------------- + - name: Prepare Build Output for Upload + if: inputs.upload_build_output == true + shell: bash + run: | + #!/bin/bash + set -e -x + BUILD_DIR="${{ runner.temp }}/${{ inputs.build_config }}" + if [ ! -d "${BUILD_DIR}" ]; then + echo "Error: Build directory ${BUILD_DIR} not found. Cannot prepare artifact." + exit 1 + fi + echo "--- Cleaning build directory: ${BUILD_DIR} ---" + rm -rf "${BUILD_DIR}/onnxruntime" || true + rm -rf "${BUILD_DIR}/pybind11" || true + rm -rf "${BUILD_DIR}/vcpkg_installed" || true + rm -f "${BUILD_DIR}/models" || true + DEPS_DIR="${BUILD_DIR}/_deps" + if [ -d "${DEPS_DIR}" ]; then + echo "Cleaning ${DEPS_DIR}, keeping onnx-src..." + find "${DEPS_DIR}" -mindepth 1 ! -regex "^${DEPS_DIR}/onnx-src\(/.*\)?$" -delete + else + echo "${DEPS_DIR} does not exist, skipping deps cleanup." + fi + echo "--- Saving executable permissions ---" + cd "${BUILD_DIR}" + find . -executable -type f -printf '%p\n' > perms.txt + echo "--- Cleanup and permission saving complete for ${BUILD_DIR} ---" - # Execute test (using the same base command but adding --test) - docker run --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume /data/models:/data/models:ro \ - --volume ${{ github.workspace }}:/onnxruntime_src \ - --volume ${{ runner.temp }}:/onnxruntime_src/build \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - -w /onnxruntime_src \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY \ - -e NIGHTLY_BUILD \ - -e ACTIONS_RUNTIME_TOKEN \ - -e ACTIONS_CACHE_URL \ - -e RUNNER_TEMP=/onnxruntime_src/build \ - ${{ inputs.docker_image_repo }} \ - /bin/bash -c "${BUILD_CMD} --test" - # ------------- End Main Build and Test Step ------------- + # ------------- Upload Build Output Step ------------- + - name: Upload Build Output Artifact + if: inputs.upload_build_output == true + uses: actions/upload-artifact@v4 + with: + name: build-output-${{ inputs.architecture }}-${{ inputs.build_config }} + path: ${{ runner.temp }}/${{ inputs.build_config }} + if-no-files-found: error - # ------------- Upload Log on Failure Step ------------- - - name: Upload VCPKG Manifest Install Log on Failure - if: failure() # This step only runs if the previous steps (like build_test) failed + # ------------- Upload Log on Build Failure Step ------------- + - name: Upload VCPKG Manifest Install Log on Update or Build Failure + if: steps.update_step.outcome == 'failure' || steps.build_step.outcome == 'failure' uses: actions/upload-artifact@v4 with: - name: vcpkg-manifest-install-log-${{ inputs.architecture }}-${{ inputs.build_config }} # Descriptive artifact name - # Use the exact path provided in the request - path: ${{ github.workspace }}/build/${{ inputs.build_config }}/${{ inputs.build_config }}/vcpkg-manifest-install.log + name: vcpkg-manifest-install-log-${{ inputs.architecture }}-${{ inputs.build_config }} + path: ${{ runner.temp }}/${{ inputs.build_config }}/${{ inputs.build_config }}/vcpkg-manifest-install.log if-no-files-found: ignore - # ------------- End Upload Log on Failure Step ------------- diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml index 2508bb2079119..621cb2630b33e 100644 --- a/.github/workflows/windows_x64_debug_build_x64_debug.yml +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -2,7 +2,7 @@ name: windows_x64_debug on: push: - branches: [ main, 'rel-*'] + branches: [ main, 'rel-*', 'snnn/linux_ci2'] pull_request: branches: [ main ] @@ -27,6 +27,18 @@ jobs: python-version: '3.12' architecture: x64 + - name: Setup VCPKG + uses: microsoft/onnxruntime-github-actions/setup-vcpkg@35f8bd42417991aa46577e9c32e445af4250f098 + with: + vcpkg-version: '2025.03.19' + vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' + + - name: Verify vcpkg setup + shell: pwsh # Use powershell to easily access env var + run: | + Write-Host "VCPKG_INSTALLATION_ROOT is set to: $env:VCPKG_INSTALLATION_ROOT" + & "$env:VCPKG_INSTALLATION_ROOT/vcpkg" version + - name: Locate vcvarsall and Setup Env uses: ./.github/actions/locate-vcvarsall-and-setup-env # Use the composite action with: diff --git a/onnxruntime/test/providers/base_tester.cc b/onnxruntime/test/providers/base_tester.cc index eecff3fa4d8ff..85f96206b5dba 100644 --- a/onnxruntime/test/providers/base_tester.cc +++ b/onnxruntime/test/providers/base_tester.cc @@ -537,7 +537,7 @@ void BaseTester::Run(ExpectResult expect_result, const std::string& expected_fai SessionOptions so; so.use_per_session_threads = false; so.session_logid = test_name_; - so.session_log_verbosity_level = 1; + so.session_log_verbosity_level = 0; so.execution_mode = execution_mode; so.use_deterministic_compute = use_determinism_; so.graph_optimization_level = TransformerLevel::Default; // 'Default' == off diff --git a/onnxruntime/test/providers/cpu/model_tests.cc b/onnxruntime/test/providers/cpu/model_tests.cc index fa6b8b7e2274d..d5f6f1ddf700e 100644 --- a/onnxruntime/test/providers/cpu/model_tests.cc +++ b/onnxruntime/test/providers/cpu/model_tests.cc @@ -444,8 +444,8 @@ ::std::vector<::std::basic_string> GetParameterStrings() { // The other EPs can choose which opsets to test. // If an EP doesn't have any CI build pipeline, then there is no need to specify any opset. #ifdef USE_TENSORRT - // tensorrt: only enable opset 12 to 17 of onnx tests - provider_names[provider_name_tensorrt] = {opset12, opset14, opset15, opset16, opset17}; + // tensorrt: only enable opset 14 to 17 of onnx tests + provider_names[provider_name_tensorrt] = {opset14, opset15, opset16, opset17}; #endif #ifdef USE_MIGRAPHX provider_names[provider_name_migraphx] = {opset7, opset8, opset9, opset10, opset11, opset12, opset13, opset14, opset15, opset16, opset17, opset18}; diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml deleted file mode 100644 index 492bada97acc9..0000000000000 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml +++ /dev/null @@ -1,221 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### -parameters: - - name: CudaVersion - displayName: CUDA version - type: string - default: '12.2' - values: - - 12.2 - - - name: SpecificArtifact - displayName: Use Specific Artifact - type: boolean - default: false - - - name: BuildId - displayName: Specific Artifact's BuildId - type: string - default: '0' - -variables: - - name: docker_base_image - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20250124.1 - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 - - - name: Repository - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: 'onnxruntimecuda11manylinuxbuild' - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: 'onnxruntimecuda12manylinuxbuild' - -stages: -- stage: Linux_Build - jobs: - - job: Linux_Build - timeoutInMinutes: 120 - variables: - skipComponentGovernanceDetection: true - CCACHE_DIR: $(Pipeline.Workspace)/ccache - workspace: - clean: all - pool: onnxruntime-Ubuntu2204-AMD-CPU - - steps: - - - checkout: self - clean: true - submodules: none - - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda - Context: tools/ci_build/github/linux/docker - DockerBuildArgs: "--build-arg BASEIMAGE=$(docker_base_image) --build-arg BUILD_UID=$( id -u )" - Repository: $(Repository) - - - task: Cache@2 - inputs: - key: '"ccache" | "${{parameters.CudaVersion}}" |"$(Build.SourceBranch)" | "$(Build.SourceVersion)"' - path: $(CCACHE_DIR) - restoreKeys: | - "ccache" | "${{parameters.CudaVersion}}" | "$(Build.SourceBranch)" - "ccache" - cacheHitVar: CACHE_RESTORED - displayName: Cach Task - - - script: | - sudo mkdir -p $(Pipeline.Workspace)/ccache - condition: ne(variables.CACHE_RESTORED, 'true') - displayName: Create Cache Dir - - - script: | - set -e -x - mkdir -p $HOME/.onnx - docker run --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - --volume $(Pipeline.Workspace)/ccache:/cache \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY=0 \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - -e CCACHE_DIR=/cache -w /onnxruntime_src \ - $(Repository) tools/ci_build/github/linux/build_cuda_ci.sh - workingDirectory: $(Build.SourcesDirectory) - displayName: Build Onnxruntime - - - script: $(Build.SourcesDirectory)/tools/ci_build/github/linux/delete_unused_files_before_upload.sh - - - task: PublishPipelineArtifact@0 - displayName: 'Publish Pipeline Artifact' - inputs: - artifactName: 'drop-linux' - targetPath: '$(Build.BinariesDirectory)/Release' - - - template: templates/explicitly-defined-final-tasks.yml - -- stage: Linux_Test - dependsOn: - - Linux_Build - jobs: - - job: Linux_Test - timeoutInMinutes: 180 - variables: - skipComponentGovernanceDetection: true - workspace: - clean: all - pool: Onnxruntime-Linux-GPU-A100-WUS3 - steps: - - checkout: self - clean: true - submodules: none - - - template: templates/flex-downloadPipelineArtifact.yml - parameters: - ArtifactName: 'drop-linux' - StepName: 'Download Pipeline Artifact - Linux Build' - TargetPath: '$(Build.BinariesDirectory)/Release' - SpecificArtifact: ${{ parameters.SpecificArtifact }} - BuildId: ${{ parameters.BuildId }} - - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda - Context: tools/ci_build/github/linux/docker - DockerBuildArgs: "--build-arg BASEIMAGE=$(docker_base_image) --build-arg BUILD_UID=$( id -u )" - Repository: $(Repository) - - - task: CmdLine@2 - inputs: - script: | - set -e -x - mkdir -p $HOME/.onnx - docker run --gpus all --rm \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory)/Release:/build/Release \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - --volume /data/onnx:/data/onnx \ - -e NVIDIA_TF32_OVERRIDE=0 \ - $(Repository) \ - /bin/bash -c ' - set -e - nvidia-smi; \ - /sbin/ldconfig -N -v $(sed "s/:/ /" <<< $LD_LIBRARY_PATH) 2>/dev/null | grep -E "libcudart.so|libcudnn.so|libnvinfer.so"; \ - cat /usr/local/cuda/include/cuda.h | grep -m1 CUDA_VERSION; \ - cat /usr/include/cudnn_version.h | grep CUDNN_MAJOR -m1 -A 2; \ - export PATH=/opt/python/cp312-cp312/bin:$PATH; \ - python3 -m pip install /build/Release/dist/*.whl; \ - python3 -u -c "from onnxruntime.capi._pybind_state import (OrtDevice as C_OrtDevice) ; \ - ort_device = C_OrtDevice(C_OrtDevice.cuda(), C_OrtDevice.default_memory(), 0); \ - print(ort_device); print(ort_device.device_type(), C_OrtDevice.cuda()); \ - assert(ort_device.device_type()==1); assert(C_OrtDevice.cuda()==1);" \ - ' - displayName: 'Check GPU' - - - task: CmdLine@2 - inputs: - script: | - set -e -x - mkdir -p $HOME/.onnx - docker run --gpus all --shm-size=1g --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 --rm \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory)/Release:/build/Release \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - --volume /data/onnx:/data/onnx \ - -e NVIDIA_TF32_OVERRIDE=0 \ - $(Repository) \ - /bin/bash -c ' - set -ex; \ - cp /onnxruntime_src/tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt /tmp/requirements.txt; \ - export PATH=/opt/python/cp312-cp312/bin:$PATH; \ - python3 -m pip install -r /tmp/requirements.txt; \ - python3 -m pip install /build/Release/dist/*.whl; \ - cd /build/Release && xargs -a /build/Release/perms.txt chmod a+x; \ - cd /onnxruntime_src/java && /onnxruntime_src/java/gradlew cmakeCheck -DcmakeBuildDir=/build/Release -DUSE_CUDA=1; \ - cd /tmp; \ - python3 /onnxruntime_src/tools/ci_build/build.py \ - --build_dir /build --config Release --test --skip_submodule_sync --build_shared_lib --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --use_binskim_compliant_compile_flags --build_wheel --enable_onnx_tests \ - --enable_transformers_tool_test --use_cuda --cuda_version=${{parameters.CudaVersion}} --cuda_home=/usr/local/cuda --cudnn_home=/usr/local/cuda \ - --enable_pybind --build_java --ctest_path "" ; \ - ' - displayName: 'Run Tests' - - - template: templates/check_test_result.yml - parameters: - FileName: '$(Build.BinariesDirectory)/Release/onnxruntime_test_all.Release.results.xml' - - - template: templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml deleted file mode 100644 index c6eabed7c5b4a..0000000000000 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml +++ /dev/null @@ -1,104 +0,0 @@ -##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### -### please do rerun set-trigger-rules.py ### -trigger: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -pr: - branches: - include: - - main - - rel-* - paths: - exclude: - - docs/** - - README.md - - CONTRIBUTING.md - - BUILD.md - - 'js/web' - - 'onnxruntime/core/providers/js' -#### end trigger #### -parameters: - - name: CudaVersion - displayName: CUDA version - type: string - default: '12.2' - values: - - 12.2 - -variables: - - template: templates/common-variables.yml - - name: docker_base_image - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20250124.1 - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 - - name: linux_trt_version - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: ${{ variables.linux_trt_version_cuda11 }} - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: ${{ variables.linux_trt_version_cuda12 }} - -jobs: -- job: Linux_Build - timeoutInMinutes: 180 - variables: - skipComponentGovernanceDetection: true - ALLOW_RELEASED_ONNX_OPSET_ONLY: '1' - ORT_CACHE_DIR: '$(Agent.TempDirectory)/ort/ccache' - TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] - workspace: - clean: all - pool: onnxruntime-tensorrt-linuxbuild-T4 - steps: - - - checkout: self - clean: true - submodules: none - - - template: templates/get-docker-image-steps.yml - parameters: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda - Context: tools/ci_build/github/linux/docker - DockerBuildArgs: " - --network=host - --build-arg BASEIMAGE=${{ variables.docker_base_image }} - --build-arg TRT_VERSION=${{ variables.linux_trt_version }} - --build-arg BUILD_UID=$( id -u ) - " - Repository: onnxruntimetensorrt86gpubuild - - - template: templates/linux-build-step-with-cache.yml - parameters: - WithCache: true - Today: $(TODAY) - AdditionalKey: gpu_tensorrt - CacheDir: '$(ORT_CACHE_DIR)' - BuildStep: - - task: CmdLine@2 - inputs: - script: | - docker run -e SYSTEM_COLLECTIONURI --gpus all --rm \ - --volume /data/onnx:/data/onnx:ro \ - --volume $(Build.SourcesDirectory):/onnxruntime_src \ - --volume $(Build.BinariesDirectory):/build \ - --volume /data/models:/build/models:ro \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx \ - --volume $(ORT_CACHE_DIR):/cache \ - -e ALLOW_RELEASED_ONNX_OPSET_ONLY=0 \ - -e NIGHTLY_BUILD \ - -e BUILD_BUILDNUMBER \ - -e CCACHE_DIR=/cache -w /onnxruntime_src \ - onnxruntimetensorrt86gpubuild tools/ci_build/github/linux/build_tensorrt_ci.sh - workingDirectory: $(Build.SourcesDirectory) - - - template: templates/explicitly-defined-final-tasks.yml From 41dde351f894dd73edce86e4391a158c63371843 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:42:14 -0700 Subject: [PATCH 193/266] Migrate Web CI into github actions (#24219) ### Description This PR migrates the Web CI into github actions. --- .../linux-web-init-and-check/action.yml | 71 +++++ .../webgpu-validate-shader-key/action.yml | 28 ++ .../parse-chromium-debug-log.js | 30 +++ .../validate-shader-key.js | 94 +++++++ .../linux-wasm-ci-build-and-test-workflow.yml | 136 ++++++++++ .github/workflows/web.yml | 71 +++++ .github/workflows/windows-web-ci-workflow.yml | 249 ++++++++++++++++++ 7 files changed, 679 insertions(+) create mode 100644 .github/actions/linux-web-init-and-check/action.yml create mode 100644 .github/actions/webgpu-validate-shader-key/action.yml create mode 100644 .github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js create mode 100644 .github/actions/webgpu-validate-shader-key/validate-shader-key.js create mode 100644 .github/workflows/linux-wasm-ci-build-and-test-workflow.yml create mode 100644 .github/workflows/web.yml create mode 100644 .github/workflows/windows-web-ci-workflow.yml diff --git a/.github/actions/linux-web-init-and-check/action.yml b/.github/actions/linux-web-init-and-check/action.yml new file mode 100644 index 0000000000000..c250f368a953e --- /dev/null +++ b/.github/actions/linux-web-init-and-check/action.yml @@ -0,0 +1,71 @@ +name: "Web Build Initialize and Check on Linux" +description: "Initializes and checks the ONNX Runtime Web build on Linux." +runs: + using: "composite" + steps: + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: "22.x" + + - name: npm ci /js/ + run: npm ci + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: npm ci /js/common/ + run: npm ci + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: run onnxruntime-common tests + run: npm test + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: run onnxruntime-common tests (enable Float16Array) + run: npm run test:f16 + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: npm ci /js/web/ + run: npm ci + shell: bash + working-directory: ${{ github.workspace }}/js/web + + - name: run TypeScript type check in /js/web/ + run: npm run prebuild + shell: bash + working-directory: ${{ github.workspace }}/js/web + + - name: run ESLint + run: npm run lint + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: Format code + run: npm run format + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: Check unformatted files + run: | + node -e "a=require('child_process').execSync('git diff --name-only').toString();if(a)throw new Error('Following source files are not formatted: (did you run \"npm run format\"?)\n'+a)" + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: TypeDoc Validation + run: npx typedoc --emit none --treatWarningsAsErrors + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: Generating documents + run: npm run build:doc + shell: bash + working-directory: ${{ github.workspace }}/js/web + + - name: Check out of dated documents + run: | + node -e "a=require('child_process').execSync('git diff --name-only').toString();if(a)throw new Error('Following documents are not up-to-date: (did you run \"npm run build:doc\"?)\n'+a)" + shell: bash + working-directory: ${{ github.workspace }}/js/web diff --git a/.github/actions/webgpu-validate-shader-key/action.yml b/.github/actions/webgpu-validate-shader-key/action.yml new file mode 100644 index 0000000000000..edf8a876041b9 --- /dev/null +++ b/.github/actions/webgpu-validate-shader-key/action.yml @@ -0,0 +1,28 @@ +name: "WebGPU Validate Shader Key" +description: "Validate if the shader key is consistent for WebGPU shaders." + +inputs: + log_file_path: + required: true + type: string + is_chromium_log: + required: false + type: boolean + default: false + +runs: + using: "composite" + steps: + - name: Validate shader keys (chromium log) + if: ${{ inputs.is_chromium_log }} + shell: cmd + run: | + node parse-chromium-debug-log.js < "${{ inputs.log_file_path }}" | node validate-shader-key.js + working-directory: ${{ github.action_path }} + + - name: Validate shader keys (native log) + if: ${{ !inputs.is_chromium_log }} + shell: cmd + run: | + node validate-shader-key.js < "${{ inputs.log_file_path }}" + working-directory: ${{ github.action_path }} diff --git a/.github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js b/.github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js new file mode 100644 index 0000000000000..2342381f03934 --- /dev/null +++ b/.github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +"use strict"; + +const { EOL } = require("os"); +const readline = require("readline"); + +// This script is used to parse the Chromium debug log and extract the raw log data. + +async function processChromiumDebugLog() { + const rl = readline.createInterface({ + input: process.stdin, + crlfDelay: Infinity, + }); + + for await (const line of rl) { + const result = + /^\[.+INFO:CONSOLE\(\d+\)]\ "(?.+)",\ source:\ [^"]+?\(\d+\)$/.exec( + line + ); + if (!result) { + continue; + } + const rawLogData = result.groups.raw_log_data; + process.stdout.write(`${rawLogData}${EOL}`); + } +} + +processChromiumDebugLog(); diff --git a/.github/actions/webgpu-validate-shader-key/validate-shader-key.js b/.github/actions/webgpu-validate-shader-key/validate-shader-key.js new file mode 100644 index 0000000000000..e8d750e77d322 --- /dev/null +++ b/.github/actions/webgpu-validate-shader-key/validate-shader-key.js @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +"use strict"; + +const { EOL } = require("os"); +const readline = require("readline"); + +// This script is used to parse the raw log data and check if there are inconsistent shader. +// When the shader key is the same, the shader code should be the same. + +const shaderMap = new Map(); + +const regexShaderStart = + /^===\ WebGPU\ Shader\ code\ \[.+?Key=\"(?.+)\"]\ Start\ ===$/; +const regexShaderEnd = + /^===\ WebGPU\ Shader\ code\ \[.+?Key=\"(?.+)\"]\ End\ ===$/; + +async function processVerboseLog() { + const rl = readline.createInterface({ + input: process.stdin, + crlfDelay: Infinity, + }); + + let currentShaderKey = null; + let currentShaderCode = null; + + for await (const line of rl) { + const resultStart = regexShaderStart.exec(line); + if (resultStart) { + if (currentShaderKey) { + throw new Error( + `Found incomplete shader code for key "${currentShaderKey}".` + ); + } + + currentShaderKey = resultStart.groups.key; + currentShaderCode = ""; + continue; + } + + const resultEnd = regexShaderEnd.exec(line); + if (resultEnd) { + if (!currentShaderKey) { + throw new Error( + `Found unexpected shader end for key "${resultEnd.groups.key}".` + ); + } else if (currentShaderKey !== resultEnd.groups.key) { + throw new Error( + `Found inconsistent shader key. Expected "${currentShaderKey}", but got "${resultEnd.groups.key}".` + ); + } + + if (shaderMap.has(currentShaderKey)) { + if (shaderMap.get(currentShaderKey) !== currentShaderCode) { + throw new Error(`Found inconsistent shader code for key "${currentShaderKey}". +=== Previous Shader Start === +${shaderMap.get(currentShaderKey)} +=== Previous Shader End === + +=== Current Shader Start === +${currentShaderCode} +=== Current Shader End ===`); + } + } else { + shaderMap.set(currentShaderKey, currentShaderCode); + } + + currentShaderKey = null; + currentShaderCode = null; + continue; + } + + if (currentShaderKey) { + currentShaderCode += line + EOL; + } + } + + if (currentShaderKey) { + throw new Error( + `Found incomplete shader code for key "${currentShaderKey}".` + ); + } + + if (shaderMap.size === 0) { + throw new Error("No shader code found."); + } + + console.log( + `All shader code is consistent. Total ${shaderMap.size} shader code found.` + ); +} + +processVerboseLog(); diff --git a/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml new file mode 100644 index 0000000000000..d67562c4a3028 --- /dev/null +++ b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml @@ -0,0 +1,136 @@ +name: "Linux WASM CI Reusable Workflow for build and test" +description: "This is a reusable workflow for Linux WASM CI pipelines to build and test" + +on: + workflow_call: + inputs: + build_config: + required: true + type: string + extra_build_args: + required: false + type: string + default: "" + skip_publish: + required: false + type: boolean + default: false + build_jsep: + required: false + type: boolean + default: false + build_webgpu: + required: false + type: boolean + default: false + +jobs: + build-wasm: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + env: + buildArch: x64 + common_build_args: --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --config ${{ inputs.build_config }} --skip_submodule_sync --build_wasm --enable_wasm_simd --enable_wasm_threads ${{ inputs.extra_build_args }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + architecture: ${{ env.buildArch }} + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Install EMSDK + run: | + set -ex + cd ${{ github.workspace }}/cmake/external/emsdk + ./emsdk install 4.0.4 + ./emsdk activate 4.0.4 + + - name: Build and test (browser) (simd + threads) + run: | + set -e -x + source ${{ github.workspace }}/cmake/external/emsdk/emsdk_env.sh + cd '${{ github.workspace }}' + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing \ + --wasm_run_tests_in_browser + + - name: Build (simd + threads + JSEP) + if: ${{ inputs.build_jsep == true }} + run: | + set -e -x + source ${{ github.workspace }}/cmake/external/emsdk/emsdk_env.sh + cd '${{ github.workspace }}' + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing_jsep \ + --use_jsep \ + --use_webnn \ + --target onnxruntime_webassembly \ + --skip_tests + + - name: Build (simd + threads + WebGPU experimental) + if: ${{ inputs.build_webgpu == true }} + run: | + set -e -x + source ${{ github.workspace }}/cmake/external/emsdk/emsdk_env.sh + cd '${{ github.workspace }}' + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing_webgpu \ + --use_webgpu \ + --use_jsep \ + --use_webnn \ + --target onnxruntime_webassembly \ + --skip_tests + + - name: Create Artifacts + if: ${{ inputs.skip_publish != true }} + run: | + mkdir -p ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing/${{ inputs.build_config }}/ort-wasm-simd-threaded.wasm ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing/${{ inputs.build_config }}/ort-wasm-simd-threaded.mjs ${{ github.workspace }}/artifacts/wasm/ + if [ -d ${{ github.workspace }}/build/wasm_inferencing_jsep ]; then + cp ${{ github.workspace }}/build/wasm_inferencing_jsep/${{ inputs.build_config }}/ort-wasm-simd-threaded.jsep.wasm ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing_jsep/${{ inputs.build_config }}/ort-wasm-simd-threaded.jsep.mjs ${{ github.workspace }}/artifacts/wasm/ + fi + + - name: Create WebGPU Artifacts + if: ${{ inputs.skip_publish != true && inputs.build_webgpu == true }} + run: | + mkdir -p ${{ github.workspace }}/artifacts/wasm_webgpu/ + cp ${{ github.workspace }}/build/wasm_inferencing_webgpu/${{ inputs.build_config }}/ort-wasm-simd-threaded.jsep.wasm ${{ github.workspace }}/artifacts/wasm_webgpu/ + cp ${{ github.workspace }}/build/wasm_inferencing_webgpu/${{ inputs.build_config }}/ort-wasm-simd-threaded.jsep.mjs ${{ github.workspace }}/artifacts/wasm_webgpu/ + + - name: Upload WASM artifacts + if: ${{ inputs.skip_publish != true }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.build_config }}_wasm + path: ${{ github.workspace }}/artifacts/wasm + + - name: Upload WebGPU artifacts + if: ${{ inputs.skip_publish != true && inputs.build_webgpu == true }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.build_config }}_wasm_webgpu + path: ${{ github.workspace }}/artifacts/wasm_webgpu + + - name: Publish test results + if: ${{ always() && inputs.build_config == 'Debug' }} + uses: actions/upload-artifact@v4 + with: + name: test-results + path: ${{ github.workspace }}/build/**/*.results.xml diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml new file mode 100644 index 0000000000000..8490252ca657b --- /dev/null +++ b/.github/workflows/web.yml @@ -0,0 +1,71 @@ +name: Web CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + precheck: + runs-on: ubuntu-latest + outputs: + commit_sha: ${{ steps.extract_commit.outputs.commit_sha }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: true + + - name: Init and Precheck + uses: ./.github/actions/linux-web-init-and-check + + - name: Extract commit SHA + id: extract_commit + run: echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT + shell: bash + + wasm_Debug: + needs: precheck + uses: ./.github/workflows/linux-wasm-ci-build-and-test-workflow.yml + with: + build_config: Debug + extra_build_args: "--enable_wasm_profiling" + build_jsep: true + build_webgpu: true + + wasm_Release: + needs: precheck + uses: ./.github/workflows/linux-wasm-ci-build-and-test-workflow.yml + with: + build_config: Release + extra_build_args: "--target onnxruntime_webassembly --skip_tests --enable_wasm_api_exception_catching --disable_rtti" + build_jsep: true + build_webgpu: true + + web_Debug: + needs: + - precheck + - wasm_Debug + uses: ./.github/workflows/windows-web-ci-workflow.yml + with: + commit_override: ${{ needs.precheck.outputs.commit_sha }} + build_config: Debug + + web_Release: + needs: + - precheck + - wasm_Release + uses: ./.github/workflows/windows-web-ci-workflow.yml + with: + commit_override: ${{ needs.precheck.outputs.commit_sha }} + build_config: Release diff --git a/.github/workflows/windows-web-ci-workflow.yml b/.github/workflows/windows-web-ci-workflow.yml new file mode 100644 index 0000000000000..d18601da6279b --- /dev/null +++ b/.github/workflows/windows-web-ci-workflow.yml @@ -0,0 +1,249 @@ +name: "Windows Web CI Workflow" +description: "Windows Web CI pipeline for building and testing ONNX Runtime Web" + +on: + workflow_call: + inputs: + commit_override: + type: string + default: "" + build_config: + type: string + default: "Debug" + npm_packaging_mode: + type: string + default: "dev" + package_name: + type: string + default: "NPM_packages" + run_webgpu_tests: + type: boolean + default: true + +jobs: + build_onnxruntime_web: + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-WEBGPU-A10"] + + env: + webgpu_commandline_extra_flags: "--chromium-flags=--ignore-gpu-blocklist --chromium-flags=--gpu-vendor-id=0x10de" + CHROME_BIN: 'C:\Program Files\Google\Chrome\Application\chrome.exe' + + timeout-minutes: 60 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: false + + - name: Read commit SHA and checkout + if: ${{ inputs.commit_override != '' }} + shell: cmd + run: | + git fetch origin +${{ inputs.commit_override }}:refs/remotes/origin/${{ inputs.commit_override }} + git checkout --force ${{ inputs.commit_override }} + + - name: Write commit SHA to __commit.txt + if: ${{ inputs.commit_override == '' }} + shell: cmd + run: | + echo.${{ github.sha }}>${{ github.workspace }}/__commit.txt + + - name: Checkout submodule onnx + shell: cmd + run: | + git submodule sync -- cmake\external\onnx + git submodule update --init -- cmake\external\onnx + + - name: Force EOL to LF on windows for /js/** + shell: cmd + run: | + echo.>>.gitattributes + echo /js/** text=auto eol=lf>>.gitattributes + rd /s /q js + git checkout -- js/** + git checkout -- .gitattributes + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.x" + + - name: Download WebAssembly artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.build_config }}_wasm + path: ${{ github.workspace }}/artifacts_wasm + + - name: Binplace dist files (.wasm) + shell: cmd + run: | + mkdir ${{ github.workspace }}\js\web\dist + copy ${{ github.workspace }}\artifacts_wasm\ort-*.wasm ${{ github.workspace }}\js\web\dist\ + + - name: Binplace dist files (.mjs) + shell: cmd + run: | + copy ${{ github.workspace }}\artifacts_wasm\ort-*.mjs ${{ github.workspace }}\js\web\dist\ + + - name: npm ci for /js/ + run: npm ci + working-directory: ${{ github.workspace }}/js + + - name: npm ci for /js/common/ + run: npm ci + working-directory: ${{ github.workspace }}/js/common + + - name: npm ci for /js/web/ + run: npm ci + working-directory: ${{ github.workspace }}/js/web + + - uses: actions/cache@v3 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Pack NPM packages + shell: pwsh + run: | + . ${{ github.workspace }}\tools\ci_build\github\js\pack-npm-packages.ps1 ${{ inputs.npm_packaging_mode }} ${{ github.workspace }} web + + - name: Check active Chrome processes (before test) + if: ${{ runner.debug == '1' }} + shell: pwsh + run: | + Get-WmiObject Win32_Process -Filter "name = 'chrome.exe'" | Format-List CommandLine + + - name: Run ort-web tests (wasm,webgl backend) + if: ${{ inputs.run_webgpu_tests != true }} + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\01 + dir ${{ runner.temp }}\web\test\01 + npm test -- -e=chrome -b=webgl,wasm --user-data-dir=${{ runner.temp }}\web\test\01 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests (ALL backends) + if: ${{ inputs.run_webgpu_tests == true }} + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\02 + dir ${{ runner.temp }}\web\test\02 + npm test -- -e=chrome -b=webgl,wasm,webgpu ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\02 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests (Suite1, webgpu, IO-binding=gpu-tensor) + if: ${{ inputs.run_webgpu_tests == true }} + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\03 + dir ${{ runner.temp }}\web\test\03 + npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-tensor ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\03 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests (Suite1, webgpu, IO-binding=gpu-location) + if: ${{ inputs.run_webgpu_tests == true }} + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\04 + dir ${{ runner.temp }}\web\test\04 + npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-location ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\04 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests - WebGL packed mode + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\05 + dir ${{ runner.temp }}\web\test\05 + npm test -- --webgl.pack -b=webgl -e=chrome --user-data-dir=${{ runner.temp }}\web\test\05 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests - WebAssembly proxy + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\06 + dir ${{ runner.temp }}\web\test\06 + npm test -- --wasm.proxy -b=wasm -e=chrome --user-data-dir=${{ runner.temp }}\web\test\06 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + # WebGPU EP tests + - name: Download WebAssembly WebGPU artifacts + if: ${{ inputs.run_webgpu_tests == true }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.build_config }}_wasm_webgpu + path: ${{ github.workspace }}/artifacts_wasm_webgpu + + - name: Binplace dist files (.wasm) for WebGPU + if: ${{ inputs.run_webgpu_tests == true }} + shell: cmd + run: | + copy /Y ${{ github.workspace }}\artifacts_wasm_webgpu\ort-*.wasm ${{ github.workspace }}\js\web\dist\ + + - name: Binplace dist files (.mjs) for WebGPU + if: ${{ inputs.run_webgpu_tests == true }} + shell: cmd + run: | + copy /Y ${{ github.workspace }}\artifacts_wasm_webgpu\ort-*.mjs ${{ github.workspace }}\js\web\dist\ + + - name: Run ort-web tests - WebGPU EP + if: ${{ inputs.run_webgpu_tests == true }} + continue-on-error: true + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\07 + dir ${{ runner.temp }}\web\test\07 + npm test --webgpu-ep -- suite1 ${{ inputs.build_config == 'Debug' && '--log-verbose' || '' }} -b=webgpu -e=chrome ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\07 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Validate shader keys - WebGPU EP + if: ${{ inputs.run_webgpu_tests == true && inputs.build_config == 'Debug' }} + continue-on-error: true + uses: ./.github/actions/webgpu-validate-shader-key + with: + log_file_path: ${{ runner.temp }}\web\test\07\chrome_debug.log + is_chromium_log: true + + - name: E2E package consuming test + if: ${{ inputs.build_config == 'Release' }} + run: npm run test:e2e -- --browser=Chrome_default + working-directory: ${{ github.workspace }}\js\web + + - name: Create artifacts directory + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: mkdir ${{ github.workspace }}\artifacts_npm + + - name: Copy onnxruntime-common artifacts + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: | + if exist ${{ github.workspace }}\js\common\onnxruntime-common-*.tgz ( + copy ${{ github.workspace }}\js\common\onnxruntime-common-*.tgz ${{ github.workspace }}\artifacts_npm\ + ) + + - name: Copy onnxruntime-web artifacts + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: copy ${{ github.workspace }}\js\web\onnxruntime-web-*.tgz ${{ github.workspace }}\artifacts_npm\ + + - name: Upload NPM packages + if: ${{ inputs.build_config == 'Release' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.package_name }} + path: ${{ github.workspace }}\artifacts_npm + + - name: Log Chrome processes (after test) + if: ${{ always() && runner.debug == '1' }} + shell: cmd + run: | + for %%i in (01 02 03 04 05 06 07) do ( + if exist ${{ runner.temp }}\web\test\%%i ( + echo ------------------- BEGIN %%i ------------------- + type ${{ runner.temp }}\web\test\%%i\chrome_debug.log + echo ------------------- END %%i ------------------- + ) + ) From 4a669fd1625f9953cdbe6e7602cde560a0e25e4a Mon Sep 17 00:00:00 2001 From: Hector Li Date: Fri, 28 Mar 2025 18:24:28 -0700 Subject: [PATCH 194/266] update the readme doc for the tool ep_weight_sharing_ctx_gen (#24233) ### Description update the readme to remove something Qnn specific for the tool ep_weight_sharing_ctx_gen --------- Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com> --- onnxruntime/test/ep_weight_sharing_ctx_gen/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md b/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md index be1a1fe039366..1d76d37079a44 100644 --- a/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md @@ -1,6 +1,10 @@ -# ONNXRuntime Qnn Context Generator +# ONNXRuntime EP Context Model Generation with Weight Sharing -This tool provides the way to generate Onnx models that wraps QNN context binary warpt with weight sharing enabled. The options to use with the tool are listed below: +[EP context with weight sharing design doc](https://onnxruntime.ai/docs/execution-providers/EP-Context-Design.html#epcontext-with-weight-sharing) + +OnnxRuntime provides the ep_weight_sharing_ctx_gen tool to automate the weight-sharing workflow. This tool handles the entire process. This tool is specifically designed for weight sharing scenarios, streamlining the EPContext model generation process. + +Example command line: `ep_weight_sharing_ctx_gen [options...] model_1_path,model_2_path` From 7ef0ddc580af51ca66804cba716f31a592bb56fa Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Fri, 28 Mar 2025 21:59:19 -0700 Subject: [PATCH 195/266] [WebGPU EP] If Implementation for WebGPU EP (#24242) Increases operator covereage for WebGPU EP. --- onnxruntime/core/framework/session_state.cc | 2 +- .../core/providers/webgpu/controlflow/if.cc | 77 +++++++++++++++++++ .../core/providers/webgpu/controlflow/if.h | 22 ++++++ .../webgpu/webgpu_execution_provider.cc | 12 +-- 4 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/controlflow/if.cc create mode 100644 onnxruntime/core/providers/webgpu/controlflow/if.h diff --git a/onnxruntime/core/framework/session_state.cc b/onnxruntime/core/framework/session_state.cc index 27aa4f38a4ec9..a8c1a7515ae82 100644 --- a/onnxruntime/core/framework/session_state.cc +++ b/onnxruntime/core/framework/session_state.cc @@ -1127,7 +1127,7 @@ Status SessionState::CreateSubgraphSessionState() { if (!ep.empty() && ep != kCpuExecutionProvider && ep != kCudaExecutionProvider && ep != kRocmExecutionProvider && ep != kDmlExecutionProvider && - ep != kJsExecutionProvider) { + ep != kJsExecutionProvider && ep != kWebGpuExecutionProvider) { // SessionState is only used when ORT is executing the subgraph. If a non-ORT EP has taken the control flow // node containing the subgraph it will create whatever state it needs internally. continue; diff --git a/onnxruntime/core/providers/webgpu/controlflow/if.cc b/onnxruntime/core/providers/webgpu/controlflow/if.cc new file mode 100644 index 0000000000000..233d1f760383f --- /dev/null +++ b/onnxruntime/core/providers/webgpu/controlflow/if.cc @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/controlflow/if.h" + +using namespace ONNX_NAMESPACE; +using namespace onnxruntime::common; + +namespace onnxruntime { +namespace webgpu { + +ONNX_OPERATOR_VERSIONED_KERNEL_EX(If, + kOnnxDomain, + 1, 10, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 0) // 'cond' needs to be on CPU + .TypeConstraint("B", DataTypeImpl::GetTensorType()) + .TypeConstraint("V", DataTypeImpl::AllFixedSizeTensorTypes()), + If); +// output shape rules requiring the output shapes of the 'THEN' and 'ELSE' +// branches to be the same were relaxed in opset-11 +ONNX_OPERATOR_VERSIONED_KERNEL_EX(If, + kOnnxDomain, + 11, 12, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 0) // 'cond' needs to be on CPU + .TypeConstraint("B", DataTypeImpl::GetTensorType()) + .TypeConstraint("V", DataTypeImpl::AllFixedSizeTensorTypes()), + If); + +// opset-13 supports sequence type for If's subgraph outputs +ONNX_OPERATOR_VERSIONED_KERNEL_EX(If, + kOnnxDomain, + 13, 18, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 0) // 'cond' needs to be on CPU + .TypeConstraint("B", DataTypeImpl::GetTensorType()) + // Support sequence/optional tensors when all WebGPU infra + // (including tests runner) supports it + .TypeConstraint("V", DataTypeImpl::AllFixedSizeTensorTypes()), + If); + +// opset-19 supports float8 +ONNX_OPERATOR_VERSIONED_KERNEL_EX(If, + kOnnxDomain, + 19, 20, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 0) // 'cond' needs to be on CPU + .TypeConstraint("B", DataTypeImpl::GetTensorType()) + // Support sequence/optional tensors when all WebGPU infra + // (including tests runner) supports it + .TypeConstraint("V", DataTypeImpl::AllFixedSizeTensorTypes()), + If); + +ONNX_OPERATOR_KERNEL_EX(If, + kOnnxDomain, + 21, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 0) // 'cond' needs to be on CPU + .TypeConstraint("B", DataTypeImpl::GetTensorType()) + // Support sequence/optional tensors when all WebGPU infra + // (including tests runner) supports it + .TypeConstraint("V", DataTypeImpl::AllFixedSizeTensorTypes()), + If); + +Status If::Compute(OpKernelContext* ctx) const { + // call the base CPU version. + return onnxruntime::If::Compute(ctx); +} + +} // namespace webgpu +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/controlflow/if.h b/onnxruntime/core/providers/webgpu/controlflow/if.h new file mode 100644 index 0000000000000..0755c5d33d7a3 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/controlflow/if.h @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/common/common.h" +#include "core/providers/cpu/controlflow/if.h" + +namespace onnxruntime { +namespace webgpu { + +// Use the CPU implementation for the logic +class If final : public onnxruntime::If { + public: + If(const OpKernelInfo& info) : onnxruntime::If(info) {} + + Status Compute(OpKernelContext* ctx) const override; +}; + +} // namespace webgpu +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 4eddcfde1c0b7..2427bf62cc658 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -373,7 +373,8 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 23, class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, If); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, If); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 18, If); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, If); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, 20, If); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, If); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 7, 8, BatchNormalization); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 9, 13, BatchNormalization); @@ -700,10 +701,11 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, From 8de342ad2594c354c068ad1edf182345d857844e Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Fri, 28 Mar 2025 22:20:39 -0700 Subject: [PATCH 196/266] Update linux-dnnl.yml: rename the pipeline (#24240) Update linux-dnnl.yml: rename the pipeline to Linux DNNL CI --- .github/workflows/linux-dnnl.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-dnnl.yml b/.github/workflows/linux-dnnl.yml index 60720a1ac562f..c0cd23ff90ff4 100644 --- a/.github/workflows/linux-dnnl.yml +++ b/.github/workflows/linux-dnnl.yml @@ -4,7 +4,7 @@ # This file is very similar to linux_ci.yml, but much simpler -name: Linux CI +name: Linux DNNL CI on: push: From d71aa4d88cd23b77459021e7e134d0b8d7dccf70 Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Sat, 29 Mar 2025 13:56:11 +0800 Subject: [PATCH 197/266] [webgpu] Fix test_layer_normalization_2d_axis0 (#24223) The optional 'Mean' and 'InvStdDev' outputs of the LayerNormalization were not implemented. --------- Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- .../core/providers/webgpu/nn/layer_norm.cc | 69 +++++++++++++------ .../core/providers/webgpu/nn/layer_norm.h | 25 ++++--- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc index cf2939555057a..aafb41ad4d089 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc @@ -24,7 +24,13 @@ Status LayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { if (has_bias_) { shader.AddInput("bias", ShaderUsage::UseUniform); } - shader.AddOutput("output", ShaderUsage::UseUniform); + shader.AddOutput("y", ShaderUsage::UseUniform); + if (has_mean_output_) { + shader.AddOutput("mean_output", ShaderUsage::None); + } + if (has_inv_std_dev_output_) { + shader.AddOutput("inv_std_dev_output", ShaderUsage::None); + } int components = x.NumComponents(); std::string bias = (has_bias_) ? " + bias[j]" : ""; @@ -48,8 +54,14 @@ Status LayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { << "for (var j: u32 = 0; j < uniforms.norm_size_vectorized; j++) {\n" << " let f32input = f32_val_t(x[j + offset]);\n" << " let f32scale = f32_val_t(scale[j]);\n" - << " output[j + offset] = x_value_t((f32input" << simpl2 << ") * inv_std_dev * f32scale)" << bias << ";\n" + << " y[j + offset] = x_value_t((f32input" << simpl2 << ") * inv_std_dev * f32scale)" << bias << ";\n" << "}\n"; + if (has_mean_output_) { + shader.MainFunctionBody() << "mean_output[global_idx] = mean;\n"; + } + if (has_inv_std_dev_output_) { + shader.MainFunctionBody() << "inv_std_dev_output[global_idx] = inv_std_dev;\n"; + } return Status::OK(); } @@ -62,8 +74,6 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex const auto x_shape = x->Shape(); - auto* output = context.Output(0, x_shape); - if (x_shape.Size() == 0) { return Status::OK(); } @@ -85,13 +95,27 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex scale_size, " and bias size of ", bias_size); } - LayerNormProgram program{bias != nullptr, is_fp16, simplified}; + TensorShapeVector mean_dim; + for (size_t i = 0; i < x_shape.NumDimensions(); ++i) { + if (i < axis) { + mean_dim.push_back(x_shape[i]); + } else { + mean_dim.push_back(1); + } + } + TensorShape mean_shape(mean_dim); + + auto* y = context.Output(0, x_shape); + auto* mean = context.Output(1, mean_shape); + auto* inv_std_dev = context.Output(2, mean_shape); + + LayerNormProgram program{bias != nullptr, is_fp16, simplified, mean != nullptr, inv_std_dev != nullptr}; program .CacheHint(simplified) .AddInputs({{x, ProgramTensorMetadataDependency::Type, components}}) .AddInputs({{scale, ProgramTensorMetadataDependency::Type, components}}) - .AddOutputs({{output, ProgramTensorMetadataDependency::None, components}}) + .AddOutputs({{y, ProgramTensorMetadataDependency::None, components}}) .SetDispatchGroupSize((norm_count + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) .AddUniformVariables({ {static_cast(norm_count)}, @@ -109,25 +133,26 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex if (bias != nullptr) { program.AddInput({bias, ProgramTensorMetadataDependency::Type, components}); } + + if (mean != nullptr) { + program.AddOutputs({{mean, ProgramTensorMetadataDependency::None}}); + } + if (inv_std_dev != nullptr) { + program.AddOutputs({{inv_std_dev, ProgramTensorMetadataDependency::None}}); + } + return context.RunProgram(program); } -ONNX_OPERATOR_KERNEL_EX( - LayerNormalization, - kOnnxDomain, - 17, - kWebGpuExecutionProvider, - (*KernelDefBuilder::Create()) - .TypeConstraint("T", WebGpuSupportedFloatTypes()), - LayerNorm); - -ONNX_OPERATOR_KERNEL_EX( - SimplifiedLayerNormalization, - kOnnxDomain, - 1, - kWebGpuExecutionProvider, - (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), - LayerNorm); +ONNX_OPERATOR_KERNEL_EX(LayerNormalization, kOnnxDomain, 17, kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), + LayerNorm); + +ONNX_OPERATOR_KERNEL_EX(SimplifiedLayerNormalization, kOnnxDomain, 1, kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", WebGpuSupportedFloatTypes()) + .TypeConstraint("U", WebGpuSupportedFloatTypes()), + LayerNorm); } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.h b/onnxruntime/core/providers/webgpu/nn/layer_norm.h index 17a9edbf4dd01..c7cb9280a0b77 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.h +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.h @@ -11,25 +11,28 @@ namespace webgpu { class LayerNormProgram final : public Program { public: - LayerNormProgram(bool has_bias, - bool is_fp16, - bool simplified) : Program{"LayerNorm"}, - has_bias_{has_bias}, - is_fp16_{is_fp16}, - simplified_{simplified} {} + LayerNormProgram(bool has_bias, bool is_fp16, bool simplified, bool has_mean_output, + bool has_inv_std_dev_output) + : Program{"LayerNorm"}, + has_bias_{has_bias}, + is_fp16_{is_fp16}, + simplified_{simplified}, + has_mean_output_{has_mean_output}, + has_inv_std_dev_output_{has_inv_std_dev_output} {} Status GenerateShaderCode(ShaderHelper& sh) const override; - WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( - {"norm_count", ProgramUniformVariableDataType::Uint32}, - {"norm_size", ProgramUniformVariableDataType::Uint32}, - {"norm_size_vectorized", ProgramUniformVariableDataType::Uint32}, - {"epsilon", ProgramUniformVariableDataType::Float32}); + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"norm_count", ProgramUniformVariableDataType::Uint32}, + {"norm_size", ProgramUniformVariableDataType::Uint32}, + {"norm_size_vectorized", ProgramUniformVariableDataType::Uint32}, + {"epsilon", ProgramUniformVariableDataType::Float32}); private: bool has_bias_; bool is_fp16_; bool simplified_; + bool has_mean_output_; + bool has_inv_std_dev_output_; }; template From f1d790c29543373f47fc58a46809f71055925b99 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Sat, 29 Mar 2025 13:16:00 -0700 Subject: [PATCH 198/266] [webgpu] fix LayerNorm with empty input (#24244) ### Description This PR fixes test case `CudaKernelTest.LayerNorm_NullInput`, in which the input is 0-sized for LayerNorm. `context.Output()` need to be called before returning. --- onnxruntime/core/providers/webgpu/nn/layer_norm.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc index aafb41ad4d089..21ef3676244ec 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc @@ -74,10 +74,6 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex const auto x_shape = x->Shape(); - if (x_shape.Size() == 0) { - return Status::OK(); - } - const bool is_fp16 = x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16; const size_t axis = NormalizeAxis(axis_, x_shape.NumDimensions()); @@ -109,6 +105,10 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex auto* mean = context.Output(1, mean_shape); auto* inv_std_dev = context.Output(2, mean_shape); + if (x_shape.Size() == 0) { + return Status::OK(); + } + LayerNormProgram program{bias != nullptr, is_fp16, simplified, mean != nullptr, inv_std_dev != nullptr}; program From 492af7a3c08fe3fa0cf7159e318666b711225333 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Mar 2025 13:52:19 +0000 Subject: [PATCH 199/266] Bump actions/setup-python from 4 to 5 (#24251) --- .github/workflows/linux-wasm-ci-build-and-test-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml index d67562c4a3028..81b9c41af6dbf 100644 --- a/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml +++ b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml @@ -38,7 +38,7 @@ jobs: submodules: recursive - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.12" architecture: ${{ env.buildArch }} From 83650edc8992881e6afa025faab754657a13cd93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Mar 2025 08:27:58 -0700 Subject: [PATCH 200/266] Bump actions/cache from 3 to 4 (#24250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
Release notes

Sourced from actions/cache's releases.

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/cache/compare/v3...v4.0.0

v3.4.3

What's Changed

Full Changelog: https://github.com/actions/cache/compare/v3.4.2...v3.4.3

v3.4.2

What's Changed

[!IMPORTANT] As a reminder, there were important backend changes to release v3.4.0, see those release notes and the announcement for more details.

Full Changelog: https://github.com/actions/cache/compare/v3.4.0...v3.4.2

v3.4.1

[!WARNING] This version was incorrectly released using a SHA pointing to a newer version for immutable actions only. Please use v3.4.2 (or v3) instead.

v3.4.0

⚠️ Important Changes

The cache backend service has been rewritten from the ground up for improved performance and reliability. actions/cache now integrates with the new cache service (v2) APIs.

The new service will gradually roll out as of February 1st, 2025. The legacy service will also be sunset on the same date. Changes in these release are fully backward compatible.

We are deprecating some versions of this action. We recommend upgrading to version v4 or v3 as soon as possible before February 1st, 2025. (Upgrade instructions below).

If you are using pinned SHAs, please use the SHAs of versions v4.2.0 or v3.4.0

If you do not upgrade, all workflow runs using any of the deprecated actions/cache will fail.

Upgrading to the recommended versions will not break your workflows.

Read more about the change & access the migration guide: reference to the announcement.

Minor changes

... (truncated)

Changelog

Sourced from actions/cache's changelog.

Releases

4.2.3

  • Bump @actions/cache to v4.0.3 (obfuscates SAS token in debug logs for cache entries)

4.2.2

  • Bump @actions/cache to v4.0.2

4.2.1

  • Bump @actions/cache to v4.0.1

4.2.0

TLDR; The cache backend service has been rewritten from the ground up for improved performance and reliability. actions/cache now integrates with the new cache service (v2) APIs.

The new service will gradually roll out as of February 1st, 2025. The legacy service will also be sunset on the same date. Changes in these release are fully backward compatible.

We are deprecating some versions of this action. We recommend upgrading to version v4 or v3 as soon as possible before February 1st, 2025. (Upgrade instructions below).

If you are using pinned SHAs, please use the SHAs of versions v4.2.0 or v3.4.0

If you do not upgrade, all workflow runs using any of the deprecated actions/cache will fail.

Upgrading to the recommended versions will not break your workflows.

4.1.2

  • Add GitHub Enterprise Cloud instances hostname filters to inform API endpoint choices - #1474
  • Security fix: Bump braces from 3.0.2 to 3.0.3 - #1475

4.1.1

  • Restore original behavior of cache-hit output - #1467

4.1.0

  • Ensure cache-hit output is set when a cache is missed - #1404
  • Deprecate save-always input - #1452

4.0.2

  • Fixed restore fail-on-cache-miss not working.

4.0.1

  • Updated isGhes check

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/cache&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) Dependabot will merge this PR once it's up-to-date and CI passes on it, as requested by @fs-eire. [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/macos-ci-build-and-test-workflow.yml | 2 +- .github/workflows/windows-web-ci-workflow.yml | 2 +- .github/workflows/windows_cuda.yml | 2 +- .github/workflows/windows_webgpu.yml | 2 +- .github/workflows/windows_x64_debug_build_x64_debug.yml | 2 +- .github/workflows/windows_x64_release_build_x64_release.yml | 2 +- .../workflows/windows_x64_release_dnnl_build_x64_release.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/macos-ci-build-and-test-workflow.yml b/.github/workflows/macos-ci-build-and-test-workflow.yml index eb8d4ad76d964..dfe97f8370e99 100644 --- a/.github/workflows/macos-ci-build-and-test-workflow.yml +++ b/.github/workflows/macos-ci-build-and-test-workflow.yml @@ -70,7 +70,7 @@ jobs: xcode_version: ${{ env.xcode_version }} use_cache: true - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ diff --git a/.github/workflows/windows-web-ci-workflow.yml b/.github/workflows/windows-web-ci-workflow.yml index d18601da6279b..ce0e5167eb0a0 100644 --- a/.github/workflows/windows-web-ci-workflow.yml +++ b/.github/workflows/windows-web-ci-workflow.yml @@ -98,7 +98,7 @@ jobs: run: npm ci working-directory: ${{ github.workspace }}/js/web - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ diff --git a/.github/workflows/windows_cuda.yml b/.github/workflows/windows_cuda.yml index a36f0c3142d7d..0687bf0a2529d 100644 --- a/.github/workflows/windows_cuda.yml +++ b/.github/workflows/windows_cuda.yml @@ -65,7 +65,7 @@ jobs: java-version: '17' architecture: x64 - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ diff --git a/.github/workflows/windows_webgpu.yml b/.github/workflows/windows_webgpu.yml index 908f28ae174d3..bf60df1c1ba7f 100644 --- a/.github/workflows/windows_webgpu.yml +++ b/.github/workflows/windows_webgpu.yml @@ -91,7 +91,7 @@ jobs: shell: cmd working-directory: ${{ github.workspace }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml index 621cb2630b33e..b2c4010d0b142 100644 --- a/.github/workflows/windows_x64_debug_build_x64_debug.yml +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -87,7 +87,7 @@ jobs: run: | nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\Debug -ConfigFile ${{ github.workspace }}\NuGet.config - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ diff --git a/.github/workflows/windows_x64_release_build_x64_release.yml b/.github/workflows/windows_x64_release_build_x64_release.yml index 58a94c2f2208a..c057997b7275e 100644 --- a/.github/workflows/windows_x64_release_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_build_x64_release.yml @@ -75,7 +75,7 @@ jobs: run: | nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ diff --git a/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml b/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml index 5b45f040c990b..5e83a0dd54dfb 100644 --- a/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_dnnl_build_x64_release.yml @@ -75,7 +75,7 @@ jobs: run: | nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: onnx-node-tests-cache with: path: ${{ github.workspace }}/js/test/ From 22787aecb4b575998be23c8b2ec19ac3530af20f Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Mon, 31 Mar 2025 08:43:28 -0700 Subject: [PATCH 201/266] [QNN EP] Add platform-agnostic EP option to specify QNN backend, `backend_type` (#24235) Add a platform-agnostic EP option to specify QNN backend, `backend_type`. In typical usage, this should supersede the `backend_path` EP option. `backend_path` requires specifying a path to the QNN backend library which is different between Windows and non-Windows platforms (e.g., QnnCpu.dll vs. libQnnCpu.so). It will not be removed for backwards compatibility. It also provides the flexibility to specify an arbitrary backend path. --- .../core/session/onnxruntime_c_api.h | 104 ++++++++++++------ .../example/javavalidator/SimpleTest.kt | 4 +- .../java/ai/onnxruntime/InferenceTest.java | 9 +- js/common/lib/inference-session.ts | 10 +- js/node/src/session_options_helper.cc | 13 ++- .../providers/qnn/qnn_execution_provider.cc | 96 ++++++++++++++-- .../test/ep_weight_sharing_ctx_gen/README.md | 45 ++++---- .../command_args_parser.cc | 27 +++-- .../test/ep_weight_sharing_ctx_gen/main.cc | 6 - onnxruntime/test/onnx/main.cc | 17 +-- .../test/perftest/command_args_parser.cc | 7 +- onnxruntime/test/perftest/ort_test_session.cc | 14 ++- .../test/providers/qnn/argmaxmin_op_test.cc | 12 +- .../test/providers/qnn/average_pool_test.cc | 14 +-- .../test/providers/qnn/batch_norm_htp_test.cc | 19 +--- onnxruntime/test/providers/qnn/cast_test.cc | 8 +- .../test/providers/qnn/clip_op_test.cc | 28 +---- onnxruntime/test/providers/qnn/conv_test.cc | 28 +---- .../test/providers/qnn/flatten_op_test.cc | 28 +---- .../providers/qnn/gather_elems_op_test.cc | 18 +-- .../test/providers/qnn/gather_op_htp_test.cc | 14 +-- .../test/providers/qnn/gemm_op_test.cc | 18 +-- .../providers/qnn/instance_norm_htp_test.cc | 6 +- .../test/providers/qnn/layer_norm_test.cc | 12 +- .../providers/qnn/leakyrelu_op_htp_test.cc | 14 +-- .../providers/qnn/logical_comp_ops_test.cc | 18 +-- onnxruntime/test/providers/qnn/lrn_op_test.cc | 13 +-- .../test/providers/qnn/matmul_test.cpp | 32 +----- .../test/providers/qnn/max_min_op_test.cc | 12 +- .../test/providers/qnn/pad_op_test.cpp | 22 +--- .../test/providers/qnn/pool_op_test.cpp | 14 +-- .../test/providers/qnn/qnn_basic_test.cc | 23 ++++ .../test/providers/qnn/qnn_test_utils.cc | 4 +- .../test/providers/qnn/reduce_op_test.cc | 18 +-- .../providers/qnn/reshape_expand_op_test.cc | 18 +-- onnxruntime/test/providers/qnn/resize_test.cc | 18 +-- .../test/providers/qnn/simple_op_htp_test.cc | 54 ++------- .../test/providers/qnn/slice_htp_test.cc | 20 +--- .../test/providers/qnn/split_op_test.cc | 18 +-- .../qnn/squeeze_unsqueeze_op_test.cc | 30 +---- .../test/providers/qnn/tile_op_test.cc | 12 +- .../test/providers/qnn/topk_op_test.cc | 12 +- .../test/providers/qnn/transpose_htp_test.cc | 14 +-- .../test/providers/qnn/where_htp_test.cc | 8 +- 44 files changed, 356 insertions(+), 575 deletions(-) diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 6481592232a58..6d4cc8a1f2fa9 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -3646,45 +3646,77 @@ struct OrtApi { * that should be used to add it. * * QNN supported keys: - * "backend_path": file path to QNN backend library. - * "profiling_level": QNN profiling level, options: "off", "basic", "detailed". Default to off. + * "backend_type": Type of QNN backend. Specifies a backend path that is the associated QNN backend library file + * name. E.g., given backend type "htp", on Windows, the backend path would be "QnnHtp.dll", and on other + * platforms, it would be "libQnnHtp.so". Mutually exclusive with "backend_path". + * Available options: + * - "cpu" + * - "gpu" + * - "htp": Default. + * - "saver" + * "backend_path": File path to QNN backend library. Mutually exclusive with "backend_type". + * "profiling_level": QNN profiling level. + * Available options: + * - "off": Default. + * - "basic" + * - "detailed" * "profiling_file_path": QNN profiling file path if ETW not enabled. * "rpc_control_latency": QNN RPC control latency. * "vtcm_mb": QNN VTCM size in MB. default to 0(not set). - * "htp_performance_mode": QNN performance mode, options: "burst", "balanced", "default", "high_performance", - * "high_power_saver", "low_balanced", "extreme_power_saver", "low_power_saver", "power_saver", "sustained_high_performance". Default to "default". + * "htp_performance_mode": QNN performance mode. + * Available options: + * - "burst" + * - "balanced" + * - "default": Default. + * - "high_performance" + * - "high_power_saver" + * - "low_balanced" + * - "extreme_power_saver" + * - "low_power_saver" + * - "power_saver" + * - "sustained_high_performance" * "qnn_saver_path": File path to the QNN Saver backend library. If specified, QNN Saver will be enabled and will - * dump QNN API calls to disk for replay/debugging. QNN Saver produces incorrect model inference results and - * may alter model/EP partitioning. Use only for debugging. - * "qnn_context_priority": QNN context priority, options: "low", "normal", "normal_high", "high". Default to "normal". - * "htp_graph_finalization_optimization_mode": Set the optimization mode for graph finalization on the HTP backend. Available options: - * - "0": Default. - * - "1": Faster preparation time, less optimal graph. - * - "2": Longer preparation time, more optimal graph. - * - "3": Longest preparation time, most likely even more optimal graph. See QNN SDK documentation for specific details. - * "soc_model": The SoC model number. Refer to the QNN SDK documentation for valid values. Defaults to "0" (unknown). - * "htp_arch": The minimum HTP architecture the driver will use to select compatible QNN operators. Available options: - * - "0": Default (none). - * - "68" - * - "69" - * - "73" - * - "75" + * dump QNN API calls to disk for replay/debugging. QNN Saver produces incorrect model inference results and + * may alter model/EP partitioning. Use only for debugging. + * "qnn_context_priority": QNN context priority. + * Available options: + * - "low" + * - "normal": Default. + * - "normal_high" + * - "high" + * "htp_graph_finalization_optimization_mode": Set the optimization mode for graph finalization on the HTP backend. + * Available options: + * - "0": Default. + * - "1": Faster preparation time, less optimal graph. + * - "2": Longer preparation time, more optimal graph. + * - "3": Longest preparation time, most likely even more optimal graph. See QNN SDK documentation for specific + * details. + * "soc_model": The SoC model number. Refer to the QNN SDK documentation for valid values. + * Defaults to "0" (unknown). + * "htp_arch": The minimum HTP architecture the driver will use to select compatible QNN operators. + * Available options: + * - "0": Default (none). + * - "68" + * - "69" + * - "73" + * - "75" * "device_id": The ID of the device to use when setting 'htp_arch'. Defaults to "0" (for single device). * "enable_htp_fp16_precision": Used for float32 model for HTP backend. - * Enable the float32 model to be inferenced with fp16 precision. Otherwise, it will be fp32 precision. + * Enable the float32 model to be inferenced with fp16 precision. Otherwise, it will be fp32 precision. * - "0": With fp32 precision. * - "1": Default. With fp16 precision. * "offload_graph_io_quantization": Offload graph input quantization and graph output dequantization to another - * execution provider (typically CPU EP). - * - "0": Disabled. QNN EP will handle quantization and dequantization of graph I/O. - * - "1": Enabled. This is the default value. - * "enable_htp_spill_fill_buffer": Enable HTP spill fill buffer setting. The flag is used while generating context binary. - * - "0": Default. Disabled. - * - "1": Enabled. + * execution provider (typically CPU EP). + * - "0": Disabled. QNN EP will handle quantization and dequantization of graph I/O. + * - "1": Enabled. This is the default value. + * "enable_htp_spill_fill_buffer": Enable HTP spill fill buffer setting. The flag is used while generating context + * binary. + * - "0": Default. Disabled. + * - "1": Enabled. * "enable_htp_shared_memory_allocator": Enable the QNN HTP shared memory allocator. Requires libcdsprpc.so/dll to - * be available. - * - "0": Default. Disabled. - * - "1": Enabled. + * be available. + * - "0": Default. Disabled. + * - "1": Enabled. * "dump_json_qnn_graph": Set to "1" to dump QNN graphs generated by QNN EP as JSON files. Each graph partition * assigned to QNN EP is dumped to a separate file. * "json_qnn_graph_dir": Directory in which to dump QNN JSON graphs. If not specified, QNN graphs are dumped in the @@ -3692,18 +3724,18 @@ struct OrtApi { * * SNPE supported keys: * "runtime": SNPE runtime engine, options: "CPU", "CPU_FLOAT32", "GPU", "GPU_FLOAT32_16_HYBRID", "GPU_FLOAT16", - * "DSP", "DSP_FIXED8_TF", "AIP_FIXED_TF", "AIP_FIXED8_TF". - * Mapping to SNPE Runtime_t definition: CPU, CPU_FLOAT32 => zdl::DlSystem::Runtime_t::CPU; - * GPU, GPU_FLOAT32_16_HYBRID => zdl::DlSystem::Runtime_t::GPU; - * GPU_FLOAT16 => zdl::DlSystem::Runtime_t::GPU_FLOAT16; - * DSP, DSP_FIXED8_TF => zdl::DlSystem::Runtime_t::DSP. - * AIP_FIXED_TF, AIP_FIXED8_TF => zdl::DlSystem::Runtime_t::AIP_FIXED_TF. + * "DSP", "DSP_FIXED8_TF", "AIP_FIXED_TF", "AIP_FIXED8_TF". + * Mapping to SNPE Runtime_t definition: + * CPU, CPU_FLOAT32 => zdl::DlSystem::Runtime_t::CPU; + * GPU, GPU_FLOAT32_16_HYBRID => zdl::DlSystem::Runtime_t::GPU; + * GPU_FLOAT16 => zdl::DlSystem::Runtime_t::GPU_FLOAT16; + * DSP, DSP_FIXED8_TF => zdl::DlSystem::Runtime_t::DSP. + * AIP_FIXED_TF, AIP_FIXED8_TF => zdl::DlSystem::Runtime_t::AIP_FIXED_TF. * "priority": execution priority, options: "low", "normal". * "buffer_type": ITensor or user buffers, options: "ITENSOR", user buffer with different types - "TF8", "TF16", "UINT8", "FLOAT". * "ITENSOR" -- default, ITensor which is float only. * "TF8" -- quantized model required, "FLOAT" -- for both quantized or non-quantized model * "enable_init_cache": enable SNPE init caching feature, set to 1 to enabled it. Disabled by default. - * If SNPE is not available (due to a non Snpe enabled build or its dependencies not being installed), this function will fail. * * XNNPACK supported keys: * "intra_op_num_threads": number of thread-pool size to use for XNNPACK execution provider. diff --git a/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt b/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt index 5e6bee6cac9f4..0af8b6f1a8ab1 100644 --- a/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt +++ b/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt @@ -82,9 +82,7 @@ class SimpleTest { OrtProvider.QNN -> { if (OrtEnvironment.getAvailableProviders().contains(OrtProvider.QNN)) { - // Since this is running in an Android environment, we use the .so library - val qnnLibrary = "libQnnHtp.so" - val providerOptions = Collections.singletonMap("backend_path", qnnLibrary) + val providerOptions = Collections.singletonMap("backend_type", "htp") opts.addQnn(providerOptions) } else { Log.println(Log.INFO, TAG, "NO QNN EP available, skip the test") diff --git a/java/src/test/java/ai/onnxruntime/InferenceTest.java b/java/src/test/java/ai/onnxruntime/InferenceTest.java index e11537492d3a7..83cdc32dbaeb5 100644 --- a/java/src/test/java/ai/onnxruntime/InferenceTest.java +++ b/java/src/test/java/ai/onnxruntime/InferenceTest.java @@ -2125,13 +2125,8 @@ private static SqueezeNetTuple openSessionSqueezeNet(EnumSet provid options.addXnnpack(Collections.emptyMap()); break; case QNN: - { - String backendPath = OS.WINDOWS.isCurrentOs() ? "/QnnCpu.dll" : "/libQnnCpu.so"; - options.addQnn( - Collections.singletonMap( - "backend_path", TestHelpers.getResourcePath(backendPath).toString())); - break; - } + options.addQnn(Collections.singletonMap("backend_type", "cpu")); + break; case VITIS_AI: case RK_NPU: case MI_GRAPH_X: diff --git a/js/common/lib/inference-session.ts b/js/common/lib/inference-session.ts index 330d4121475ec..4ef4891b5b46a 100644 --- a/js/common/lib/inference-session.ts +++ b/js/common/lib/inference-session.ts @@ -310,9 +310,15 @@ export declare namespace InferenceSession { export interface QnnExecutionProviderOption extends ExecutionProviderOption { readonly name: 'qnn'; /** - * Specify a path to the QnnHtp.dll file. + * Specify the QNN backend type. E.g., 'cpu' or 'htp'. + * Mutually exclusive with `backendPath`. * - * @default 'QnnHtp.dll' + * @default 'htp' + */ + backendType?: string; + /** + * Specify a path to the QNN backend library. + * Mutually exclusive with `backendType`. */ backendPath?: string; /** diff --git a/js/node/src/session_options_helper.cc b/js/node/src/session_options_helper.cc index 1ac61ba4e2e81..3c607d88e5402 100644 --- a/js/node/src/session_options_helper.cc +++ b/js/node/src/session_options_helper.cc @@ -83,6 +83,14 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess #endif #ifdef USE_QNN if (name == "qnn") { + Napi::Value backend_type = obj.Get("backendType"); + if (!backend_type.IsUndefined()) { + if (backend_type.IsString()) { + qnn_options["backend_type"] = backend_type.As().Utf8Value(); + } else { + ORT_NAPI_THROW_TYPEERROR(epList.Env(), "Invalid argument: backendType must be a string."); + } + } Napi::Value backend_path = obj.Get("backendPath"); if (!backend_path.IsUndefined()) { if (backend_path.IsString()) { @@ -136,11 +144,6 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess #endif #ifdef USE_QNN } else if (name == "qnn") { - // Ensure that the backend_path option are set to default values if not provided. - if (qnn_options.find("backend_path") == qnn_options.end()) { - qnn_options["backend_path"] = "QnnHtp.dll"; - } - sessionOptions.AppendExecutionProvider("QNN", qnn_options); #endif } else { diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index 2606ace8127d3..142a7362ad6ae 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -4,6 +4,8 @@ #include "qnn_execution_provider.h" #include +#include +#include #include #include "core/providers/qnn/ort_api.h" @@ -22,6 +24,60 @@ namespace onnxruntime { constexpr const char* QNN = "QNN"; +static std::string MakeSharedLibraryPath(std::string_view name) { +#if defined(_WIN32) + return MakeString(name, ".dll"); +#else + return MakeString("lib", name, ".so"); +#endif +} + +const std::string kDefaultCpuBackendPath = MakeSharedLibraryPath("QnnCpu"); +const std::string kDefaultGpuBackendPath = MakeSharedLibraryPath("QnnGpu"); +const std::string kDefaultHtpBackendPath = MakeSharedLibraryPath("QnnHtp"); +const std::string kDefaultSaverBackendPath = MakeSharedLibraryPath("QnnSaver"); + +static bool ParseBackendTypeName(std::string_view backend_type_name, std::string& backend_path) { + constexpr std::string_view kCpuBackendTypeName{"cpu"}; + constexpr std::string_view kGpuBackendTypeName{"gpu"}; + constexpr std::string_view kHtpBackendTypeName{"htp"}; + constexpr std::string_view kSaverBackendTypeName{"saver"}; + + constexpr std::array kAllowedBackendTypeNames{ + kCpuBackendTypeName, + kGpuBackendTypeName, + kHtpBackendTypeName, + kSaverBackendTypeName, + }; + + std::optional associated_backend_path{}; + if (backend_type_name == kCpuBackendTypeName) { + associated_backend_path = kDefaultCpuBackendPath; + } else if (backend_type_name == kGpuBackendTypeName) { + associated_backend_path = kDefaultGpuBackendPath; + } else if (backend_type_name == kHtpBackendTypeName) { + associated_backend_path = kDefaultHtpBackendPath; + } else if (backend_type_name == kSaverBackendTypeName) { + associated_backend_path = kDefaultSaverBackendPath; + } + + if (associated_backend_path.has_value()) { + backend_path = std::move(*associated_backend_path); + return true; + } + + std::ostringstream warning{}; + warning << "Invalid backend type name: " << backend_type_name << ". Allowed backend type names: "; + for (size_t i = 0; i < kAllowedBackendTypeNames.size(); ++i) { + warning << kAllowedBackendTypeNames[i]; + if (i + 1 < kAllowedBackendTypeNames.size()) { + warning << ", "; + } + } + LOGS_DEFAULT(WARNING) << warning.str(); + return false; +} + static void ParseProfilingLevel(std::string profiling_level_string, qnn::ProfilingLevel& profiling_level) { std::transform(profiling_level_string.begin(), @@ -201,15 +257,39 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio LOGS_DEFAULT(VERBOSE) << "User specified option - stop share EP contexts across sessions: " << stop_share_ep_contexts_; } - static const std::string BACKEND_PATH = "backend_path"; - auto backend_path_pos = provider_options_map.find(BACKEND_PATH); + std::string backend_path{}; + { + std::optional backend_path_from_options{}; + + static const std::string BACKEND_TYPE = "backend_type"; + static const std::string BACKEND_PATH = "backend_path"; - std::string backend_path; - if (backend_path_pos != provider_options_map.end()) { - backend_path = backend_path_pos->second; - LOGS_DEFAULT(VERBOSE) << "Backend path: " << backend_path; - } else { - LOGS_DEFAULT(ERROR) << "No backend path provided."; + auto backend_type_it = provider_options_map.find(BACKEND_TYPE); + auto backend_path_it = provider_options_map.find(BACKEND_PATH); + + if (backend_type_it != provider_options_map.end() && backend_path_it != provider_options_map.end()) { + ORT_THROW("Only one of '", BACKEND_TYPE, "' and '", BACKEND_PATH, "' should be set."); + } + + if (backend_type_it != provider_options_map.end()) { + if (std::string parsed_backend_path; ParseBackendTypeName(backend_type_it->second, parsed_backend_path)) { + backend_path_from_options = parsed_backend_path; + } else { + LOGS_DEFAULT(ERROR) << "Failed to parse '" << BACKEND_TYPE << "' value."; + } + } else if (backend_path_it != provider_options_map.end()) { + backend_path_from_options = backend_path_it->second; + } + + if (backend_path_from_options.has_value()) { + backend_path = std::move(*backend_path_from_options); + } else { + const auto& default_backend_path = kDefaultHtpBackendPath; + backend_path = default_backend_path; + LOGS_DEFAULT(WARNING) << "Unable to determine backend path from provider options. Using default."; + } + + LOGS_DEFAULT(VERBOSE) << "Using backend path: " << backend_path; } std::string profiling_file_path; diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md b/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md index 1d76d37079a44..66b8467bda335 100644 --- a/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/README.md @@ -6,32 +6,33 @@ OnnxRuntime provides the ep_weight_sharing_ctx_gen tool to automate the weight-s Example command line: -`ep_weight_sharing_ctx_gen [options...] model_1_path,model_2_path` +``` +ep_weight_sharing_ctx_gen [options...] model1_path,model2_path -./ep_weight_sharing_ctx_gen -e qnn -v -i "soc_model|60 htp_graph_finalization_optimization_mode|3" /mnt/c/model1.onnx,/mnt/c/model2.onnx +Example: ./ep_weight_sharing_ctx_gen -e qnn -i "soc_model|60 htp_graph_finalization_optimization_mode|3" -C "ep.context_node_name_prefix|_part1" ./model1.onnx,./model2.onnx Options: - - -e [qnn|tensorrt|openvino|vitisai]: Specifies the compile based provider qnn, tensorrt, openvino, vitisai. Default is qnn. - - -v: Show verbose information. - - -C: [session_config_entries]: Specify session configuration entries as key-value pairs: -C "| |" - Refer to onnxruntime_session_options_config_keys.h for valid keys and values. - [Example] -C "ep.context_enable|1 ep.context_embed_mode|0". These are set as default so can be ignored. - - -i: [provider_options]: Specify QNN EP specific runtime options as key value pairs. Different runtime options available are: + -e [qnn|tensorrt|openvino|vitisai]: Specifies the compile based provider 'qnn', 'tensorrt', 'openvino', 'vitisai'. Default: 'qnn'. + -v: Show verbose information. + -C: Specify session configuration entries as key-value pairs: -C "| |" + Refer to onnxruntime_session_options_config_keys.h for valid keys and values. + Force ep.context_enable to 1 and ep.context_embed_mode to 0. Change ep.context_file_path is not allowed. + [Example] -C "ep.context_node_name_prefix|_part1" + -i: Specify EP specific runtime options as key value pairs. Different runtime options available are: [Usage]: -i '| |' - [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. Default to HTP backend lib in current folder. - [vtcm_mb]: QNN VTCM size in MB. default to 0(not set). - [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'. - [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). - [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). - [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. - Otherwise, it will be fp32 precision. Only works for float32 model. Defaults to '0' (with FP32 precision.). - [enable_htp_weight_sharing]: Allows common weights across graphs to be shared and stored in a single context binary. Defaults to '1' (enabled). + [QNN only] [backend_type]: QNN backend type. E.g., 'cpu', 'htp'. Mutually exclusive with 'backend_path'. + [QNN only] [backend_path]: QNN backend path. E.g., '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. Mutually exclusive with 'backend_type'. + [QNN only] [vtcm_mb]: QNN VTCM size in MB. default to 0(not set). + [QNN only] [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'. + [QNN only] [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). + [QNN only] [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). + [QNN only] [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. + Otherwise, it will be fp32 precision. Works for float32 model for HTP backend. Defaults to '1' (with FP16 precision.). + [QNN only] [offload_graph_io_quantization]: Offload graph input quantization and graph output dequantization to another EP (typically CPU EP). + Defaults to '1' (another EP (typically CPU EP) handles the graph I/O quantization and dequantization). + [QNN only] [enable_htp_spill_fill_buffer]: Enable HTP spill file buffer, used while generating QNN context binary. [Example] -i "vtcm_mb|8 htp_arch|73" - -h: help. - + -h: help +``` diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc index ccfccf2e08dfc..cecf5575d42a5 100644 --- a/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/command_args_parser.cc @@ -28,20 +28,23 @@ namespace qnnctxgen { /*static*/ void CommandLineParser::ShowUsage() { printf( + "%s", "ep_weight_sharing_ctx_gen [options...] model1_path,model2_path\n" - "Example: ./ep_weight_sharing_ctx_gen -i \"soc_model|60 htp_graph_finalization_optimization_mode|3\" -C \"ep.context_node_name_prefix|_part1\" ./model1.onnx,./model2.onnx\n" + "\n" + "Example: ./ep_weight_sharing_ctx_gen -e qnn -i \"soc_model|60 htp_graph_finalization_optimization_mode|3\" -C \"ep.context_node_name_prefix|_part1\" ./model1.onnx,./model2.onnx\n" + "\n" "Options:\n" - "\t-e [qnn|tensorrt|openvino|vitisai]: Specifies the compile based provider 'qnn','tensorrt','openvino', 'vitisai'. " - "Default:'qnn'.\n" + "\t-e [qnn|tensorrt|openvino|vitisai]: Specifies the compile based provider 'qnn', 'tensorrt', 'openvino', 'vitisai'. Default: 'qnn'.\n" "\t-v: Show verbose information.\n" "\t-C: Specify session configuration entries as key-value pairs: -C \"| |\" \n" "\t Refer to onnxruntime_session_options_config_keys.h for valid keys and values. \n" - "\t Force ep.context_enable to 1 and ep.context_embed_mode to 0. Change ep.context_file_path is not allowed." + "\t Force ep.context_enable to 1 and ep.context_embed_mode to 0. Change ep.context_file_path is not allowed.\n" "\t [Example] -C \"ep.context_node_name_prefix|_part1\" \n" "\t-i: Specify EP specific runtime options as key value pairs. Different runtime options available are: \n" "\t [Usage]: -i '| |'\n" "\n" - "\t [QNN only] [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. default to HTP backend\n" + "\t [QNN only] [backend_type]: QNN backend type. E.g., 'cpu', 'htp'. Mutually exclusive with 'backend_path'.\n" + "\t [QNN only] [backend_path]: QNN backend path. E.g., '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. Mutually exclusive with 'backend_type'.\n" "\t [QNN only] [vtcm_mb]: QNN VTCM size in MB. default to 0(not set).\n" "\t [QNN only] [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'.\n" "\t [QNN only] [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). \n" @@ -49,8 +52,8 @@ namespace qnnctxgen { "\t [QNN only] [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. \n" "\t Otherwise, it will be fp32 precision. Works for float32 model for HTP backend. Defaults to '1' (with FP16 precision.). \n" "\t [QNN only] [offload_graph_io_quantization]: Offload graph input quantization and graph output dequantization to another EP (typically CPU EP). \n" - "\t Defaults to '1' (QNN EP handles the graph I/O quantization and dequantization). \n" - "\t [QNN only] [enable_htp_spill_fill_buffer]: Enable HTP spill file buffer, used while generating QNN context binary." + "\t Defaults to '1' (another EP (typically CPU EP) handles the graph I/O quantization and dequantization). \n" + "\t [QNN only] [enable_htp_spill_fill_buffer]: Enable HTP spill file buffer, used while generating QNN context binary.\n" "\t [Example] -i \"vtcm_mb|8 htp_arch|73\" \n" "\n" "\t-h: help\n"); @@ -149,7 +152,8 @@ static bool ParseSessionConfigs(const std::string& configs_string, std::string key(token.substr(0, pos)); std::string value(token.substr(pos + 1)); - if (key == "backend_path" || key == "vtcm_mb" || key == "soc_model" || key == "htp_arch") { + if (key == "backend_type" || key == "backend_path" || key == "vtcm_mb" || key == "soc_model" || + key == "htp_arch") { // no validation } else if (key == "htp_graph_finalization_optimization_mode") { std::unordered_set supported_htp_graph_final_opt_modes = {"0", "1", "2", "3"}; @@ -171,9 +175,10 @@ static bool ParseSessionConfigs(const std::string& configs_string, ORT_THROW("Wrong value for " + key + ". select from: " + str); } } else { - ORT_THROW(R"(Wrong key type entered. Choose from options: ['backend_path', 'vtcm_mb', 'htp_performance_mode', - 'htp_graph_finalization_optimization_mode', 'soc_model', 'htp_arch', 'enable_htp_fp16_precision', - 'offload_graph_io_quantization', 'enable_htp_spill_fill_buffer'])"); + ORT_THROW( + "Wrong key type entered. Choose from options: ['backend_type', 'backend_path', 'vtcm_mb', " + "'htp_performance_mode', 'htp_graph_finalization_optimization_mode', 'soc_model', 'htp_arch', " + "'enable_htp_fp16_precision', 'offload_graph_io_quantization', 'enable_htp_spill_fill_buffer']"); } test_config.run_config.provider_options[key] = value; diff --git a/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc b/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc index 92671e52f62f9..18abe1eb131d8 100644 --- a/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc +++ b/onnxruntime/test/ep_weight_sharing_ctx_gen/main.cc @@ -138,12 +138,6 @@ int real_main(int argc, char* argv[]) { std::string provider_name_ = test_config.machine_config.provider_type_name; if (provider_name_ == onnxruntime::kQnnExecutionProvider) { #ifdef USE_QNN -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif - so.AppendExecutionProvider("QNN", provider_options); #else ORT_THROW("QNN is not supported in this build\n"); diff --git a/onnxruntime/test/onnx/main.cc b/onnxruntime/test/onnx/main.cc index 99c3e44e13013..1d66c488775d3 100644 --- a/onnxruntime/test/onnx/main.cc +++ b/onnxruntime/test/onnx/main.cc @@ -59,7 +59,8 @@ void usage() { "\t Refer to onnxruntime_session_options_config_keys.h for valid keys and values. \n" "\t [Example] -C \"session.disable_cpu_ep_fallback|1 ep.context_enable|1\" \n" "\t-i: Specify EP specific runtime options as key value pairs. Different runtime options available are: \n" - "\t [QNN only] [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/folderpath/libQnnCpu.so'.\n" + "\t [QNN only] [backend_type]: QNN backend type. E.g., 'cpu', 'htp'. Mutually exclusive with 'backend_path'.\n" + "\t [QNN only] [backend_path]: QNN backend path. E.g., '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. Mutually exclusive with 'backend_type'.\n" "\t [QNN only] [profiling_level]: QNN profiling level, options: 'basic', 'detailed', default 'off'.\n" "\t [QNN only] [profiling_file_path]: QNN profiling file path if ETW not enabled.\n" "\t [QNN only] [rpc_control_latency]: QNN rpc control latency. default to 10.\n" @@ -80,7 +81,7 @@ void usage() { "\t [QNN only] [offload_graph_io_quantization]: Offload graph input quantization and graph output dequantization to another EP (typically CPU EP). \n" "\t Defaults to '0' (QNN EP handles the graph I/O quantization and dequantization). \n" "\t [Usage]: -e -i '| |' \n\n" - "\t [Example] [For QNN EP] -e qnn -i \"profiling_level|detailed backend_path|/folderpath/libQnnCpu.so\" \n\n" + "\t [Example] [For QNN EP] -e qnn -i \"profiling_level|detailed backend_type|cpu\" \n\n" "\t [SNPE only] [runtime]: SNPE runtime, options: 'CPU', 'GPU', 'GPU_FLOAT16', 'DSP', 'AIP_FIXED_TF'. \n" "\t [SNPE only] [priority]: execution priority, options: 'low', 'normal'. \n" "\t [SNPE only] [buffer_type]: options: 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. default: ITENSOR'. \n" @@ -554,7 +555,8 @@ int real_main(int argc, char* argv[], Ort::Env& env) { if (supported_profiling_level.find(value) == supported_profiling_level.end()) { ORT_THROW("Supported profiling_level: off, basic, detailed"); } - } else if (key == "rpc_control_latency" || key == "vtcm_mb" || key == "soc_model" || key == "device_id") { + } else if (key == "backend_type" || key == "rpc_control_latency" || key == "vtcm_mb" || key == "soc_model" || + key == "device_id") { // no validation } else if (key == "htp_performance_mode") { std::set supported_htp_perf_mode = {"burst", "balanced", "default", "high_performance", @@ -602,10 +604,11 @@ int real_main(int argc, char* argv[], Ort::Env& env) { ORT_THROW("Wrong value for ", key, ". select from: ", str); } } else { - ORT_THROW(R"(Wrong key type entered. Choose from options: ['backend_path', -'profiling_level', 'profiling_file_path', 'rpc_control_latency', 'vtcm_mb', 'htp_performance_mode', -'qnn_saver_path', 'htp_graph_finalization_optimization_mode', 'qnn_context_priority', -'soc_model', 'htp_arch', 'device_id', 'enable_htp_fp16_precision', 'offload_graph_io_quantization'])"); + ORT_THROW( + "Wrong key type entered. Choose from options: ['backend_type', 'backend_path', " + "'profiling_level', 'profiling_file_path', 'rpc_control_latency', 'vtcm_mb', 'htp_performance_mode', " + "'qnn_saver_path', 'htp_graph_finalization_optimization_mode', 'qnn_context_priority', " + "'soc_model', 'htp_arch', 'device_id', 'enable_htp_fp16_precision', 'offload_graph_io_quantization']"); } qnn_options[key] = value; diff --git a/onnxruntime/test/perftest/command_args_parser.cc b/onnxruntime/test/perftest/command_args_parser.cc index 5031d557ee2f0..591e277b2bbca 100644 --- a/onnxruntime/test/perftest/command_args_parser.cc +++ b/onnxruntime/test/perftest/command_args_parser.cc @@ -82,9 +82,10 @@ namespace perftest { "\t [OpenVINO only] [enable_opencl_throttling]: Enables OpenCL queue throttling for GPU device(Reduces the CPU Utilization while using GPU) \n" "\t [Example] [For OpenVINO EP] -e openvino -i \"device_type|CPU num_of_threads|5 enable_opencl_throttling|true cache_dir|\"\"\"\n" "\n" - "\t [QNN only] [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/folderpath/libQnnCpu.so'.\n" + "\t [QNN only] [backend_type]: QNN backend type. E.g., 'cpu', 'htp'. Mutually exclusive with 'backend_path'.\n" + "\t [QNN only] [backend_path]: QNN backend path. E.g., '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. Mutually exclusive with 'backend_type'.\n" "\t [QNN only] [profiling_level]: QNN profiling level, options: 'basic', 'detailed', default 'off'.\n" - "\t [profiling_file_path] : QNN profiling file path if ETW not enabled.\n" + "\t [QNN only] [profiling_file_path] : QNN profiling file path if ETW not enabled.\n" "\t [QNN only] [rpc_control_latency]: QNN rpc control latency. default to 10.\n" "\t [QNN only] [vtcm_mb]: QNN VTCM size in MB. default to 0(not set).\n" "\t [QNN only] [htp_performance_mode]: QNN performance mode, options: 'burst', 'balanced', 'default', 'high_performance', \n" @@ -104,7 +105,7 @@ namespace perftest { "\t [QNN only] [enable_htp_spill_fill_buffer]: Enable HTP spill fill buffer, used while generating QNN context binary.\n" "\t [QNN only] [enable_htp_shared_memory_allocator]: Enable the QNN HTP shared memory allocator and use it for inputs and outputs. Requires libcdsprpc.so/dll to be available.\n" "\t Defaults to '0' (disabled).\n" - "\t [Example] [For QNN EP] -e qnn -i \"backend_path|/folderpath/libQnnCpu.so\" \n" + "\t [Example] [For QNN EP] -e qnn -i \"backend_type|cpu\" \n" "\n" "\t [TensorRT only] [trt_max_partition_iterations]: Maximum iterations for TensorRT parser to get capability.\n" "\t [TensorRT only] [trt_min_subgraph_size]: Minimum size of TensorRT subgraphs.\n" diff --git a/onnxruntime/test/perftest/ort_test_session.cc b/onnxruntime/test/perftest/ort_test_session.cc index a8ba0964e96ff..86d04fb4bbc2b 100644 --- a/onnxruntime/test/perftest/ort_test_session.cc +++ b/onnxruntime/test/perftest/ort_test_session.cc @@ -199,11 +199,12 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device std::string option_string = performance_test_config.run_config.ep_runtime_config_string; #endif ParseSessionConfigs(option_string, provider_options, - {"backend_path", "profiling_file_path", "profiling_level", "rpc_control_latency", - "vtcm_mb", "soc_model", "device_id", "htp_performance_mode", "qnn_saver_path", - "htp_graph_finalization_optimization_mode", "qnn_context_priority", "htp_arch", - "enable_htp_fp16_precision", "offload_graph_io_quantization", "enable_htp_spill_fill_buffer", - "enable_htp_shared_memory_allocator", "dump_json_qnn_graph", "json_qnn_graph_dir"}); + {"backend_type", "backend_path", "profiling_file_path", "profiling_level", + "rpc_control_latency", "vtcm_mb", "soc_model", "device_id", "htp_performance_mode", + "qnn_saver_path", "htp_graph_finalization_optimization_mode", "qnn_context_priority", + "htp_arch", "enable_htp_fp16_precision", "offload_graph_io_quantization", + "enable_htp_spill_fill_buffer", "enable_htp_shared_memory_allocator", "dump_json_qnn_graph", + "json_qnn_graph_dir"}); for (const auto& provider_option : provider_options) { const std::string& key = provider_option.first; const std::string& value = provider_option.second; @@ -216,7 +217,8 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device if (supported_profiling_level.find(value) == supported_profiling_level.end()) { ORT_THROW("Supported profiling_level: off, basic, detailed"); } - } else if (key == "rpc_control_latency" || key == "vtcm_mb" || key == "soc_model" || key == "device_id") { + } else if (key == "backend_type" || key == "rpc_control_latency" || key == "vtcm_mb" || key == "soc_model" || + key == "device_id") { // no validation } else if (key == "htp_performance_mode") { std::set supported_htp_perf_mode = {"burst", "balanced", "default", "high_performance", diff --git a/onnxruntime/test/providers/qnn/argmaxmin_op_test.cc b/onnxruntime/test/providers/qnn/argmaxmin_op_test.cc index 0dd223bca6114..1ee556dfea294 100644 --- a/onnxruntime/test/providers/qnn/argmaxmin_op_test.cc +++ b/onnxruntime/test/providers/qnn/argmaxmin_op_test.cc @@ -44,11 +44,7 @@ static void RunCPUArgMxxOpTest(const std::string& op_type, TestInputDef i int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; RunQnnModelTest(BuildOpTestCase(op_type, {input_def}, {}, attrs), provider_options, @@ -65,11 +61,7 @@ static void RunQDQArgMxxOpTest(const std::string& op_type, TestInputDef i int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase(op_type, {input_def}, {}, attrs), // baseline float32 model diff --git a/onnxruntime/test/providers/qnn/average_pool_test.cc b/onnxruntime/test/providers/qnn/average_pool_test.cc index 16dd84ace2e0e..7969f4472629a 100644 --- a/onnxruntime/test/providers/qnn/average_pool_test.cc +++ b/onnxruntime/test/providers/qnn/average_pool_test.cc @@ -26,11 +26,7 @@ static void RunAveragePoolOpTest(const std::string& op_type, ExpectedEPNodeAssignment expected_ep_assignment, int opset = 18) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase(op_type, input_defs, {}, attrs), @@ -49,11 +45,7 @@ static void RunQDQAveragePoolOpTest(const std::string& op_type, int opset = 18, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase(op_type, input_defs, {}, attrs), @@ -190,4 +182,4 @@ TEST_F(QnnHTPBackendTests, AveragePool_AutopadSameLower_HTP_u8) { } // namespace test } // namespace onnxruntime -#endif // !defined(ORT_MINIMAL_BUILD) \ No newline at end of file +#endif // !defined(ORT_MINIMAL_BUILD) diff --git a/onnxruntime/test/providers/qnn/batch_norm_htp_test.cc b/onnxruntime/test/providers/qnn/batch_norm_htp_test.cc index 7471b44fafc63..73bb6f2d203c0 100644 --- a/onnxruntime/test/providers/qnn/batch_norm_htp_test.cc +++ b/onnxruntime/test/providers/qnn/batch_norm_htp_test.cc @@ -155,11 +155,7 @@ static void RunBatchNormQDQTest(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Runs model with DQ-> InstanceNorm -> Q and compares the outputs of the CPU and QNN EPs. @@ -176,11 +172,7 @@ static void RunBatchNormFP16Test(const TestInputDef& input_def, const TestInputDef& bias_def, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestInputDef input_fp16_def = ConvertToFP16InputDef(input_def); @@ -277,12 +269,7 @@ TEST_F(QnnHTPBackendTests, BatchNorm_FP16) { TEST_F(QnnHTPBackendTests, BatchNorm_FP32_as_FP16) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif - + provider_options["backend_type"] = "htp"; provider_options["enable_htp_fp16_precision"] = "1"; constexpr int64_t num_channels = 2; diff --git a/onnxruntime/test/providers/qnn/cast_test.cc b/onnxruntime/test/providers/qnn/cast_test.cc index 3a90a6db6d5c0..2326b2949a6bd 100644 --- a/onnxruntime/test/providers/qnn/cast_test.cc +++ b/onnxruntime/test/providers/qnn/cast_test.cc @@ -52,11 +52,7 @@ static void RunCastOpTest(const std::vector& shape, ONNX_NAMESPACE::Ten bool use_htp, bool enable_fp16_precision = true) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = use_htp ? "QnnHtp.dll" : "QnnCpu.dll"; -#else - provider_options["backend_path"] = use_htp ? "libQnnHtp.so" : "libQnnCpu.so"; -#endif + provider_options["backend_type"] = use_htp ? "htp" : "cpu"; provider_options["offload_graph_io_quantization"] = "0"; if (use_htp && enable_fp16_precision) { @@ -134,4 +130,4 @@ TEST_F(QnnHTPBackendTests, TestCastInt32ToInt64HTP) { } // namespace test } // namespace onnxruntime -#endif // !defined(ORT_MINIMAL_BUILD) \ No newline at end of file +#endif // !defined(ORT_MINIMAL_BUILD) diff --git a/onnxruntime/test/providers/qnn/clip_op_test.cc b/onnxruntime/test/providers/qnn/clip_op_test.cc index 2ac34acbf16e2..512403bc5a10b 100644 --- a/onnxruntime/test/providers/qnn/clip_op_test.cc +++ b/onnxruntime/test/providers/qnn/clip_op_test.cc @@ -24,12 +24,7 @@ static void RunClipTest(const TestInputDef& input_def, int opset = 13, bool enable_fp16_precision = true) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = on_cpu_backend ? "QnnCpu.dll" : "QnnHtp.dll"; -#else - provider_options["backend_path"] = on_cpu_backend ? "libQnnCpu.so" : "libQnnHtp.so"; -#endif + provider_options["backend_type"] = on_cpu_backend ? "cpu" : "htp"; if (!on_cpu_backend && enable_fp16_precision) { provider_options["enable_htp_fp16_precision"] = "1"; @@ -111,12 +106,7 @@ static void RunQDQClipTestOnHTP(const TestInputDef& input_def, int opset = 13, bool use_contrib_qdq = false) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase("Clip", {input_def}, {min_max_defs}, {}); @@ -200,12 +190,7 @@ TEST_F(QnnHTPBackendTests, Clip_U8_Rank5) { }; ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(model_fn, @@ -217,12 +202,7 @@ TEST_F(QnnHTPBackendTests, Clip_U8_Rank5) { // Test FP16 Clip with min (FP16) TEST_F(QnnHTPBackendTests, Clip_FP16) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; auto f32_input = TestInputDef({1, 3, 2, 2}, false, {-10.0f, -8.0f, -3.5f, 2.2f, diff --git a/onnxruntime/test/providers/qnn/conv_test.cc b/onnxruntime/test/providers/qnn/conv_test.cc index 5562da10b5463..b15042a808c37 100644 --- a/onnxruntime/test/providers/qnn/conv_test.cc +++ b/onnxruntime/test/providers/qnn/conv_test.cc @@ -87,12 +87,7 @@ static void RunCPUConvOpTest(const std::string& conv_op_type, const TestInputDef int opset = 13, float fp32_abs_err = 1e-5f) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; auto build_fn = BuildF32ConvTestCase(conv_op_type, input_def, weights_def, bias_def, strides, pads, @@ -313,12 +308,7 @@ static void RunHTPConvOpTest(const std::string& conv_op_type, const TestInputDef QDQTolerance tolerance = QDQTolerance(), std::optional output_activation = std::nullopt) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildF32ConvTestCase(conv_op_type, input_def, weights_def, bias_def, strides, pads, dilations, @@ -351,12 +341,7 @@ static void RunHTPConvOpPerChannelTest(const std::string& conv_op_type, const Te QDQTolerance tolerance = QDQTolerance(), std::optional output_activation = std::nullopt) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_fn = BuildF32ConvTestCase(conv_op_type, input_def, weights_def, bias_def, strides, pads, dilations, @@ -671,12 +656,7 @@ TEST_F(QnnCPUBackendTests, ConvTranspose1Df32_DynamicWeights_DefaultBias) { // So, Conv gets processed before Mul node TEST_F(QnnHTPBackendTests, Test_QDQConvWithDynamicWeightsFromMul) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto BuildConvMulGraph = [](ModelTestBuilder& builder) { diff --git a/onnxruntime/test/providers/qnn/flatten_op_test.cc b/onnxruntime/test/providers/qnn/flatten_op_test.cc index 9c87fae512b72..da2d452c788cf 100644 --- a/onnxruntime/test/providers/qnn/flatten_op_test.cc +++ b/onnxruntime/test/providers/qnn/flatten_op_test.cc @@ -22,12 +22,7 @@ static void RunFlattenTestOnCPU(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, int opset = 13) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; RunQnnModelTest(BuildOpTestCase("Flatten", {input_def}, {}, attrs), provider_options, @@ -73,12 +68,7 @@ static void RunFlattenTestOnHTP(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, int opset = 13) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; RunQnnModelTest(BuildOpTestCase("Flatten", {input_def}, {}, attrs), provider_options, @@ -95,12 +85,7 @@ static void RunQDQFlattenTestOnHTP(const TestInputDef& input_def, int opset = 13, bool use_contrib_qdq = false) { ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase("Flatten", {input_def}, {}, attrs); @@ -167,12 +152,7 @@ TEST_F(QnnHTPBackendTests, Flatten_QDQ8bit_Rank5) { }; ProviderOptions provider_options; - -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(model_fn, diff --git a/onnxruntime/test/providers/qnn/gather_elems_op_test.cc b/onnxruntime/test/providers/qnn/gather_elems_op_test.cc index 4cce75d6927df..9036410139b48 100644 --- a/onnxruntime/test/providers/qnn/gather_elems_op_test.cc +++ b/onnxruntime/test/providers/qnn/gather_elems_op_test.cc @@ -62,11 +62,7 @@ static void RunCPUGatherElemsOpTest(const TestInputDef& input_def, ProviderOptions provider_options; float fp32_abs_err = 1e-5f; // default tolerance -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase("GatherElements", {input_def}, {indices_def}, attrs), @@ -87,11 +83,7 @@ static void RunHTPQDQGatherElemsOpTest(const TestInputDef& input_def, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase("GatherElements", {input_def}, {indices_def}, attrs); @@ -116,11 +108,7 @@ static void RunHTPGatherElemsOpTest(const TestInputDef& input_def, ProviderOptions provider_options; float fp32_abs_err = 1e-5f; // default tolerance -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase("GatherElements", {input_def}, {indices_def}, attrs), diff --git a/onnxruntime/test/providers/qnn/gather_op_htp_test.cc b/onnxruntime/test/providers/qnn/gather_op_htp_test.cc index 3db96ddb548d2..326354dffa8ae 100644 --- a/onnxruntime/test/providers/qnn/gather_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/gather_op_htp_test.cc @@ -58,11 +58,7 @@ static void RunQDQGatherOpTest(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase("Gather", {input_def}, {indices_def}, attrs); @@ -170,11 +166,7 @@ static void RunOpTest(const std::string& op_type, const std::string& op_domain = kOnnxDomain, float fp32_abs_err = 1e-3f) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Runs model with a Q/DQ binary op and compares the outputs of the CPU and QNN EPs. @@ -199,4 +191,4 @@ TEST_F(QnnHTPBackendTests, GatherOp_IndicesStaticInt64) { } // namespace test } // namespace onnxruntime -#endif \ No newline at end of file +#endif diff --git a/onnxruntime/test/providers/qnn/gemm_op_test.cc b/onnxruntime/test/providers/qnn/gemm_op_test.cc index 4d82578cb8536..a7c86806bf426 100644 --- a/onnxruntime/test/providers/qnn/gemm_op_test.cc +++ b/onnxruntime/test/providers/qnn/gemm_op_test.cc @@ -24,11 +24,7 @@ static void RunGemmTestOnCPU(const std::vector>& input_de int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase("Gemm", input_defs, {}, attrs), @@ -198,11 +194,7 @@ void RunCPUReshapeGemmTest(const TestInputDef& input, const TestInputDef< ExpectedEPNodeAssignment expected_ep_assignment, float fp32_abs_err = 1e-5f) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; auto build_fn = BuildReshapeGemmTestCase(input, shape, weight, bias); RunQnnModelTest(build_fn, provider_options, 18, expected_ep_assignment, fp32_abs_err); } @@ -283,11 +275,7 @@ static void RunQDQGemmTestOnHTP(const std::vector>& input_de QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase("Gemm", input_defs, {}, attrs); diff --git a/onnxruntime/test/providers/qnn/instance_norm_htp_test.cc b/onnxruntime/test/providers/qnn/instance_norm_htp_test.cc index d4f66b72e0a4c..4823b152b0269 100644 --- a/onnxruntime/test/providers/qnn/instance_norm_htp_test.cc +++ b/onnxruntime/test/providers/qnn/instance_norm_htp_test.cc @@ -74,11 +74,7 @@ static void RunInstanceNormQDQTest(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Runs model with DQ-> InstanceNorm -> Q and compares the outputs of the CPU and QNN EPs. diff --git a/onnxruntime/test/providers/qnn/layer_norm_test.cc b/onnxruntime/test/providers/qnn/layer_norm_test.cc index b2997c627827d..182877ddf200c 100644 --- a/onnxruntime/test/providers/qnn/layer_norm_test.cc +++ b/onnxruntime/test/providers/qnn/layer_norm_test.cc @@ -23,11 +23,7 @@ static void RunLayerNormCpuTest(const TestInputDef& input_def, const std::vector& attrs, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase("LayerNormalization", {input_def, scale_def}, {}, attrs), @@ -148,11 +144,7 @@ static void RunLayerNormQDQTest(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, bool use_contrib_qdq_ops = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase("LayerNormalization", {input_def, scale_def}, {}, attrs), diff --git a/onnxruntime/test/providers/qnn/leakyrelu_op_htp_test.cc b/onnxruntime/test/providers/qnn/leakyrelu_op_htp_test.cc index 77d96b56d23ef..ec85fd3dd339d 100644 --- a/onnxruntime/test/providers/qnn/leakyrelu_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/leakyrelu_op_htp_test.cc @@ -23,11 +23,7 @@ static void RunLeakyReluOpQDQTest(const TestInputDef& input_def, int opset, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase("LeakyRelu", {input_def}, {}, attrs), @@ -62,11 +58,7 @@ TEST_F(QnnHTPBackendTests, LeakyReluOpSet16) { // Test Leaky Relu where input is FP16 and alpha is FP32 TEST_F(QnnHTPBackendTests, LeakyReluFP16OpSet16) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto input_def = TestInputDef({1, 2, 3}, false, {-40.0f, -20.0f, 1.0f, 10.0f, 30.0f, 40.0f}); @@ -83,4 +75,4 @@ TEST_F(QnnHTPBackendTests, LeakyReluFP16OpSet16) { } // namespace test } // namespace onnxruntime -#endif \ No newline at end of file +#endif diff --git a/onnxruntime/test/providers/qnn/logical_comp_ops_test.cc b/onnxruntime/test/providers/qnn/logical_comp_ops_test.cc index eca018c4b5ded..18e19efca13d7 100644 --- a/onnxruntime/test/providers/qnn/logical_comp_ops_test.cc +++ b/onnxruntime/test/providers/qnn/logical_comp_ops_test.cc @@ -68,11 +68,7 @@ static void RunCPULogicalOpTest(const std::string& op_type, const std::vector(op_type, shape), @@ -154,11 +146,7 @@ TEST_F(QnnHTPBackendTests, LogicalOpLessOrEqual4D) { // Tests a QDQ graph with an Equal node followed by a Cast. TEST_F(QnnHTPBackendTests, EqualToCast4D) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Model building function that creates a QDQ graph with an Equal node followed by diff --git a/onnxruntime/test/providers/qnn/lrn_op_test.cc b/onnxruntime/test/providers/qnn/lrn_op_test.cc index 1744be53d5caa..bb3a40a47a750 100644 --- a/onnxruntime/test/providers/qnn/lrn_op_test.cc +++ b/onnxruntime/test/providers/qnn/lrn_op_test.cc @@ -64,12 +64,11 @@ static void RunCPULRNOpTest(const TestInputDef& input_def, int64_t size, ProviderOptions provider_options; float fp32_abs_err = 1e-5f; // default tolerance -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; +#if !defined(_WIN32) fp32_abs_err = 1.5e-5f; // On linux we need slightly larger tolerance. #endif + + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildLRNTestCase(input_def, size, alpha, beta, bias), @@ -87,11 +86,7 @@ static void RunQDQLRNOpTest(const TestInputDef& input_def, int64_t size, float alpha = 0.0001f, float beta = 0.75f, float bias = 1.0f, int opset = 13, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildLRNTestCase(input_def, size, alpha, beta, bias), diff --git a/onnxruntime/test/providers/qnn/matmul_test.cpp b/onnxruntime/test/providers/qnn/matmul_test.cpp index 5cf915e9a4729..09ead72889bca 100644 --- a/onnxruntime/test/providers/qnn/matmul_test.cpp +++ b/onnxruntime/test/providers/qnn/matmul_test.cpp @@ -31,19 +31,7 @@ static void RunMatMulOpTest(bool is_htp_backend, const std::vector& sha ExpectedEPNodeAssignment expected_ep_assignment = ExpectedEPNodeAssignment::All, int opset = 18, float f32_abs_err = 1e-4f) { ProviderOptions provider_options; - if (is_htp_backend) { -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif - } else { -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif - } + provider_options["backend_type"] = is_htp_backend ? "htp" : "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildMatMulOpTestCase( @@ -139,11 +127,7 @@ static void RunQDQMatMulOpTest(const std::vector& shape_0, const std::v int opset = 21, bool use_contrib_qdq = false, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestInputDef input0_def( @@ -170,11 +154,7 @@ static void RunQDQPerChannelMatMulOpTest( ExpectedEPNodeAssignment expected_ep_assignment = ExpectedEPNodeAssignment::All, int opset = 21, bool use_contrib_qdq = false, bool enable_fp16_precision = true) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; if (enable_fp16_precision) { @@ -314,11 +294,7 @@ TEST_F(QnnHTPBackendTests, MatMulOp_QDQ) { // Got specific shapes and input ranges (quant params) from customer model. TEST_F(QnnHTPBackendTests, MatMulOp_QDQ_Regression_uint16_dynamic_inputs) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Test with rank 4 inputs diff --git a/onnxruntime/test/providers/qnn/max_min_op_test.cc b/onnxruntime/test/providers/qnn/max_min_op_test.cc index c7f5eaa0a0af5..bea2e807d4453 100644 --- a/onnxruntime/test/providers/qnn/max_min_op_test.cc +++ b/onnxruntime/test/providers/qnn/max_min_op_test.cc @@ -21,11 +21,7 @@ static void RunCPUMinOrMaxOpTest(const std::string& op_type, int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase(op_type, input_defs, {}, {}, kOnnxDomain), @@ -43,11 +39,7 @@ static void RunQDQMinOrMaxOpTest(const std::string& op_type, int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase(op_type, input_defs, {}, {}, kOnnxDomain), // baseline float32 model diff --git a/onnxruntime/test/providers/qnn/pad_op_test.cpp b/onnxruntime/test/providers/qnn/pad_op_test.cpp index 3497a9ceff664..e0bf18a350dff 100644 --- a/onnxruntime/test/providers/qnn/pad_op_test.cpp +++ b/onnxruntime/test/providers/qnn/pad_op_test.cpp @@ -103,19 +103,7 @@ static void RunPadOpTest(const TestInputDef& data_def, bool enable_fp16_precision = false, float f32_abs_err = 1e-5f) { ProviderOptions provider_options; - if (use_htp) { -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif - } else { -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif - } + provider_options["backend_type"] = use_htp ? "htp" : "cpu"; provider_options["offload_graph_io_quantization"] = "0"; if (enable_fp16_precision) { @@ -140,11 +128,7 @@ static void RunQDQPadOpTest(const TestInputDef& data_def, bool constant_value_quantized = true, int opset = 18) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildPadTestCase(data_def, pads_def, constant_value_def, attrs), @@ -437,4 +421,4 @@ TEST_F(QnnHTPBackendTests, Pad5d) { } // namespace test } // namespace onnxruntime -#endif // !defined(ORT_MINIMAL_BUILD) \ No newline at end of file +#endif // !defined(ORT_MINIMAL_BUILD) diff --git a/onnxruntime/test/providers/qnn/pool_op_test.cpp b/onnxruntime/test/providers/qnn/pool_op_test.cpp index 76399b413f97b..ae194bd2ef920 100644 --- a/onnxruntime/test/providers/qnn/pool_op_test.cpp +++ b/onnxruntime/test/providers/qnn/pool_op_test.cpp @@ -55,11 +55,7 @@ static void RunPoolOpTest(const std::string& op_type, ExpectedEPNodeAssignment expected_ep_assignment, int opset = 18) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase(op_type, {input_def}, {}, attrs), @@ -79,11 +75,7 @@ static void RunQDQPoolOpTest(const std::string& op_type, bool use_contrib_qdq_ops = false, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase(op_type, {input_def}, {}, attrs), @@ -300,4 +292,4 @@ TEST_F(QnnHTPBackendTests, GlobalMaxPool_LargeInput2_u8) { } // namespace test } // namespace onnxruntime -#endif // !defined(ORT_MINIMAL_BUILD) \ No newline at end of file +#endif // !defined(ORT_MINIMAL_BUILD) diff --git a/onnxruntime/test/providers/qnn/qnn_basic_test.cc b/onnxruntime/test/providers/qnn/qnn_basic_test.cc index 0b51b6f8e503d..ae976c164734b 100644 --- a/onnxruntime/test/providers/qnn/qnn_basic_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_basic_test.cc @@ -222,6 +222,29 @@ TEST(QnnEP, TestDisableCPUFallback_ConflictingConfig) { } } +TEST(QnnEP, TestInvalidSpecificationOfBothBackendTypeAndBackendPath) { + onnxruntime::ProviderOptions provider_options{}; + provider_options["backend_type"] = "cpu"; +#if defined(_WIN32) + provider_options["backend_path"] = "QnnCpu.dll"; +#else + provider_options["backend_path"] = "libQnnCpu.so"; +#endif + + Ort::SessionOptions so{}; + so.AppendExecutionProvider("QNN", provider_options); + + const ORTCHAR_T* ort_model_path = ORT_MODEL_FOLDER "constant_floats.onnx"; + + try { + Ort::Session session(*ort_env, ort_model_path, so); + FAIL(); + } catch (const Ort::Exception& e) { + ASSERT_EQ(e.GetOrtErrorCode(), ORT_FAIL); + ASSERT_THAT(e.what(), testing::HasSubstr("Only one of 'backend_type' and 'backend_path' should be set.")); + } +} + // Conv node `Conv` is not supported: GetFileLength for conv_qdq_external_ini.bin failed:open file conv_qdq_external_ini.bin fail, // errcode = 2 - The system cannot find the file specified. TEST_F(QnnHTPBackendTests, TestConvWithExternalData) { diff --git a/onnxruntime/test/providers/qnn/qnn_test_utils.cc b/onnxruntime/test/providers/qnn/qnn_test_utils.cc index 2361e179d1cf1..6f8a7a9ecb602 100644 --- a/onnxruntime/test/providers/qnn/qnn_test_utils.cc +++ b/onnxruntime/test/providers/qnn/qnn_test_utils.cc @@ -279,7 +279,7 @@ static BackendSupport GetHTPSupport(const onnxruntime::logging::Logger& logger) MockKernelLookup kernel_lookup; onnxruntime::GraphViewer graph_viewer(graph); std::unique_ptr qnn_ep = QnnExecutionProviderWithOptions( - {{"backend_path", "QnnHtp.dll"}, {"offload_graph_io_quantization", "0"}}); + {{"backend_type", "htp"}, {"offload_graph_io_quantization", "0"}}); GraphOptimizerRegistry graph_optimizer_registry(nullptr, nullptr, nullptr); // as a placeholder to feed into GetCapability qnn_ep->SetLogger(&logger); @@ -343,7 +343,7 @@ static BackendSupport GetCPUSupport(const onnxruntime::logging::Logger& logger) MockKernelLookup kernel_lookup; onnxruntime::GraphViewer graph_viewer(graph); std::unique_ptr qnn_ep = QnnExecutionProviderWithOptions( - {{"backend_path", "QnnCpu.dll"}, {"offload_graph_io_quantization", "0"}}); + {{"backend_type", "cpu"}, {"offload_graph_io_quantization", "0"}}); GraphOptimizerRegistry graph_optimizer_registry(nullptr, nullptr, nullptr); // as a placeholder to feed into GetCapability qnn_ep->SetLogger(&logger); diff --git a/onnxruntime/test/providers/qnn/reduce_op_test.cc b/onnxruntime/test/providers/qnn/reduce_op_test.cc index 290630c1254f9..f96e5338369b2 100644 --- a/onnxruntime/test/providers/qnn/reduce_op_test.cc +++ b/onnxruntime/test/providers/qnn/reduce_op_test.cc @@ -84,18 +84,10 @@ static void RunReduceTest(const std::string& op_type, ProviderOptions provider_options; provider_options["offload_graph_io_quantization"] = "0"; if (enable_fp16) { -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["enable_htp_fp16_precision"] = "1"; } else { -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; } RunQnnModelTest(BuildReduceOpTestCase(op_type, @@ -419,11 +411,7 @@ static void RunReduceOpQDQTest(const std::string& op_type, int opset, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; constexpr bool noop_with_empty_axes = false; diff --git a/onnxruntime/test/providers/qnn/reshape_expand_op_test.cc b/onnxruntime/test/providers/qnn/reshape_expand_op_test.cc index ea55cb46099bb..b978e3a0790db 100644 --- a/onnxruntime/test/providers/qnn/reshape_expand_op_test.cc +++ b/onnxruntime/test/providers/qnn/reshape_expand_op_test.cc @@ -25,11 +25,7 @@ static void RunReshapeExpandTestOnCPU(const std::string& op_type, int opset = 19) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase(op_type, {input_def}, {shape_def}, attrs), @@ -157,11 +153,7 @@ static void RunReshapeExpandTestOnHTP(const std::string& op_type, int opset = 19) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase(op_type, {input_def}, {shape_def}, attrs), @@ -182,11 +174,7 @@ static void RunQDQReshapeExpandTestOnHTP(const std::string& op_type, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase(op_type, {input_def}, {shape_def}, attrs); diff --git a/onnxruntime/test/providers/qnn/resize_test.cc b/onnxruntime/test/providers/qnn/resize_test.cc index e1ac1d7889954..fbd729fa998d9 100644 --- a/onnxruntime/test/providers/qnn/resize_test.cc +++ b/onnxruntime/test/providers/qnn/resize_test.cc @@ -122,11 +122,7 @@ static void RunCPUResizeOpTest(const TestInputDef& input_def, const std:: ExpectedEPNodeAssignment expected_ep_assignment, int opset = 19) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(GetResizeModelBuilder(input_def, sizes_data, mode, coordinate_transformation_mode, nearest_mode), @@ -141,11 +137,7 @@ static void RunCPUResizeOpTestWithScales(const TestInputDef& input_def, c ExpectedEPNodeAssignment expected_ep_assignment, int opset = 19) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(GetResizeModelBuilderWithScales(input_def, scales_data, mode, coordinate_transformation_mode, nearest_mode), @@ -163,11 +155,7 @@ static void RunQDQResizeOpTest(const TestInputDef& input_def, int opset = 19, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(GetResizeModelBuilder(input_def, sizes_data, mode, coordinate_transformation_mode, nearest_mode), diff --git a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc index 2d7d034ac2ad6..f9c9e0f709495 100644 --- a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc @@ -27,11 +27,7 @@ static void RunOpTestOnCPU(const std::string& op_type, ExpectedEPNodeAssignment expected_ep_assignment, const std::string& op_domain = kOnnxDomain) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(BuildOpTestCase(op_type, input_defs, {}, attrs, op_domain), @@ -127,11 +123,7 @@ static void RunQDQOpTest(const std::string& op_type, bool use_contrib_qdq = false, QDQTolerance tolerance = QDQTolerance()) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase(op_type, input_defs, {}, attrs, op_domain), @@ -153,11 +145,7 @@ static void RunOpTest(const std::string& op_type, float fp32_abs_err = 1e-5f, bool enable_htp_fp16_precision = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; if (enable_htp_fp16_precision) { provider_options["enable_htp_fp16_precision"] = "1"; @@ -180,11 +168,7 @@ static void RunFP16OpTest(const std::string& op_type, const std::string& op_domain = kOnnxDomain, float tolerance = 0.004f) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; std::vector> input_fp16_defs; input_fp16_defs.reserve(input_defs.size()); @@ -783,11 +767,7 @@ TEST_F(QnnHTPBackendTests, SpaceToDepthOp_U16) { TEST_F(QnnHTPBackendTests, QuantAccuracyTest) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Note: a graph input -> Q -> DQ -> is optimized by Qnn to have a perfectly accurate output. @@ -1215,11 +1195,7 @@ TEST_F(QnnHTPBackendTests, Add_U8_U16_Convert) { TestInputDef input1_def({1, 2, 2, 2}, false, input1_data); ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; TestQDQModelAccuracy(BuildOpTestCase("Add", {input0_def, input1_def}, {}, {}, kOnnxDomain), @@ -1281,11 +1257,7 @@ TEST_F(QnnHTPBackendTests, DQ_Q_ConvertFusion_SameType) { TestInputDef input1_def({1, 2, 2, 2}, false, input1_data); ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; QuantParams out_qparams_u8 = {1.0f, 128}; @@ -1412,11 +1384,7 @@ static GetTestModelFn BuildHardSigmoidFusionTestCase(TestInputDef& in TEST_F(QnnHTPBackendTests, HardSigmoidFusedIntoHardSwish_FP32_as_FP16) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["enable_htp_fp16_precision"] = "1"; @@ -1439,11 +1407,7 @@ TEST_F(QnnHTPBackendTests, HardSigmoidFusedIntoHardSwish_FP32_as_FP16) { TEST_F(QnnHTPBackendTests, HardSigmoidFusedIntoHardSwish_FP16) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; std::vector input_data = {-8.0f, -2.0f, 0.0f, 0.5f, 0.9f, 1.1f, 3.3f, 8.0f, -7.0f, 0.0f, 0.2f, 0.4f, 0.8f, 2.1f, 4.3f, 7.0f}; diff --git a/onnxruntime/test/providers/qnn/slice_htp_test.cc b/onnxruntime/test/providers/qnn/slice_htp_test.cc index dc16192188e0b..9c50f47d462bc 100644 --- a/onnxruntime/test/providers/qnn/slice_htp_test.cc +++ b/onnxruntime/test/providers/qnn/slice_htp_test.cc @@ -44,11 +44,7 @@ TEST_F(QnnCPUBackendTests, Slice_SharedInitializersBugFix) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; RunQnnModelTest(model_fn, provider_options, @@ -79,11 +75,7 @@ static void RunSliceQDQTest(const TestInputDef& data_def, ExpectedEPNodeAssignment expected_ep_assignment, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; const std::vector> f32_inputs = {data_def}; @@ -116,11 +108,7 @@ static void RunSliceNonQDQOnHTP(const TestInputDef& data_def, const TestInputDef& steps_def, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; auto f32_model_builder = BuildOpTestCase("Slice", {data_def}, {starts_def, ends_def, axes_def, steps_def}, {}); RunQnnModelTest(f32_model_builder, @@ -207,4 +195,4 @@ TEST_F(QnnHTPBackendTests, SliceU8_MultAxes_LargeEnd) { } // namespace test } // namespace onnxruntime -#endif \ No newline at end of file +#endif diff --git a/onnxruntime/test/providers/qnn/split_op_test.cc b/onnxruntime/test/providers/qnn/split_op_test.cc index 52603b1be5045..bdd322168ee01 100644 --- a/onnxruntime/test/providers/qnn/split_op_test.cc +++ b/onnxruntime/test/providers/qnn/split_op_test.cc @@ -60,11 +60,7 @@ static void RunSplitOpTestOnCPU(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; const bool split_is_input = opset >= 13; RunQnnModelTest(BuildSplitTestCase(input_def, split, split_is_input, axis, num_outputs), @@ -247,11 +243,7 @@ static void RunSplitOpTestOnHTP(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; const bool split_is_input = opset >= 13; RunQnnModelTest(BuildSplitTestCase(input_def, split, split_is_input, axis, num_outputs), @@ -271,11 +263,7 @@ static void RunQDQSplitOpTestOnHTP(const TestInputDef& input_def, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; const bool split_is_input = opset >= 13; diff --git a/onnxruntime/test/providers/qnn/squeeze_unsqueeze_op_test.cc b/onnxruntime/test/providers/qnn/squeeze_unsqueeze_op_test.cc index ead1843e843c1..43e24ce93a22b 100644 --- a/onnxruntime/test/providers/qnn/squeeze_unsqueeze_op_test.cc +++ b/onnxruntime/test/providers/qnn/squeeze_unsqueeze_op_test.cc @@ -23,11 +23,7 @@ static void RunSqueezeTestOnCPU(const std::string& op_type, // Squeeze or Unsqu int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; RunQnnModelTest(BuildOpTestCase(op_type, {input_def}, {axes_def}, {}), provider_options, @@ -132,11 +128,7 @@ static void RunSqueezeTestOnHTP(const std::string& op_type, // Squeeze or Unsqu int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; RunQnnModelTest(BuildOpTestCase(op_type, {input_def}, {axes_def}, {}), provider_options, @@ -156,11 +148,7 @@ static void RunQDQSqueezeTestOnHTP(const std::string& op_type, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase(op_type, {input_def}, {axes_def}, {}); @@ -215,11 +203,7 @@ TEST_F(QnnHTPBackendTests, Squeeze_Rank5_Rank2_f32) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(model_fn, @@ -272,11 +256,7 @@ TEST_F(QnnHTPBackendTests, Unsqueeze_Rank3_Rank5_f32) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; RunQnnModelTest(model_fn, diff --git a/onnxruntime/test/providers/qnn/tile_op_test.cc b/onnxruntime/test/providers/qnn/tile_op_test.cc index 023d6562c6f95..7ad6fcca95eb5 100644 --- a/onnxruntime/test/providers/qnn/tile_op_test.cc +++ b/onnxruntime/test/providers/qnn/tile_op_test.cc @@ -23,11 +23,7 @@ static void RunTileTestOnCPU(const TestInputDef& input_def, int opset = 13) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; RunQnnModelTest(BuildOpTestCase("Tile", {input_def}, {repeats_def}, {}), provider_options, @@ -93,11 +89,7 @@ static void RunQDQTileTestOnHTP(const TestInputDef& input_def, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildOpTestCase("Tile", {input_def}, {repeats_def}, {}); diff --git a/onnxruntime/test/providers/qnn/topk_op_test.cc b/onnxruntime/test/providers/qnn/topk_op_test.cc index b338dd727bf00..84e7299dbe3bb 100644 --- a/onnxruntime/test/providers/qnn/topk_op_test.cc +++ b/onnxruntime/test/providers/qnn/topk_op_test.cc @@ -43,11 +43,7 @@ static void RunTopKTestOnCPU(const TestInputDef& input_def, int opset = 19) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnCpu.dll"; -#else - provider_options["backend_path"] = "libQnnCpu.so"; -#endif + provider_options["backend_type"] = "cpu"; RunQnnModelTest(BuildTopKTestCase(input_def, k_def, attrs), provider_options, @@ -149,11 +145,7 @@ static void RunQDQTopKTestOnHTP(const TestInputDef& input_def, bool use_contrib_qdq = false) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; auto f32_model_builder = BuildTopKTestCase(input_def, k_def, attrs); diff --git a/onnxruntime/test/providers/qnn/transpose_htp_test.cc b/onnxruntime/test/providers/qnn/transpose_htp_test.cc index b7bec34f7dcbd..f206e517408bf 100644 --- a/onnxruntime/test/providers/qnn/transpose_htp_test.cc +++ b/onnxruntime/test/providers/qnn/transpose_htp_test.cc @@ -65,11 +65,7 @@ static void RunTransposeQDQTest(const TestInputDef& input_def, const std::vector& attrs, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Runs model with DQ-> Transpose -> Q and compares the outputs of the CPU and QNN EPs. @@ -94,11 +90,7 @@ static void RunTransposeNonQDQOnHTP(const TestInputDef& input_def, ExpectedEPNodeAssignment expected_ep_assignment, bool enable_fp16_precision = true) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; if (enable_fp16_precision) { provider_options["enable_htp_fp16_precision"] = "1"; @@ -139,4 +131,4 @@ TEST_F(QnnHTPBackendTests, TransposeFloatOnHTP) { } // namespace test } // namespace onnxruntime -#endif \ No newline at end of file +#endif diff --git a/onnxruntime/test/providers/qnn/where_htp_test.cc b/onnxruntime/test/providers/qnn/where_htp_test.cc index e1b0604b314e1..bb3e229bbc9f8 100644 --- a/onnxruntime/test/providers/qnn/where_htp_test.cc +++ b/onnxruntime/test/providers/qnn/where_htp_test.cc @@ -74,11 +74,7 @@ static void RunWhereQDQTest(const TestInputDef& condition_def, const TestInputDef& y_def, ExpectedEPNodeAssignment expected_ep_assignment) { ProviderOptions provider_options; -#if defined(_WIN32) - provider_options["backend_path"] = "QnnHtp.dll"; -#else - provider_options["backend_path"] = "libQnnHtp.so"; -#endif + provider_options["backend_type"] = "htp"; provider_options["offload_graph_io_quantization"] = "0"; // Runs model with DQ-> Where -> Q and compares the outputs of the CPU and QNN EPs. @@ -141,4 +137,4 @@ TEST_F(QnnHTPBackendTests, WhereLargeDataBroadcastTransformedU8) { } // namespace test } // namespace onnxruntime -#endif \ No newline at end of file +#endif From ad2e56524cc61e962060765165ef00ff9c79cd6f Mon Sep 17 00:00:00 2001 From: xhcao Date: Tue, 1 Apr 2025 00:06:25 +0800 Subject: [PATCH 202/266] [webgpu] Fix opset-12 softmax nhwc issue (#24227) ### Description ### Motivation and Context --- onnxruntime/core/providers/webgpu/math/softmax.cc | 8 ++++++-- onnxruntime/core/providers/webgpu/math/softmax.h | 3 ++- onnxruntime/test/providers/cpu/math/softmax_test.cc | 3 +-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/math/softmax.cc b/onnxruntime/core/providers/webgpu/math/softmax.cc index 6a6cfe154b91c..178ca0b9e0515 100644 --- a/onnxruntime/core/providers/webgpu/math/softmax.cc +++ b/onnxruntime/core/providers/webgpu/math/softmax.cc @@ -156,7 +156,9 @@ Status Softmax::ComputeInternal(ComputeContext& context) const { // normalize axis size_t axis = static_cast(HandleNegativeAxis(axis_, input_rank)); - bool is_transpose_required = axis < input_rank - 1; + // The `axis` attribute of the opset lower than version 13 describes the axis of the inputs when coerced to 2D, + // the 0th axis most likely describes the batch_size, so transpose is not required on old opset versions. + bool is_transpose_required = axis < input_rank - 1 && opset_ >= 13; TensorShape transposed_input_shape; Tensor transposed_input_tensor; @@ -179,7 +181,9 @@ Status Softmax::ComputeInternal(ComputeContext& context) const { intermediate_output = context.CreateGPUTensor(output_tensor->DataType(), transposed_input_shape); } - const int64_t cols = is_transpose_required ? transposed_input_shape[input_rank - 1] : input_shape[input_rank - 1]; + // The `axis` attribute of the opset lower than version 13 separates input tensor's dimensions into two parts, + // one part is treated as batch size, and the other part is performed by Softmax. + const int64_t cols = is_transpose_required ? transposed_input_shape[input_rank - 1] : (opset_ >= 13 ? input_shape[input_rank - 1] : input_shape.SizeFromDimension(axis)); const int64_t rows = input_shape.Size() / cols; const int64_t components = GetMaxComponents(cols); const auto packed_cols = cols / components; diff --git a/onnxruntime/core/providers/webgpu/math/softmax.h b/onnxruntime/core/providers/webgpu/math/softmax.h index cc97611dcb4bc..532a56ff0be41 100644 --- a/onnxruntime/core/providers/webgpu/math/softmax.h +++ b/onnxruntime/core/providers/webgpu/math/softmax.h @@ -14,7 +14,7 @@ namespace webgpu { class Softmax final : public WebGpuKernel { public: Softmax(const OpKernelInfo& info) : WebGpuKernel{info} { - int opset_ = info.node().SinceVersion(); + opset_ = info.node().SinceVersion(); int64_t axis; Status status = info.GetAttr("axis", &axis); @@ -33,6 +33,7 @@ class Softmax final : public WebGpuKernel { private: int64_t axis_; + int opset_; }; class SoftmaxProgram final : public Program { diff --git a/onnxruntime/test/providers/cpu/math/softmax_test.cc b/onnxruntime/test/providers/cpu/math/softmax_test.cc index 03f5fdaab2780..1c6375ebdb0b1 100644 --- a/onnxruntime/test/providers/cpu/math/softmax_test.cc +++ b/onnxruntime/test/providers/cpu/math/softmax_test.cc @@ -422,8 +422,7 @@ TEST(SoftmaxOperator, GH15949_regression_test) { {0.00032932f, 0.01798029f, 0.9816904f}); // disable TRT as it does not support axis=0 as used by the model - // TODO: Fix the Softmax operator of WebGPU EP. - tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kWebGpuExecutionProvider}); + tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); } } // namespace test From 528f29a875f674da76ccc4e3ec0069e42bd0397b Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 31 Mar 2025 09:23:36 -0700 Subject: [PATCH 203/266] Extend pyright exclude list in pyproject.toml (#24246) ### Description Improve the performance of file glob for pyright. This helps to improve VSCode performance (if pyright plugin is installed) --- pyproject.toml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f95fb0ff955a4..09a203772aaf9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,15 @@ convention = "google" [tool.pyright] -exclude = ["onnxruntime/core/flatbuffers/*"] +exclude = [ + "onnxruntime/core/flatbuffers/*", + "cmake/external/**", + "**/node_modules/**", + "**/__pycache__/**", + "**/build/**", + "**/build_*/**", + "**/.DS_Store/**", +] reportMissingImports = false [tool.ruff] From ba2999c5a424ed92d2628948220aad88edee1eb6 Mon Sep 17 00:00:00 2001 From: jing-bao Date: Tue, 1 Apr 2025 01:03:40 +0800 Subject: [PATCH 204/266] [js/web] Add Wasm Relaxed SIMD support to wasm backend (#22794) ### Description Add Wasm Relaxed SIMD support. Use integer dot product instructions for QGemmU8X8. 1. Build with --enable_wasm_relaxed_simd 2. Use env.wasm.relaxedSimd to run it ### Motivation and Context https://github.com/microsoft/onnxruntime/issues/22533 --------- Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- cmake/CMakeLists.txt | 1 + cmake/adjust_global_compile_flags.cmake | 5 +- cmake/external/xnnpack.cmake | 7 +- cmake/onnxruntime_mlas.cmake | 6 + cmake/onnxruntime_unittests.cmake | 5 +- cmake/onnxruntime_webassembly.cmake | 4 +- onnxruntime/core/mlas/inc/mlas.h | 5 +- onnxruntime/core/mlas/lib/mlasi.h | 5 + onnxruntime/core/mlas/lib/qgemm.h | 8 + .../mlas/lib/qgemm_kernel_wasmrelaxedsimd.cpp | 563 ++++++++++++++++++ tools/ci_build/build.py | 7 + 11 files changed, 611 insertions(+), 5 deletions(-) create mode 100644 onnxruntime/core/mlas/lib/qgemm_kernel_wasmrelaxedsimd.cpp diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 30123fc066f1e..b81df151562dc 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -193,6 +193,7 @@ option(onnxruntime_ENABLE_WEBASSEMBLY_DEBUG_INFO "Enable this option to turn on option(onnxruntime_ENABLE_WEBASSEMBLY_PROFILING "Enable this option to turn on WebAssembly profiling and preserve function names" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL "Enable this option to allow WebAssembly to output optimized model" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64 "Enable this option to allow WebAssembly to use 64bit memory" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD "Enable WebAssembly Relaxed SIMD" OFF) # Enable bitcode for iOS option(onnxruntime_ENABLE_BITCODE "Enable bitcode for iOS only" OFF) diff --git a/cmake/adjust_global_compile_flags.cmake b/cmake/adjust_global_compile_flags.cmake index 45ad3cd140a8a..8f5ef15c53ef2 100644 --- a/cmake/adjust_global_compile_flags.cmake +++ b/cmake/adjust_global_compile_flags.cmake @@ -35,7 +35,10 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") set(CMAKE_CXX_FLAGS_DEBUG "-g2") endif() - if (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + string(APPEND CMAKE_C_FLAGS " -msimd128 -mrelaxed-simd") + string(APPEND CMAKE_CXX_FLAGS " -msimd128 -mrelaxed-simd") + elseif (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) string(APPEND CMAKE_C_FLAGS " -msimd128") string(APPEND CMAKE_CXX_FLAGS " -msimd128") endif() diff --git a/cmake/external/xnnpack.cmake b/cmake/external/xnnpack.cmake index 02ef9a198a803..d0ab770053be1 100644 --- a/cmake/external/xnnpack.cmake +++ b/cmake/external/xnnpack.cmake @@ -143,7 +143,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/scalar.c) list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/wasm.c) - if(onnxruntime_ENABLE_WEBASSEMBLY_SIMD) + if(onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/wasmsimd.c) + list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/wasmrelaxedsimd.c) + target_compile_options(XNNPACK PRIVATE "-msimd128") + target_compile_options(XNNPACK PRIVATE "-mrelaxed-simd") + elseif(onnxruntime_ENABLE_WEBASSEMBLY_SIMD) list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/wasmsimd.c) target_compile_options(XNNPACK PRIVATE "-msimd128") endif() diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index 98f2a9b099dad..8decca10937ba 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -287,6 +287,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") ${mlas_platform_srcs} ${MLAS_SRC_DIR}/qgemm_kernel_wasmsimd.cpp ) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + set(mlas_platform_srcs + ${mlas_platform_srcs} + ${MLAS_SRC_DIR}/qgemm_kernel_wasmrelaxedsimd.cpp + ) + endif() else() file(GLOB_RECURSE mlas_platform_srcs "${MLAS_SRC_DIR}/scalar/*.cpp" diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index b5d7139c6adfd..08807faa3e9b7 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -222,8 +222,11 @@ function(AddTest) else() set(TEST_NODE_FLAGS) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + message(WARNING "Use system `node` to test Wasm relaxed SIMD. Please make sure to install node v21 or newer.") + set(NODE_EXECUTABLE node) # prefer Node from emsdk so the version is more deterministic - if (DEFINED ENV{EMSDK_NODE}) + elseif (DEFINED ENV{EMSDK_NODE}) set(NODE_EXECUTABLE $ENV{EMSDK_NODE}) else() message(WARNING "EMSDK_NODE environment variable was not set. Falling back to system `node`.") diff --git a/cmake/onnxruntime_webassembly.cmake b/cmake/onnxruntime_webassembly.cmake index f3afaf7033fd1..bfb73e14ce7a4 100644 --- a/cmake/onnxruntime_webassembly.cmake +++ b/cmake/onnxruntime_webassembly.cmake @@ -485,7 +485,9 @@ jsepDownload:_pp_") list(APPEND target_name_list "wasm") - if (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + list(APPEND target_name_list "relaxedsimd") + elseif (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) list(APPEND target_name_list "simd") endif() diff --git a/onnxruntime/core/mlas/inc/mlas.h b/onnxruntime/core/mlas/inc/mlas.h index 8033eab8262a0..db21157d2fdce 100644 --- a/onnxruntime/core/mlas/inc/mlas.h +++ b/onnxruntime/core/mlas/inc/mlas.h @@ -63,7 +63,10 @@ Module Name: #endif #if defined(__wasm__) #define MLAS_TARGET_WASM -#if defined(__wasm_simd128__) +#if defined(__wasm_relaxed_simd__) +#define MLAS_TARGET_WASM_RELAXED_SIMD +#define MLAS_TARGET_WASM_SIMD +#elif defined(__wasm_simd128__) #define MLAS_TARGET_WASM_SIMD #else #define MLAS_TARGET_WASM_SCALAR diff --git a/onnxruntime/core/mlas/lib/mlasi.h b/onnxruntime/core/mlas/lib/mlasi.h index b5599af85c200..7532f8eeb5a9b 100644 --- a/onnxruntime/core/mlas/lib/mlasi.h +++ b/onnxruntime/core/mlas/lib/mlasi.h @@ -996,9 +996,14 @@ extern const MLAS_GEMM_QUANT_DISPATCH MlasGemmS8S8DispatchSdot; extern const MLAS_GEMM_QUANT_DISPATCH MlasGemmU8X8DispatchUmmla; extern const MLAS_GEMM_QUANT_DISPATCH MlasGemmS8S8DispatchSmmla; extern const MLAS_GEMM_QUANT_DISPATCH MlasGemmU8X8DispatchWasmSimd; +extern const MLAS_GEMM_QUANT_DISPATCH MlasGemmU8X8DispatchWasmRelaxedSimd; extern const MLAS_GEMM_QUANT_DISPATCH MlasGemmQuantDispatchDefault; extern const MLAS_GEMM_QUANT_DISPATCH MlasGemm8X8DispatchPOWER10; +#if defined(MLAS_TARGET_WASM_RELAXED_SIMD) +extern bool HasUSDot(); +#endif + // // Symmetric quantized qgemm dispatch structure // diff --git a/onnxruntime/core/mlas/lib/qgemm.h b/onnxruntime/core/mlas/lib/qgemm.h index bcd878efa681b..596267c3abdff 100644 --- a/onnxruntime/core/mlas/lib/qgemm.h +++ b/onnxruntime/core/mlas/lib/qgemm.h @@ -886,6 +886,14 @@ MlasGemmQuantGetDispatch( if(BIsSigned || !AIsSigned) { GemmQuantDispatch = &MlasGemmU8X8DispatchNeon; } +#elif defined(MLAS_TARGET_WASM_RELAXED_SIMD) + if (!AIsSigned) { + if (HasUSDot()) { + GemmQuantDispatch = &MlasGemmU8X8DispatchWasmRelaxedSimd; + } else { + GemmQuantDispatch = &MlasGemmU8X8DispatchWasmSimd; + } + } #elif defined(MLAS_TARGET_WASM_SIMD) if (!AIsSigned) { GemmQuantDispatch = &MlasGemmU8X8DispatchWasmSimd; diff --git a/onnxruntime/core/mlas/lib/qgemm_kernel_wasmrelaxedsimd.cpp b/onnxruntime/core/mlas/lib/qgemm_kernel_wasmrelaxedsimd.cpp new file mode 100644 index 0000000000000..a3a0fa758d377 --- /dev/null +++ b/onnxruntime/core/mlas/lib/qgemm_kernel_wasmrelaxedsimd.cpp @@ -0,0 +1,563 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + qgemm_kernel_wasmrelaxedsimd.cpp + +Abstract: + + This module implements QGEMM kernel for WebAssembly Relaxed SIMD128. + +--*/ + +#include "mlasi.h" +#include "qgemm.h" + +bool HasUSDot() { +// Check out-of-bounds behavior of Relaxed Integer Dot Product with Accumulation with signed and unsigned input (e.g. vpdpbusd). + const v128_t int8_input = wasm_i8x16_const(0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0); + const volatile v128_t xint8_input = wasm_i8x16_const(0, 0, 0, -128, 0, 0, -128, 0, 0, -128, 0, 0, -128, 0, 0, 0); // volatile to confuse Clang which otherwise ICE's + const v128_t xint8_output = wasm_i32x4_relaxed_dot_i8x16_i7x16_add(int8_input, xint8_input, wasm_i8x16_const_splat(0)); + + const volatile v128_t overflow_input = wasm_i8x16_const(-128, -128, -128, -128, -128, -128, -1, -1, -1, -1, -128, -128, -1, -1, -1, -1); // volatile to confuse Clang which otherwise ICE's + const v128_t overflow_output = wasm_i32x4_relaxed_dot_i8x16_i7x16_add(wasm_i8x16_const_splat(-128), overflow_input, wasm_i8x16_const_splat(0)); + return !wasm_v128_any_true(wasm_v128_or( + wasm_v128_xor(xint8_output, wasm_i32x4_const_splat(128)), + wasm_v128_xor(overflow_output, wasm_i32x4_const(-65536, -98048, -98048, -130560)))); +} + +// wasm implementation of "_mm_unpacklo_epi8" +v128_t __attribute__((__always_inline__, __nodebug__)) wasm_i8x16_unpacklo_relaxed(v128_t a, v128_t b) { + return wasm_i8x16_shuffle(a, b, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23); +} + +// wasm implementation of "_mm_unpacklo_epi16" +v128_t __attribute__((__always_inline__, __nodebug__)) wasm_i16x8_unpacklo_relaxed(v128_t a, v128_t b) { + return wasm_i8x16_shuffle(a, b, 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23); +} + +// wasm implementation of "_mm_unpackhi_epi16" +v128_t __attribute__((__always_inline__, __nodebug__)) wasm_i16x8_unpackhi_relaxed(v128_t a, v128_t b) { + return wasm_i8x16_shuffle(a, b, 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31); +} + +struct MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD +{ + typedef uint8_t PackedAType; + typedef uint8_t PackedBType; + typedef uint8_t OffsetAType; + typedef int8_t OffsetBType; + + static constexpr size_t PackedK = 4; + static constexpr MLAS_GEMM_QUANT_STRIDES Strides{ 12, 128, 128 }; + static constexpr MLAS_GEMM_QUANT_STRIDES PackedStrides{0, 0, 0}; +}; + +constexpr size_t MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedK; +constexpr MLAS_GEMM_QUANT_STRIDES MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::Strides; + +template<> +MLAS_FORCEINLINE +int32_t +MlasGemmQuantFixupZeroPointB( + int32_t ZeroPointB, + bool BIsSigned + ) +{ + if (!BIsSigned) { + ZeroPointB = MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::OffsetBType(ZeroPointB ^ 0x80); + } + + return ZeroPointB; +} + +template<> +void +MlasGemmQuantCopyPackA( + MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedAType* D, + const uint8_t* A, + size_t lda, + size_t CountM, + size_t CountK, + int32_t* RowSumBuffer, + bool AIsSigned + ) +{ + MLAS_UNREFERENCED_PARAMETER(AIsSigned); + const v128_t ZeroVector = wasm_i64x2_const(0, 0); + const v128_t OnesWordBroadcast = wasm_i16x8_splat(1); + uint8_t PaddedMatrixAData[8] = { 0 }; + + // + // Process a single row of matrix A in a loop. + // + + while (CountM > 0) { + + const uint8_t* a = A; + size_t k = CountK; + v128_t ReductionVector = ZeroVector; + + // + // Copy the source bytes to the packed buffer. + // + // The packed buffer has the same data ordering as the source bytes, + // but CountK is aligned up to a multiple of 4 to maintain 32-bit + // alignment. All extra bytes are zero-padded. + // + // Zero extend the source bytes to 16-bits and accumulate + // into an intermediate per-row + // accumulator. CountK cannot be greater than 128 to avoid overflowing + // these signed 16-bit accumulators. + // + + while (k >= 8) { + + v128_t Bytes = wasm_v128_load64_zero(&a[0]); + v128_t Words = wasm_i8x16_unpacklo_relaxed(Bytes, ZeroVector); + + ReductionVector = wasm_i16x8_add(ReductionVector, Words); + + wasm_v128_store64_lane(&D[0], Bytes, 0); + + a += 8; + D += 8; + k -= 8; + } + + if (k > 0) { + + // + // Copy the remaining bytes to the zero padded stack buffer. + // + + uint8_t* padded = PaddedMatrixAData; + uint8_t* padded_end = padded + k; + + do { + padded[0] = a[0]; + padded++; + a++; + } while (padded < padded_end); + + v128_t Bytes = wasm_v128_load64_zero(PaddedMatrixAData); + v128_t Words = wasm_i8x16_unpacklo_relaxed(Bytes, ZeroVector); + + ReductionVector = wasm_i16x8_add(ReductionVector, Words); + + // + // Copy quads of 8-bit values from the vector to the packed + // buffer and rotate the vector for the next iteration. + // + + for (size_t quads = (k + 3) / 4; quads > 0; quads--) { + *((int32_t*)D) = wasm_i32x4_extract_lane(Bytes, 0); + D += 4; + Bytes = wasm_i32x4_shuffle(Bytes, wasm_i32x4_splat(0), 1, 2, 3, 0); + } + } + + // + // Reduce the partial accumulators. + // + + ReductionVector = wasm_i32x4_dot_i16x8(ReductionVector, OnesWordBroadcast); + ReductionVector = wasm_i32x4_add(ReductionVector, + wasm_i32x4_shuffle(ReductionVector, wasm_i32x4_splat(0), 2, 3, 2, 3)); + ReductionVector = wasm_i32x4_add(ReductionVector, + wasm_i32x4_shuffle(ReductionVector, wasm_i32x4_splat(0), 1, 0, 1, 0)); + + *RowSumBuffer++ = wasm_i32x4_extract_lane(ReductionVector, 0); + + A += lda; + CountM -= 1; + } +} + + +MLAS_FORCEINLINE +void +MlasGemmU8X8CopyPackBProcessWasmRelaxedSimd( + MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedBType* D, + v128_t BytesRow0, + v128_t BytesRow1, + v128_t BytesRow2, + v128_t BytesRow3, + v128_t BitFlipVector, + v128_t OnesByteBroadcast, + v128_t ColumnSums[2] +) +{ + v128_t PairsInterleaved0 = wasm_i8x16_unpacklo_relaxed(BytesRow0, BytesRow1); + v128_t PairsInterleaved1 = wasm_i8x16_unpacklo_relaxed(BytesRow2, BytesRow3); + + PairsInterleaved0 = wasm_v128_xor(PairsInterleaved0, BitFlipVector); + PairsInterleaved1 = wasm_v128_xor(PairsInterleaved1, BitFlipVector); + + v128_t QuadsInterleaved0 = wasm_i16x8_unpacklo_relaxed(PairsInterleaved0, PairsInterleaved1); + v128_t QuadsInterleaved1 = wasm_i16x8_unpackhi_relaxed(PairsInterleaved0, PairsInterleaved1); + + ColumnSums[0] = wasm_i32x4_relaxed_dot_i8x16_i7x16_add(QuadsInterleaved0, OnesByteBroadcast, ColumnSums[0]); + ColumnSums[1] = wasm_i32x4_relaxed_dot_i8x16_i7x16_add(QuadsInterleaved1, OnesByteBroadcast, ColumnSums[1]); + + wasm_v128_store(&D[0], QuadsInterleaved0); + wasm_v128_store(&D[16], QuadsInterleaved1); +} + +template<> +void +MlasGemmQuantCopyPackB( + MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedBType* D, + const uint8_t* B, + size_t ldb, + size_t CountN, + size_t CountK, + int32_t* ColumnSumBuffer, + bool BIsSigned + ) +{ + const v128_t OnesByteBroadcast = wasm_i8x16_splat(1); + const v128_t BitFlipVector = wasm_i32x4_splat(BIsSigned ? 0 : 0x80808080); + + // + // Process 8 columns of matrix B in a loop. + // + + while (CountN >= 8) { + + const uint8_t* b = B; + size_t k = CountK; + v128_t ColumnSums[2]; + + ColumnSums[0] = wasm_i64x2_const(0, 0); + ColumnSums[1] = wasm_i64x2_const(0, 0); + + // + // Interleave rows of matrix B and write to the packed buffer. + // + + while (k >= MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedK) { + + v128_t BytesRow0 = wasm_v128_load64_zero(&b[0]); + v128_t BytesRow1 = wasm_v128_load64_zero(&b[ldb]); + v128_t BytesRow2 = wasm_v128_load64_zero(&b[ldb * 2]); + v128_t BytesRow3 = wasm_v128_load64_zero(&b[ldb * 3]); + + MlasGemmU8X8CopyPackBProcessWasmRelaxedSimd(D, BytesRow0, BytesRow1, BytesRow2, BytesRow3, BitFlipVector, OnesByteBroadcast, ColumnSums); + + b += ldb * 4; + D += 32; + k -= 4; + } + + if (k > 0) { + + v128_t BytesRow0 = wasm_v128_load64_zero(&b[0]); + v128_t BytesRow1 = BitFlipVector; + v128_t BytesRow2 = BitFlipVector; + v128_t BytesRow3 = BitFlipVector; + + if (k >= 2) { + BytesRow1 = wasm_v128_load64_zero(&b[ldb]); + } + + if (k >= 3) { + BytesRow2 = wasm_v128_load64_zero(&b[ldb * 2]); + } + + MlasGemmU8X8CopyPackBProcessWasmRelaxedSimd(D, BytesRow0, BytesRow1, BytesRow2, BytesRow3, BitFlipVector, OnesByteBroadcast, ColumnSums); + + D += 32; + } + + wasm_v128_store(&ColumnSumBuffer[0], ColumnSums[0]); + wasm_v128_store(&ColumnSumBuffer[4], ColumnSums[1]); + ColumnSumBuffer += 8; + + B += 8; + CountN -= 8; + } + + // + // Process the remaining columns of matrix B. + // + + if (CountN > 0) { + + const uint8_t* b = B; + size_t k = CountK; + v128_t ColumnSums[2]; + uint8_t PaddedMatrixBData[32]; + + wasm_v128_store(&PaddedMatrixBData[0], BitFlipVector); + wasm_v128_store(&PaddedMatrixBData[16], BitFlipVector); + + ColumnSums[0] = wasm_i64x2_const(0, 0); + ColumnSums[1] = wasm_i64x2_const(0, 0); + + // + // Interleave rows of matrix B using an intermediate zero padded stack + // buffer and write to the packed buffer. + // + + while (k >= MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedK) { + + const uint8_t* bcopy = b; + uint8_t* padded = PaddedMatrixBData; + uint8_t* padded_end = padded + CountN; + + do { + padded[0] = bcopy[0]; + padded[8] = bcopy[ldb]; + padded[16] = bcopy[ldb * 2]; + padded[24] = bcopy[ldb * 3]; + padded++; + bcopy++; + } while (padded < padded_end); + + v128_t BytesRow0 = wasm_v128_load64_zero(&PaddedMatrixBData[0]); + v128_t BytesRow1 = wasm_v128_load64_zero(&PaddedMatrixBData[8]); + v128_t BytesRow2 = wasm_v128_load64_zero(&PaddedMatrixBData[16]); + v128_t BytesRow3 = wasm_v128_load64_zero(&PaddedMatrixBData[24]); + + MlasGemmU8X8CopyPackBProcessWasmRelaxedSimd(D, BytesRow0, BytesRow1, BytesRow2, BytesRow3, BitFlipVector, OnesByteBroadcast, ColumnSums); + + b += ldb * 4; + D += 32; + k -= 4; + } + + if (k > 0) { + + const uint8_t* bcopy = b; + uint8_t* padded = PaddedMatrixBData; + uint8_t* padded_end = padded + CountN; + + wasm_v128_store(&PaddedMatrixBData[0], BitFlipVector); + wasm_v128_store(&PaddedMatrixBData[16], BitFlipVector); + + if (k == 3) { + do { + padded[0] = bcopy[0]; + padded[8] = bcopy[ldb]; + padded[16] = bcopy[ldb * 2]; + padded++; + bcopy++; + } while (padded < padded_end); + } else if (k == 2) { + do { + padded[0] = bcopy[0]; + padded[8] = bcopy[ldb]; + padded++; + bcopy++; + } while (padded < padded_end); + } else { + do { + padded[0] = bcopy[0]; + padded++; + bcopy++; + } while (padded < padded_end); + } + + v128_t BytesRow0 = wasm_v128_load64_zero(&PaddedMatrixBData[0]); + v128_t BytesRow1 = wasm_v128_load64_zero(&PaddedMatrixBData[8]); + v128_t BytesRow2 = wasm_v128_load64_zero(&PaddedMatrixBData[16]); + v128_t BytesRow3 = wasm_v128_load64_zero(&PaddedMatrixBData[24]); + + MlasGemmU8X8CopyPackBProcessWasmRelaxedSimd(D, BytesRow0, BytesRow1, BytesRow2, BytesRow3, BitFlipVector, OnesByteBroadcast, ColumnSums); + } + + wasm_v128_store(&ColumnSumBuffer[0], ColumnSums[0]); + wasm_v128_store(&ColumnSumBuffer[4], ColumnSums[1]); + } +} + +MLAS_FORCEINLINE +void +MlasGemmU8X8MultiplyAccumulateRowWasmRelaxedSimd( + v128_t ABroadcast, + const uint8_t* B, + v128_t Accumulators[2] +) +{ + v128_t BElements0 = wasm_v128_load(&B[0]); + v128_t BElements1 = wasm_v128_load(&B[16]); + + Accumulators[0] = wasm_i32x4_relaxed_dot_i8x16_i7x16_add(BElements0, ABroadcast, Accumulators[0]); + Accumulators[1] = wasm_i32x4_relaxed_dot_i8x16_i7x16_add(BElements1, ABroadcast, Accumulators[1]); +} + + +template<> +size_t +MlasGemmQuantKernel( + const MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedAType* A, + const MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedBType* B, + int32_t* C, + size_t PackedCountK, + size_t CountM, + size_t CountN, + size_t ldc, + const int32_t* RowSumBuffer, + const int32_t* ColumnSumBuffer, + const int32_t* ZeroPointB, + bool ZeroMode + ) +{ + MLAS_UNREFERENCED_PARAMETER(CountM); + MLAS_UNREFERENCED_PARAMETER(ldc); + + while (CountN > 0) { + + v128_t Accumulators[2]; + + // + // Initialize the accumulators with the row and column sums. + // + + int32_t RowSumValue = RowSumBuffer[0]; + + if (ZeroPointB != nullptr) { + + int32_t ScaledRowSumBuffer[8]; + + for (size_t i = 0; i < 8; i++) { + ScaledRowSumBuffer[i] = RowSumValue * ZeroPointB[i]; + } + + ZeroPointB += 8; + + Accumulators[0] = wasm_v128_load(&ScaledRowSumBuffer[0]); + Accumulators[1] = wasm_v128_load(&ScaledRowSumBuffer[4]); + + } + else { + + Accumulators[0] = wasm_i32x4_splat(RowSumValue); + Accumulators[1] = Accumulators[0]; + } + + Accumulators[0] = wasm_i32x4_add(Accumulators[0], wasm_v128_load(&ColumnSumBuffer[0])); + Accumulators[1] = wasm_i32x4_add(Accumulators[1], wasm_v128_load(&ColumnSumBuffer[4])); + ColumnSumBuffer += 8; + + // + // Broadcast each pair of 16-bit values from the matrix A and multiply + // with the pair of 16-bit values from matrix B, and add the 32-bit + // intermediate into the accumulator registers. + // + + const uint8_t* a = A; + size_t k = PackedCountK; + + while (k >= 4) { + + v128_t AElements = wasm_v128_load((v128_t*)a); + v128_t ABroadcast; + + ABroadcast = wasm_i32x4_shuffle(AElements, wasm_i32x4_splat(0), 0, 0, 0, 0); + MlasGemmU8X8MultiplyAccumulateRowWasmRelaxedSimd(ABroadcast, &B[0], Accumulators); + + ABroadcast = wasm_i32x4_shuffle(AElements, wasm_i32x4_splat(0), 1, 1, 1, 1); + MlasGemmU8X8MultiplyAccumulateRowWasmRelaxedSimd(ABroadcast, &B[32], Accumulators); + + ABroadcast = wasm_i32x4_shuffle(AElements, wasm_i32x4_splat(0), 2, 2, 2, 2); + MlasGemmU8X8MultiplyAccumulateRowWasmRelaxedSimd(ABroadcast, &B[64], Accumulators); + + ABroadcast = wasm_i32x4_shuffle(AElements, wasm_i32x4_splat(0), 3, 3, 3, 3); + MlasGemmU8X8MultiplyAccumulateRowWasmRelaxedSimd(ABroadcast, &B[96], Accumulators); + + a += 4 * 4; + B += 4 * 32; + k -= 4; + } + + while (k > 0) { + + v128_t ABroadcast = wasm_i32x4_splat(*((int32_t*)a)); + MlasGemmU8X8MultiplyAccumulateRowWasmRelaxedSimd(ABroadcast, &B[0], Accumulators); + + a += 4; + B += 32; + k -= 1; + } + + // + // Output the accumulator block after optionally accumulating the values + // from matrix C. + // + + if (CountN >= 8) { + + if (!ZeroMode) { + Accumulators[0] = wasm_i32x4_add(Accumulators[0], wasm_v128_load(&C[0])); + Accumulators[1] = wasm_i32x4_add(Accumulators[1], wasm_v128_load(&C[4])); + } + + wasm_v128_store(&C[0], Accumulators[0]); + wasm_v128_store(&C[4], Accumulators[1]); + + C += 8; + CountN -= 8; + + } + else { + + // + // Output the remaining partial output block. + // + + if ((CountN & 4) != 0) { + + if (!ZeroMode) { + Accumulators[0] = wasm_i32x4_add(Accumulators[0], wasm_v128_load(&C[0])); + } + + wasm_v128_store(&C[0], Accumulators[0]); + C += 4; + + Accumulators[0] = Accumulators[1]; + } + + if ((CountN & 2) != 0) { + + if (!ZeroMode) { + Accumulators[0] = wasm_i32x4_add(Accumulators[0], wasm_v128_load64_zero(&C[0])); + } + + wasm_v128_store64_lane(&C[0], Accumulators[0], 0); + C += 2; + + Accumulators[0] = wasm_i32x4_shuffle(Accumulators[0], wasm_i32x4_splat(0), 2, 3, 2, 3); + } + + if ((CountN & 1) != 0) { + + int32_t AccumulatorValue = wasm_i32x4_extract_lane(Accumulators[0], 0); + + if (!ZeroMode) { + AccumulatorValue += C[0]; + } + + C[0] = AccumulatorValue; + } + + CountN = 0; + } + } + + return 1; +} + +const MLAS_GEMM_QUANT_DISPATCH MlasGemmU8X8DispatchWasmRelaxedSimd = { + MlasGemmQuantOperation, + nullptr, + nullptr, + MLAS_GEMM_U8X8_KERNEL_WASMRELAXEDSIMD::PackedK, + 0, + 4 // multiple of kernel stride M +}; diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 2493887dfc347..c667df0369c91 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -513,6 +513,7 @@ def convert_arg_line_to_args(self, arg_line): parser.add_argument("--emsdk_version", default="4.0.4", help="Specify version of emsdk") parser.add_argument("--enable_wasm_simd", action="store_true", help="Enable WebAssembly SIMD") + parser.add_argument("--enable_wasm_relaxed_simd", action="store_true", help="Enable WebAssembly Relaxed SIMD") parser.add_argument("--enable_wasm_threads", action="store_true", help="Enable WebAssembly multi-threads support") parser.add_argument( @@ -1434,6 +1435,12 @@ def generate_build_tree( cmake_args.append("-Donnxruntime_DNNL_ACL_ROOT=" + args.dnnl_acl_root) if args.build_wasm: cmake_args.append("-Donnxruntime_ENABLE_WEBASSEMBLY_SIMD=" + ("ON" if args.enable_wasm_simd else "OFF")) + if args.enable_wasm_relaxed_simd: + if not args.enable_wasm_simd: + raise BuildError( + "Wasm Relaxed SIMD (--enable_wasm_relaxed_simd) is only available with Wasm SIMD (--enable_wasm_simd)." + ) + cmake_args += ["-Donnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD=ON"] if args.use_migraphx: cmake_args.append("-Donnxruntime_MIGRAPHX_HOME=" + migraphx_home) if args.use_rocm: From 4eeefd7260b7fa42a71dd1a08b423d5e7c722050 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 31 Mar 2025 10:36:12 -0700 Subject: [PATCH 205/266] Add shader key validation step in WebGPU CI pipeline (#24243) ### Description This PR adds a shader key validation step to the WebGPU CI pipeline. The shader key validation works in this way: - first, run onnxruntime_test_all with verbose logging, dumping the logs into a file - then, parse the file and found WebGPU EP program logs. The log contains the following information: - the shader cache key - the corresponding shader code The script will aggregate those information and make sure for each cache key, the corresponding shader code must be consistent. To make the validation work, this PR also modified a few things: - set the locale of `std::wclog` to ".UTF-8" to support Unicode characters. Otherwise the logger will fail and no longer output future logs. A fix is submitted in PR #24237 but there is a concern if this may potentially break some users. Setting inside onnxruntime_test_all is pretty safe. - re-enable the WebGPU device auto collect which was introduced in https://github.com/microsoft/onnxruntime/pull/24115. Now we have a better way to detect cache key inconsistency. ### Next Step The newly added test is marked as `continue-on-error: true`, which means even if it failed it does not block the CI pipeline. We should fix those failures one-by-one and eventually the test should pass. then we can remove the `continue-on-error: true` flag. --- .../webgpu-validate-shader-key/action.yml | 5 +- .../validate-shader-key.js | 40 ++++++++++-- .github/workflows/windows_webgpu.yml | 63 ++++++++++++------- onnxruntime/test/unittest_main/test_main.cc | 9 +++ onnxruntime/test/util/default_providers.cc | 4 -- 5 files changed, 86 insertions(+), 35 deletions(-) diff --git a/.github/actions/webgpu-validate-shader-key/action.yml b/.github/actions/webgpu-validate-shader-key/action.yml index edf8a876041b9..7b341d38ea906 100644 --- a/.github/actions/webgpu-validate-shader-key/action.yml +++ b/.github/actions/webgpu-validate-shader-key/action.yml @@ -14,14 +14,15 @@ runs: using: "composite" steps: - name: Validate shader keys (chromium log) - if: ${{ inputs.is_chromium_log }} + # GitHub Actions treats all inputs as strings even if it's specified as a boolean. + if: ${{ inputs.is_chromium_log == 'true' }} shell: cmd run: | node parse-chromium-debug-log.js < "${{ inputs.log_file_path }}" | node validate-shader-key.js working-directory: ${{ github.action_path }} - name: Validate shader keys (native log) - if: ${{ !inputs.is_chromium_log }} + if: ${{ !inputs.is_chromium_log != 'true' }} shell: cmd run: | node validate-shader-key.js < "${{ inputs.log_file_path }}" diff --git a/.github/actions/webgpu-validate-shader-key/validate-shader-key.js b/.github/actions/webgpu-validate-shader-key/validate-shader-key.js index e8d750e77d322..aae689c17552a 100644 --- a/.github/actions/webgpu-validate-shader-key/validate-shader-key.js +++ b/.github/actions/webgpu-validate-shader-key/validate-shader-key.js @@ -11,10 +11,12 @@ const readline = require("readline"); const shaderMap = new Map(); +const regexStartingProgram = + /onnxruntime::webgpu::WebGpuContext::Run.+Starting program \"(?.+)\"/; const regexShaderStart = - /^===\ WebGPU\ Shader\ code\ \[.+?Key=\"(?.+)\"]\ Start\ ===$/; + /^===\ WebGPU\ Shader\ code\ \[.+?(Key=\"(?.+)\")?]\ Start\ ===$/; const regexShaderEnd = - /^===\ WebGPU\ Shader\ code\ \[.+?Key=\"(?.+)\"]\ End\ ===$/; + /^===\ WebGPU\ Shader\ code\ \[.+?(Key=\"(?.+)\")?]\ End\ ===$/; async function processVerboseLog() { const rl = readline.createInterface({ @@ -22,10 +24,17 @@ async function processVerboseLog() { crlfDelay: Infinity, }); + let lastProgramKey = null; let currentShaderKey = null; let currentShaderCode = null; for await (const line of rl) { + const startingProgram = regexStartingProgram.exec(line); + if (startingProgram) { + lastProgramKey = startingProgram.groups.key; + continue; + } + const resultStart = regexShaderStart.exec(line); if (resultStart) { if (currentShaderKey) { @@ -34,7 +43,18 @@ async function processVerboseLog() { ); } - currentShaderKey = resultStart.groups.key; + const key = resultStart.groups.key ?? lastProgramKey; + if (!key) { + throw new Error( + 'No shader key is found in the log. Please use debug build or enable verbose logging in session options in release build.' + ); + } + if (lastProgramKey && key !== lastProgramKey) { + throw new Error( + `Found incorrect shader key from log. Expected "${lastProgramKey}", but got "${key}".` + ); + } + currentShaderKey = key; currentShaderCode = ""; continue; } @@ -45,9 +65,17 @@ async function processVerboseLog() { throw new Error( `Found unexpected shader end for key "${resultEnd.groups.key}".` ); - } else if (currentShaderKey !== resultEnd.groups.key) { + } + + const key = resultEnd.groups.key ?? lastProgramKey; + if (!key) { + throw new Error( + 'No shader key is found in the log. Please use debug build or enable verbose logging in session options in release build.' + ); + } + if (lastProgramKey && key !== lastProgramKey) { throw new Error( - `Found inconsistent shader key. Expected "${currentShaderKey}", but got "${resultEnd.groups.key}".` + `Found incorrect shader key from log. Expected "${lastProgramKey}", but got "${key}".` ); } @@ -87,7 +115,7 @@ ${currentShaderCode} } console.log( - `All shader code is consistent. Total ${shaderMap.size} shader code found.` + `All shader code is consistent. Total ${shaderMap.size} shader keys found.` ); } diff --git a/.github/workflows/windows_webgpu.yml b/.github/workflows/windows_webgpu.yml index bf60df1c1ba7f..e8cea1c5805a3 100644 --- a/.github/workflows/windows_webgpu.yml +++ b/.github/workflows/windows_webgpu.yml @@ -24,10 +24,10 @@ jobs: OnnxRuntimeBuildDirectory: ${{ github.workspace }} DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true setVcvars: true - ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + ALLOW_RELEASED_ONNX_OPSET_ONLY: "0" DocUpdateNeeded: false - NVIDIA_TF32_OVERRIDE: '0' - ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + NVIDIA_TF32_OVERRIDE: "0" + ONNXRUNTIME_TEST_GPU_DEVICE_ID: "0" steps: - name: Checkout uses: actions/checkout@v4 @@ -38,7 +38,7 @@ jobs: - name: Setup Python 3.12 uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: "3.12" architecture: x64 - name: Locate vcvarsall and Setup Env @@ -54,13 +54,13 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: "20.x" - name: Setup Java uses: actions/setup-java@v4 with: - distribution: 'temurin' - java-version: '17' + distribution: "temurin" + java-version: "17" architecture: x64 - name: API Documentation Check and generate @@ -78,12 +78,12 @@ jobs: env: PROCESSOR_ARCHITECTURE: x64 with: - dotnet-version: '8.x' + dotnet-version: "8.x" - name: Use Nuget 6.x uses: nuget/setup-nuget@v2 with: - nuget-version: '6.x' + nuget-version: "6.x" - name: NuGet restore run: | @@ -113,13 +113,30 @@ jobs: } Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + - name: Run tests (onnxruntime_test_all) with verbose logging + shell: pwsh + run: | + $env:ORT_UNIT_TEST_MAIN_LOG_LEVEL = "0" + .\onnxruntime_test_all.exe 2>.\onnxruntime_test_all_stderr.log + working-directory: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + + - name: Check log file + shell: cmd + run: | + dir ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\onnxruntime_test_all_stderr.log + + - name: Validate shader keys + continue-on-error: true + uses: ./.github/actions/webgpu-validate-shader-key + with: + log_file_path: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\onnxruntime_test_all_stderr.log + - name: Validate C# native delegates run: python tools\ValidateNativeDelegateAttributes.py shell: cmd working-directory: ${{ github.workspace }}\csharp continue-on-error: true - webgpu_external_dawn_build_x64_RelWithDebInfo: runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] timeout-minutes: 300 @@ -133,7 +150,7 @@ jobs: - name: Setup Python 3.12 uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: "3.12" architecture: x64 - name: Locate vcvarsall and Setup Env @@ -177,12 +194,12 @@ jobs: runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Win2022-GPU-A10"] timeout-minutes: 300 env: - OrtPackageId: Microsoft.ML.OnnxRuntime - OnnxRuntimeBuildDirectory: ${{ github.workspace }} - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' - DocUpdateNeeded: false - ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: "0" + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: "0" steps: - name: Checkout uses: actions/checkout@v4 @@ -193,7 +210,7 @@ jobs: - name: Setup Python 3.12 uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: "3.12" architecture: x64 - name: Locate vcvarsall and Setup Env @@ -209,13 +226,13 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: "20.x" - name: Setup Java uses: actions/setup-java@v4 with: - distribution: 'temurin' - java-version: '17' + distribution: "temurin" + java-version: "17" architecture: x64 - name: API Documentation Check and generate @@ -233,12 +250,12 @@ jobs: env: PROCESSOR_ARCHITECTURE: x64 with: - dotnet-version: '8.x' + dotnet-version: "8.x" - name: Use Nuget 6.x uses: nuget/setup-nuget@v2 with: - nuget-version: '6.x' + nuget-version: "6.x" - name: NuGet restore run: | diff --git a/onnxruntime/test/unittest_main/test_main.cc b/onnxruntime/test/unittest_main/test_main.cc index b558a7f00f7bc..56c11039328bc 100644 --- a/onnxruntime/test/unittest_main/test_main.cc +++ b/onnxruntime/test/unittest_main/test_main.cc @@ -5,6 +5,10 @@ #include #include #include +#ifdef _WIN32 +#include +#include +#endif #ifndef USE_ONNXRUNTIME_DLL #ifdef __GNUC__ @@ -29,6 +33,11 @@ std::unique_ptr ort_env; // ortenv_setup() and ortenv_teardown() are used by onnxruntime/test/xctest/xcgtest.mm so can't be file local extern "C" void ortenv_setup() { +#ifdef _WIN32 + // Set the locale to UTF-8 to ensure proper handling of wide characters on Windows + std::wclog.imbue(std::locale(".UTF-8", std::locale::ctype)); +#endif + OrtThreadingOptions tpo; // allow verbose logging to be enabled by setting this environment variable to a numeric log level diff --git a/onnxruntime/test/util/default_providers.cc b/onnxruntime/test/util/default_providers.cc index 83fb548968d77..c1564997c42b8 100644 --- a/onnxruntime/test/util/default_providers.cc +++ b/onnxruntime/test/util/default_providers.cc @@ -303,10 +303,6 @@ std::unique_ptr DefaultWebGpuExecutionProvider() { ORT_ENFORCE(config_options.AddConfigEntry(webgpu::options::kStorageBufferCacheMode, webgpu::options::kBufferCacheMode_Disabled) .IsOK()); - // Disable device auto collect - ORT_ENFORCE(config_options.AddConfigEntry(webgpu::options::kPreserveDevice, - webgpu::options::kPreserveDevice_ON) - .IsOK()); return WebGpuProviderFactoryCreator::Create(config_options)->CreateProvider(); #else return nullptr; From 30115cfe4d13d958b53ee747cc00781595f9d9d9 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 31 Mar 2025 12:24:56 -0700 Subject: [PATCH 206/266] upgrade dawn version to 4cb1f9be152a4fa6bb695c08cd707ab078a1e2fb (#24247) ### Description Bump version of Dawn to 4cb1f9be152a4fa6bb695c08cd707ab078a1e2fb. ### Changes to the patches to Dawn: Removed patches because they are already merged into upstream or resolved in a different way: - (public) CMake fix to support Emscripten v4.0.3+ - (private) Fix external ref count for "external" device in emwgpu C++ implementation - (private) Allow "external" buffer in emwgpu C++ implementation Keep unchanged patches: - (private) Remove hard-coded CMAKE_OSX_DEPLOYMENT_TARGET in Dawn's CMake files Rewritten patches: - (public) Fix emwgpu C++ implementation for buffer destroy ### Corresponding changes in ORT - Dawn API changes - follow changes to `wgpu::Limits` - remove the usage of `DAWN_EMSCRIPTEN_TOOLCHAIN` - use `wgpu::InstanceDescriptor` in `wgpu::Instance` creation in WASM since it is supported now. --- cmake/deps.txt | 2 +- .../external/onnxruntime_external_deps.cmake | 23 +--- cmake/patches/dawn/dawn.patch | 127 ++---------------- .../core/providers/webgpu/webgpu_context.cc | 34 ++--- .../core/providers/webgpu/webgpu_context.h | 2 +- 5 files changed, 29 insertions(+), 159 deletions(-) diff --git a/cmake/deps.txt b/cmake/deps.txt index 060dd72d655d3..71218fd049afb 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -57,5 +57,5 @@ extensions;https://github.com/microsoft/onnxruntime-extensions/archive/c24b7bab0 composable_kernel;https://github.com/ROCmSoftwarePlatform/composable_kernel/archive/204da9c522cebec5220bba52cd3542ebcaf99e7a.zip;1827348efd47831c13074245274d41b7cae8a557 directx_headers;https://github.com/microsoft/DirectX-Headers/archive/refs/tags/v1.613.1.zip;47653509a3371eabb156360f42faf582f314bf2e cudnn_frontend;https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.7.0.zip;d0753d8d5b39947ca0729d7773cb84653a129eb1 -dawn;https://github.com/google/dawn/archive/40a9fa79f76e6c76cca9e2fa69ea07f202f1d2e6.zip;e224563d5ab4a8e53a517b06f721242533bce722 +dawn;https://github.com/google/dawn/archive/4cb1f9be152a4fa6bb695c08cd707ab078a1e2fb.zip;de39336b7715f53c14eec61072293b85cc73b691 kleidiai;https://github.com/ARM-software/kleidiai/archive/refs/tags/v1.4.0.tar.gz;22d3b57b54a61c194ab256ff11b0353a3b220244 diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index a477d6edb3a3f..552b8b5329fb0 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -623,9 +623,7 @@ if (onnxruntime_USE_WEBGPU) set(DAWN_ENABLE_NULL OFF CACHE BOOL "" FORCE) set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "" FORCE) set(DAWN_BUILD_TESTS OFF CACHE BOOL "" FORCE) - if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - set(DAWN_EMSCRIPTEN_TOOLCHAIN "${REPO_ROOT}/cmake/external/emsdk/upstream/emscripten" CACHE STRING "" FORCE) - else() + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE BOOL "" FORCE) set(DAWN_ENABLE_INSTALL ON CACHE BOOL "" FORCE) @@ -713,27 +711,14 @@ if (onnxruntime_USE_WEBGPU) # # The dawn.patch contains the following changes: # - # - (public) CMake fix to support Emscripten v4.0.3+ - # This change allows Dawn to find the file "gen_struct_info.py" in the correct location. - # https://dawn-review.googlesource.com/c/dawn/+/225514 - # - # - (public) Fix emwgpu C++ implementation for buffer destroy + # - (private) Allow WGPUBufferImpl class to destroy the buffer in the destructor # In native implementation, wgpuBufferRelease will trigger the buffer destroy (if refcount decreased to 0). But - # in emwgpu implementation, the buffer destroy won't happen. This change fixes the bug. - # https://dawn-review.googlesource.com/c/dawn/+/226315 - # - # - (private) Allow "external" buffer in emwgpu C++ implementation - # This change allows WGPUBufferImpl to destroy the buffer when the refcount decreased to 0 only for non-external - # buffer. - # "external buffer" means the GPUBuffer instance created in JavaScript and imported to C++ by `importJsBuffer`. + # in emwgpu implementation, the buffer destroy won't happen. This change adds a destructor to the buffer class + # to destroy the buffer when the refcount is 0 for non-external buffers. # # - (private) Remove hard-coded CMAKE_OSX_DEPLOYMENT_TARGET in Dawn's CMake files # https://github.com/microsoft/onnxruntime/pull/23729 # - # - (private) Fix external ref count for "external" device in emwgpu C++ implementation - # This change fixes the incorrect external ref count for class WGPUDeviceImpl when used with "external" device. - # "external device" means the GPUDevice instance created in JavaScript and imported to C++ by `importJsDevice`. - # # PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn.patch EXCLUDE_FROM_ALL diff --git a/cmake/patches/dawn/dawn.patch b/cmake/patches/dawn/dawn.patch index b578b858eac59..1ce9c75f750f1 100644 --- a/cmake/patches/dawn/dawn.patch +++ b/cmake/patches/dawn/dawn.patch @@ -11,116 +11,24 @@ index 50638e2456..efa42711e6 100644 - set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum macOS version" FORCE) -endif () \ No newline at end of file -diff --git a/src/emdawnwebgpu/CMakeLists.txt b/src/emdawnwebgpu/CMakeLists.txt -index 6e8ae37593..633af91eef 100644 ---- a/src/emdawnwebgpu/CMakeLists.txt -+++ b/src/emdawnwebgpu/CMakeLists.txt -@@ -77,9 +77,17 @@ if (${DAWN_ENABLE_EMSCRIPTEN}) - "${arg_UNPARSED_ARGUMENTS}") - endif() - -+ # since Emscripten 4.0.3, file gen_struct_info.py is moved to outside of directory maint. -+ if (EXISTS "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/gen_struct_info.py") -+ set(EM_GEN_STRUCT_INFO_SCRIPT "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/gen_struct_info.py") -+ elseif (EXISTS "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/gen_struct_info.py") -+ set(EM_GEN_STRUCT_INFO_SCRIPT "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/gen_struct_info.py") -+ else() -+ message(FATAL_ERROR "Dawn: Failed to locate file gen_struct_info.py from Emscripten.") -+ endif() - set(ARGS - ${Python3_EXECUTABLE} -- "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/gen_struct_info.py" -+ "${EM_GEN_STRUCT_INFO_SCRIPT}" - -q - "${EM_BUILD_GEN_DIR}/struct_info_webgpu.json" - "-I=${EM_BUILD_GEN_DIR}/include" -diff --git a/src/emdawnwebgpu/README.md b/src/emdawnwebgpu/README.md -index efd6491cd6..8ebc5d28b6 100644 ---- a/src/emdawnwebgpu/README.md -+++ b/src/emdawnwebgpu/README.md -@@ -56,7 +56,7 @@ Set up the build directory using emcmake - mkdir out/cmake-wasm - cd out/cmake-wasm - --# Make sure the path is to the source checkout of Emscripten, not emsdk's release. -+# If using Emscripten v4.0.2 or lower, make sure the path is to the source checkout of Emscripten, not emsdk's release. - emcmake cmake -GNinja -DDAWN_EMSCRIPTEN_TOOLCHAIN="path/to/emscripten" ../.. - - ninja diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp -index f1c5a7d50e..16f2495712 100644 +index 5bfac41dcc..71a153daaa 100644 --- a/third_party/emdawnwebgpu/webgpu.cpp +++ b/third_party/emdawnwebgpu/webgpu.cpp -@@ -131,7 +131,6 @@ class RefCounted : NonMovable { - bool Release() { - if (mRefCount.fetch_sub(1u, std::memory_order_release) == 1u) { - std::atomic_thread_fence(std::memory_order_acquire); -- emwgpuDelete(this); - return true; - } - return false; -@@ -234,6 +233,7 @@ class Ref { - static void Release(T value) { - if (value != nullptr && value->RefCounted::Release()) { - delete value; -+ emwgpuDelete(value); - } - } - -@@ -641,7 +641,8 @@ struct WGPUAdapterImpl final : public EventSource, public RefCounted { - struct WGPUBufferImpl final : public EventSource, - public RefCountedWithExternalCount { - public: -- WGPUBufferImpl(const EventSource* source, bool mappedAtCreation); -+ WGPUBufferImpl(const EventSource* source, bool mappedAtCreation, bool isExternal); +@@ -692,6 +692,7 @@ struct WGPUBufferImpl final : public EventSource, + WGPUBufferImpl(const EventSource* source, bool mappedAtCreation); + // Injection constructor used when we already have a backing Buffer. + WGPUBufferImpl(const EventSource* source, WGPUBufferMapState mapState); + ~WGPUBufferImpl(); void Destroy(); const void* GetConstMappedRange(size_t offset, size_t size); -@@ -671,6 +672,7 @@ struct WGPUBufferImpl final : public EventSource, - }; - MapRequest mPendingMapRequest; - WGPUBufferMapState mMapState; -+ bool mIsExternal; - }; - - struct WGPUQueueImpl final : public EventSource, public RefCounted { -@@ -1164,11 +1166,15 @@ WGPUAdapter emwgpuCreateAdapter(const EventSource* source) { - - WGPUBuffer emwgpuCreateBuffer(const EventSource* source, - bool mappedAtCreation = false) { -- return new WGPUBufferImpl(source, mappedAtCreation); -+ return new WGPUBufferImpl(source, mappedAtCreation, true); - } - - WGPUDevice emwgpuCreateDevice(const EventSource* source, WGPUQueue queue) { -- return new WGPUDeviceImpl(source, queue); -+ // This function is only called from JS via `importJsDevice()`, which -+ // needs to increment the external ref count to fix the behavior. -+ WGPUDeviceImpl* device = new WGPUDeviceImpl(source, queue); -+ device->AddExternalRef(); -+ return device; - } - - WGPUQueue emwgpuCreateQueue(const EventSource* source) { -@@ -1275,15 +1281,22 @@ WGPUAdapterImpl::WGPUAdapterImpl(const EventSource* source) - // WGPUBuffer implementations. - // ---------------------------------------------------------------------------- - --WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, bool mappedAtCreation) -+WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, bool mappedAtCreation, bool isExternal) - : EventSource(source), - mMapState(mappedAtCreation ? WGPUBufferMapState_Mapped -- : WGPUBufferMapState_Unmapped) { -+ : WGPUBufferMapState_Unmapped), -+ mIsExternal(isExternal) { - if (mappedAtCreation) { - mPendingMapRequest = {kNullFutureId, WGPUMapMode_Write}; - } - } +@@ -1361,6 +1362,12 @@ WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, + RefCountedWithExternalCount(kImportedFromJS), + mMapState(mapState) {} +WGPUBufferImpl::~WGPUBufferImpl() { -+ if (!mIsExternal) { ++ if (!IsImported()) { + Destroy(); + } +} @@ -128,20 +36,3 @@ index f1c5a7d50e..16f2495712 100644 void WGPUBufferImpl::Destroy() { emwgpuBufferDestroy(this); AbortPendingMap("Buffer was destroyed before mapping was resolved."); -@@ -1504,6 +1517,7 @@ WGPUFuture WGPUShaderModuleImpl::GetCompilationInfo( - void wgpu##Name##Release(WGPU##Name o) { \ - if (o->Release()) { \ - delete o; \ -+ emwgpuDelete(o); \ - } \ - } - WGPU_OBJECTS(DEFINE_WGPU_DEFAULT_ADDREF_RELEASE) -@@ -1638,7 +1652,7 @@ void wgpuBufferUnmap(WGPUBuffer buffer) { - - WGPUBuffer wgpuDeviceCreateBuffer(WGPUDevice device, - const WGPUBufferDescriptor* descriptor) { -- WGPUBuffer buffer = new WGPUBufferImpl(device, descriptor->mappedAtCreation); -+ WGPUBuffer buffer = new WGPUBufferImpl(device, descriptor->mappedAtCreation, false); - emwgpuDeviceCreateBuffer(device, descriptor, buffer); - return buffer; - } diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 9234aab58dd99..0471e08c4a215 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -110,7 +110,7 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi device_desc.requiredFeatures = required_features.data(); device_desc.requiredFeatureCount = required_features.size(); } - wgpu::RequiredLimits required_limits = GetRequiredLimits(adapter); + wgpu::Limits required_limits = GetRequiredLimits(adapter); device_desc.requiredLimits = &required_limits; // TODO: revise temporary error handling @@ -139,9 +139,7 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi // cache adapter info ORT_ENFORCE(Device().GetAdapterInfo(&adapter_info_)); // cache device limits - wgpu::SupportedLimits device_supported_limits; - ORT_ENFORCE(Device().GetLimits(&device_supported_limits)); - device_limits_ = device_supported_limits.limits; + ORT_ENFORCE(Device().GetLimits(&device_limits_)); #if !defined(__wasm__) supports_buffer_map_extended_usages_ = device_.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages); @@ -508,20 +506,20 @@ std::vector WebGpuContext::GetAvailableRequiredFeatures(const return required_features; } -wgpu::RequiredLimits WebGpuContext::GetRequiredLimits(const wgpu::Adapter& adapter) const { - wgpu::RequiredLimits required_limits{}; - wgpu::SupportedLimits adapter_limits; +wgpu::Limits WebGpuContext::GetRequiredLimits(const wgpu::Adapter& adapter) const { + wgpu::Limits required_limits{}; + wgpu::Limits adapter_limits; ORT_ENFORCE(adapter.GetLimits(&adapter_limits)); - required_limits.limits.maxBindGroups = adapter_limits.limits.maxBindGroups; - required_limits.limits.maxComputeWorkgroupStorageSize = adapter_limits.limits.maxComputeWorkgroupStorageSize; - required_limits.limits.maxComputeWorkgroupsPerDimension = adapter_limits.limits.maxComputeWorkgroupsPerDimension; - required_limits.limits.maxStorageBufferBindingSize = adapter_limits.limits.maxStorageBufferBindingSize; - required_limits.limits.maxBufferSize = adapter_limits.limits.maxBufferSize; - required_limits.limits.maxComputeInvocationsPerWorkgroup = adapter_limits.limits.maxComputeInvocationsPerWorkgroup; - required_limits.limits.maxComputeWorkgroupSizeX = adapter_limits.limits.maxComputeWorkgroupSizeX; - required_limits.limits.maxComputeWorkgroupSizeY = adapter_limits.limits.maxComputeWorkgroupSizeY; - required_limits.limits.maxComputeWorkgroupSizeZ = adapter_limits.limits.maxComputeWorkgroupSizeZ; + required_limits.maxBindGroups = adapter_limits.maxBindGroups; + required_limits.maxComputeWorkgroupStorageSize = adapter_limits.maxComputeWorkgroupStorageSize; + required_limits.maxComputeWorkgroupsPerDimension = adapter_limits.maxComputeWorkgroupsPerDimension; + required_limits.maxStorageBufferBindingSize = adapter_limits.maxStorageBufferBindingSize; + required_limits.maxBufferSize = adapter_limits.maxBufferSize; + required_limits.maxComputeInvocationsPerWorkgroup = adapter_limits.maxComputeInvocationsPerWorkgroup; + required_limits.maxComputeWorkgroupSizeX = adapter_limits.maxComputeWorkgroupSizeX; + required_limits.maxComputeWorkgroupSizeY = adapter_limits.maxComputeWorkgroupSizeY; + required_limits.maxComputeWorkgroupSizeZ = adapter_limits.maxComputeWorkgroupSizeZ; return required_limits; } @@ -740,13 +738,9 @@ WebGpuContext& WebGpuContextFactory::CreateContext(const WebGpuContextConfig& co #endif // Step.2 - Create wgpu::Instance -#if !defined(__wasm__) wgpu::InstanceDescriptor instance_desc{}; instance_desc.capabilities.timedWaitAnyEnable = true; default_instance_ = wgpu::CreateInstance(&instance_desc); -#else - default_instance_ = wgpu::CreateInstance(nullptr); -#endif ORT_ENFORCE(default_instance_ != nullptr, "Failed to create wgpu::Instance."); }); diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 96f5a0cebc5c1..11e388a22e03f 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -161,7 +161,7 @@ class WebGpuContext final { std::vector GetEnabledDeviceToggles() const; std::vector GetDisabledDeviceToggles() const; std::vector GetAvailableRequiredFeatures(const wgpu::Adapter& adapter) const; - wgpu::RequiredLimits GetRequiredLimits(const wgpu::Adapter& adapter) const; + wgpu::Limits GetRequiredLimits(const wgpu::Adapter& adapter) const; void WriteTimestamp(uint32_t query_index); struct PendingKernelInfo { From 5982430af66f52a288cb8b2181e0b5b2e09118c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Mar 2025 14:17:58 -0700 Subject: [PATCH 207/266] Bump dsaltares/fetch-gh-release-asset from 1.1.0 to 1.1.2 (#24248) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dsaltares/fetch-gh-release-asset](https://github.com/dsaltares/fetch-gh-release-asset) from 1.1.0 to 1.1.2.
Release notes

Sourced from dsaltares/fetch-gh-release-asset's releases.

1.1.2

What's Changed

New Contributors

Full Changelog: https://github.com/dsaltares/fetch-gh-release-asset/compare/1.1.1...1.1.2

1.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/dsaltares/fetch-gh-release-asset/compare/1.1.0...1.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dsaltares/fetch-gh-release-asset&package-manager=github_actions&previous-version=1.1.0&new-version=1.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/linux_cuda_ci.yml | 2 +- .github/workflows/linux_tensorrt_ci.yml | 2 +- .github/workflows/reusable_linux_build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux_cuda_ci.yml b/.github/workflows/linux_cuda_ci.yml index d1001deb28bf0..23b6a9e752ab2 100644 --- a/.github/workflows/linux_cuda_ci.yml +++ b/.github/workflows/linux_cuda_ci.yml @@ -44,7 +44,7 @@ jobs: uses: actions/checkout@v4 - name: Download ORT Actions Asset (v0.0.2) - uses: dsaltares/fetch-gh-release-asset@1.1.0 + uses: dsaltares/fetch-gh-release-asset@1.1.2 with: repo: 'microsoft/onnxruntime-github-actions' version: 'tags/v0.0.2' diff --git a/.github/workflows/linux_tensorrt_ci.yml b/.github/workflows/linux_tensorrt_ci.yml index 0d3b7e532ebfb..9440003ddf801 100644 --- a/.github/workflows/linux_tensorrt_ci.yml +++ b/.github/workflows/linux_tensorrt_ci.yml @@ -44,7 +44,7 @@ jobs: uses: actions/checkout@v4 - name: Download ORT Actions Asset (v0.0.2) - uses: dsaltares/fetch-gh-release-asset@1.1.0 + uses: dsaltares/fetch-gh-release-asset@1.1.2 with: repo: 'microsoft/onnxruntime-github-actions' version: 'tags/v0.0.2' diff --git a/.github/workflows/reusable_linux_build.yml b/.github/workflows/reusable_linux_build.yml index a8d55b203bdca..5c25b36a65197 100644 --- a/.github/workflows/reusable_linux_build.yml +++ b/.github/workflows/reusable_linux_build.yml @@ -82,7 +82,7 @@ jobs: python-version: ${{ inputs.python_version }} - name: Download ORT Actions Asset (v0.0.2) # <-- Adjust version as needed - uses: dsaltares/fetch-gh-release-asset@1.1.0 # Action to download assets + uses: dsaltares/fetch-gh-release-asset@1.1.2 # Action to download assets with: repo: 'microsoft/onnxruntime-github-actions' # The repo containing the actions version: 'tags/v0.0.2' # The specific tag/version to use From e2274150db8817cd99a56b84dd14c55e6f97aff9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Mar 2025 17:29:41 -0700 Subject: [PATCH 208/266] Bump vite from 6.2.3 to 6.2.4 in /js/web/test/e2e/exports/testcases/vite-default (#24255) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.3 to 6.2.4.
Release notes

Sourced from vite's releases.

v6.2.4

Please refer to CHANGELOG.md for details.

Changelog

Sourced from vite's changelog.

6.2.4 (2025-03-31)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vite&package-manager=npm_and_yarn&previous-version=6.2.3&new-version=6.2.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../e2e/exports/testcases/vite-default/package-lock.json | 8 ++++---- .../test/e2e/exports/testcases/vite-default/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json index 08c73d8e74beb..9e4730a407d57 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json @@ -12,7 +12,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", - "vite": "^6.2.3" + "vite": "^6.2.4" } }, "node_modules/@babel/helper-string-parser": { @@ -1069,9 +1069,9 @@ } }, "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", + "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/js/web/test/e2e/exports/testcases/vite-default/package.json b/js/web/test/e2e/exports/testcases/vite-default/package.json index 4ef5b46691850..e06733f917e3f 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package.json @@ -13,6 +13,6 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", - "vite": "^6.2.3" + "vite": "^6.2.4" } } From 5068ab9b190c549b546241aa7ffbe5007868f595 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Mon, 31 Mar 2025 20:04:12 -0700 Subject: [PATCH 209/266] [WebGPU EP] fixes bugs in split implementation (#24259) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following errors: ``` [ONNXRuntimeError] : 1 : FAIL : WebGPU validation failed. Error while parsing WGSL: :48:1 error: unexpected token } ^    - While validating [ShaderModuleDescriptor]  - While calling [Device].CreateShaderModule([ShaderModuleDescriptor]). ``` ``` [E:onnxruntime:sam, sequential_executor.cc:572 onnxruntime::ExecuteKernel] Non-zero status code returned while running Split node. Name:'/Split_1' Status Message: WebGPU validation failed. Error while parsing WGSL: :62:14 error: cannot index type 'u32' index -= uniforms.sizes_in_split_axis[output_number - 1u]; ``` --- .../core/providers/webgpu/tensor/split.cc | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/tensor/split.cc b/onnxruntime/core/providers/webgpu/tensor/split.cc index d93b75fa21c16..150b0beb897f5 100644 --- a/onnxruntime/core/providers/webgpu/tensor/split.cc +++ b/onnxruntime/core/providers/webgpu/tensor/split.cc @@ -29,20 +29,16 @@ void WriteBufferData(std::ostream& os, const ShaderVariableHelper& input, for (size_t i = 0; i < outputs.size(); ++i) { const auto buffer_write = outputs[i]->SetByIndices("indices", input.GetByOffset("global_idx")); if (outputs.size() == 1) { - os << buffer_write; + os << buffer_write << "\n"; } else if (i == 0) { - os << " if (output_number == 0u) {\n" - << " " << buffer_write << "\n"; + os << " if (output_number == 0u) { " << buffer_write << " }\n"; } else if (i == outputs.size() - 1) { - os << " } else {\n" - << " " << buffer_write << "\n"; + os << " else { " << buffer_write << " }\n"; } else { - os << " } else if (output_number == " << i << "u) {\n" - << " " << buffer_write << "\n"; + os << " else if (output_number == " << i << "u) { " << buffer_write << " }\n"; } } - os << " }\n" - << "}\n"; + os << "}\n"; } } // namespace @@ -68,7 +64,7 @@ Status SplitProgram::GenerateShaderCode(ShaderHelper& shader) const { << " var index = " << input.IndicesGet("indices", axis_) << ";\n" << " let output_number = calculate_output_index(index);\n" << " if (output_number != 0u) {\n" - << " index -= uniforms.sizes_in_split_axis[output_number - 1u];\n" + << " index -= " << GetElementAt("uniforms.sizes_in_split_axis", "output_number - 1u", output_count) << ";\n" << " " << input.IndicesSet("indices", axis_, "index") << "\n" << " }\n" << " write_buffer_data(output_number, global_idx, indices);\n"; From 1b48cc41d01ae53ca1fbb197121591d0e7be466f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 12:23:41 -0700 Subject: [PATCH 210/266] Bump microsoft/onnxruntime-github-actions from 35f8bd42417991aa46577e9c32e445af4250f098 to f3d90afe522476c858909e0de2be0b12bc890068 (#24249) Bumps [microsoft/onnxruntime-github-actions](https://github.com/microsoft/onnxruntime-github-actions) from 35f8bd42417991aa46577e9c32e445af4250f098 to f3d90afe522476c858909e0de2be0b12bc890068.
Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/windows_x64_debug_build_x64_debug.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml index b2c4010d0b142..9017314f22a22 100644 --- a/.github/workflows/windows_x64_debug_build_x64_debug.yml +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -28,7 +28,7 @@ jobs: architecture: x64 - name: Setup VCPKG - uses: microsoft/onnxruntime-github-actions/setup-vcpkg@35f8bd42417991aa46577e9c32e445af4250f098 + uses: microsoft/onnxruntime-github-actions/setup-vcpkg@f3d90afe522476c858909e0de2be0b12bc890068 with: vcpkg-version: '2025.03.19' vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' From 5b080558b98889327249c1fec3257fd362354fa3 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 1 Apr 2025 15:37:35 -0400 Subject: [PATCH 211/266] Update xcode and iphoneSimulatorVersion after MacOS-14 (#24260) ### Description Update xcode and iphoneSimulatorVersion after MacOS-14 ### Motivation and Context iOS packaging pipeline and Github Action were still using the old xcode version after https://github.com/microsoft/onnxruntime/pull/23293 --- .github/workflows/ios.yml | 6 +++--- .../templates/stages/mac-ios-packaging-build-stage.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index d2738f7d09d79..2c51bf0ce476f 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -17,7 +17,7 @@ concurrency: jobs: iOS_CI_on_Mac: - runs-on: macos-13 + runs-on: macos-14 steps: - name: Checkout repository uses: actions/checkout@v4 @@ -60,5 +60,5 @@ jobs: timeout-minutes: 150 env: - XCODE_VERSION: 14.3.1 - IOS_SIMULATOR_RUNTIME_VERSION: 16.4 \ No newline at end of file + XCODE_VERSION: 15.3.0 + IOS_SIMULATOR_RUNTIME_VERSION: 17.4 \ No newline at end of file diff --git a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml index eeef3b96edd4c..9815e1ac94d24 100644 --- a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml +++ b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml @@ -23,8 +23,8 @@ stages: # Note: Keep the Xcode version and iOS simulator version compatible. # Check the table here to see what iOS simulator versions are supported by a particular Xcode version: # https://developer.apple.com/support/xcode/ - xcodeVersion: "14.3.1" - iosSimulatorRuntimeVersion: "16.4" + xcodeVersion: "15.3.0" + iosSimulatorRuntimeVersion: "17.4" ${{ if eq(parameters.packageVariant, 'Full') }}: buildSettingsFile: "tools/ci_build/github/apple/default_full_apple_framework_build_settings.json" cPodName: onnxruntime-c From 24620e70d9f14956a0dc84bb8a332dcd64c95a94 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 1 Apr 2025 15:37:55 -0400 Subject: [PATCH 212/266] =?UTF-8?q?Exclude=20onnxruntime-inference-example?= =?UTF-8?q?s=20directory=20from=20Component=20Gover=E2=80=A6=20(#24258)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …nance ### Description Exclude onnxruntime-inference-examples directory from Component Governance ### Motivation and Context onnxruntime-inference-examples is a extneral repos --- .../azure-pipelines/c-api-noopenmp-packaging-pipelines.yml | 2 ++ .../ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index 17e841360efd0..722e7696ba738 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -92,6 +92,8 @@ extends: enabled: true analyzeTargetGlob: $(Build.ArtifactStagingDirectory)/**.dll sourceAnalysisPool: "Onnxruntime-Win-CPU-2022" + componentgovernance: + ignoreDirectories: $(Build.SourcesDirectory)/onnxruntime-inference-examples sourceRepositoriesToScan: exclude: - repository: onnxruntime-inference-examples diff --git a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml index 83d41f23d9de2..f9363e821a36a 100644 --- a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml @@ -91,6 +91,8 @@ extends: sourceAnalysisPool: name: onnxruntime-Win-CPU-2022 os: windows + componentgovernance: + ignoreDirectories: $(Build.SourcesDirectory)/onnxruntime-inference-examples sourceRepositoriesToScan: exclude: - repository: onnxruntime-inference-examples From 67216c89965731898a252b23cbcc681a0465c540 Mon Sep 17 00:00:00 2001 From: Yueqing Zhang Date: Wed, 2 Apr 2025 08:27:56 +0800 Subject: [PATCH 213/266] [VitisAI] Fixed include error. (#24199) ### Description include mp11 as it is used for provider related headers ### Motivation and Context VitisAI failed to be built on latest g++ version. --- cmake/onnxruntime_providers_vitisai.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/onnxruntime_providers_vitisai.cmake b/cmake/onnxruntime_providers_vitisai.cmake index 561a323533f48..e40521e564ab8 100644 --- a/cmake/onnxruntime_providers_vitisai.cmake +++ b/cmake/onnxruntime_providers_vitisai.cmake @@ -20,7 +20,7 @@ ) source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_vitisai_cc_srcs}) onnxruntime_add_shared_library(onnxruntime_providers_vitisai ${onnxruntime_providers_vitisai_cc_srcs}) - onnxruntime_add_include_to_target(onnxruntime_providers_vitisai ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers) + onnxruntime_add_include_to_target(onnxruntime_providers_vitisai ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers Boost::mp11) target_link_libraries(onnxruntime_providers_vitisai PRIVATE ${ONNXRUNTIME_PROVIDERS_SHARED}) if(MSVC) onnxruntime_add_include_to_target(onnxruntime_providers_vitisai dbghelp) From a5bc69c5a93548541553b0ddaba4d7261a802629 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 2 Apr 2025 09:32:12 -0700 Subject: [PATCH 214/266] Migrate pull:wasm to github action (#24269) ### Description The ADO Web CI is migrated to Github Actions now. This PR makes the corresponding changes to the `npm run pull:wasm` command to use the new Github Action. ### Motivation and Context --- js/web/script/pull-prebuilt-wasm-artifacts.ts | 343 ++++++++++++------ 1 file changed, 225 insertions(+), 118 deletions(-) diff --git a/js/web/script/pull-prebuilt-wasm-artifacts.ts b/js/web/script/pull-prebuilt-wasm-artifacts.ts index a07849a154e01..e5eace8d80dcf 100644 --- a/js/web/script/pull-prebuilt-wasm-artifacts.ts +++ b/js/web/script/pull-prebuilt-wasm-artifacts.ts @@ -8,159 +8,266 @@ // WebAssembly side, so there is no need to rebuild WebAssembly. // // It performs the following operations: -// 1. query build ID for latest successful build on main branch or the specified one from command line argument -// 2. query download URL of build artifacts -// 3. download and unzip the files to folders +// 1. use GitHub Actions REST API as much as possible to get metadata about the status of build and workflow runs. +// - query the main branch if no "run" parameter is specified +// - if "run" is specified, it can be a run ID, PR number, branch name, or commit SHA. Try each possibility. +// +// 2. When the artifact is found, use GitHub CLI (gh) to download the artifacts directly to the dist folder. // import fs from 'fs'; import { bootstrap as globalAgentBootstrap } from 'global-agent'; import https from 'https'; -import jszip from 'jszip'; import path from 'path'; +import minimist from 'minimist'; +import { execSync } from 'child_process'; const HELP_MESSAGE = ` pull-prebuilt-wasm-artifacts Usage: - npm run pull:wasm [config] [buildID] [help|h] + npm run pull:wasm [run] [options] - node ./pull-prebuilt-wasm-artifacts [config] [buildID] [help|h] + node ./pull-prebuilt-wasm-artifacts [run] [options] + Run can be specified in one of the following ways: + action_run_id + PR number + branch name (default: "main") - config optional, "release"(default) or "debug" - buildID optional, if not specified, use latest main branch, otherwise a number for a specified build ID - help|h print this message and exit +Options: + -d --debug specify the debug build type of the artifacts to download. + -l --latest if set, will always use the latest build, even if it is not completed yet. + --webgpu-ep if set, will use the webgpu EP wasm build instead of the default(JSEP) one. + -h --help print this message and exit `; -const argv = process.argv.slice(2); +const args = minimist(process.argv.slice(2), { + alias: { + debug: ['d'], + help: ['h'], + latest: ['l'], + }, +}); -if ( - argv.indexOf('--help') !== -1 || - argv.indexOf('-h') !== -1 || - argv.indexOf('help') !== -1 || - argv.indexOf('h') !== -1 -) { +if (args.help || args.h) { console.log(HELP_MESSAGE); process.exit(); } -const arg0isConfig = argv[0] === 'debug' || argv[0] === 'release'; -const arg0isInteger = !arg0isConfig && !isNaN(parseInt(argv[0], 10)); -const config = arg0isConfig ? argv[0] : 'release'; -const buildId = arg0isInteger ? argv[0] : (argv[1] ?? ''); +// Check if GitHub CLI (gh) is installed and available in PATH +try { + execSync('gh --version', { stdio: 'pipe' }).toString().trim(); +} catch (e) { + console.error('Error: GitHub CLI (gh) is not installed or not in PATH.'); + console.error('Please install it from https://cli.github.com/ and try again.'); + process.exit(1); +} + +// in NPM script, the args are parsed as: +// npm [npm_command] [npm_flags] -- [user_flags] +// +// The npm_flags will be parsed and removed by NPM, so they will not be available in process.argv directly. Instead, +// they are available in process.env.npm_config_* variables. +// +// For example, if the user runs the command like this: +// > npm run pull:wasm -- --debug +// In this case, `--debug` will be available in `args.debug` +// +// If the user runs the command like this: +// > npm run pull:wasm --debug +// In this case, `--debug` will be available in `process.env.npm_config_debug`, but not in `args.debug` directly. +// +// The following code checks both the command line arguments and the npm_config_* environment variables to get the correct values. +const debug = args.debug || process.env.npm_config_d || process.env.npm_config_debug; +const latest = args.latest || process.env.npm_config_l || process.env.npm_config_latest; +const webgpuEp = args['webgpu-ep'] || process.env.npm_config_webgpu_ep; + +const folderName = (debug ? 'Debug_wasm' : 'Release_wasm') + (webgpuEp ? '_webgpu' : ''); +const allowImcomplete = latest; -const folderName = config === 'release' ? 'Release_wasm' : 'Debug_wasm'; +const run = args._[0]; // The first non-option argument -function downloadJson(url: string, onSuccess: (data: any) => void) { - https.get(url, (res) => { - const { statusCode } = res; - const contentType = res.headers['content-type']; +const GITHUB_ACTION_REQUEST_OPTIONS = { + headers: { + 'user-agent': 'onnxruntime-web artifact pull', + accept: 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28', + }, +}; - if (statusCode !== 200) { - throw new Error(`Failed to download build list. HTTP status code = ${statusCode}`); - } - if (!contentType || !/^application\/json/.test(contentType)) { - throw new Error(`unexpected content type: ${contentType}`); - } - res.setEncoding('utf8'); - let rawData = ''; - res.on('data', (chunk) => { - rawData += chunk; - }); - res.on('end', () => { - onSuccess(JSON.parse(rawData)); - }); +async function downloadJson(url: string): Promise { + return new Promise((resolve, reject) => { + https + .get(url, GITHUB_ACTION_REQUEST_OPTIONS, (res) => { + const { statusCode } = res; + const contentType = res.headers['content-type']; + + if (!statusCode) { + reject(new Error('No response statud code from server.')); + return; + } + if (statusCode >= 400 && statusCode < 500) { + resolve(null); + return; + } else if (statusCode !== 200) { + reject(new Error(`Failed to download build list. HTTP status code = ${statusCode}`)); + return; + } + if (!contentType || !/^application\/json/.test(contentType)) { + reject(new Error(`unexpected content type: ${contentType}`)); + return; + } + res.setEncoding('utf8'); + let rawData = ''; + res.on('data', (chunk) => { + rawData += chunk; + }); + res.on('end', () => { + try { + resolve(JSON.parse(rawData)); + } catch (e) { + reject(e); + } + }); + res.on('error', (err) => { + reject(err); + }); + }) + .on('error', (err) => { + reject(err); + }); }); } -function downloadZip(url: string, onSuccess: (data: Buffer) => void) { - https.get(url, (res) => { - const { statusCode } = res; - const contentType = res.headers['content-type']; +async function downloadArtifactsForRun(run: any): Promise { + const data = await downloadJson(run.artifacts_url); - if (statusCode !== 200) { - throw new Error(`Failed to download build list. HTTP status code = ${statusCode}`); - } - if (!contentType || !/^application\/zip/.test(contentType)) { - throw new Error(`unexpected content type: ${contentType}`); + for (const v of data.artifacts) { + if (v.name === folderName && !v.expired) { + console.log(`=== Ready to download artifacts "${folderName}" from run: ${run.id} ===`); + + const WASM_FOLDER = path.join(__dirname, '../dist'); + if (!fs.existsSync(WASM_FOLDER)) { + fs.mkdirSync(WASM_FOLDER); + } else { + const filesToDelete = ['ort-wasm-simd-threaded.jsep.mjs', 'ort-wasm-simd-threaded.jsep.wasm']; + if (!folderName.endsWith('_webgpu')) { + filesToDelete.push('ort-wasm-simd-threaded.mjs', 'ort-wasm-simd-threaded.wasm'); + } + fs.readdirSync(WASM_FOLDER).forEach((file) => { + if (filesToDelete.includes(file)) { + const filePath = path.join(WASM_FOLDER, file); + console.log(`Deleting old file: ${filePath}`); + fs.unlinkSync(filePath); + } + }); + } + + execSync(`gh run download ${run.id} -n ${folderName} -D "${WASM_FOLDER}" -R Microsoft/onnxruntime`); + + return; } + } - const chunks: Buffer[] = []; - res.on('data', (chunk) => { - chunks.push(chunk); - }); - res.on('end', () => { - onSuccess(Buffer.concat(chunks)); - }); - }); + throw new Error(`No artifact "${folderName}" found for the specified build.`); } -function extractFile(zip: jszip, folder: string, file: string, artifactName: string) { - zip - .file(`${artifactName}/${file}`)! - .nodeStream() - .pipe(fs.createWriteStream(path.join(folder, file))) - .on('finish', () => { - console.log('# file downloaded and extracted: ' + file); - }); -} +async function main() { + // Bootstrap global-agent to honor the proxy settings in + // environment variables, e.g. GLOBAL_AGENT_HTTPS_PROXY. + // See https://github.com/gajus/global-agent/blob/v3.0.0/README.md#environment-variables for details. + globalAgentBootstrap(); + + console.log( + `=== Start to pull WebAssembly artifacts "${folderName}" from CI for ${run ? `Run: "${run}"` : 'main branch'} ===`, + ); + + let sha: string | undefined; + + // If param `run` is specified, we try to figure out what it is. + if (!run) { + // API reference: https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow + const mainRunData = await downloadJson( + `https://api.github.com/repos/Microsoft/onnxruntime/actions/workflows/152051496/runs?branch=main${allowImcomplete ? '' : '&status=completed'}&per_page=1&exclude_pull_requests=1`, + ); + if (mainRunData.workflow_runs.length === 0) { + throw new Error('No build found'); + } + const run = mainRunData.workflow_runs[0]; + await downloadArtifactsForRun(run); + } else { + // If `run` is a number, it is a run ID or PR number + const runId = parseInt(run, 10); + // check if runId only contains digits + const isRunIdDigitsOnly = /^\d+$/.test(run); + if (isRunIdDigitsOnly && !isNaN(runId)) { + // Try to treat it as a run ID + console.log(' # Trying to treat it as a run ID: ' + runId); + const runData = await downloadJson(`https://api.github.com/repos/Microsoft/onnxruntime/actions/runs/${runId}`); + if (runData) { + console.log(`=== Found run: ${runId} ===`); + await downloadArtifactsForRun(runData); + return; + } + + // If not found, try to treat it as a PR number + console.log(` # Run ID ${runId} not found or not accessible.`); + + // API reference: https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request + const prData = await downloadJson(`https://api.github.com/repos/Microsoft/onnxruntime/pulls/${runId}`); + sha = prData?.head?.sha; + } + + if (sha) { + console.log(` # Found PR #${run} with SHA: ${sha}`); + } else { + // Try to treat the run parameter as a branch name or commit SHA + console.log(` # Trying to treat "${run}" as a branch name`); -console.log( - `=== Start to pull ${config} WebAssembly artifacts from CI for ${ - buildId ? `build "${buildId}"` : 'latest "main" branch' - } ===`, -); - -// Bootstrap global-agent to honor the proxy settings in -// environment variables, e.g. GLOBAL_AGENT_HTTPS_PROXY. -// See https://github.com/gajus/global-agent/blob/v3.0.0/README.md#environment-variables for details. -globalAgentBootstrap(); - -const filter = buildId - ? `&buildIds=${buildId}` - : '&definitions=161' + - '&resultFilter=succeeded%2CpartiallySucceeded' + - '&$top=1' + - '&repositoryId=Microsoft/onnxruntime' + - '&repositoryType=GitHub' + - '&branchName=refs/heads/main'; - -// API reference: https://docs.microsoft.com/en-us/rest/api/azure/devops/build/builds/list -downloadJson( - `https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/builds?api-version=6.1-preview.6${filter}`, - (data) => { - const buildId = data.value[0].id; - - console.log(`=== Found latest build on main branch: ${buildId} ===`); - - // API reference: https://docs.microsoft.com/en-us/rest/api/azure/devops/build/artifacts/get%20artifact - downloadJson( - `https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/builds/${buildId}/artifacts?api-version=6.1-preview.5`, - (data) => { - let zipLink; - for (const v of data.value) { - if (v.name === folderName) { - zipLink = v.resource.downloadUrl; + // First, try as a branch name + const branchData = await downloadJson( + `https://api.github.com/repos/Microsoft/onnxruntime/branches/${encodeURIComponent(run)}`, + ); + if (branchData) { + sha = branchData.commit.sha; + console.log(` # Found branch "${run}" with SHA: ${sha}`); + } else { + const isPossibleSha = /^[0-9a-f]{7,40}$/.test(`${run}`.trim()); + if (isPossibleSha) { + // If not a branch, try as a commit SHA (works with both full and short SHA) + console.log(` # Trying to treat "${run}" as a commit SHA`); + const commitData = await downloadJson( + `https://api.github.com/repos/Microsoft/onnxruntime/commits/${encodeURIComponent(run)}`, + ); + if (commitData) { + sha = commitData.sha; + console.log(` # Found commit with full SHA: ${sha}`); } } + } - console.log('=== Ready to download zip files ==='); + if (!sha) { + throw new Error(`Could not identify "${run}" as a run ID, PR number, branch name, or commit SHA`); + } + } - const WASM_FOLDER = path.join(__dirname, '../dist'); - if (!fs.existsSync(WASM_FOLDER)) { - fs.mkdirSync(WASM_FOLDER); - } - downloadZip(zipLink, (buffer) => { - void jszip.loadAsync(buffer).then((zip) => { - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.wasm', folderName); - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.wasm', folderName); - - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.mjs', folderName); - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.mjs', folderName); - }); - }); - }, + // Now that we have the SHA, query for workflow runs associated with this SHA + const workflowRunsData = await downloadJson( + `https://api.github.com/repos/Microsoft/onnxruntime/actions/workflows/152051496/runs?head_sha=${sha}`, ); - }, -); + + if (!workflowRunsData || workflowRunsData.workflow_runs.length === 0) { + throw new Error(`No Web CI workflow runs found for SHA: ${sha}`); + } + + // Get the latest run + const latestRun = workflowRunsData.workflow_runs[0]; + console.log(`=== Found run for SHA ${sha}: ${latestRun.html_url} ===`); + + // Download artifacts from this run + await downloadArtifactsForRun(latestRun); + } +} + +void main(); From b37939061d81db25a3cab32a46e87c2fb6fbb10d Mon Sep 17 00:00:00 2001 From: Chi Lo <54722500+chilo-ms@users.noreply.github.com> Date: Wed, 2 Apr 2025 10:23:46 -0700 Subject: [PATCH 215/266] Ensure to use correct GPU device in RunSince when it's invoked by new thread (#24192) Running cuda kernel on incorrect GPU device will end up getting CUDA error: `invalid resource handle.` CUDA EP and TRT EP both have this issue when ExecutionMode::ORT_PARALLEL is enabled. Repro code: ````python provider = [ [ ('TensorrtExecutionProvider', { 'device_id': 0, }), ], [ ('TensorrtExecutionProvider', { 'device_id': 1, }), ] ] class ThreadObj(): def __init__(self, model_path: str, iterations: int, idx: int): ... sess_opt = ort.SessionOptions() sess_opt.execution_mode = ort.ExecutionMode.ORT_PARALLEL self.inference_session = ort.InferenceSession(model_path, sess_opt, provider[idx % 2]) def warmup(self): self.inference_session.run(None, self.input) def run(self, thread_times, threads_complete): for iter in range(self.iterations): self.inference_session.run(None, self.input) def thread_target(obj, thread_times, threads_complete): obj.run(thread_times, threads_complete) ... iterations = 500 num_threads = 13 t_obj_list = [] thread_list = [] for tidx in range(num_threads): obj = ThreadObj(model_path, iterations, tidx) t_obj_list.append(obj) obj.warmup() for t_obj in t_obj_list: thread = threading.Thread(target=thread_target, daemon=True, args=(t_obj,thread_times,threads_complete,)) thread.start() thread_list.append(thread) ... ```` The reason is when the inference session is initialized, it can be bound to device > 0, whereas when running the inference, i.e. RunSince can be invoked by a new thread and new threads default to using device 0, then we will hit the error of using the incorrect GPU device. This PR provides a general fix for both CUDA EP and TRT EP to call cudaSetDeivce in RunSince. --- .../core/framework/stream_handles.h | 21 +++ onnxruntime/core/framework/session_state.cc | 13 ++ .../framework/stream_execution_context.cc | 15 ++ .../providers/cuda/cuda_execution_provider.cc | 2 - .../core/providers/cuda/cuda_stream_handle.cc | 1 + .../tensorrt/tensorrt_execution_provider.cc | 18 -- .../onnxruntime_test_python_ort_parallel.py | 154 ++++++++++++++++++ tools/ci_build/build.py | 2 + 8 files changed, 206 insertions(+), 20 deletions(-) create mode 100644 onnxruntime/test/python/onnxruntime_test_python_ort_parallel.py diff --git a/include/onnxruntime/core/framework/stream_handles.h b/include/onnxruntime/core/framework/stream_handles.h index 01631e1fb2aa6..402ea2da2148c 100644 --- a/include/onnxruntime/core/framework/stream_handles.h +++ b/include/onnxruntime/core/framework/stream_handles.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include "core/framework/allocator.h" #include "core/framework/ortdevice.h" @@ -154,6 +155,12 @@ class Notification { // TODO: use a better way to dispatch handles. using CreateStreamFn = std::function(const OrtDevice&)>; +// This SetDevice function is used by TRT EP or CUDA EP to handle the case where ExecutionMode::ORT_PARALLEL is enabled. +// In that case, ORT retrieves a thread from the thread pool to run kernels for a given session. +// Since new threads default to using device 0, but the session may be tightly bound to a device > 0, +// This SetDevice function will be called in RunSince to ensure running kernels on a correct GPU device. +using SetDeviceFn = std::function; + // an interface of a simple registry which hold the handles EP registered. // make it interface so we can pass it through shared library based execution providers class IStreamCommandHandleRegistry { @@ -171,6 +178,20 @@ class IStreamCommandHandleRegistry { WaitNotificationFn fn) = 0; // register a handle about how to create stream on given device type. virtual void RegisterCreateStreamFn(OrtDevice::DeviceType device_type, CreateStreamFn f) = 0; + + // Register a SetDevice function. + // This interface is currently used by TRT EP or CUDA EP only. + virtual void RegisterSetDeviceFn(OrtDevice::DeviceType device_type, SetDeviceFn f) { + ORT_UNUSED_PARAMETER(device_type); + ORT_UNUSED_PARAMETER(f); + }; + + // Get a SetDevice function. + // This interface is currently used by TRT EP or CUDA EP only and is called in RunSince from stream execution. + virtual std::optional GetSetDeviceFn(OrtDevice::DeviceType device_type) const { + ORT_UNUSED_PARAMETER(device_type); + return std::nullopt; + }; }; } // namespace onnxruntime diff --git a/onnxruntime/core/framework/session_state.cc b/onnxruntime/core/framework/session_state.cc index a8c1a7515ae82..d174d6cc72ead 100644 --- a/onnxruntime/core/framework/session_state.cc +++ b/onnxruntime/core/framework/session_state.cc @@ -54,11 +54,24 @@ class StreamCommandHandleRegistryImpl : public IStreamCommandHandleRegistry { create_stream_map_.insert({device_type, f}); } + void RegisterSetDeviceFn(const OrtDevice::DeviceType device_type, SetDeviceFn f) override { + set_device_map_.insert({device_type, f}); + } + + std::optional GetSetDeviceFn(const OrtDevice::DeviceType device_type) const override { + auto it = set_device_map_.find(device_type); + if (it != set_device_map_.end()) { + return it->second; + } + return std::nullopt; + } + StreamCommandHandleRegistryImpl() = default; private: InlinedHashMap notification_wait_map_; InlinedHashMap create_stream_map_; + InlinedHashMap set_device_map_; }; #endif diff --git a/onnxruntime/core/framework/stream_execution_context.cc b/onnxruntime/core/framework/stream_execution_context.cc index dd7f4d35b34bd..e8beb98749028 100644 --- a/onnxruntime/core/framework/stream_execution_context.cc +++ b/onnxruntime/core/framework/stream_execution_context.cc @@ -205,6 +205,21 @@ void RunSince(size_t stream_idx, StreamExecutionContext& ctx, SessionScope& sess end = std::min(end, range->stream_pc_range[stream_idx].second); #endif +#ifdef ORT_ENABLE_STREAM + // If the device stream has corresponding SetDevice function registered, it means GPU device should be properly set to the correct device. + // The reason SetDevice should be called here is: + // - RunSince function can be invoked from a new thread + // - new threads default to using device 0, but the session may be tightly bound to a device > 0. + auto device_stream = ctx.GetDeviceStream(stream_idx); + if (device_stream) { + auto set_device_fn = ctx.GetSessionState().GetStreamHandleRegistryInstance().GetSetDeviceFn(device_stream->GetDevice().Type()); + if (set_device_fn.has_value()) { + auto device_id = device_stream->GetDevice().Id(); + set_device_fn.value()(device_id); + } + } +#endif + while (since < end) { if (!ctx.TaskStatus().IsOK()) { ctx.CompleteTask(); diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc index 886fddd8f8a27..635eb67bbedd0 100644 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc @@ -420,8 +420,6 @@ Status CUDAExecutionProvider::Sync() const { } Status CUDAExecutionProvider::OnRunStart(const onnxruntime::RunOptions& run_options) { - // always set CUDA device when session::Run() in case it runs in a worker thread - CUDA_RETURN_IF_ERROR(cudaSetDevice(GetDeviceId())); CudaGraphAnnotation_t cuda_graph_annotation_id = GetPerThreadContext().GetCudaGraphAnnotationId(run_options); if (IsGraphCaptureEnabled() && !GetPerThreadContext().IsGraphCaptured(cuda_graph_annotation_id) && GetPerThreadContext().IsGraphCaptureAllowed(cuda_graph_annotation_id)) { diff --git a/onnxruntime/core/providers/cuda/cuda_stream_handle.cc b/onnxruntime/core/providers/cuda/cuda_stream_handle.cc index e9b159516dad9..51fd2c67b7478 100644 --- a/onnxruntime/core/providers/cuda/cuda_stream_handle.cc +++ b/onnxruntime/core/providers/cuda/cuda_stream_handle.cc @@ -266,6 +266,7 @@ void RegisterCudaStreamHandles(IStreamCommandHandleRegistry& stream_handle_regis ep_info](const OrtDevice& device) { return std::make_unique(external_stream, device, cpu_allocator, release_cpu_buffer_on_cuda_stream, false, external_cudnn_handle, external_cublas_handle, ep_info); }); + stream_handle_registry.RegisterSetDeviceFn(device_type, [](OrtDevice::DeviceId id) { CUDA_CALL_THROW(cudaSetDevice(id)); }); } } // namespace onnxruntime diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index 00f53b96f931a..523ebbfae807a 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -3538,15 +3538,6 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView // Create compute function compute_info.compute_func = [this](FunctionState state, const OrtApi* api, OrtKernelContext* context) { - // The GPU device is set again here to handle multithreading scenarios. - // Consider the following: - // Users can create multiple threads to initialize separate inference sessions on different devices (not just the default device 0) - // Later, additional threads may be spawned to execute inference_session.Run(), which calls this compute function. - // Since new threads default to using device 0, it’s necessary to explicitly set the correct device to ensure computations run on the intended GPU. - // Note: Based on our measurements on the A100 GPU with CUDA 12, the execution time for cudaSetDevice is approximately 0.004 ms, which is negligible - // and does not impact runtime performance. - CUDA_CALL_THROW(cudaSetDevice(device_id_)); - Ort::KernelContext ctx(context); TensorrtFuncState* trt_state = reinterpret_cast(state); @@ -4221,15 +4212,6 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromPrecompiledEngine(con // Create compute function compute_info.compute_func = [this](FunctionState state, const OrtApi* api, OrtKernelContext* context) { - // The GPU device is set again here to handle multithreading scenarios. - // Consider the following: - // Users can create multiple threads to initialize separate inference sessions on different devices (not just the default device 0) - // Later, additional threads may be spawned to execute inference_session.Run(), which calls this compute function. - // Since new threads default to using device 0, it’s necessary to explicitly set the correct device to ensure computations run on the intended GPU. - // Note: Based on our measurements on the A100 GPU with CUDA 12, the execution time for cudaSetDevice is approximately 0.004 ms, which is negligible - // and does not impact runtime performance. - CUDA_CALL_THROW(cudaSetDevice(device_id_)); - Ort::KernelContext ctx(context); TensorrtShortFuncState* trt_state = reinterpret_cast(state); diff --git a/onnxruntime/test/python/onnxruntime_test_python_ort_parallel.py b/onnxruntime/test/python/onnxruntime_test_python_ort_parallel.py new file mode 100644 index 0000000000000..c28bfb930e417 --- /dev/null +++ b/onnxruntime/test/python/onnxruntime_test_python_ort_parallel.py @@ -0,0 +1,154 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import ctypes +import sys +import threading +import time +import unittest + +import numpy as np +from helper import get_name + +import onnxruntime as onnxrt + + +class ThreadObj: + def __init__(self, model_path: str, iterations: int, idx: int, num_device: int, provider_options_list: list): + self.iterations = iterations + sess_opt = onnxrt.SessionOptions() + sess_opt.graph_optimization_level = onnxrt.GraphOptimizationLevel.ORT_DISABLE_ALL + sess_opt.execution_mode = onnxrt.ExecutionMode.ORT_PARALLEL # ORT will use thread from inter-op thread pool + self.inference_session = onnxrt.InferenceSession(model_path, sess_opt, provider_options_list[idx % num_device]) + self.input = { + "Input3": np.ones([1, 1, 28, 28], np.float32), + } + self.idx = idx + + def warmup(self): + print(f"[THREAD {self.idx}] running warmup") + self.inference_session.run(None, self.input) + print(f"[THREAD {self.idx}] warmup done") + + def run(self, thread_times, threads_complete): + for iter in range(self.iterations): + print(f"[THREAD {self.idx}] running iteration {iter}") + thread_times[self.idx] = time.time() + self.inference_session.run(None, self.input) + thread_times[self.idx] = time.time() + print(f"[THREAD {self.idx}] completed iteration {iter}") + threads_complete[0] += 1 + + +def thread_target(obj, thread_times, threads_complete): + obj.run(thread_times, threads_complete) + + +# This unittest class creates 10 threads, each thread creates its own inference session and runs one warmup sequentially. +# Once all threads finish their warmup run, all threads run multiple inference runs concurrently. +class TestParallelRun(unittest.TestCase): + def test_select_ep_to_run_ort_parallel_execution_mode(self): + if "TensorrtExecutionProvider" in onnxrt.get_available_providers(): + cuda_lib = self.load_cuda_lib() + device_cnt = self.cuda_device_count(cuda_lib) + assert device_cnt > 0 + print(f"Number of GPUs available: {device_cnt}") + self.run_inference_with_parallel_execution_mode("TensorrtExecutionProvider", device_cnt) + elif "CUDAExecutionProvider" in onnxrt.get_available_providers(): + cuda_lib = self.load_cuda_lib() + device_cnt = self.cuda_device_count(cuda_lib) + assert device_cnt > 0 + print(f"Number of GPUs available: {device_cnt}") + self.run_inference_with_parallel_execution_mode("CUDAExecutionProvider", device_cnt) + + def load_cuda_lib(self): + cuda_lib = None + if sys.platform == "win32": + cuda_lib = "nvcuda.dll" + elif sys.platform == "linux": + cuda_lib = "libcuda.so" + elif sys.platform == "darwin": + cuda_lib = "libcuda.dylib" + + if cuda_lib is not None: + try: + return ctypes.CDLL(cuda_lib) + except OSError: + pass + return None + + def cuda_device_count(self, cuda_lib): + if cuda_lib is None: + return -1 + num_device = ctypes.c_int() + cuda_lib.cuInit(0) + result = cuda_lib.cuDeviceGetCount(ctypes.byref(num_device)) + if result != 0: + error_str = ctypes.c_char_p() + cuda_lib.cuGetErrorString(result, ctypes.byref(error_str)) + print(f"cuDeviceGetCount failed with error code {result}: {error_str.value.decode()}") + return -1 + return num_device.value + + def run_inference_with_parallel_execution_mode(self, ep, num_device): + provider_options = [] + for i in range(num_device): + option = [ + ( + ep, + { + "device_id": i, + }, + ), + ] + provider_options.append(option) + + model_path = get_name("mnist.onnx") + iterations = 20 + hang_time = 60 + + num_threads = 10 + t_obj_list = [] + thread_list = [] + + threads_complete = [0] + thread_times = [0] * num_threads + + for tidx in range(num_threads): + obj = ThreadObj(model_path, iterations, tidx, num_device, provider_options) + t_obj_list.append(obj) + obj.warmup() + + for t_obj in t_obj_list: + thread = threading.Thread( + target=thread_target, + daemon=True, + args=( + t_obj, + thread_times, + threads_complete, + ), + ) + thread.start() + thread_list.append(thread) + + time.sleep(5) + while True: + for t_time in thread_times: + if time.time() - t_time < hang_time: + continue + else: + print("Hang occured, ending test") + exit(1) + if threads_complete[0] == num_threads: + break + time.sleep(5) + + for thread in thread_list: + thread.join() + + print("All threads completed") + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index c667df0369c91..698de85c5984b 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -2438,6 +2438,8 @@ def run_onnxruntime_tests(args, source_dir, ctest_path, build_dir, configs): if args.use_cuda: log.info("Testing CUDA Graph feature") run_subprocess([sys.executable, "onnxruntime_test_python_cudagraph.py"], cwd=cwd, dll_path=dll_path) + log.info("Testing running inference concurrently") + run_subprocess([sys.executable, "onnxruntime_test_python_ort_parallel.py"], cwd=cwd, dll_path=dll_path) if args.use_dml: log.info("Testing DML Graph feature") From b5d15bc9cc793f3a69aa120505191440132b18e8 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 2 Apr 2025 16:12:40 -0400 Subject: [PATCH 216/266] Adding build-system to pyproject.toml (#24216) --- tools/ci_build/github/linux/python/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/ci_build/github/linux/python/requirements.txt b/tools/ci_build/github/linux/python/requirements.txt index 42e5c3d18840f..e51cfb38f57a3 100644 --- a/tools/ci_build/github/linux/python/requirements.txt +++ b/tools/ci_build/github/linux/python/requirements.txt @@ -1,9 +1,10 @@ numpy==2.1.2 mypy pytest +setuptools>=68.2.2 wheel onnx==1.17.0 ; python_version < '3.13' protobuf==4.21.12 sympy==1.12 flatbuffers -psutil +psutil \ No newline at end of file From bc7b07dbb41a2f441dbed1a91855563ba0dd8a31 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 2 Apr 2025 13:54:45 -0700 Subject: [PATCH 217/266] [WebGPU EP] Implements ceil mode for Average Pool (#24270) Ceil mode is required for rtdetr model. The actual ceil mode calculation is already implemented in the PoolAttributes::ComputeOutputSize() method from pool_attributes.h under CPU EP. --- onnxruntime/core/providers/webgpu/nn/pool.cc | 2 -- onnxruntime/test/providers/cpu/nn/pool_op_test.cc | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/nn/pool.cc b/onnxruntime/core/providers/webgpu/nn/pool.cc index 79072a1dbaba8..12c135dbbf46d 100644 --- a/onnxruntime/core/providers/webgpu/nn/pool.cc +++ b/onnxruntime/core/providers/webgpu/nn/pool.cc @@ -169,8 +169,6 @@ Status PoolProgram::GenerateShaderCode(ShaderHelper& shader) const { template Status Pool::ComputeInternal(ComputeContext& context) const { - // TODO: support 'ceil' mode. - ORT_RETURN_IF_NOT(pool_attrs_.ceil_mode == 0, "Using ceil is not supported yet."); // TODO: support 'column major' storage_order. ORT_RETURN_IF_NOT(pool_attrs_.storage_order == 0, "Using column major storage_order is not supported yet."); diff --git a/onnxruntime/test/providers/cpu/nn/pool_op_test.cc b/onnxruntime/test/providers/cpu/nn/pool_op_test.cc index b6eb812e6a399..36150d03a7d36 100644 --- a/onnxruntime/test/providers/cpu/nn/pool_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/pool_op_test.cc @@ -645,9 +645,8 @@ TEST(PoolTest, MaxPool_10_Dilation_Ceil1_2d) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); - // TODO: Enable the case for WebGPU once ceil is supported. test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); + {kTensorrtExecutionProvider, kAclExecutionProvider}); } TEST(PoolTest, MaxPool_10_DilationPadding_3d) { @@ -1006,9 +1005,8 @@ TEST(PoolTest, AveragePool_10_ceil1_2d) { test.AddInput("X", x_dims, x_vals); test.AddOutput("Y", expected_dims, expected_vals); - // TODO: Enable the case for WebGPU once ceil is supported. test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kTensorrtExecutionProvider, kAclExecutionProvider, kWebGpuExecutionProvider}); + {kTensorrtExecutionProvider, kAclExecutionProvider}); } TEST(PoolTest, AveragePool_19_dilation_2d) { From 55aa03c161b8adf435af53c36a6233b458723e3b Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 3 Apr 2025 00:52:35 -0700 Subject: [PATCH 218/266] Pin vcpkg version (#24284) ### Description Pin vcpkg version. Yesterday vcpkg-tool made a new release that broke all our Linux pipelines. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../locate-vcvarsall-and-setup-env/action.yml | 30 +++++------- .github/workflows/android.yml | 10 ++++ .github/workflows/linux-dnnl.yml | 6 +++ .../linux-wasm-ci-build-and-test-workflow.yml | 9 +++- .github/workflows/linux_ci.yml | 6 +++ .github/workflows/linux_cuda_ci.yml | 40 ++++++---------- .github/workflows/linux_tensorrt_ci.yml | 40 +++++++--------- .github/workflows/reusable_linux_build.yml | 46 +++++++------------ .github/workflows/windows_build_x64_asan.yml | 2 +- .github/workflows/windows_dml.yml | 2 - .github/workflows/windows_openvino.yml | 6 +-- .github/workflows/windows_tensorrt.yml | 6 +-- .../windows_x64_debug_build_x64_debug.yml | 14 +----- ..._x64_release_vitisai_build_x64_release.yml | 2 +- .github/workflows/windows_x86.yml | 2 +- tools/ci_build/build.py | 5 +- .../linux/docker/scripts/install_os_deps.sh | 11 +---- .../docker/scripts/manylinux/install_deps.sh | 5 -- .../scripts/manylinux/install_shared_deps.sh | 6 --- 19 files changed, 103 insertions(+), 145 deletions(-) diff --git a/.github/actions/locate-vcvarsall-and-setup-env/action.yml b/.github/actions/locate-vcvarsall-and-setup-env/action.yml index f652a98ed2fe5..2fe3658b465c0 100644 --- a/.github/actions/locate-vcvarsall-and-setup-env/action.yml +++ b/.github/actions/locate-vcvarsall-and-setup-env/action.yml @@ -12,30 +12,22 @@ outputs: runs: using: "composite" steps: - - name: Download ORT Actions Asset (v0.0.3) - uses: dsaltares/fetch-gh-release-asset@1.1.0 # Action to download assets - with: - repo: 'microsoft/onnxruntime-github-actions' # The repo containing the actions - version: 'tags/v0.0.3' # The specific tag/version to use - file: 'onnxruntime-actions-v0.0.3.zip' # The asset filename (matches release workflow output) - target: 'onnxruntime-actions.zip' # Local filename to save as - - - name: Unzip ORT Actions (Windows) - shell: pwsh - run: | - # Create a directory to hold them (-Force acts like -p, creates parents if needed) - New-Item -Path '.\.github\_downloaded_actions' -ItemType Directory -Force - # Unzip the archive to the target directory - Expand-Archive -Path '.\onnxruntime-actions.zip' -DestinationPath '.\.github\_downloaded_actions' -Force - Write-Host "Unzipped contents:" - # List the contents recursively (Windows equivalent of ls -lR) - Get-ChildItem -Path '.\.github\_downloaded_actions' -Recurse - name: Setup VCPKG - uses: ./.github/_downloaded_actions/setup-vcpkg + uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.5 with: vcpkg-version: '2025.03.19' vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' + cmake-version: '3.31.6' + cmake-hash: '0f1584e8666cf4a65ec514bd02afe281caabf1d45d2c963f3151c41484f457386aa03273ab25776a670be02725354ce0b46f3a5121857416da37366342a833a0' + add-cmake-to-path: 'true' + disable-terrapin: 'false' + + - name: Verify vcpkg setup + shell: pwsh # Use powershell to easily access env var + run: | + Write-Host "VCPKG_INSTALLATION_ROOT is set to: $env:VCPKG_INSTALLATION_ROOT" + & "$env:VCPKG_INSTALLATION_ROOT/vcpkg" version - name: Find vcvarsall.bat id: find-vcvarsall diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0e06f8707da5f..a456d8b036e7b 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -29,6 +29,16 @@ jobs: java-version: '17' architecture: x64 + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.5 + with: + vcpkg-version: '2025.03.19' + vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + - name: Setup Android NDK uses: ./.github/actions/setup-android-ndk with: diff --git a/.github/workflows/linux-dnnl.yml b/.github/workflows/linux-dnnl.yml index c0cd23ff90ff4..948de1889bf64 100644 --- a/.github/workflows/linux-dnnl.yml +++ b/.github/workflows/linux-dnnl.yml @@ -16,6 +16,12 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + packages: write + attestations: write + id-token: write + jobs: build-linux-x64-release-dnnl: name: Build Linux x64 Release (DNNL EP) diff --git a/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml index 81b9c41af6dbf..b0ba518242aa8 100644 --- a/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml +++ b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml @@ -42,7 +42,14 @@ jobs: with: python-version: "3.12" architecture: ${{ env.buildArch }} - + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.5 + with: + vcpkg-version: '2025.03.19' + vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: diff --git a/.github/workflows/linux_ci.yml b/.github/workflows/linux_ci.yml index 2f2a97a00bb31..daa985212552a 100644 --- a/.github/workflows/linux_ci.yml +++ b/.github/workflows/linux_ci.yml @@ -29,6 +29,12 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + packages: write + attestations: write + id-token: write + jobs: # --- x64 Builds --- build-linux-x64-debug: diff --git a/.github/workflows/linux_cuda_ci.yml b/.github/workflows/linux_cuda_ci.yml index 23b6a9e752ab2..66369f43f9aea 100644 --- a/.github/workflows/linux_cuda_ci.yml +++ b/.github/workflows/linux_cuda_ci.yml @@ -10,6 +10,12 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + packages: write + attestations: write + id-token: write + jobs: build-linux-cuda-x64-release: name: Build Linux CUDA x64 Release @@ -43,30 +49,14 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Download ORT Actions Asset (v0.0.2) - uses: dsaltares/fetch-gh-release-asset@1.1.2 - with: - repo: 'microsoft/onnxruntime-github-actions' - version: 'tags/v0.0.2' - file: 'onnxruntime-actions-v0.0.2.zip' - target: 'onnxruntime-actions.zip' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Unzip ORT Actions - run: | - mkdir -p ./.github/_downloaded_actions - unzip -q onnxruntime-actions.zip -d ./.github/_downloaded_actions - echo "Unzipped contents:" - ls -lR ./.github/_downloaded_actions - - # --- Build the Docker image needed for testing --- - - name: Build Docker Image for Testing - uses: ./.github/_downloaded_actions/build-docker-image # Use downloaded action + - uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.5 + id: build_docker_image_step with: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda - Repository: onnxruntimecuda12manylinuxbuild - DockerBuildArgs: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1' + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecuda12manylinuxbuild + build-args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1' + push: true + azure-container-registry-name: onnxruntimebuildcache env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action @@ -102,9 +92,9 @@ jobs: # So build.py --build_dir build/Release inside the container correctly finds the artifacts. - name: Test ONNX Runtime id: test_step - uses: ./.github/_downloaded_actions/run-build-script-in-docker # Use downloaded action + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@v0.0.5 with: - docker_image: onnxruntimecuda12manylinuxbuild # Use the same image + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} build_config: Release mode: 'test' # Set mode to test execution_providers: 'cuda' diff --git a/.github/workflows/linux_tensorrt_ci.yml b/.github/workflows/linux_tensorrt_ci.yml index 9440003ddf801..ca4c825a95edb 100644 --- a/.github/workflows/linux_tensorrt_ci.yml +++ b/.github/workflows/linux_tensorrt_ci.yml @@ -10,6 +10,12 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + packages: write + attestations: write + id-token: write + jobs: build-linux-TensorRT-x64-release: name: Build Linux TensorRT x64 Release @@ -41,32 +47,18 @@ jobs: packages: read steps: - name: Checkout code - uses: actions/checkout@v4 - - - name: Download ORT Actions Asset (v0.0.2) - uses: dsaltares/fetch-gh-release-asset@1.1.2 - with: - repo: 'microsoft/onnxruntime-github-actions' - version: 'tags/v0.0.2' - file: 'onnxruntime-actions-v0.0.2.zip' - target: 'onnxruntime-actions.zip' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Unzip ORT Actions - run: | - mkdir -p ./.github/_downloaded_actions - unzip -q onnxruntime-actions.zip -d ./.github/_downloaded_actions - echo "Unzipped contents:" - ls -lR ./.github/_downloaded_actions + uses: actions/checkout@v4 # --- Build the Docker image needed for testing --- - name: Build Docker Image for Testing - uses: ./.github/_downloaded_actions/build-docker-image # Use downloaded action + uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.5 + id: build_docker_image_step with: - Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda - Repository: onnxruntimetensorrt86gpubuild - DockerBuildArgs: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 --build-arg TRT_VERSION=10.9.0.34-1.cuda12.8 --network=host' + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimetensorrt86gpubuild + build-args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20250124.1 --build-arg TRT_VERSION=10.9.0.34-1.cuda12.8 --network=host' + push: true + azure-container-registry-name: onnxruntimebuildcache env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action @@ -102,9 +94,9 @@ jobs: # So build.py --build_dir build/Release inside the container correctly finds the artifacts. - name: Test ONNX Runtime id: test_step - uses: ./.github/_downloaded_actions/run-build-script-in-docker # Use downloaded action + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@v0.0.5 with: - docker_image: onnxruntimetensorrt86gpubuild # Use the same image + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} build_config: Release mode: 'test' # Set mode to test execution_providers: 'cuda tensorrt' diff --git a/.github/workflows/reusable_linux_build.yml b/.github/workflows/reusable_linux_build.yml index 5c25b36a65197..7ff9260558ebf 100644 --- a/.github/workflows/reusable_linux_build.yml +++ b/.github/workflows/reusable_linux_build.yml @@ -70,8 +70,9 @@ jobs: - "1ES.Pool=${{ inputs.pool_name }}" permissions: contents: read - packages: read - + packages: write + attestations: write + id-token: write steps: - name: Checkout code uses: actions/checkout@v4 @@ -81,30 +82,15 @@ jobs: with: python-version: ${{ inputs.python_version }} - - name: Download ORT Actions Asset (v0.0.2) # <-- Adjust version as needed - uses: dsaltares/fetch-gh-release-asset@1.1.2 # Action to download assets - with: - repo: 'microsoft/onnxruntime-github-actions' # The repo containing the actions - version: 'tags/v0.0.2' # The specific tag/version to use - file: 'onnxruntime-actions-v0.0.2.zip' # The asset filename (matches release workflow output) - target: 'onnxruntime-actions.zip' # Local filename to save as - env: - # Use default token for public repos, provide PAT for private if necessary - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Unzip ORT Actions - run: | - mkdir -p ./.github/_downloaded_actions # Create a directory to hold them - unzip onnxruntime-actions.zip -d ./.github/_downloaded_actions - echo "Unzipped contents:" - ls -lR ./.github/_downloaded_actions # Verify structure - - name: Build Docker Image (${{ inputs.architecture }} / ${{ inputs.build_config }}) - uses: ./.github/_downloaded_actions/build-docker-image + uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.5 + id: build_docker_image_step with: - Dockerfile: ${{ github.workspace }}/${{ inputs.dockerfile_path }} - Repository: ${{ inputs.docker_image_repo }} - DockerBuildArgs: ${{ inputs.docker_build_args }} + dockerfile: ${{ github.workspace }}/${{ inputs.dockerfile_path }} + image-name: ghcr.io/microsoft/onnxruntime/${{ inputs.docker_image_repo }} + build-args: ${{ inputs.docker_build_args }} + push: true + azure-container-registry-name: onnxruntimebuildcache env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} @@ -117,9 +103,9 @@ jobs: # ------------- Update Step (CMake Generation) ------------- - name: Generate Build Files (CMake) (${{ inputs.architecture }} / ${{ inputs.build_config }}) id: update_step - uses: ./.github/_downloaded_actions/run-build-script-in-docker + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@v0.0.5 with: - docker_image: ${{ inputs.docker_image_repo }} + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} build_config: ${{ inputs.build_config }} mode: 'update' execution_providers: ${{ inputs.execution_providers }} # Pass down EP list @@ -129,9 +115,9 @@ jobs: # ------------- Build Step (Compilation) ------------- - name: Build ONNX Runtime (${{ inputs.architecture }} / ${{ inputs.build_config }}) id: build_step - uses: ./.github/_downloaded_actions/run-build-script-in-docker + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@v0.0.5 with: - docker_image: ${{ inputs.docker_image_repo }} + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} build_config: ${{ inputs.build_config }} mode: 'build' execution_providers: ${{ inputs.execution_providers }} # Pass down EP list @@ -142,9 +128,9 @@ jobs: - name: Test ONNX Runtime (${{ inputs.architecture }} / ${{ inputs.build_config }}) id: test_step if: inputs.run_tests == true - uses: ./.github/_downloaded_actions/run-build-script-in-docker + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@v0.0.5 with: - docker_image: ${{ inputs.docker_image_repo }} + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} build_config: ${{ inputs.build_config }} mode: 'test' execution_providers: ${{ inputs.execution_providers }} # Pass down EP list diff --git a/.github/workflows/windows_build_x64_asan.yml b/.github/workflows/windows_build_x64_asan.yml index 22c62f1c39411..b42fbac33d549 100644 --- a/.github/workflows/windows_build_x64_asan.yml +++ b/.github/workflows/windows_build_x64_asan.yml @@ -46,4 +46,4 @@ jobs: @echo off echo %PATH% python -m pip install -r "%GITHUB_WORKSPACE%\tools\ci_build/github/windows\python\requirements.txt" - python "%GITHUB_WORKSPACE%\tools\ci_build\build.py" --config Debug --build_dir "%RUNNER_TEMP%\build" --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_generator "Visual Studio 17 2022" --disable_memleak_checker --enable_address_sanitizer \ No newline at end of file + python "%GITHUB_WORKSPACE%\tools\ci_build\build.py" --config Debug --build_dir "%RUNNER_TEMP%\build" --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_generator "Visual Studio 17 2022" --disable_memleak_checker --enable_address_sanitizer diff --git a/.github/workflows/windows_dml.yml b/.github/workflows/windows_dml.yml index c7a4c796555d6..57656d951d40a 100644 --- a/.github/workflows/windows_dml.yml +++ b/.github/workflows/windows_dml.yml @@ -114,5 +114,3 @@ jobs: uses: ./.github/actions/install-onnxruntime-wheel with: whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist - - \ No newline at end of file diff --git a/.github/workflows/windows_openvino.yml b/.github/workflows/windows_openvino.yml index 45ffa40273df8..04d252ebcba19 100644 --- a/.github/workflows/windows_openvino.yml +++ b/.github/workflows/windows_openvino.yml @@ -96,7 +96,7 @@ jobs: Remove-Item -Force $OutputPath # Confirm success - Write-Output "OpenVINO extracted to $ExtractPath" + Write-Output "OpenVINO extracted to $ExtractPath" - name: Set OpenVINORootDir shell: pwsh @@ -143,7 +143,7 @@ jobs: Write-Output "Selected environment variables exported successfully" - + - name: Generate onnxruntime.sln shell: pwsh @@ -169,4 +169,4 @@ jobs: --build_shared_lib ` --use_openvino CPU ` --use_binskim_compliant_compile_flags ` - --test --enable_onnx_tests \ No newline at end of file + --test --enable_onnx_tests diff --git a/.github/workflows/windows_tensorrt.yml b/.github/workflows/windows_tensorrt.yml index 1f52b79b67d67..cf1658b390fad 100644 --- a/.github/workflows/windows_tensorrt.yml +++ b/.github/workflows/windows_tensorrt.yml @@ -79,7 +79,7 @@ jobs: working-directory: ${{ runner.temp }} run: | python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --parallel --use_binskim_compliant_compile_flags --build_dir build --skip_submodule_sync --build_shared_lib --build --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8" --cuda_home="${{ runner.temp }}\v12.2" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 - shell: cmd + shell: cmd - name: Add build dir to PATH shell: powershell @@ -95,7 +95,7 @@ jobs: - name: Run tests working-directory: ${{ runner.temp }} run: | - mklink /D /J ${{ github.workspace }}\RelWithDebInfo\models ${{ github.workspace }}\models + mklink /D /J ${{ github.workspace }}\RelWithDebInfo\models ${{ github.workspace }}\models python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --parallel --use_binskim_compliant_compile_flags --build_dir build --skip_submodule_sync --build_shared_lib --test --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.8.0.43.Windows10.x86_64.cuda-12.8" --cuda_home="${{ runner.temp }}\v12.2" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 shell: cmd - timeout-minutes: 180 \ No newline at end of file + timeout-minutes: 180 diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml index 9017314f22a22..effb6037f695c 100644 --- a/.github/workflows/windows_x64_debug_build_x64_debug.yml +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -2,7 +2,7 @@ name: windows_x64_debug on: push: - branches: [ main, 'rel-*', 'snnn/linux_ci2'] + branches: [ main, 'rel-*'] pull_request: branches: [ main ] @@ -27,18 +27,6 @@ jobs: python-version: '3.12' architecture: x64 - - name: Setup VCPKG - uses: microsoft/onnxruntime-github-actions/setup-vcpkg@f3d90afe522476c858909e0de2be0b12bc890068 - with: - vcpkg-version: '2025.03.19' - vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' - - - name: Verify vcpkg setup - shell: pwsh # Use powershell to easily access env var - run: | - Write-Host "VCPKG_INSTALLATION_ROOT is set to: $env:VCPKG_INSTALLATION_ROOT" - & "$env:VCPKG_INSTALLATION_ROOT/vcpkg" version - - name: Locate vcvarsall and Setup Env uses: ./.github/actions/locate-vcvarsall-and-setup-env # Use the composite action with: diff --git a/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml index 10c1f6858dc2f..0ef97f07a0fe9 100644 --- a/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml +++ b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml @@ -106,7 +106,7 @@ jobs: exit $LASTEXITCODE } Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} - working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" env: OrtPackageId: Microsoft.ML.OnnxRuntime OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build diff --git a/.github/workflows/windows_x86.yml b/.github/workflows/windows_x86.yml index c0aaaf30974a5..2819123e47670 100644 --- a/.github/workflows/windows_x86.yml +++ b/.github/workflows/windows_x86.yml @@ -124,4 +124,4 @@ jobs: env: OrtPackageId: Microsoft.ML.OnnxRuntime OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' \ No newline at end of file + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 698de85c5984b..0fea6acc110f0 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -1283,7 +1283,10 @@ def generate_build_tree( # Fallback to checkout vcpkg from github vcpkg_installation_root = os.path.join(os.path.abspath(build_dir), "vcpkg") if not os.path.exists(vcpkg_installation_root): - run_subprocess(["git", "clone", "https://github.com/microsoft/vcpkg.git", "--recursive"], cwd=build_dir) + run_subprocess( + ["git", "clone", "-b", "2025.03.19", "https://github.com/microsoft/vcpkg.git", "--recursive"], + cwd=build_dir, + ) vcpkg_toolchain_path = Path(vcpkg_installation_root) / "scripts" / "buildsystems" / "vcpkg.cmake" if args.build_wasm: diff --git a/tools/ci_build/github/linux/docker/scripts/install_os_deps.sh b/tools/ci_build/github/linux/docker/scripts/install_os_deps.sh index eba897c7c816b..c38b036159393 100755 --- a/tools/ci_build/github/linux/docker/scripts/install_os_deps.sh +++ b/tools/ci_build/github/linux/docker/scripts/install_os_deps.sh @@ -63,12 +63,7 @@ if [[ ("$DISTRIBUTOR" = "CentOS" || "$DISTRIBUTOR" = "RedHatEnterprise") && $SYS else LIBDIR="lib" fi -if [[ $SYS_LONG_BIT = "64" && "$GLIBC_VERSION" -gt "9" ]]; then - echo "Installing azcopy" - mkdir -p /tmp/azcopy - GetFile https://aka.ms/downloadazcopy-v10-linux /tmp/azcopy/azcopy.tar.gz - tar --strip 1 -xf /tmp/azcopy/azcopy.tar.gz -C /tmp/azcopy - cp /tmp/azcopy/azcopy /usr/bin +if [[ $SYS_LONG_BIT = "64" && "$GLIBC_VERSION" -gt "9" ]]; then echo "Installing cmake" GetFile https://github.com/Kitware/CMake/releases/download/v3.31.5/cmake-3.31.5-Linux-x86_64.tar.gz /tmp/src/cmake-3.31.5-Linux-x86_64.tar.gz tar -zxf /tmp/src/cmake-3.31.5-Linux-x86_64.tar.gz --strip=1 -C /usr @@ -90,10 +85,6 @@ fi cd /tmp/src -if ! [ -x "$(command -v protoc)" ]; then - $SCRIPT_DIR/install_protobuf.sh -p $INSTALL_PREFIX -fi - if [ $DEVICE_TYPE = "gpu" ]; then if [[ $INSTALL_DEPS_DISTRIBUTED_SETUP = true ]]; then source ${0/%install_os_deps.sh/install_openmpi.sh} diff --git a/tools/ci_build/github/linux/docker/scripts/manylinux/install_deps.sh b/tools/ci_build/github/linux/docker/scripts/manylinux/install_deps.sh index 5483f55c01942..ee33866e4286a 100755 --- a/tools/ci_build/github/linux/docker/scripts/manylinux/install_deps.sh +++ b/tools/ci_build/github/linux/docker/scripts/manylinux/install_deps.sh @@ -32,11 +32,6 @@ source "$LOCAL_DIR/install_shared_deps.sh" cd /tmp/src -if ! [ -x "$(command -v protoc)" ]; then -# shellcheck disable=SC1091 - source "$PARENT_DIR/install_protobuf.sh" -fi - export ONNX_ML=1 export CMAKE_ARGS="-DONNX_GEN_PB_TYPE_STUBS=OFF -DONNX_WERROR=OFF" diff --git a/tools/ci_build/github/linux/docker/scripts/manylinux/install_shared_deps.sh b/tools/ci_build/github/linux/docker/scripts/manylinux/install_shared_deps.sh index ec29fd45f07a7..6cb52aa3fbf87 100755 --- a/tools/ci_build/github/linux/docker/scripts/manylinux/install_shared_deps.sh +++ b/tools/ci_build/github/linux/docker/scripts/manylinux/install_shared_deps.sh @@ -38,12 +38,6 @@ function GetFile { cd /tmp/src -echo "Installing azcopy" -mkdir -p /tmp/azcopy -GetFile https://aka.ms/downloadazcopy-v10-linux /tmp/azcopy/azcopy.tar.gz -tar --strip 1 -xf /tmp/azcopy/azcopy.tar.gz -C /tmp/azcopy -cp /tmp/azcopy/azcopy /usr/bin - echo "Installing Node.js" # The EOL for nodejs v18.17.1 LTS is April 2025 GetFile https://nodejs.org/dist/v18.17.1/node-v18.17.1-linux-x64.tar.gz /tmp/src/node-v18.17.1-linux-x64.tar.gz From a14d586d7ab1d0453aeb736468ecc82f3a398c8f Mon Sep 17 00:00:00 2001 From: Yateng Hong Date: Thu, 3 Apr 2025 23:58:30 +0800 Subject: [PATCH 219/266] Support load TensorRT V3 plugin (#24211) ### Description TensorRT V3 plugin is not able to load in TensorRT EP. The change deprecates `getPluginCreatorList` with `getAllCreators` to load V1 and V3 plugin creators. ### Motivation and Context Support load TensorRT plugin. Reference: https://github.com/NVIDIA/TensorRT/blob/8c6d69ddec0b2feff12f55472dc5d55cb6861d53/python/src/infer/pyPlugin.cpp#L2971C1-L2995C6 --- .../tensorrt_execution_provider_custom_ops.cc | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_custom_ops.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_custom_ops.cc index e93d3565fe33d..90a4294fb47f0 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_custom_ops.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_custom_ops.cc @@ -60,19 +60,31 @@ common::Status CreateTensorRTCustomOpDomainList(std::vector& TensorrtLogger trt_logger = GetTensorrtLogger(false); initLibNvInferPlugins(&trt_logger, ""); -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Ignore warning C4996: 'nvinfer1::*' was declared deprecated -#endif - int num_plugin_creator = 0; - auto plugin_creators = getPluginRegistry()->getPluginCreatorList(&num_plugin_creator); + auto plugin_creators = getPluginRegistry()->getAllCreators(&num_plugin_creator); std::unordered_set registered_plugin_names; for (int i = 0; i < num_plugin_creator; i++) { auto plugin_creator = plugin_creators[i]; - std::string plugin_name(plugin_creator->getPluginName()); - LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] " << plugin_name << ", version : " << plugin_creator->getPluginVersion(); + nvinfer1::AsciiChar const* plugin_name = nullptr; + if (std::strcmp(plugin_creators[i]->getInterfaceInfo().kind, "PLUGIN CREATOR_V1") == 0) { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Ignore warning C4996: 'nvinfer1::*' was declared deprecated +#endif + auto plugin_creator_v1 = static_cast(plugin_creator); + plugin_name = plugin_creator_v1->getPluginName(); + LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] " << plugin_name << ", version : " << plugin_creator_v1->getPluginVersion(); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + } else if (std::strcmp(plugin_creators[i]->getInterfaceInfo().kind, "PLUGIN CREATOR_V3ONE") == 0) { + auto plugin_creator_v3 = static_cast(plugin_creator); + plugin_name = plugin_creator_v3->getPluginName(); + LOGS_DEFAULT(VERBOSE) << "[TensorRT EP][V3ONE] " << plugin_name << ", version : " << plugin_creator_v3->getPluginVersion(); + } else { + ORT_THROW("Unknown plugin creator type"); + } // plugin has different versions and we only register once if (registered_plugin_names.find(plugin_name) != registered_plugin_names.end()) { @@ -80,15 +92,11 @@ common::Status CreateTensorRTCustomOpDomainList(std::vector& } created_custom_op_list.push_back(std::make_unique(onnxruntime::kTensorrtExecutionProvider, nullptr)); // Make sure TensorRTCustomOp object won't be cleaned up - created_custom_op_list.back().get()->SetName(plugin_creator->getPluginName()); + created_custom_op_list.back().get()->SetName(plugin_name); custom_op_domain->custom_ops_.push_back(created_custom_op_list.back().get()); registered_plugin_names.insert(plugin_name); } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - custom_op_domain->domain_ = "trt.plugins"; domain_list.push_back(custom_op_domain.get()); } catch (const std::exception&) { From 21db38c155498f5b689e6076239c19f02e4935e7 Mon Sep 17 00:00:00 2001 From: Yateng Hong Date: Thu, 3 Apr 2025 23:58:41 +0800 Subject: [PATCH 220/266] Expose TRT preview features as EP option (#24212) ### Description Expose TRT preview features as EP option. ### Motivation and Context Add support to turn on TensorRT preview features. For example, > If the IPluginV3OneBuildV2 build capability is used, the plugin can also communicate to TensorRT that certain input-output pairs are aliased (share the same data buffer). TensorRT will query IPluginV3OneBuildV2::getAliasedInput to determine any such aliasing behavior. To use this feature, **PreviewFeature::kALIASED_PLUGIN_IO_10_03** must be enabled. --------- Co-authored-by: Vcpkg Builder --- .../tensorrt/tensorrt_provider_options.h | 6 ++-- .../tensorrt/tensorrt_execution_provider.cc | 30 ++++++++++++++++++- .../tensorrt/tensorrt_execution_provider.h | 2 ++ .../tensorrt_execution_provider_info.cc | 4 +++ .../tensorrt_execution_provider_info.h | 1 + .../tensorrt/tensorrt_provider_factory.cc | 1 + .../core/session/provider_bridge_ort.cc | 2 ++ .../python/onnxruntime_pybind_state.cc | 7 ++++- 8 files changed, 49 insertions(+), 4 deletions(-) diff --git a/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h index f6a5d05d0e790..687f74c94f154 100644 --- a/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h +++ b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h @@ -42,13 +42,15 @@ struct OrtTensorRTProviderOptionsV2 { int trt_sparsity_enable{0}; // Control if sparsity can be used by TRT. Default 0 = false, 1 = true int trt_builder_optimization_level{3}; // Set the builder optimization level. WARNING: levels below 3 do not guarantee good engine performance, but greatly improve build time. Default 3, valid range [0-5] int trt_auxiliary_streams{-1}; // Set maximum number of auxiliary streams per inference stream. Setting this value to 0 will lead to optimal memory usage. Default -1 = heuristics - const char* trt_tactic_sources{nullptr}; // pecify the tactics to be used by adding (+) or removing (-) tactics from the default + const char* trt_tactic_sources{nullptr}; // Specify the tactics to be used by adding (+) or removing (-) tactics from the default // tactic sources (default = all available tactics) e.g. "-CUDNN,+CUBLAS" available keys: "CUBLAS"|"CUBLAS_LT"|"CUDNN"|"EDGE_MASK_CONVOLUTIONS" - const char* trt_extra_plugin_lib_paths{nullptr}; // specify extra TensorRT plugin library paths + const char* trt_extra_plugin_lib_paths{nullptr}; // Specify extra TensorRT plugin library paths const char* trt_profile_min_shapes{nullptr}; // Specify the range of the input shapes to build the engine with const char* trt_profile_max_shapes{nullptr}; // Specify the range of the input shapes to build the engine with const char* trt_profile_opt_shapes{nullptr}; // Specify the range of the input shapes to build the engine with int trt_cuda_graph_enable{0}; // Enable CUDA graph in ORT TRT + const char* trt_preview_features{nullptr}; // Specify the preview features to be enabled, features should be separated by comma + // available keys: "ALIASED_PLUGIN_IO_10_03" /* * Please note that there are rules for using following context model related provider options: diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index 523ebbfae807a..2c443cdc33458 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -1282,6 +1282,22 @@ TensorrtExecutionProvider::PerThreadContext& TensorrtExecutionProvider::GetPerTh return *context; } +std::vector ParseTrtPreviewFeatures(const std::string& str) { + std::vector featureNames{SplitToStringVec(str, ',')}; + + std::vector previewFeatures; + previewFeatures.reserve(featureNames.size()); + for (auto featureName : featureNames) { + if (featureName == "ALIASED_PLUGIN_IO_10_03") { + previewFeatures.push_back(nvinfer1::PreviewFeature::kALIASED_PLUGIN_IO_10_03); + } else { + throw std::invalid_argument(std::string("Unkown or unsupported preview feature: ") + featureName); + } + } + + return previewFeatures; +} + TensorrtExecutionProvider::TensorrtExecutionProvider(const TensorrtExecutionProviderInfo& info) : IExecutionProvider{onnxruntime::kTensorrtExecutionProvider, OrtDevice(OrtDevice::GPU, OrtDevice::MemType::DEFAULT, @@ -1380,6 +1396,7 @@ TensorrtExecutionProvider::TensorrtExecutionProvider(const TensorrtExecutionProv cuda_graph_enable_ = info.cuda_graph_enable; engine_hw_compatible_ = info.engine_hw_compatible; op_types_to_exclude_ = info.op_types_to_exclude; + preview_features_ = ParseTrtPreviewFeatures(info.preview_features); } else { try { const std::string max_partition_iterations_env = onnxruntime::GetEnvironmentVar(tensorrt_env_vars::kMaxPartitionIterations); @@ -3186,6 +3203,11 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView LOGS_DEFAULT(VERBOSE) << "[TensorRT EP] Tactic sources are limited using " << tactic_sources_; } + // Set preview feature flags + for (auto feature : preview_features_) { + trt_config->setPreviewFeature(feature, true); + } + // Build TRT engine (if needed) and load TRT engine if: // (1) Graph has no dynamic shape input // (2) All the dynamic shape inputs have associated explicit profiles specified by user @@ -3526,7 +3548,8 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView context_memory_sharing_enable_, &max_ctx_mem_size_, dynamic_range_map, engine_decryption_enable_, engine_decryption_, engine_encryption_, timing_cache_enable_, global_cache_path_, force_timing_cache_match_, detailed_build_log_, build_heuristics_enable_, sparsity_enable_, builder_optimization_level_, - auxiliary_streams_, !tactic_sources_.empty(), tactics, cuda_graph_enable_, cache_prefix_, cache_suffix, engine_hw_compatible_}; + auxiliary_streams_, !tactic_sources_.empty(), tactics, cuda_graph_enable_, cache_prefix_, cache_suffix, engine_hw_compatible_, + preview_features_}; *state = p.release(); return 0; }; @@ -3808,6 +3831,11 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView } #endif + // Set preview feature flags + for (auto feature : trt_state->preview_features) { + trt_config->setPreviewFeature(feature, true); + } + // Build engine std::unique_ptr serialized_engine; { diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h index 934cc06eed45f..f6c8f7d7dd46b 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h @@ -201,6 +201,7 @@ struct TensorrtFuncState { std::string cache_prefix; std::string cache_suffix; bool engine_hw_compatible = false; + std::vector preview_features; }; // Minimum information to construct kernel function state for direct engine load code path @@ -333,6 +334,7 @@ class TensorrtExecutionProvider : public IExecutionProvider { std::string cache_prefix_; bool engine_hw_compatible_ = false; std::string op_types_to_exclude_; + std::vector preview_features_; // The format is as for TENSORRT_VERSION: (MAJOR * 100 + MINOR) * 100 + PATCH int32_t trt_version_; diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.cc index bc0d00ec6791f..ace5bbe65fc24 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.cc @@ -57,6 +57,7 @@ constexpr const char* kEngineHwCompatible = "trt_engine_hw_compatible"; constexpr const char* kONNXBytestream = "trt_onnx_bytestream"; constexpr const char* kONNXBytestreamSize = "trt_onnx_bytestream_size"; constexpr const char* kOpTypesToExclude = "trt_op_types_to_exclude"; +constexpr const char* kPreviewFeatures = "trt_preview_features"; } // namespace provider_option_names } // namespace tensorrt @@ -136,6 +137,7 @@ TensorrtExecutionProviderInfo TensorrtExecutionProviderInfo::FromProviderOptions }) .AddAssignmentToReference(tensorrt::provider_option_names::kONNXBytestreamSize, info.onnx_bytestream_size) .AddAssignmentToReference(tensorrt::provider_option_names::kOpTypesToExclude, info.op_types_to_exclude) + .AddAssignmentToReference(tensorrt::provider_option_names::kPreviewFeatures, info.preview_features) .Parse(options)); // add new provider option here. info.user_compute_stream = user_compute_stream; @@ -191,6 +193,7 @@ ProviderOptions TensorrtExecutionProviderInfo::ToProviderOptions(const TensorrtE {tensorrt::provider_option_names::kONNXBytestream, MakeStringWithClassicLocale(info.onnx_bytestream)}, {tensorrt::provider_option_names::kONNXBytestreamSize, MakeStringWithClassicLocale(info.onnx_bytestream_size)}, {tensorrt::provider_option_names::kOpTypesToExclude, MakeStringWithClassicLocale(info.op_types_to_exclude)}, + {tensorrt::provider_option_names::kPreviewFeatures, MakeStringWithClassicLocale(info.preview_features)}, }; return options; } @@ -361,5 +364,6 @@ void TensorrtExecutionProviderInfo::UpdateProviderOptions(void* provider_options trt_provider_options_v2.trt_onnx_bytestream = internal_options.onnx_bytestream; trt_provider_options_v2.trt_onnx_bytestream_size = internal_options.onnx_bytestream_size; trt_provider_options_v2.trt_op_types_to_exclude = copy_string_if_needed(internal_options.op_types_to_exclude); + trt_provider_options_v2.trt_preview_features = copy_string_if_needed(internal_options.preview_features); } } // namespace onnxruntime diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h index a6fda73b55529..139319829c210 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h @@ -61,6 +61,7 @@ struct TensorrtExecutionProviderInfo { std::string engine_cache_prefix{""}; bool engine_hw_compatible{false}; std::string op_types_to_exclude{""}; + std::string preview_features{""}; static TensorrtExecutionProviderInfo FromProviderOptions(const ProviderOptions& options); static ProviderOptions ToProviderOptions(const TensorrtExecutionProviderInfo& info); diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_provider_factory.cc b/onnxruntime/core/providers/tensorrt/tensorrt_provider_factory.cc index e4521ddd18ade..0d2e88d17519c 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_provider_factory.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_provider_factory.cc @@ -119,6 +119,7 @@ struct Tensorrt_Provider : Provider { info.onnx_bytestream = options.trt_onnx_bytestream; info.onnx_bytestream_size = options.trt_onnx_bytestream_size; info.op_types_to_exclude = options.trt_op_types_to_exclude == nullptr ? "" : options.trt_op_types_to_exclude; + info.preview_features = options.trt_preview_features == nullptr ? "" : options.trt_preview_features; return std::make_shared(info); } diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 5fd197d7a798b..ba90d55a6b8e8 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -1944,6 +1944,7 @@ OrtTensorRTProviderOptionsV2 OrtTensorRTProviderOptionsToOrtTensorRTProviderOpti trt_options_converted.trt_ep_context_embed_mode = 0; trt_options_converted.trt_engine_cache_prefix = ""; trt_options_converted.trt_engine_hw_compatible = 0; + trt_options_converted.trt_preview_features = ""; return trt_options_converted; } @@ -2609,6 +2610,7 @@ ORT_API(void, OrtApis::ReleaseTensorRTProviderOptions, _Frees_ptr_opt_ OrtTensor delete[] ptr->trt_ep_context_file_path; delete[] ptr->trt_onnx_model_folder_path; delete[] ptr->trt_op_types_to_exclude; + delete[] ptr->trt_preview_features; } std::unique_ptr p(ptr); diff --git a/onnxruntime/python/onnxruntime_pybind_state.cc b/onnxruntime/python/onnxruntime_pybind_state.cc index 9a9243e2750d6..975502063ac2a 100644 --- a/onnxruntime/python/onnxruntime_pybind_state.cc +++ b/onnxruntime/python/onnxruntime_pybind_state.cc @@ -526,7 +526,7 @@ std::unique_ptr CreateExecutionProviderInstance( // and TRT EP instance, so it won't be released.) std::string calibration_table, cache_path, cache_prefix, timing_cache_path, lib_path, trt_tactic_sources, trt_extra_plugin_lib_paths, min_profile, max_profile, opt_profile, ep_context_file_path, - onnx_model_folder_path, trt_op_types_to_exclude; + onnx_model_folder_path, trt_op_types_to_exclude, preview_features; auto it = provider_options_map.find(type); if (it != provider_options_map.end()) { OrtTensorRTProviderOptionsV2 params; @@ -827,6 +827,11 @@ std::unique_ptr CreateExecutionProviderInstance( } else if (option.first == "trt_op_types_to_exclude") { trt_op_types_to_exclude = option.second; params.trt_op_types_to_exclude = trt_op_types_to_exclude.c_str(); + } else if (option.first == "trt_preview_features") { + if (!option.second.empty()) { + preview_features = option.second; + params.trt_preview_features = preview_features.c_str(); + } } else { ORT_THROW("Invalid TensorRT EP option: ", option.first); } From 8465ca38546782531e79cc942eb22e3f2101cfe2 Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Fri, 4 Apr 2025 02:25:51 +0800 Subject: [PATCH 221/266] [webgpu] test_layer_normalization_3d_axis0_epsilon (#24276) This uses dummy override shapes to bypass the 'components' check. --- .../core/providers/webgpu/nn/layer_norm.cc | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc index 21ef3676244ec..1c35596ea0dc4 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc @@ -18,6 +18,13 @@ static size_t NormalizeAxis(int64_t axis, size_t tensor_rank) { return onnxruntime::narrow(axis < 0 ? axis + rank : axis); } +// Get a dummy override shape to bypass the program's check of shape and components for inputs and outputs. It's okay, +// as 'LayerNormProgram' doesn't actually use the override shape. +static TensorShape GetOverrideShape(const TensorShape& shape, int components) { + TensorShape override_shape{shape.Size() / components}; + return override_shape; +} + Status LayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); shader.AddInput("scale", ShaderUsage::UseUniform); @@ -111,11 +118,11 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex LayerNormProgram program{bias != nullptr, is_fp16, simplified, mean != nullptr, inv_std_dev != nullptr}; - program - .CacheHint(simplified) - .AddInputs({{x, ProgramTensorMetadataDependency::Type, components}}) - .AddInputs({{scale, ProgramTensorMetadataDependency::Type, components}}) - .AddOutputs({{y, ProgramTensorMetadataDependency::None, components}}) + program.CacheHint(simplified) + .AddInputs({{x, ProgramTensorMetadataDependency::Type, GetOverrideShape(x->Shape(), components), components}}) + .AddInputs( + {{scale, ProgramTensorMetadataDependency::Type, GetOverrideShape(scale->Shape(), components), components}}) + .AddOutputs({{y, ProgramTensorMetadataDependency::None, GetOverrideShape(y->Shape(), components), components}}) .SetDispatchGroupSize((norm_count + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) .AddUniformVariables({ {static_cast(norm_count)}, @@ -131,7 +138,8 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex }); if (bias != nullptr) { - program.AddInput({bias, ProgramTensorMetadataDependency::Type, components}); + program.AddInput( + {bias, ProgramTensorMetadataDependency::Type, GetOverrideShape(bias->Shape(), components), components}); } if (mean != nullptr) { From 7a551887a2021bc38406a891d51e4f469f1af348 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:37:46 -0700 Subject: [PATCH 222/266] [webgpu][dawn API optimization] reduce number of calls to wgpuDeviceHasFeature (#24281) ### Description This PR is one of a series of changes for optimization of Dawn API usage. Currently, the WebGPU EP has some suboptimal code paths that result in unnecessary Dawn API calls. Reducing the number of calls to those API will help improve the performance of the WebGPU EP, especially on WebAssembly. This PR optimizes the usage of `wgpuDeviceHasFeature`. --- onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc | 2 +- .../contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc | 2 +- onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc | 2 +- .../webgpu/quantization/subgroup_matrix_matmul_nbits.cc | 2 +- onnxruntime/core/providers/webgpu/compute_context.h | 4 ++-- onnxruntime/core/providers/webgpu/webgpu_context.cc | 6 ++++++ onnxruntime/core/providers/webgpu/webgpu_context.h | 2 ++ 7 files changed, 14 insertions(+), 6 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 52c705abb1003..26b08159a3b84 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -468,7 +468,7 @@ bool CanApplyFlashAttention(const Tensor* bias, const Tensor* present_key, const parameters.head_size_ == parameters.v_head_size_ && bias == nullptr && parameters.sequence_length_ > 1 && - context.Device().HasFeature(wgpu::FeatureName::Subgroups) && + context.HasFeature(wgpu::FeatureName::Subgroups) && present_key != nullptr && present_value != nullptr && present_key->SizeInBytes() > 0 && present_value->SizeInBytes() > 0 && parameters.head_size_ % 4 == 0; } diff --git a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc index 6d2370db853ee..ad8319aeff1ad 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/dp4a_matmul_nbits.cc @@ -444,7 +444,7 @@ bool CanApplyDP4AMatrixMatMulNBits(onnxruntime::webgpu::ComputeContext& context, bool has_zero_points) { // macOS - Avoid using dp4a on Metal, as it does not appear to have native dp4a support. // https://github.com/gpuweb/gpuweb/issues/2677#issuecomment-1713292226 - bool use_dp4a = context.Device().HasFeature(wgpu::FeatureName::Subgroups) && + bool use_dp4a = context.HasFeature(wgpu::FeatureName::Subgroups) && context.AdapterInfo().backendType != wgpu::BackendType::Metal; return (accuracy_level == 4 && block_size % 32 == 0 && batch_count == 1 && components_k == 4 && K % 128 == 0 && N % 16 == 0 && diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index be105a0fd4374..e8a15b8d47a56 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -572,7 +572,7 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context // TODO: Support output_number > 1. Some cases are failed when output_number > 1. constexpr uint32_t output_number = 1; const uint32_t tile_m = M > kMinMForTileOptimization ? 4 : 1; - const bool has_subgroup = context.Device().HasFeature(wgpu::FeatureName::Subgroups); + const bool has_subgroup = context.HasFeature(wgpu::FeatureName::Subgroups); const bool use_subgroup = has_subgroup && context.AdapterInfo().vendor == std::string_view{"intel"} && components_a == 4 && block_size == 32; MatMulNBitsProgram program{output_number, block_size, tile_m, static_cast(components_b), has_zero_points, use_subgroup}; if (M > kMinMForTileOptimization && block_size == 32) { diff --git a/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc index cb024d2a758a9..b1dce049214eb 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/subgroup_matrix_matmul_nbits.cc @@ -203,7 +203,7 @@ bool CanApplySubgroupMatrixMatMulNBits(onnxruntime::webgpu::ComputeContext& cont uint32_t K, bool has_zero_points) { #if !defined(__wasm__) - const bool has_subgroup_matrix = context.Device().HasFeature(wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix); + const bool has_subgroup_matrix = context.HasFeature(wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix); #else const bool has_subgroup_matrix = false; #endif diff --git a/onnxruntime/core/providers/webgpu/compute_context.h b/onnxruntime/core/providers/webgpu/compute_context.h index 23fa10a0d5489..3117208c7be7d 100644 --- a/onnxruntime/core/providers/webgpu/compute_context.h +++ b/onnxruntime/core/providers/webgpu/compute_context.h @@ -37,8 +37,8 @@ class ComputeContext { inline const wgpu::Limits& DeviceLimits() const { return webgpu_context_.DeviceLimits(); } - inline const wgpu::Device& Device() const { - return webgpu_context_.Device(); + inline bool HasFeature(wgpu::FeatureName feature) const { + return webgpu_context_.DeviceHasFeature(feature); } // diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 0471e08c4a215..955b54e873261 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -140,6 +140,12 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi ORT_ENFORCE(Device().GetAdapterInfo(&adapter_info_)); // cache device limits ORT_ENFORCE(Device().GetLimits(&device_limits_)); + // cache device features + wgpu::SupportedFeatures supported_features; + Device().GetFeatures(&supported_features); + for (size_t i = 0; i < supported_features.featureCount; i++) { + device_features_.insert(supported_features.features[i]); + } #if !defined(__wasm__) supports_buffer_map_extended_usages_ = device_.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages); diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 11e388a22e03f..2f044400afee2 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -80,6 +80,7 @@ class WebGpuContext final { const wgpu::AdapterInfo& AdapterInfo() const { return adapter_info_; } const wgpu::Limits& DeviceLimits() const { return device_limits_; } + bool DeviceHasFeature(wgpu::FeatureName feature) const { return device_features_.find(feature) != device_features_.end(); } const wgpu::CommandEncoder& GetCommandEncoder() { if (!current_command_encoder_) { @@ -208,6 +209,7 @@ class WebGpuContext final { wgpu::AdapterInfo adapter_info_; wgpu::Limits device_limits_; + std::unordered_set device_features_; wgpu::CommandEncoder current_command_encoder_; wgpu::ComputePassEncoder current_compute_pass_encoder_; From d23881358ea8ffcc454f2642dabc101dce6c5889 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:38:30 -0700 Subject: [PATCH 223/266] Bump next from 15.2.3 to 15.2.4 in /js/web/test/e2e/exports/testcases/nextjs-default (#24283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [next](https://github.com/vercel/next.js) from 15.2.3 to 15.2.4.
Release notes

Sourced from next's releases.

v15.2.4

[!NOTE]
This release is backporting bug fixes. It does not include all pending features/changes on canary.

Core Changes

  • Match subrequest handling for edge and node (#77474)
  • exclude images and static media from dev origin check (#77417)
  • ensure /__next middleware URLs are included in the origin check (#77416)
  • remove direct ip/port bypass in dev origin check (#77414)
  • switch development origin verification to be opt-in rather than opt-out (#77395)

Credits

Huge thanks to @​ijjk and @​ztanner for helping!

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=next&package-manager=npm_and_yarn&previous-version=15.2.3&new-version=15.2.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../nextjs-default/package-lock.json | 80 +++++++++---------- .../testcases/nextjs-default/package.json | 2 +- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json b/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json index 11a5c1ac3f2ee..6f749319def3d 100644 --- a/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json +++ b/js/web/test/e2e/exports/testcases/nextjs-default/package-lock.json @@ -8,7 +8,7 @@ "name": "nextjs-default", "version": "0.1.0", "dependencies": { - "next": "15.2.3", + "next": "15.2.4", "react": "^19.0.0", "react-dom": "^19.0.0" } @@ -385,15 +385,15 @@ } }, "node_modules/@next/env": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.3.tgz", - "integrity": "sha512-a26KnbW9DFEUsSxAxKBORR/uD9THoYoKbkpFywMN/AFvboTt94b8+g/07T8J6ACsdLag8/PDU60ov4rPxRAixw==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.4.tgz", + "integrity": "sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==", "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.3.tgz", - "integrity": "sha512-uaBhA8aLbXLqwjnsHSkxs353WrRgQgiFjduDpc7YXEU0B54IKx3vU+cxQlYwPCyC8uYEEX7THhtQQsfHnvv8dw==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.4.tgz", + "integrity": "sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw==", "cpu": [ "arm64" ], @@ -407,9 +407,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.3.tgz", - "integrity": "sha512-pVwKvJ4Zk7h+4hwhqOUuMx7Ib02u3gDX3HXPKIShBi9JlYllI0nU6TWLbPT94dt7FSi6mSBhfc2JrHViwqbOdw==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.4.tgz", + "integrity": "sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew==", "cpu": [ "x64" ], @@ -423,9 +423,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.3.tgz", - "integrity": "sha512-50ibWdn2RuFFkOEUmo9NCcQbbV9ViQOrUfG48zHBCONciHjaUKtHcYFiCwBVuzD08fzvzkWuuZkd4AqbvKO7UQ==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.4.tgz", + "integrity": "sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ==", "cpu": [ "arm64" ], @@ -439,9 +439,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.3.tgz", - "integrity": "sha512-2gAPA7P652D3HzR4cLyAuVYwYqjG0mt/3pHSWTCyKZq/N/dJcUAEoNQMyUmwTZWCJRKofB+JPuDVP2aD8w2J6Q==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.4.tgz", + "integrity": "sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA==", "cpu": [ "arm64" ], @@ -455,9 +455,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.3.tgz", - "integrity": "sha512-ODSKvrdMgAJOVU4qElflYy1KSZRM3M45JVbeZu42TINCMG3anp7YCBn80RkISV6bhzKwcUqLBAmOiWkaGtBA9w==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.4.tgz", + "integrity": "sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw==", "cpu": [ "x64" ], @@ -471,9 +471,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.3.tgz", - "integrity": "sha512-ZR9kLwCWrlYxwEoytqPi1jhPd1TlsSJWAc+H/CJHmHkf2nD92MQpSRIURR1iNgA/kuFSdxB8xIPt4p/T78kwsg==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.4.tgz", + "integrity": "sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw==", "cpu": [ "x64" ], @@ -487,9 +487,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.3.tgz", - "integrity": "sha512-+G2FrDcfm2YDbhDiObDU/qPriWeiz/9cRR0yMWJeTLGGX6/x8oryO3tt7HhodA1vZ8r2ddJPCjtLcpaVl7TE2Q==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.4.tgz", + "integrity": "sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg==", "cpu": [ "arm64" ], @@ -503,9 +503,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.3.tgz", - "integrity": "sha512-gHYS9tc+G2W0ZC8rBL+H6RdtXIyk40uLiaos0yj5US85FNhbFEndMA2nW3z47nzOWiSvXTZ5kBClc3rD0zJg0w==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.4.tgz", + "integrity": "sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ==", "cpu": [ "x64" ], @@ -651,12 +651,12 @@ } }, "node_modules/next": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/next/-/next-15.2.3.tgz", - "integrity": "sha512-x6eDkZxk2rPpu46E1ZVUWIBhYCLszmUY6fvHBFcbzJ9dD+qRX6vcHusaqqDlnY+VngKzKbAiG2iRCkPbmi8f7w==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/next/-/next-15.2.4.tgz", + "integrity": "sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==", "license": "MIT", "dependencies": { - "@next/env": "15.2.3", + "@next/env": "15.2.4", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -671,14 +671,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.2.3", - "@next/swc-darwin-x64": "15.2.3", - "@next/swc-linux-arm64-gnu": "15.2.3", - "@next/swc-linux-arm64-musl": "15.2.3", - "@next/swc-linux-x64-gnu": "15.2.3", - "@next/swc-linux-x64-musl": "15.2.3", - "@next/swc-win32-arm64-msvc": "15.2.3", - "@next/swc-win32-x64-msvc": "15.2.3", + "@next/swc-darwin-arm64": "15.2.4", + "@next/swc-darwin-x64": "15.2.4", + "@next/swc-linux-arm64-gnu": "15.2.4", + "@next/swc-linux-arm64-musl": "15.2.4", + "@next/swc-linux-x64-gnu": "15.2.4", + "@next/swc-linux-x64-musl": "15.2.4", + "@next/swc-win32-arm64-msvc": "15.2.4", + "@next/swc-win32-x64-msvc": "15.2.4", "sharp": "^0.33.5" }, "peerDependencies": { diff --git a/js/web/test/e2e/exports/testcases/nextjs-default/package.json b/js/web/test/e2e/exports/testcases/nextjs-default/package.json index 9bad599248259..297b4b56e9bb7 100644 --- a/js/web/test/e2e/exports/testcases/nextjs-default/package.json +++ b/js/web/test/e2e/exports/testcases/nextjs-default/package.json @@ -11,6 +11,6 @@ "dependencies": { "react": "^19.0.0", "react-dom": "^19.0.0", - "next": "15.2.3" + "next": "15.2.4" } } From cbaa8bc78d3dea49f8dc208942032e66a76f0f41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:28:53 -0700 Subject: [PATCH 224/266] Bump image-size from 1.1.1 to 1.2.1 in /js/react_native/e2e (#24278) Bumps [image-size](https://github.com/image-size/image-size) from 1.1.1 to 1.2.1.
Release notes

Sourced from image-size's releases.

v1.2.1

Fixes

Full Changelog: https://github.com/image-size/image-size/compare/v1.2.0...v1.2.1

v1.2.0

This release adds support for JPEG-XL ( #409 )

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=image-size&package-manager=npm_and_yarn&previous-version=1.1.1&new-version=1.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- js/react_native/e2e/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/react_native/e2e/package-lock.json b/js/react_native/e2e/package-lock.json index 2907534fdddd1..fff331486dfc1 100644 --- a/js/react_native/e2e/package-lock.json +++ b/js/react_native/e2e/package-lock.json @@ -7643,9 +7643,9 @@ } }, "node_modules/image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", "license": "MIT", "dependencies": { "queue": "6.0.2" From a28da4b90a17c9729c9448c5702c302e3bd2566b Mon Sep 17 00:00:00 2001 From: quic-zhaoxul Date: Fri, 4 Apr 2025 04:30:53 +0800 Subject: [PATCH 225/266] [QNN-EP] Enhance QNN-EP support for Softmax with opset < 13. (#24180) ### Description - Add support to Softmax operator with opset < 13 to op builder in QNN-EP. ### Motivation and Context - Enhance QNN-EP support for Softmax with opset < 13. --- .../builder/opbuilder/softmax_op_builder.cc | 277 ++++++++++-------- .../test/providers/qnn/simple_op_htp_test.cc | 16 +- 2 files changed, 170 insertions(+), 123 deletions(-) diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/softmax_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/softmax_op_builder.cc index 7326523737383..e8acaf75143d8 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/softmax_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/softmax_op_builder.cc @@ -1,6 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include +#include +#include +#include +#include + #include "core/providers/qnn/builder/opbuilder/base_op_builder.h" #include "core/providers/qnn/builder/qnn_utils.h" #include "core/providers/qnn/builder/qnn_model_wrapper.h" @@ -14,10 +20,6 @@ class SoftmaxOpBuilder : public BaseOpBuilder { SoftmaxOpBuilder() : BaseOpBuilder("SoftmaxOpBuilder") {} ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(SoftmaxOpBuilder); - Status IsOpSupported(QnnModelWrapper& qnn_model_wrapper, - const NodeUnit& node_unit, - const logging::Logger& logger) const override final ORT_MUST_USE_RESULT; - protected: Status ProcessInputs(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit, @@ -37,34 +39,24 @@ constexpr int32_t GetDefaultAxisAttribute(int opset_version) { return opset_version < 13 ? 1 : -1; } -Status SoftmaxOpBuilder::IsOpSupported(QnnModelWrapper& qnn_model_wrapper, - const NodeUnit& node_unit, - const logging::Logger& logger) const { - ORT_UNUSED_PARAMETER(logger); - const int opset_version = node_unit.SinceVersion(); +std::vector FlattenShapeFromAxis(std::vector& input_shape, int32_t axis) { + /* + Return the shape with all dimensions multiplied onward from the specified axis. If axis is 0, the returned shape + will include an additional batch of size 1 as the first dimension. + */ + assert(axis >= 0 && axis < input_shape.size()); + std::vector output_shape(input_shape.begin(), input_shape.begin() + axis); - // The QNN HTP backend only supports an `axis` attribute that refers to the last input dimension. - // QNN EP is able to support arbitrary axis attributes by wrapping the QNN operator with transposes. - // However, the exception is Softmax/LogSoftmax with opset < 13. For these older ONNX operators, only - // axis == input_rank - 1 is supported. - if (opset_version < 13) { - const std::string& op_type = node_unit.OpType(); - - int32_t axis = GetDefaultAxisAttribute(opset_version); - Qnn_Scalar_t axis_qnn_scalar = QNN_SCALAR_INIT; - ORT_RETURN_IF_ERROR(ProcessAxisAttribute(qnn_model_wrapper, node_unit, axis_qnn_scalar, axis)); - std::vector input_shape; - ORT_RETURN_IF_NOT(qnn_model_wrapper.GetOnnxShape(node_unit.Inputs()[0].node_arg, input_shape), - "QNN EP: Cannot get shape for Softmax input"); - ORT_RETURN_IF(axis != static_cast(input_shape.size() - 1), - "QNN ", op_type.c_str(), - " only supports an `axis` attribute equal to input_rank-1 (or -1) for ONNX opset < 13"); + if (axis == 0) { + output_shape.push_back(1); // Additional batch included } + output_shape.push_back( + std::accumulate(input_shape.begin() + axis, input_shape.end(), 1, std::multiplies())); - return AddToModelBuilder(qnn_model_wrapper, node_unit, logger, true); + return output_shape; } -static std::vector GetTransposePermToUseLastAxis(uint32_t input_rank, uint32_t axis) { +std::vector GetTransposePermToUseLastAxis(uint32_t input_rank, uint32_t axis) { assert(axis < input_rank); std::vector transpose_perm; transpose_perm.reserve(input_rank); @@ -87,58 +79,84 @@ Status SoftmaxOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, bool do_op_validation) const { const bool is_npu_backend = IsNpuBackend(qnn_model_wrapper.GetQnnBackendType()); const auto& inputs = node_unit.Inputs(); + const std::string& input_name = inputs[0].node_arg.Name(); assert(inputs.size() == 1); - int32_t axis = GetDefaultAxisAttribute(node_unit.SinceVersion()); + const int opset_version = node_unit.SinceVersion(); + int32_t axis = GetDefaultAxisAttribute(opset_version); Qnn_Scalar_t axis_qnn_scalar = QNN_SCALAR_INIT; ORT_RETURN_IF_ERROR(ProcessAxisAttribute(qnn_model_wrapper, node_unit, axis_qnn_scalar, axis)); TensorInfo input_info = {}; ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(inputs[0], input_info)); - const size_t input_rank = input_info.shape.size(); - - // If the axis attribute refers to the last dimension, then process the input as normal. - if (!is_npu_backend || axis == static_cast(input_rank) - 1) { - return ProcessInput(qnn_model_wrapper, inputs[0], logger, input_names); - } - - // - // The axis does **not** refer to the last input dimension. Must wrap transposes around the operator to be able to use - // QNN's Softmax operator, which always uses an axis value that refers to the last dimension. - // - - std::vector transpose_perm = GetTransposePermToUseLastAxis(static_cast(input_rank), - static_cast(axis)); - - const std::string& input_name = inputs[0].node_arg.Name(); - std::string op_input_name = input_info.is_initializer ? input_name : input_name + "_ort_qnn_ep_transpose"; - input_names.push_back(op_input_name); - - std::vector op_input_shape = input_info.shape; - op_input_shape[input_rank - 1] = input_info.shape[axis]; - op_input_shape[axis] = input_info.shape[input_rank - 1]; - + size_t input_rank = input_info.shape.size(); ORT_RETURN_IF(input_info.is_initializer, "QNN EP does not support (Log)Softmax with an initializer input, ", "which should be optimized away by the ORT optimizer"); - // Input is dynamic, so add transpose node before input. - const bool is_graph_input = qnn_model_wrapper.IsGraphInput(input_name); - - ORT_RETURN_IF_ERROR(qnn_model_wrapper.AddTransposeNode(node_unit.Index(), - input_name, - op_input_name, + if (opset_version < 13) { + /* + For Onnx Softmax with opset < 13, its behavior is to flatten the input starting from the axis, and perform + softmax operation along the axis dimension, then reshape back to the original input shape. + QNN EP is able to support arbitrary axis attribute by wrapping reshapes around the operator. + + Here provides an example: + Given an input with shape=(3, 4, 5) and axis=1. Its behavior is to reshape the input to (3, 20), perform softmax, + and then reshape back to (3, 4, 5). + + When axis equals 0, the reshape output shape includes an additional batch of size 1 as the first dimension. + Here provides an example: + Given an input with shape=(3, 4, 5) and axis=0. Its behavior is to reshape the input to (1, 60), perform softmax, + and then reshape back to (3, 4, 5). + */ + std::string reshape_output_name = input_name + "_ort_qnn_ep_reshape"; + std::vector reshape_output_shape = FlattenShapeFromAxis(input_info.shape, axis); + + // Input is dynamic, so add reshape node before input. + const bool is_graph_input = qnn_model_wrapper.IsGraphInput(input_name); + + ORT_RETURN_IF_ERROR(qnn_model_wrapper.AddReshapeNode(input_name, + reshape_output_name, input_info.shape, - transpose_perm, - op_input_shape, + reshape_output_shape, input_info.qnn_data_type, input_info.quant_param, do_op_validation, - is_graph_input)); - - Qnn_TensorType_t tensor_type = qnn_model_wrapper.GetTensorType(op_input_name); - QnnTensorWrapper input_tensorwrapper(op_input_name, tensor_type, input_info.qnn_data_type, - std::move(input_info.quant_param), std::move(op_input_shape), {}); - ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(input_tensorwrapper)), "Failed to add tensor."); + is_graph_input, + false)); + input_names.push_back(reshape_output_name); + } else if (is_npu_backend && axis != static_cast(input_rank) - 1) { + /* + For Onnx Softmax with opset >= 13, the QNN HTP backend only supports the axis attribute that refers to the last + input dimension. + QNN EP is able to support arbitrary axis attribute by wrapping transposes around the operator. + */ + std::string transpose_output_name = input_name + "_ort_qnn_ep_transpose"; + std::vector transpose_perm = GetTransposePermToUseLastAxis(static_cast(input_rank), + static_cast(axis)); + + std::vector transpose_output_shape = input_info.shape; + transpose_output_shape[input_rank - 1] = input_info.shape[axis]; + transpose_output_shape[axis] = input_info.shape[input_rank - 1]; + + // Input is dynamic, so add transpose node before input. + const bool is_graph_input = qnn_model_wrapper.IsGraphInput(input_name); + + ORT_RETURN_IF_ERROR(qnn_model_wrapper.AddTransposeNode(node_unit.Index(), + input_name, + transpose_output_name, + input_info.shape, + transpose_perm, + transpose_output_shape, + input_info.qnn_data_type, + input_info.quant_param, + do_op_validation, + is_graph_input, + false)); + input_names.push_back(transpose_output_name); + } else { + // Process the input as normal. + return ProcessInput(qnn_model_wrapper, inputs[0], logger, input_names); + } return Status::OK(); } @@ -151,76 +169,105 @@ Status SoftmaxOpBuilder::ProcessAttributesAndOutputs(QnnModelWrapper& qnn_model_ const bool is_npu_backend = IsNpuBackend(qnn_model_wrapper.GetQnnBackendType()); const std::string& op_type = node_unit.OpType(); const auto& outputs = node_unit.Outputs(); + const std::string& orig_output_name = outputs[0].node_arg.Name(); assert(outputs.size() == 1); - int32_t axis = GetDefaultAxisAttribute(node_unit.SinceVersion()); + const int opset_version = node_unit.SinceVersion(); + int32_t axis = GetDefaultAxisAttribute(opset_version); Qnn_Scalar_t axis_qnn_scalar = QNN_SCALAR_INIT; ORT_RETURN_IF_ERROR(ProcessAxisAttribute(qnn_model_wrapper, node_unit, axis_qnn_scalar, axis)); TensorInfo output_info = {}; ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(outputs[0], output_info)); - const size_t output_rank = output_info.shape.size(); - const bool axis_is_last_dim = static_cast(axis) == output_rank - 1; + size_t output_rank = output_info.shape.size(); - // If axis refers to the last dimension, process outputs as usual. - if (!is_npu_backend || axis_is_last_dim) { - QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), QNN_OP_SOFTMAX_PARAM_AXIS, axis_qnn_scalar); + if (opset_version < 13) { + std::string reshape_input_name = orig_output_name + "_ort_qnn_ep_reshape"; + + std::vector reshape_input_shape = FlattenShapeFromAxis(output_info.shape, axis); + if (axis == 0) { + // Override axis due to the inserted batch=1 to the first dimension + axis_qnn_scalar.uint32Value = 1; + } + QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), QNN_OP_SOFTMAX_PARAM_AXIS, axis_qnn_scalar); std::vector param_tensor_names; param_tensor_names.push_back(axis_param.GetParamTensorName()); qnn_model_wrapper.AddParamWrapper(std::move(axis_param)); - return ProcessOutputs(qnn_model_wrapper, node_unit, - std::move(input_names), - std::move(param_tensor_names), - logger, do_op_validation, GetQnnOpType(op_type)); - } - - // - // The axis **does** not refer to the last dimension. Must wrap the operator with Transposes to be able to use - // QNN's Softmax operator, which only supports an axis that refers to the last dimension. - // - - axis_qnn_scalar.uint32Value = static_cast(output_rank - 1); // NOTE: override axis. - QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), QNN_OP_SOFTMAX_PARAM_AXIS, axis_qnn_scalar); - - std::vector param_tensor_names; - param_tensor_names.push_back(axis_param.GetParamTensorName()); - qnn_model_wrapper.AddParamWrapper(std::move(axis_param)); - - const std::string& orig_output_name = outputs[0].node_arg.Name(); - std::string op_output_name = orig_output_name + "_ort_qnn_ep_transpose"; - - std::vector op_output_shape = output_info.shape; - op_output_shape[output_rank - 1] = output_info.shape[axis]; - op_output_shape[axis] = output_info.shape[output_rank - 1]; - - QnnTensorWrapper output_tensorwrapper(op_output_name, QNN_TENSOR_TYPE_NATIVE, output_info.qnn_data_type, - output_info.quant_param.Copy(), std::vector(op_output_shape)); - ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(output_tensorwrapper)), "Failed to add tensor."); - ORT_RETURN_IF_NOT(qnn_model_wrapper.CreateQnnNode(utils::GetNodeName(node_unit), - QNN_OP_PACKAGE_NAME_QTI_AISW, - GetQnnOpType(node_unit.OpType()), - std::move(input_names), - {op_output_name}, - std::move(param_tensor_names)), - "Failed to add node."); - - const bool is_graph_output = qnn_model_wrapper.IsGraphOutput(orig_output_name); - std::vector transpose_perm = GetTransposePermToUseLastAxis(static_cast(output_rank), - static_cast(axis)); - - ORT_RETURN_IF_ERROR(qnn_model_wrapper.AddTransposeNode(node_unit.Index(), - op_output_name, + QnnTensorWrapper output_tensorwrapper(reshape_input_name, QNN_TENSOR_TYPE_NATIVE, output_info.qnn_data_type, + output_info.quant_param.Copy(), std::vector(reshape_input_shape)); + ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(output_tensorwrapper)), "Failed to add tensor."); + ORT_RETURN_IF_NOT(qnn_model_wrapper.CreateQnnNode(utils::GetNodeName(node_unit), + QNN_OP_PACKAGE_NAME_QTI_AISW, + GetQnnOpType(node_unit.OpType()), + std::move(input_names), + {reshape_input_name}, + std::move(param_tensor_names)), + "Failed to add node."); + + const bool is_graph_output = qnn_model_wrapper.IsGraphOutput(orig_output_name); + ORT_RETURN_IF_ERROR(qnn_model_wrapper.AddReshapeNode(reshape_input_name, orig_output_name, - op_output_shape, - transpose_perm, + reshape_input_shape, output_info.shape, output_info.qnn_data_type, output_info.quant_param, do_op_validation, false, is_graph_output)); + } else if (is_npu_backend && axis != static_cast(output_rank) - 1) { + std::string transpose_input_name = orig_output_name + "_ort_qnn_ep_transpose"; + + std::vector transpose_input_shape = output_info.shape; + transpose_input_shape[output_rank - 1] = output_info.shape[axis]; + transpose_input_shape[axis] = output_info.shape[output_rank - 1]; + + // Override axis due to the actual shape after the inserted transpose node + axis_qnn_scalar.uint32Value = static_cast(output_rank) - 1; + + QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), QNN_OP_SOFTMAX_PARAM_AXIS, axis_qnn_scalar); + std::vector param_tensor_names; + param_tensor_names.push_back(axis_param.GetParamTensorName()); + qnn_model_wrapper.AddParamWrapper(std::move(axis_param)); + + QnnTensorWrapper output_tensorwrapper(transpose_input_name, QNN_TENSOR_TYPE_NATIVE, output_info.qnn_data_type, + output_info.quant_param.Copy(), std::vector(transpose_input_shape)); + ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(output_tensorwrapper)), "Failed to add tensor."); + ORT_RETURN_IF_NOT(qnn_model_wrapper.CreateQnnNode(utils::GetNodeName(node_unit), + QNN_OP_PACKAGE_NAME_QTI_AISW, + GetQnnOpType(node_unit.OpType()), + std::move(input_names), + {transpose_input_name}, + std::move(param_tensor_names)), + "Failed to add node."); + + const bool is_graph_output = qnn_model_wrapper.IsGraphOutput(orig_output_name); + std::vector transpose_perm = GetTransposePermToUseLastAxis(static_cast(output_rank), + static_cast(axis)); + + ORT_RETURN_IF_ERROR(qnn_model_wrapper.AddTransposeNode(node_unit.Index(), + transpose_input_name, + orig_output_name, + transpose_input_shape, + transpose_perm, + output_info.shape, + output_info.qnn_data_type, + output_info.quant_param, + do_op_validation, + false, + is_graph_output)); + } else { + QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), QNN_OP_SOFTMAX_PARAM_AXIS, axis_qnn_scalar); + std::vector param_tensor_names; + param_tensor_names.push_back(axis_param.GetParamTensorName()); + qnn_model_wrapper.AddParamWrapper(std::move(axis_param)); + + return ProcessOutputs(qnn_model_wrapper, node_unit, + std::move(input_names), + std::move(param_tensor_names), + logger, do_op_validation, GetQnnOpType(op_type)); + } return Status::OK(); } diff --git a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc index f9c9e0f709495..0eec5f800916f 100644 --- a/onnxruntime/test/providers/qnn/simple_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/simple_op_htp_test.cc @@ -555,18 +555,18 @@ TEST_F(QnnHTPBackendTests, UnaryOp_Softmax13_U16_NonLastAxis_LargeInput) { } // Check that QNN compiles DQ -> Softmax -> Q as a single unit. -// Test that the default axis (1) for SoftMax opset < 13 does not work. -TEST_F(QnnHTPBackendTests, UnaryOp_Softmax11_DefaultAxisFails) { +// Test that the default axis (1) for SoftMax opset < 13 works. +TEST_F(QnnHTPBackendTests, UnaryOp_Softmax11_DefaultAxis) { RunQDQOpTest("Softmax", {TestInputDef({1, 2, 3}, false, -5.0f, 5.0f)}, {}, // Uses default axis of 1 for opset < 13. 11, - ExpectedEPNodeAssignment::None); + ExpectedEPNodeAssignment::All); } // Check that QNN compiles DQ -> Softmax -> Q as a single unit. // Test that setting an axis value of -1 works for Softmax opset < 13. -TEST_F(QnnHTPBackendTests, UnaryOp_Softmax11_SetValidAxis) { +TEST_F(QnnHTPBackendTests, UnaryOp_Softmax11_SetAxis) { RunQDQOpTest("Softmax", {TestInputDef({1, 2, 3}, false, -5.0f, 5.0f)}, {utils::MakeAttribute("axis", static_cast(-1))}, @@ -597,19 +597,19 @@ TEST_F(QnnHTPBackendTests, UnaryOp_LogSoftmax13_NonLastAxis) { } // Check that QNN compiles DQ -> LogSoftmax -> Q as a single unit. -// Test that the default axis (1) for LogSoftmax opset < 13 does not work. -TEST_F(QnnHTPBackendTests, UnaryOp_LogSoftmax11_DefaultAxisFails) { +// Test that the default axis (1) for LogSoftmax opset < 13 works. +TEST_F(QnnHTPBackendTests, UnaryOp_LogSoftmax11_DefaultAxis) { std::vector input_data = GetFloatDataInRange(-5.0f, 5.0f, 6); RunQDQOpTest("LogSoftmax", {TestInputDef({1, 2, 3}, false, input_data)}, {}, // Uses default axis of 1 for opset < 13. 11, - ExpectedEPNodeAssignment::None); + ExpectedEPNodeAssignment::All); } // Check that QNN compiles DQ -> LogSoftmax -> Q as a single unit. // Test that setting an axis value of -1 works for LogSoftmax opset < 13. -TEST_F(QnnHTPBackendTests, UnaryOp_LogSoftmax11_SetValidAxis) { +TEST_F(QnnHTPBackendTests, UnaryOp_LogSoftmax11_SetAxis) { std::vector input_data = GetFloatDataInRange(-5.0f, 5.0f, 6); RunQDQOpTest("LogSoftmax", {TestInputDef({1, 2, 3}, false, input_data)}, From e5e906ee9cfbe1a1b9d155b7a9dd6abe50a9e18b Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 3 Apr 2025 21:09:56 -0400 Subject: [PATCH 226/266] Update publish-nuget.yml to correct feed. (#24299) ### Description Since we are no longer supporting cuda 11, we want to update the `publish-nuget.ym`l to the correct feed. ### Motivation and Context --- tools/ci_build/github/azure-pipelines/publish-nuget.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/publish-nuget.yml b/tools/ci_build/github/azure-pipelines/publish-nuget.yml index 7ad0aa3b95d9d..ace0d62204551 100644 --- a/tools/ci_build/github/azure-pipelines/publish-nuget.yml +++ b/tools/ci_build/github/azure-pipelines/publish-nuget.yml @@ -21,9 +21,9 @@ parameters: variables: - name: ArtifactFeed ${{ if eq(parameters.isReleaseBuild, false) }}: - value: ort-cuda-11-nightly + value: ORT-Nightly ${{ else }}: - value: onnxruntime-cuda-11 + value: onnxruntime-cuda-12 extends: # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. # For non-production pipelines, use "Unofficial" as defined below. From 3dfc2ae346bd89de97efbb9acee6f42a90be6c06 Mon Sep 17 00:00:00 2001 From: Jianhui Dai Date: Fri, 4 Apr 2025 09:47:17 +0800 Subject: [PATCH 227/266] [webgpu] Optimize MatMulNBits for f16 Block32 prefill performance (#23908) ### Description This commit improve the MatMulNBits f16 Block32 prefill performance, by increasing tiling size and enhancing memory efficiency. Achieved a +2x performance boost on Intel iGPUs for Phi-3.5-mini f16 model. ### Motivation and Context See above. --- .../webgpu/quantization/matmul_nbits.cc | 154 ++++++++++++++++++ .../webgpu/quantization/matmul_nbits.h | 13 ++ 2 files changed, 167 insertions(+) diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc index e8a15b8d47a56..0e75990045b4a 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.cc @@ -523,6 +523,125 @@ Status MatMulNBitsProgram::GenerateShaderCode(ShaderHelper& shader) const { return Status::OK(); } +Status MatMulNBitsWideTileProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& a = shader.AddInput("input_a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& b = shader.AddInput("input_b", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& scales = shader.AddInput("scales", ShaderUsage::UseUniform); + const auto& y = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias | ShaderUsage::UseIndicesTypeAlias); + + // Bock size 32, `a` component size 4, 8 `a` components per block. + constexpr uint32_t kAComponentsForBlock32 = 8; + + const uint32_t workgroup_size = WorkgroupSizeX() * WorkgroupSizeY(); + ORT_ENFORCE(tile_m_ == workgroup_size / 8, "tile_m must be workgroup_size / 8."); + ORT_ENFORCE(tile_n_ == workgroup_size, "tile_n must be workgroup_size."); + + // memory read/write helpers + shader.AdditionalImplementation() << "fn mm_read_a(batch : u32, row : u32, col : u32) -> input_a_value_t {\n"; + shader.AdditionalImplementation() << " if (row < uniforms.input_a_shape[1] && col < uniforms.input_a_shape[2]) {\n"; + shader.AdditionalImplementation() << " return " << a.GetByIndices("input_a_indices_t(batch, row, col)") << ";\n"; + shader.AdditionalImplementation() << " }\n"; + shader.AdditionalImplementation() << " return input_a_value_t(0);\n"; + shader.AdditionalImplementation() << "}\n"; + + shader.AdditionalImplementation() << "\n"; + shader.AdditionalImplementation() << "fn mm_read_b(row : u32, col : u32) -> input_b_value_t {\n"; + shader.AdditionalImplementation() << " if (row < uniforms.input_b_shape[0] && col < uniforms.input_b_shape[1]) {\n"; + shader.AdditionalImplementation() << " return " << b.GetByIndices("input_b_indices_t(row, col, 0)") << ";\n"; + shader.AdditionalImplementation() << " }\n"; + shader.AdditionalImplementation() << " return input_b_value_t(0);\n"; + shader.AdditionalImplementation() << "}\n"; + + shader.AdditionalImplementation() << "\n"; + shader.AdditionalImplementation() << "fn mm_read_scale(row : u32, col : u32) -> output_value_t {\n"; + shader.AdditionalImplementation() << " if (row < uniforms.input_b_shape[0] && col < uniforms.input_b_shape[1]) {\n"; + shader.AdditionalImplementation() << " return " << scales.GetByOffset("row * uniforms.input_b_shape[1] + col") << ";\n"; + shader.AdditionalImplementation() << " }\n"; + shader.AdditionalImplementation() << " return output_value_t(0);\n"; + shader.AdditionalImplementation() << "}\n"; + + shader.AdditionalImplementation() << "\n"; + shader.AdditionalImplementation() << "fn mm_write_y(batch : u32, row : u32, col : u32, value : output_value_t) {\n"; + shader.AdditionalImplementation() << " if (row < uniforms.output_shape[1] && col < uniforms.output_shape[2]) {\n"; + shader.AdditionalImplementation() << " " << y.SetByIndices("output_indices_t(batch, row, col)", "value") << "\n"; + shader.AdditionalImplementation() << " }\n"; + shader.AdditionalImplementation() << "}\n"; + + // declare const variables + shader.AdditionalImplementation() << "\n"; + shader.AdditionalImplementation() << "// A block32 containing 8 components of `a`." << "\n"; + shader.AdditionalImplementation() << "const kAComponentsForBlock32 = " << kAComponentsForBlock32 << "u;\n"; + shader.AdditionalImplementation() << "const tile_m = " << tile_m_ << "u;\n"; + shader.AdditionalImplementation() << "const tile_n = " << tile_n_ << "u;\n"; + + // declare workgroup memory + shader.AdditionalImplementation() << "\n"; + shader.AdditionalImplementation() << "var a_data_tile: array, tile_m>;\n"; + shader.AdditionalImplementation() << "\n"; + + // main + shader.MainFunctionBody() << R"MAIN_FN( + let batch = workgroup_id.z; + let row = workgroup_id.y * tile_m; + let col = workgroup_id.x * tile_n; + + let a_elements_per_col = uniforms.input_a_shape[2]; + let a_blocks_per_col = (a_elements_per_col + kAComponentsForBlock32 - 1) / kAComponentsForBlock32; + + // Utilizing an f32 accumulator mitigated precision loss with minimal + // performance impact compared to an f16 accumulator. + var results : array; + for (var a_block_idx = 0u; a_block_idx < a_blocks_per_col; a_block_idx++) { + // Load `a` elements into workgroup memory, TileM x kAComponentsForBlock32 (block32) + let a_row_idx = local_idx / kAComponentsForBlock32; + let a_col_idx = local_idx % kAComponentsForBlock32; + a_data_tile[a_row_idx][a_col_idx] = mm_read_a(batch, row + a_row_idx, a_block_idx * kAComponentsForBlock32 + a_col_idx); + workgroupBarrier(); + + let b_row = col + local_idx; + let b_col = a_block_idx; + + let b_data = mm_read_b(b_row, b_col); + let scale = mm_read_scale(b_row, b_col); + let zero_point = output_element_t(8.0); + + // `b` component size is 4. + for (var b_idx = 0u; b_idx < 4u; b_idx++) { + let b_value = b_data[b_idx]; + let b_value_lower = unpack4xU8(b_value & 0x0F0F0F0Fu); + let b_value_upper = unpack4xU8((b_value >> 4u) & 0x0F0F0F0Fu); + let b_quantized_values = mat2x4( + output_element_t(b_value_lower[0]), output_element_t(b_value_upper[0]), + output_element_t(b_value_lower[1]), output_element_t(b_value_upper[1]), + output_element_t(b_value_lower[2]), output_element_t(b_value_upper[2]), + output_element_t(b_value_lower[3]), output_element_t(b_value_upper[3])); + let b_dequantized_values = + (b_quantized_values - mat2x4(zero_point, zero_point, + zero_point, zero_point, + zero_point, zero_point, + zero_point, zero_point)) * scale; + + for (var m_idx = 0u; m_idx < tile_m; m_idx++) { + let a_data0 = a_data_tile[m_idx][b_idx * 2u]; + let a_data1 = a_data_tile[m_idx][b_idx * 2u + 1u]; + + results[m_idx] += f32(dot(a_data0, b_dequantized_values[0u])) + + f32(dot(a_data1, b_dequantized_values[1u])); + } + } + + workgroupBarrier(); + } + + // write the results + for (var m_idx = 0u; m_idx < tile_m; m_idx++) { + mm_write_y(batch, row + m_idx, col + local_idx, output_value_t(results[m_idx])); + } +)MAIN_FN"; + + return Status::OK(); +} + Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) const { const Tensor* a = context.Input(0); const Tensor* b = context.Input(1); @@ -569,6 +688,41 @@ Status MatMulNBits::ComputeInternal(onnxruntime::webgpu::ComputeContext& context return ApplyDP4AMatrixMatMulNBits(a, b, scales, M, N, K, block_size, kMinMForTileOptimization, context, y); } + // WideTileProgram + // This program is optimized for Block32 prefill using Tile16x128. + // TODO: loosen restrictions on batch_count, has_zero_points, and vendor. + const bool use_wide_tile_program = block_size == 32 && batch_count == 1 && !has_zero_points && + components_a == 4 && components_b == 4 && M >= kMinMForTileOptimization && + context.AdapterInfo().vendor == std::string_view{"intel"}; + if (use_wide_tile_program) { + // Enforce output components to 1. + components = 1; + + constexpr uint32_t workgroup_size = 128; + constexpr uint32_t tile_m = workgroup_size / 8; + constexpr uint32_t tile_n = workgroup_size; + + MatMulNBitsWideTileProgram program{tile_m, tile_n}; + program.SetWorkgroupSize(workgroup_size); + program.SetDispatchGroupSize((N + tile_n - 1) / tile_n, + (M + tile_m - 1) / tile_m, + batch_count); + program.CacheHint("Tile" + std::to_string(tile_m) + "x" + std::to_string(tile_n) + "_Block32"); + + TensorShape reshaped_a_shape{batch_count, M, K / components_a}; + TensorShape reshaped_b_shape{N, n_blocks_per_col, blob_size_in_words / components_b}; + TensorShape reshaped_y_shape{batch_count, M, N / components}; + + program + .AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, reshaped_a_shape, onnxruntime::narrow(components_a)}, + {b, ProgramTensorMetadataDependency::TypeAndRank, reshaped_b_shape, onnxruntime::narrow(components_b * 4)}, + {scales, ProgramTensorMetadataDependency::None}}) + .AddOutput({y, ProgramTensorMetadataDependency::TypeAndRank, reshaped_y_shape, onnxruntime::narrow(components)}) + .AddUniformVariable({block_size}); + return context.RunProgram(program); + } + + // Generic program // TODO: Support output_number > 1. Some cases are failed when output_number > 1. constexpr uint32_t output_number = 1; const uint32_t tile_m = M > kMinMForTileOptimization ? 4 : 1; diff --git a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h index 10221e19c7400..07c47021d516a 100644 --- a/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h +++ b/onnxruntime/contrib_ops/webgpu/quantization/matmul_nbits.h @@ -35,6 +35,19 @@ class MatMulNBitsProgram final : public Program { bool use_subgroup_; }; +class MatMulNBitsWideTileProgram final : public Program { + public: + MatMulNBitsWideTileProgram(uint32_t tile_m, uint32_t tile_n) + : Program{"MatMulNBitsWideTileProgram"}, tile_m_(tile_m), tile_n_(tile_n) {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"block_size", ProgramUniformVariableDataType::Uint32}); + + private: + uint32_t tile_m_; + uint32_t tile_n_; +}; + class MatMulNBits final : public WebGpuKernel { public: MatMulNBits(const OpKernelInfo& info) : WebGpuKernel(info) { From 82c8e56911900bf1e892345124c85b475787cb54 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 4 Apr 2025 00:24:03 -0700 Subject: [PATCH 228/266] upgrade action shellcheck to v1.30.0 (#24304) ### Description ### Motivation and Context --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8d966d358de01..21baab0fd191c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,7 +26,7 @@ jobs: level: info filter_mode: diff_context - name: shellcheck # Static check shell scripts - uses: reviewdog/action-shellcheck@v1 + uses: reviewdog/action-shellcheck@v1.30.0 with: github_token: ${{ secrets.github_token }} reporter: github-pr-check From 1cb53d0054774db37ed500e43988497c66599c11 Mon Sep 17 00:00:00 2001 From: minfhong-quic Date: Fri, 4 Apr 2025 23:29:54 +0800 Subject: [PATCH 229/266] [QNN-EP] Fix ONNX context model helper. (#24271) ### Description Fix the bug where the QNN EP generates an ONNX model with EP Context and fails to run. ### Motivation and Context When generating an ONNX model with QNN EP context where the input is scalar, the shape is not set, resulting in a null pointer and causing the subsequent run to fail. --- onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc index 93b2acb5b002c..26642459a6863 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc @@ -77,6 +77,7 @@ Status CreateNodeArgs(const std::vector& names, const OnnxTensorInfo& tensor_info = tensor_info_table.at(name); std::unique_ptr tensor_type = Factory::Create(); tensor_type->mutable_tensor_type()->set_elem_type(tensor_info.data_type_); + tensor_type->mutable_tensor_type()->mutable_shape(); for (size_t j = 0; j < tensor_info.shape_.size(); ++j) { tensor_type->mutable_tensor_type()->mutable_shape()->add_dim()->set_dim_value(tensor_info.shape_[j]); } From 318cc87f23d3b28a8b3d7617433f0a1cfd60e458 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:36:08 -0700 Subject: [PATCH 230/266] [WebGPU] fix Pad cache key (#24305) ### Description Fix cache key of Pad operator --- .github/workflows/windows_webgpu.yml | 1 - onnxruntime/core/providers/webgpu/tensor/pad.cc | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows_webgpu.yml b/.github/workflows/windows_webgpu.yml index e8cea1c5805a3..8b3b8a2fcde54 100644 --- a/.github/workflows/windows_webgpu.yml +++ b/.github/workflows/windows_webgpu.yml @@ -126,7 +126,6 @@ jobs: dir ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\onnxruntime_test_all_stderr.log - name: Validate shader keys - continue-on-error: true uses: ./.github/actions/webgpu-validate-shader-key with: log_file_path: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\onnxruntime_test_all_stderr.log diff --git a/onnxruntime/core/providers/webgpu/tensor/pad.cc b/onnxruntime/core/providers/webgpu/tensor/pad.cc index cb019892b006f..f24578a145aae 100644 --- a/onnxruntime/core/providers/webgpu/tensor/pad.cc +++ b/onnxruntime/core/providers/webgpu/tensor/pad.cc @@ -168,9 +168,9 @@ Status Pad::ComputeInternal(ComputeContext& context) const { PadProgram program{mode_, dim_value_zero, is_float16}; if (!dim_value_zero) { - program.AddInput({input_tensor, ProgramTensorMetadataDependency::TypeAndRank}); + program.AddInput({input_tensor, ProgramTensorMetadataDependency::Rank}); } - program.AddOutput({output_tensor, ProgramTensorMetadataDependency::Rank}) + program.AddOutput({output_tensor, ProgramTensorMetadataDependency::TypeAndRank}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) .CacheHint(std::to_string(static_cast(mode_)), dim_value_zero) .AddUniformVariables({{gsl::span(lower_pads.data(), lower_pads.size())}, {output_size}, {value_uint32}}); From 56f101839603f2c875234b8baca4dc0cf5f8f973 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 11:30:11 -0700 Subject: [PATCH 231/266] Bump vite from 6.2.4 to 6.2.5 in /js/web/test/e2e/exports/testcases/vite-default (#24312) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.4 to 6.2.5.
Release notes

Sourced from vite's releases.

v6.2.5

Please refer to CHANGELOG.md for details.

Changelog

Sourced from vite's changelog.

6.2.5 (2025-04-03)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vite&package-manager=npm_and_yarn&previous-version=6.2.4&new-version=6.2.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../e2e/exports/testcases/vite-default/package-lock.json | 8 ++++---- .../test/e2e/exports/testcases/vite-default/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json index 9e4730a407d57..708e458748b3a 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package-lock.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package-lock.json @@ -12,7 +12,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", - "vite": "^6.2.4" + "vite": "^6.2.5" } }, "node_modules/@babel/helper-string-parser": { @@ -1069,9 +1069,9 @@ } }, "node_modules/vite": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", - "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/js/web/test/e2e/exports/testcases/vite-default/package.json b/js/web/test/e2e/exports/testcases/vite-default/package.json index e06733f917e3f..904db7a41de9c 100644 --- a/js/web/test/e2e/exports/testcases/vite-default/package.json +++ b/js/web/test/e2e/exports/testcases/vite-default/package.json @@ -13,6 +13,6 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", - "vite": "^6.2.4" + "vite": "^6.2.5" } } From 2e94c5a40f4a5dbd4627fa98ad5e410db171ba2e Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 4 Apr 2025 12:32:47 -0700 Subject: [PATCH 232/266] [WebGPU] fix cache key of AttentionProbs/VxAttentionScore (#24309) ### Description fix the cache inconsistency of program AttentionProbs/VxAttentionScore `n_reps` is already in uniforms so do not use it from hardcoded. --- .../webgpu-validate-shader-key/action.yml | 2 +- .github/workflows/windows-web-ci-workflow.yml | 1 - onnxruntime/contrib_ops/webgpu/bert/attention.cc | 16 ++++++++-------- onnxruntime/contrib_ops/webgpu/bert/attention.h | 10 ++++------ 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.github/actions/webgpu-validate-shader-key/action.yml b/.github/actions/webgpu-validate-shader-key/action.yml index 7b341d38ea906..86406a2e91877 100644 --- a/.github/actions/webgpu-validate-shader-key/action.yml +++ b/.github/actions/webgpu-validate-shader-key/action.yml @@ -22,7 +22,7 @@ runs: working-directory: ${{ github.action_path }} - name: Validate shader keys (native log) - if: ${{ !inputs.is_chromium_log != 'true' }} + if: ${{ inputs.is_chromium_log != 'true' }} shell: cmd run: | node validate-shader-key.js < "${{ inputs.log_file_path }}" diff --git a/.github/workflows/windows-web-ci-workflow.yml b/.github/workflows/windows-web-ci-workflow.yml index ce0e5167eb0a0..57f687d8502ff 100644 --- a/.github/workflows/windows-web-ci-workflow.yml +++ b/.github/workflows/windows-web-ci-workflow.yml @@ -200,7 +200,6 @@ jobs: - name: Validate shader keys - WebGPU EP if: ${{ inputs.run_webgpu_tests == true && inputs.build_config == 'Debug' }} - continue-on-error: true uses: ./.github/actions/webgpu-validate-shader-key with: log_file_path: ${{ runner.temp }}\web\test\07\chrome_debug.log diff --git a/onnxruntime/contrib_ops/webgpu/bert/attention.cc b/onnxruntime/contrib_ops/webgpu/bert/attention.cc index 0d4afc8c13f4b..abea94d2e0b50 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/attention.cc @@ -108,9 +108,9 @@ Status AttentionProbsProgram::GenerateShaderCode(ShaderHelper& shader) const { std::ostringstream oss; InitVarStub(oss, seqlen_k_); shader.MainFunctionBody() << oss.str(); - shader.MainFunctionBody() << "let kOffset = (workgroup_id.z / " << n_reps_ << ") * uniforms.kv_sequence_length * uniforms.K;\n"; + shader.MainFunctionBody() << "let kOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.kv_sequence_length * uniforms.K;\n"; if (has_present_key_) { - shader.MainFunctionBody() << "let presentKeyOffset = (workgroup_id.z / " << n_reps_ << ") * uniforms.present_sequence_length * uniforms.K;\n"; + shader.MainFunctionBody() << "let presentKeyOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.present_sequence_length * uniforms.K;\n"; } shader.MainFunctionBody() << "var value = f32_val_t(0);\n" @@ -123,7 +123,7 @@ Status AttentionProbsProgram::GenerateShaderCode(ShaderHelper& shader) const { if ((feed_past_key_ && has_present_key_) || (past_present_share_buffer_ && !is_first_prompt_)) { shader.MainFunctionBody() << " if (n + local_id.y < past_sequence_length) {\n" - << " let pastKeyOffset = (workgroup_id.z / " << n_reps_ << ") * uniforms.past_sequence_length * uniforms.K;\n" + << " let pastKeyOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.past_sequence_length * uniforms.K;\n" << " tileK[idx] = " << (past_present_share_buffer_ ? "present_key" : "past_key") << "[pastKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x];\n" << " } else if (n + local_id.y - past_sequence_length < uniforms.kv_sequence_length) {\n" << " tileK[idx] = key[kOffset + (n + local_id.y - past_sequence_length) * uniforms.K + w + local_id.x];\n" @@ -181,7 +181,7 @@ Status ComputeAttentionProbs(onnxruntime::webgpu::ComputeContext& context, int o const int components = parameters.head_size_ % 4 == 0 ? 4 : (parameters.head_size_ % 2 == 0 ? 2 : 1); AttentionProbsProgram program{"AttentionProbs", feed_past_key, has_present_key, has_attention_bias, tile_size, - components, parameters.is_first_prompt_, parameters.n_reps, seqlen_k, parameters.past_present_share_buffer_}; + components, parameters.is_first_prompt_, seqlen_k, parameters.past_present_share_buffer_}; program.AddInputs({{Q, ProgramTensorMetadataDependency::TypeAndRank, components}, {K, ProgramTensorMetadataDependency::TypeAndRank, components}}); if (feed_past_key) { @@ -331,9 +331,9 @@ Status VxAttentionScoreProgram::GenerateShaderCode(ShaderHelper& shader) const { std::ostringstream oss; InitVarStub(oss, seqlen_k_); shader.MainFunctionBody() << oss.str(); - shader.MainFunctionBody() << "let vOffset = (workgroup_id.z / " << n_reps_ << ") * uniforms.N * uniforms.kv_sequence_length + n;\n"; + shader.MainFunctionBody() << "let vOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.N * uniforms.kv_sequence_length + n;\n"; if (has_present_value_) { - shader.MainFunctionBody() << "let presentValueOffset = (workgroup_id.z / " << n_reps_ << ") * uniforms.N * uniforms.present_sequence_length + n;\n"; + shader.MainFunctionBody() << "let presentValueOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.N * uniforms.present_sequence_length + n;\n"; } shader.MainFunctionBody() << "var value = output_value_t(0);\n" @@ -346,7 +346,7 @@ Status VxAttentionScoreProgram::GenerateShaderCode(ShaderHelper& shader) const { if ((feed_past_value_ && has_present_value_) || (past_present_share_buffer_ && !is_first_prompt_)) { shader.MainFunctionBody() << " if (w + local_id.y < past_sequence_length) {\n" - << " let pastValueOffset = (workgroup_id.z / " << n_reps_ << ") * uniforms.N * uniforms.past_sequence_length + n;\n" + << " let pastValueOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.N * uniforms.past_sequence_length + n;\n" << " tileK[idx] = " << (past_present_share_buffer_ ? "present_value" : "past_value") << "[pastValueOffset + (w + local_id.y) * uniforms.N];\n" << " } else if (w + local_id.y - past_sequence_length < uniforms.kv_sequence_length) {\n" << " tileK[idx] = v[vOffset + (w + local_id.y - past_sequence_length) * uniforms.N];\n" @@ -400,7 +400,7 @@ Status ComputeVxAttentionScore(onnxruntime::webgpu::ComputeContext& context, int const int components = parameters.v_head_size_ % 4 == 0 ? 4 : (parameters.v_head_size_ % 2 == 0 ? 2 : 1); constexpr int tile_size = 12; int tile_n_size = tile_size * components; - VxAttentionScoreProgram program{"VxAttentionScore", feed_past_value, has_present_value, tile_size, parameters.is_first_prompt_, parameters.n_reps, seqlen_k, parameters.past_present_share_buffer_}; + VxAttentionScoreProgram program{"VxAttentionScore", feed_past_value, has_present_value, tile_size, parameters.is_first_prompt_, seqlen_k, parameters.past_present_share_buffer_}; program.AddInputs({{probs, ProgramTensorMetadataDependency::TypeAndRank}, {V, ProgramTensorMetadataDependency::TypeAndRank, components}}); if (feed_past_value) { diff --git a/onnxruntime/contrib_ops/webgpu/bert/attention.h b/onnxruntime/contrib_ops/webgpu/bert/attention.h index 164ea72b07d9d..6123d2c47add1 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/attention.h @@ -34,8 +34,8 @@ class TransferBSDToBNSHProgram final : public Program class AttentionProbsProgram final : public Program { public: AttentionProbsProgram(const std::string& kernel_name, bool feed_past_key, bool has_present_key, - bool has_attention_bias, int tile_size, int components, bool is_first_prompt, int n_reps = 1, const Tensor* seqlen_k = nullptr, bool past_present_share_buffer = false) - : Program{kernel_name}, feed_past_key_(feed_past_key), has_present_key_(has_present_key), has_attention_bias_(has_attention_bias), tile_size_(tile_size), components_(components), n_reps_(n_reps), seqlen_k_(seqlen_k), past_present_share_buffer_(past_present_share_buffer), is_first_prompt_(is_first_prompt) { + bool has_attention_bias, int tile_size, int components, bool is_first_prompt, const Tensor* seqlen_k = nullptr, bool past_present_share_buffer = false) + : Program{kernel_name}, feed_past_key_(feed_past_key), has_present_key_(has_present_key), has_attention_bias_(has_attention_bias), tile_size_(tile_size), components_(components), seqlen_k_(seqlen_k), past_present_share_buffer_(past_present_share_buffer), is_first_prompt_(is_first_prompt) { } Status GenerateShaderCode(ShaderHelper& sh) const override; @@ -60,7 +60,6 @@ class AttentionProbsProgram final : public Program { bool has_attention_bias_; int tile_size_; int components_; - int n_reps_; const Tensor* seqlen_k_; bool past_present_share_buffer_; bool is_first_prompt_; @@ -90,8 +89,8 @@ class InPlaceSoftmaxProgram final : public Program { class VxAttentionScoreProgram final : public Program { public: - VxAttentionScoreProgram(const std::string& kernel_name, bool feed_past_value, bool has_present_value, int tile_size, bool is_first_prompt, int n_reps = 1, const Tensor* seqlen_k = nullptr, bool past_present_share_buffer = false) - : Program{kernel_name}, feed_past_value_(feed_past_value), has_present_value_(has_present_value), tile_size_(tile_size), n_reps_(n_reps), seqlen_k_(seqlen_k), past_present_share_buffer_(past_present_share_buffer), is_first_prompt_(is_first_prompt) { + VxAttentionScoreProgram(const std::string& kernel_name, bool feed_past_value, bool has_present_value, int tile_size, bool is_first_prompt, const Tensor* seqlen_k = nullptr, bool past_present_share_buffer = false) + : Program{kernel_name}, feed_past_value_(feed_past_value), has_present_value_(has_present_value), tile_size_(tile_size), seqlen_k_(seqlen_k), past_present_share_buffer_(past_present_share_buffer), is_first_prompt_(is_first_prompt) { } Status GenerateShaderCode(ShaderHelper& sh) const override; @@ -114,7 +113,6 @@ class VxAttentionScoreProgram final : public Program { bool feed_past_value_; bool has_present_value_; int tile_size_; - int n_reps_; const Tensor* seqlen_k_; bool past_present_share_buffer_; bool is_first_prompt_; From e944379e519fdda2c782e80d4d960483c975f604 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Fri, 4 Apr 2025 13:15:04 -0700 Subject: [PATCH 233/266] Support Gemma3 with Clip fused attention (#24280) ### Description Essentially, the vision model is traced differently (this time it's without mask.), and the input indices of op.Add and op.MatMul can be different. Also, fp16 and fp32 need different tracing patterns (op.Cast). 1. Add another traced pattern to CLIP attention to cover no attention_mask case 2. Accept different index of input on op.Add and op.MatMul (be more general) 3. fp16 and fp32 shows different pattern (op.Cast after op.Softmax) 4. Refactor test_fastgelu.py to cover torch.onnx.export(..., dynamo=True) 5. Add gemma3 vision attention (SigLip) test to cover both fp16 and fp32 ### Motivation and Context To optimize Gemma3 multi-modal model, the changes are needed. https://huggingface.co/google/gemma-3-4b-it NOTE: some related follow-ups (upstream optimizations to onnxscript-optimizer): https://github.com/microsoft/onnxscript/issues/2158 https://github.com/microsoft/onnxscript/issues/2156 --- .../transformers/fusion_attention_clip.py | 83 +++++-- .../tools/transformers/fusion_fastgelu.py | 17 +- .../models/gemma3-vision-attention_fp16.onnx | Bin 0 -> 5397 bytes .../models/gemma3-vision-attention_fp32.onnx | Bin 0 -> 8780 bytes .../python/transformers/test_gelu_fusions.py | 71 +++--- .../python/transformers/test_gemma3_vision.py | 216 ++++++++++++++++++ .../github/linux/python/requirements.txt | 3 +- .../github/windows/python/requirements.txt | 1 + .../transformers-test/requirements.txt | 1 + 9 files changed, 336 insertions(+), 56 deletions(-) create mode 100644 onnxruntime/test/python/transformers/test_data/models/gemma3-vision-attention_fp16.onnx create mode 100644 onnxruntime/test/python/transformers/test_data/models/gemma3-vision-attention_fp32.onnx create mode 100644 onnxruntime/test/python/transformers/test_gemma3_vision.py diff --git a/onnxruntime/python/tools/transformers/fusion_attention_clip.py b/onnxruntime/python/tools/transformers/fusion_attention_clip.py index 63bf6410f86c3..fe93f5cd358bf 100644 --- a/onnxruntime/python/tools/transformers/fusion_attention_clip.py +++ b/onnxruntime/python/tools/transformers/fusion_attention_clip.py @@ -126,7 +126,10 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): if node_before_layer_norm is None: continue child = self.model.find_first_child_by_type( - node_before_layer_norm, "LayerNormalization", input_name_to_nodes, False + node_before_layer_norm, + "LayerNormalization", + input_name_to_nodes, + False, ) if child is None: continue @@ -146,19 +149,26 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): qkv_nodes = self.model.match_parent_path( normalize_node, ["Add", "MatMul", "Reshape", "Transpose", "MatMul"], - [1, 1, 0, 0, 0], + [1, None, 0, 0, 0], ) if qkv_nodes is None: logger.debug("fuse_attention: failed to match qkv path") return - - reshape_qkv, transpose_qkv, matmul_qkv = qkv_nodes[2], qkv_nodes[3], qkv_nodes[-1] + reshape_qkv, transpose_qkv, matmul_qkv = ( + qkv_nodes[2], + qkv_nodes[3], + qkv_nodes[-1], + ) v_nodes = self.model.match_parent_path( - matmul_qkv, ["Reshape", "Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, 0, None] + matmul_qkv, + ["Reshape", "Transpose", "Reshape", "Add", "MatMul"], + [1, 0, 0, 0, None], ) if v_nodes is None: - v_nodes = self.model.match_parent_path(matmul_qkv, ["Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, 1]) + v_nodes = self.model.match_parent_path( + matmul_qkv, ["Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, None] + ) if v_nodes is None: logger.debug("fuse_attention: failed to match v path") return @@ -182,17 +192,30 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): ) if qk_nodes is None: qk_nodes = self.model.match_parent_path(matmul_qkv, ["Softmax", "Add", "Mul", "MatMul"], [0, 0, 0, 0]) - if qk_nodes is None: - qk_nodes = self.model.match_parent_path( - matmul_qkv, ["Cast", "Cast", "Softmax", "Add", "Mul", "MatMul"], [0, 0, 0, 0, 0, 0] - ) - if qk_nodes is None: - logger.debug("fuse_attention: failed to match qk path") - return - else: - add_mask = qk_nodes[3] - else: + if qk_nodes is not None: add_mask = qk_nodes[1] + else: + # If attention mask is not used, we can still match the qk path. + qk_nodes = self.model.match_parent_path(matmul_qkv, ["Softmax", "Mul", "MatMul"], [0, 0, 0]) + if qk_nodes is None: + # Cast nodes are added in the model for fp16. + qk_nodes = self.model.match_parent_path( + matmul_qkv, + ["Cast", "Cast", "Softmax", "Add", "Mul", "MatMul"], + [0, 0, 0, 0, 0, 0], + ) + if qk_nodes is not None: + add_mask = qk_nodes[3] + else: + # If attention mask is not used, we can still match the qk path. + qk_nodes = self.model.match_parent_path( + matmul_qkv, + ["Cast", "Cast", "Softmax", "Mul", "MatMul"], + [0, 0, 0, 0, 0], + ) + if qk_nodes is None: + logger.debug("fuse_attention: failed to match qk path") + return else: assert len(add_mask_indices) == 1 causal_mask_input_index = 1 - add_mask_indices[0] @@ -201,10 +224,14 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): matmul_qk = qk_nodes[-1] q_nodes = self.model.match_parent_path( - matmul_qk, ["Reshape", "Transpose", "Reshape", "Mul", "Add", "MatMul"], [0, 0, 0, 0, None, None] + matmul_qk, + ["Reshape", "Transpose", "Reshape", "Mul", "Add", "MatMul"], + [0, 0, 0, 0, None, None], ) if q_nodes is None: - q_nodes = self.model.match_parent_path(matmul_qk, ["Transpose", "Reshape", "Add", "MatMul"], [0, 0, 0, 1]) + q_nodes = self.model.match_parent_path( + matmul_qk, ["Transpose", "Reshape", "Add", "MatMul"], [0, 0, 0, None] + ) if q_nodes is None: logger.debug("fuse_attention: failed to match q path") return @@ -216,10 +243,14 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): add_q, matmul_q = q_nodes[-2], q_nodes[-1] k_nodes = self.model.match_parent_path( - matmul_qk, ["Transpose", "Reshape", "Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, 0, 0, None] + matmul_qk, + ["Transpose", "Reshape", "Transpose", "Reshape", "Add", "MatMul"], + [1, 0, 0, 0, 0, None], ) if k_nodes is None: - k_nodes = self.model.match_parent_path(matmul_qk, ["Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, 1]) + k_nodes = self.model.match_parent_path( + matmul_qk, ["Transpose", "Reshape", "Add", "MatMul"], [1, 0, 0, None] + ) if k_nodes is None: logger.debug("fuse_attention: failed to match k path") return @@ -242,7 +273,17 @@ def fuse(self, normalize_node, input_name_to_nodes, output_name_to_node): # 4D Add after Q x K' add_qk_nodes = self.model.match_parent_path( add_mask, - ["Where", "Sub", "Cast", "Expand", "Unsqueeze", "Unsqueeze", "Reshape", "Reshape", "Cast"], + [ + "Where", + "Sub", + "Cast", + "Expand", + "Unsqueeze", + "Unsqueeze", + "Reshape", + "Reshape", + "Cast", + ], [1, 2, 1, 0, 0, 0, 0, 0, 0], ) if add_qk_nodes is not None: diff --git a/onnxruntime/python/tools/transformers/fusion_fastgelu.py b/onnxruntime/python/tools/transformers/fusion_fastgelu.py index 210f10e2eadd4..728bd03244758 100644 --- a/onnxruntime/python/tools/transformers/fusion_fastgelu.py +++ b/onnxruntime/python/tools/transformers/fusion_fastgelu.py @@ -177,13 +177,12 @@ def fuse_2(self, tanh_node, input_name_to_nodes: dict, output_name_to_node: dict return mul_after_mul_half = children[0] + # root_node could be None when root_input is graph input root_node = self.model.get_parent( mul_after_mul_half, 0 if mul_after_mul_half.input[1] == mul_half.output[0] else 1, output_name_to_node, ) - if root_node is None: - return mul_before_tanh = self.model.match_parent(tanh_node, "Mul", 0, output_name_to_node) if mul_before_tanh is None: @@ -197,7 +196,13 @@ def fuse_2(self, tanh_node, input_name_to_nodes: dict, output_name_to_node: dict if add_before_tanh is None: return - mul_after_pow = self.model.match_parent(add_before_tanh, "Mul", None, output_name_to_node, exclude=[root_node]) + mul_after_pow = self.model.match_parent( + add_before_tanh, + "Mul", + None, + output_name_to_node, + exclude=[root_node] if root_node else [], + ) if mul_after_pow is None: return @@ -212,7 +217,9 @@ def fuse_2(self, tanh_node, input_name_to_nodes: dict, output_name_to_node: dict if not self.model.has_constant_input(pow, 3.0): return - if pow.input[0] != root_node.output[0]: + root_input = mul_after_mul_half.input[0 if mul_after_mul_half.input[1] == mul_half.output[0] else 1] + + if pow.input[0] != root_input: return subgraph_nodes = [ @@ -236,7 +243,7 @@ def fuse_2(self, tanh_node, input_name_to_nodes: dict, output_name_to_node: dict self.nodes_to_remove.extend(subgraph_nodes) fused_node = helper.make_node( "FastGelu", - inputs=[root_node.output[0]], + inputs=[root_input], outputs=mul_after_mul_half.output, name=self.model.create_node_name("FastGelu"), ) diff --git a/onnxruntime/test/python/transformers/test_data/models/gemma3-vision-attention_fp16.onnx b/onnxruntime/test/python/transformers/test_data/models/gemma3-vision-attention_fp16.onnx new file mode 100644 index 0000000000000000000000000000000000000000..49e805169ee452556aa477b3958d35b8fe437e7d GIT binary patch literal 5397 zcmeHL-A)rh6z-NhOKMdCDhwu zuC2RXK3&!-6|FS)_Z94c(h7bVi)shDvAx5gUtDe)#6w__L*2zxpz`?)>wB5+qQ1-_Q?mH9v4>ypTD$DP|!Qd|GCcfPBr|*i`)FT9070@6gRYe?0apVeb;I*^6t#Rfyb~L@^FqdoL z))9NgHYMD5b#0M4K3{Y6hPG?aCW4K%cOUWM%7=}00iV7G+!5Ud!wdHJD7C_M>G*Iv%vl7Ws{JS> zVo#Y9kP6x^XcTfnldO1loKQhhf%yzFVS~wGp5E0c7j;oe9j+&%c1-z7Tv>{%bj3Y~ zffG_M2NM(LXF_IJp1- literal 0 HcmV?d00001 diff --git a/onnxruntime/test/python/transformers/test_data/models/gemma3-vision-attention_fp32.onnx b/onnxruntime/test/python/transformers/test_data/models/gemma3-vision-attention_fp32.onnx new file mode 100644 index 0000000000000000000000000000000000000000..7fca335f1373165e1aeb56d17d0a0c896e7305b7 GIT binary patch literal 8780 zcmeI2-%is|9LLu&NB3jmJWjx=gv=0=UDW+y5{XJ6dch)pB5>o)N!iNQu01X7DWHjo zFW{w@MjpV2;Kt`LzJZV6X;;{aXQB}k63?=ev_0qd@4L@QoBb*Snz9KwbbUf~OH-(; z5^vXbEzR``>55XVD&>Vw&tMOv!{D1SiE^On?GA-ecDSRf9s*N+t+|*mtHQO-uI{`D z&ezx}E*B?a7gSS!qf*@_rRy-NIi7CXKEo$s;LwHvChF zTtHr>lqj}OvE$lCR6Yx!nz%Aw7$cM?^-Wx>7t_5%_$V<4;gVP#9038v1B9Yx z`=a7XVKSy7UTU?LS($$$F9J)|32wWp(!^Q33HNH##8zZki zNUXz(5aeVDWg#g`Y$Vyp7oWfbr`uMj?KV4#cIenHRl?34_VhMUsqbpa3UPe8>1a)* ztCJRj?ak*e@ygo9_7*d*|AD!~TEDs%G+R+>%_iDT6JpIsZib6cJ~za=Ph%;Lg(eoX^?w9afLe{d3`v{>pa)0@3qREztJo65dx6qQIuk}r;KSx1wC*y0ePlLj$Jze zDu4=%dyomc{f_NvLl@e$5b3>P%s9zsY qal~NU_Fit_vM?1T_%mXGUHC!**RIbPf48u$#5O1&>*W+Aa_9%9Xq&YF literal 0 HcmV?d00001 diff --git a/onnxruntime/test/python/transformers/test_gelu_fusions.py b/onnxruntime/test/python/transformers/test_gelu_fusions.py index 94b969ad5377d..11ae1401ff8ed 100644 --- a/onnxruntime/test/python/transformers/test_gelu_fusions.py +++ b/onnxruntime/test/python/transformers/test_gelu_fusions.py @@ -3,6 +3,7 @@ import unittest import torch +from parameterized import parameterized from parity_utilities import find_transformers_source if find_transformers_source(): @@ -43,16 +44,6 @@ def forward(self, x): return 0.5 * x * (1.0 + torch.tanh(0.7978845608028654 * x * (1.0 + 0.044715 * x * x))) -test_cases = [ - ("huggingface", "Gelu", HuggingfaceGelu), - ("huggingface", "FastGelu", HuggingfaceFastGelu), - ("huggingface", "QuickGelu", HuggingfaceQuickGelu), - ("huggingface", "FastGelu", HuggingfaceTorchGeluTanh), - ("megatron", "Gelu", MegatronGelu), - ("megatron", "FastGelu", MegatronFastGelu), -] - - class TestGeluFusions(unittest.TestCase): def verify_node_count(self, bert_model, expected_node_count, test_name): for op_type, count in expected_node_count.items(): @@ -62,25 +53,47 @@ def verify_node_count(self, bert_model, expected_node_count, test_name): print(f"{op}: {len(bert_model.get_nodes_by_op_type(op))} expected={counter}") self.assertEqual(len(bert_model.get_nodes_by_op_type(op_type)), count) - def test_fusions(self): - for test_case in test_cases: - source, operator, model_class = test_case - model = model_class() - dummy_input = torch.ones(3, dtype=torch.float32) - test_name = f"{operator}_{source}" - onnx_path = f"{test_name}.onnx" - torch.onnx.export( - model, - (dummy_input), - onnx_path, - input_names=["input"], - output_names=["output"], - ) - optimizer = optimize_model(onnx_path, "bert") - # optimizer.save_model_to_file(f"{operator}_{source}_opt.onnx") - os.remove(onnx_path) - expected_node_count = {operator: 1} - self.verify_node_count(optimizer, expected_node_count, test_name) + @parameterized.expand( + [ + (("huggingface", "Gelu", HuggingfaceGelu), True), + (("huggingface", "FastGelu", HuggingfaceFastGelu), True), + (("huggingface", "QuickGelu", HuggingfaceQuickGelu), True), + (("huggingface", "FastGelu", HuggingfaceTorchGeluTanh), True), + (("megatron", "Gelu", MegatronGelu), True), + (("megatron", "FastGelu", MegatronFastGelu), True), + (("huggingface", "Gelu", HuggingfaceGelu), False), + (("huggingface", "FastGelu", HuggingfaceFastGelu), False), + (("huggingface", "QuickGelu", HuggingfaceQuickGelu), False), + (("huggingface", "FastGelu", HuggingfaceTorchGeluTanh), False), + (("megatron", "Gelu", MegatronGelu), False), + (("megatron", "FastGelu", MegatronFastGelu), False), + ] + ) + def test_fusions(self, test_case, dynamo): + source, operator, model_class = test_case + model = model_class() + dummy_input = torch.ones(3, dtype=torch.float32) + test_name = f"{operator}_{source}" + onnx_path = f"{test_name}.onnx" + torch.onnx.export( + model, + (dummy_input,), + onnx_path, + input_names=["input"], + output_names=["output"], + dynamo=dynamo, + optimize=True, # Only meaningful when dynamo is True + ) + optimizer = optimize_model(onnx_path, "bert") + # optimizer.save_model_to_file(f"{operator}_{source}_opt.onnx") + os.remove(onnx_path) + # Remove the associated .data file (dynamo) + data_path = onnx_path + ".data" + if os.path.exists(data_path): + os.remove(data_path) + expected_node_count = {operator: 1} + + self.verify_node_count(optimizer, expected_node_count, test_name) if __name__ == "__main__": diff --git a/onnxruntime/test/python/transformers/test_gemma3_vision.py b/onnxruntime/test/python/transformers/test_gemma3_vision.py new file mode 100644 index 0000000000000..4727d2c8030d2 --- /dev/null +++ b/onnxruntime/test/python/transformers/test_gemma3_vision.py @@ -0,0 +1,216 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import os +import unittest + +import onnx +import torch +from parameterized import parameterized +from parity_utilities import find_transformers_source + +if find_transformers_source(): + from dynamo_onnx_helper import DynamoOnnxHelper + from fusion_options import FusionOptions + from onnx_model import OnnxModel + from optimizer import optimize_model +else: + from onnxruntime.transformers.dynamo_onnx_helper import DynamoOnnxHelper + from onnxruntime.transformers.fusion_options import FusionOptions + from onnxruntime.transformers.onnx_model import OnnxModel + from onnxruntime.transformers.optimizer import optimize_model + + +# https://github.com/huggingface/transformers/blob/af9b2eaa54c150741f298d6db939af6328e1dc38/src/transformers/models/siglip/modeling_siglip.py#L363 +class SiglipAttention(torch.nn.Module): + """Multi-headed attention from 'Attention Is All You Need' paper""" + + # Copied from transformers.models.clip.modeling_clip.CLIPAttention.__init__ + def __init__(self): + super().__init__() + self.embed_dim = 20 + self.num_heads = 2 + self.head_dim = self.embed_dim // self.num_heads + if self.head_dim * self.num_heads != self.embed_dim: + raise ValueError( + f"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:" + f" {self.num_heads})." + ) + self.scale = self.head_dim**-0.5 + + self.k_proj = torch.nn.Linear(self.embed_dim, self.embed_dim) + self.v_proj = torch.nn.Linear(self.embed_dim, self.embed_dim) + self.q_proj = torch.nn.Linear(self.embed_dim, self.embed_dim) + self.out_proj = torch.nn.Linear(self.embed_dim, self.embed_dim) + + self.k_proj.weight.data.fill_(1) + self.v_proj.weight.data.fill_(1) + self.q_proj.weight.data.fill_(1) + self.out_proj.weight.data.fill_(1) + self.k_proj.bias.data.fill_(1) + self.v_proj.bias.data.fill_(1) + self.q_proj.bias.data.fill_(1) + self.out_proj.bias.data.fill_(1) + + def forward( + self, + hidden_states: torch.Tensor, + attention_mask: torch.Tensor | None = None, + output_attentions: bool | None = False, + ) -> tuple[torch.Tensor, torch.Tensor | None]: + """Input shape: Batch x Time x Channel""" + + batch_size, q_len, _ = hidden_states.size() + + query_states = self.q_proj(hidden_states) + key_states = self.k_proj(hidden_states) + value_states = self.v_proj(hidden_states) + + query_states = query_states.view(batch_size, q_len, self.num_heads, self.head_dim).transpose(1, 2) + key_states = key_states.view(batch_size, q_len, self.num_heads, self.head_dim).transpose(1, 2) + value_states = value_states.view(batch_size, q_len, self.num_heads, self.head_dim).transpose(1, 2) + + k_v_seq_len = key_states.shape[-2] + attn_weights = torch.matmul(query_states, key_states.transpose(2, 3)) * self.scale + + if attn_weights.size() != (batch_size, self.num_heads, q_len, k_v_seq_len): + raise ValueError( + f"Attention weights should be of size {(batch_size, self.num_heads, q_len, k_v_seq_len)}, but is" + f" {attn_weights.size()}" + ) + + if attention_mask is not None: + if attention_mask.size() != (batch_size, 1, q_len, k_v_seq_len): + raise ValueError( + f"Attention mask should be of size {(batch_size, 1, q_len, k_v_seq_len)}, but is {attention_mask.size()}" + ) + attn_weights = attn_weights + attention_mask + + # upcast attention to fp32 + attn_weights = torch.nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query_states.dtype) + attn_output = torch.matmul(attn_weights, value_states) + + if attn_output.size() != (batch_size, self.num_heads, q_len, self.head_dim): + raise ValueError( + f"`attn_output` should be of size {(batch_size, self.num_heads, q_len, self.head_dim)}, but is" + f" {attn_output.size()}" + ) + + attn_output = attn_output.transpose(1, 2).contiguous() + attn_output = attn_output.reshape(batch_size, q_len, self.embed_dim) + + attn_output = self.out_proj(attn_output) + + return attn_output, attn_weights + + +class Gemma3VSIGLIPAttentionAndLayerNorm(torch.nn.Module): + def __init__(self): + super().__init__() + self.attn = SiglipAttention() + self.ln = torch.nn.LayerNorm(20, eps=1e-05) + + def forward(self, x): + # SkipLayerNorm ------+ + # | | + # Attention | + # | | + # MatMul | + # | | + # SkipLayerNorm ------+ + + # SkipLayerNorm + x = x + x + x = self.ln(x) + residual = x + + # Attention + MatMul + x, _ = self.attn(x) + + # SkipLayerNorm + x = residual + x + x = self.ln(x) + return x + + +class TestFusion(unittest.TestCase): + def verify_fusion(self, optimized_model, expected_model_filename): + optimized_model.topological_sort(is_deterministic=True) + + expected_model_path = os.path.join(os.path.dirname(__file__), "test_data", "models", expected_model_filename) + expected_model = OnnxModel(onnx.load(expected_model_path)) + expected_model.topological_sort(is_deterministic=True) + + nodes = optimized_model.model.graph.node + self.assertEqual(len(nodes), len(expected_model.model.graph.node)) + + for i in range(len(nodes)): + self.assertEqual(nodes[i], expected_model.model.graph.node[i]) + + for expected_initializer in expected_model.model.graph.initializer: + self.assertTrue( + OnnxModel.has_same_value( + optimized_model.get_initializer(expected_initializer.name), + expected_initializer, + ) + ) + + def export(self, model, inputs) -> onnx.ModelProto: + with torch.no_grad(): + onnx_program = torch.onnx.export( + model, + args=inputs, + # f=os.path.join(os.path.dirname(__file__), "export.onnx"), + dynamo=True, + optimize=True, + ) + return onnx_program.model_proto # type: ignore + + def tearDown(self): + paths = [ + os.path.join(os.path.dirname(__file__), "export.onnx"), + os.path.join(os.path.dirname(__file__), "export.onnx.data"), + ] + for path in paths: + if os.path.exists(path): + os.remove(path) + + @parameterized.expand( + [ + (torch.float32, "gemma3-vision-attention_fp32.onnx"), + (torch.float16, "gemma3-vision-attention_fp16.onnx"), + ] + ) + def test_gemma3_vision_attention(self, dtype, model_name): + model = Gemma3VSIGLIPAttentionAndLayerNorm().eval().to(dtype) + inputs = (torch.randn(1, 2, 20, dtype=dtype),) + original_model = self.export(model, inputs) + + # TODO(titaiwang): Upstream these processings to onnxscript pass + onnx_model_wrapper = DynamoOnnxHelper(original_model) + onnx_model_wrapper.convert_constants_to_initializers() + onnx_model_wrapper.clear_metadata() + model_path = os.path.join(os.path.dirname(__file__), "export.onnx") + onnx_model_wrapper.model.save_model_to_file( + model_path, + use_external_data_format=True, + all_tensors_to_one_file=True, + convert_attribute=True, + ) + + options = FusionOptions("clip") + optimized_model = optimize_model( + model_path, + model_type="clip", + num_heads=2, + hidden_size=20, + optimization_options=options, + opt_level=0, + ) + self.verify_fusion(optimized_model, model_name) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/ci_build/github/linux/python/requirements.txt b/tools/ci_build/github/linux/python/requirements.txt index e51cfb38f57a3..1a580b848a55a 100644 --- a/tools/ci_build/github/linux/python/requirements.txt +++ b/tools/ci_build/github/linux/python/requirements.txt @@ -7,4 +7,5 @@ onnx==1.17.0 ; python_version < '3.13' protobuf==4.21.12 sympy==1.12 flatbuffers -psutil \ No newline at end of file +psutil +onnxscript==0.2.3 diff --git a/tools/ci_build/github/windows/python/requirements.txt b/tools/ci_build/github/windows/python/requirements.txt index 200b9c2e50288..2b222c4b1d4a4 100644 --- a/tools/ci_build/github/windows/python/requirements.txt +++ b/tools/ci_build/github/windows/python/requirements.txt @@ -8,3 +8,4 @@ protobuf==4.21.12 sympy==1.12 flatbuffers psutil +onnxscript==0.2.3 diff --git a/tools/ci_build/requirements/transformers-test/requirements.txt b/tools/ci_build/requirements/transformers-test/requirements.txt index 0fb37e3a1550a..47286c364a90f 100644 --- a/tools/ci_build/requirements/transformers-test/requirements.txt +++ b/tools/ci_build/requirements/transformers-test/requirements.txt @@ -11,3 +11,4 @@ parameterized>=0.8.1 sentencepiece psutil einops +onnxscript==0.2.3 From 11fda2adb93a48404fa29e090f651b5825f95f0e Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 4 Apr 2025 13:40:17 -0700 Subject: [PATCH 234/266] Update packaging pipeline for Nodejs binding (#24301) ### Description Update packaging pipeline for Nodejs binding. This change updates the pipeline to perform all Node.js binding builds, including: - Windows x64 ( CPU, DML, WebGPU ) - Windows arm64 ( CPU, DML, WebGPU ) - Linux x64 ( CPU, CUDA, TensorRT, WebGPU ) - Linux arm64 ( CPU ) - MacOS x64 ( CPU, CoreML, WebGPU ) - MacOS arm64 ( CPU, CoreML, WebGPU ) #### Dependencies The Node.js binding depends on the Nuget package from the same build. Because NPM has a size limit so we cannot fit libonnxruntime_provider_cuda.so into it. The Node.js binding works in a way that an installation script will try to download the Nuget package of the corresponding version. --- .../c-api-noopenmp-packaging-pipelines.yml | 23 +++ .../stages/nodejs-linux-packaging-stage.yml | 57 ++++++ .../stages/nodejs-win-packaging-stage.yml | 192 ++++++++++++++++++ .../stages/nuget-combine-cuda-stage.yml | 5 + .../nuget-linux-cuda-packaging-stage.yml | 11 +- .../azure-pipelines/templates/c-api-cpu.yml | 177 +++++++--------- .../linux-cpu-packaging-pipeline.yml | 2 +- .../github/linux/build_nodejs_package.sh | 6 + 8 files changed, 362 insertions(+), 111 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/stages/nodejs-linux-packaging-stage.yml create mode 100644 tools/ci_build/github/azure-pipelines/stages/nodejs-win-packaging-stage.yml create mode 100755 tools/ci_build/github/linux/build_nodejs_package.sh diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index 722e7696ba738..8f1189b05858c 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -147,6 +147,29 @@ extends: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} + - template: stages/nodejs-win-packaging-stage.yml + parameters: + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + ArtifactName: 'drop-onnxruntime-nodejs-win-x64' + StageName: 'Windows_Nodejs_Packaging_x64' + BuildCommand: --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --use_webgpu --build_nodejs --cmake_generator "Visual Studio 17 2022" + BuildArch: 'x64' + EnvSetupScript: 'setup_env.bat' + sln_platform: 'x64' + DoEsrp: ${{ parameters.DoEsrp }} + PublishWebGpuBuildTools: true + + - template: stages/nodejs-win-packaging-stage.yml + parameters: + IsReleaseBuild: ${{ parameters.IsReleaseBuild }} + ArtifactName: 'drop-onnxruntime-nodejs-win-arm64' + StageName: 'Windows_Nodejs_Packaging_arm64' + BuildCommand: --arm64 --skip_submodule_sync --build_shared_lib --enable_onnx_tests --enable_wcos --use_telemetry --use_dml --use_webgpu --build_nodejs --cmake_generator "Visual Studio 17 2022" + BuildArch: 'x64' + EnvSetupScript: 'setup_env.bat' + sln_platform: 'arm64' + DoEsrp: ${{ parameters.DoEsrp }} + DependsOnStageName: Windows_Nodejs_Packaging_x64 - template: nuget/templates/dml-vs-2022.yml parameters: diff --git a/tools/ci_build/github/azure-pipelines/stages/nodejs-linux-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nodejs-linux-packaging-stage.yml new file mode 100644 index 0000000000000..e1247565d8f5b --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/stages/nodejs-linux-packaging-stage.yml @@ -0,0 +1,57 @@ +parameters: +- name: CudaVersion + type: string + default: '12.2' + +stages: +- stage: Linux_Nodejs_Packaging_x64 + dependsOn: [] + jobs: + - job: Linux_Nodejs_Packaging_x64 + dependsOn: [] + workspace: + clean: all + timeoutInMinutes: 180 + pool: + name: 'onnxruntime-Ubuntu2204-AMD-CPU' + os: linux + variables: + - template: ../templates/common-variables.yml + - name: CUDA_VERSION_MAJOR + ${{ if eq(parameters.CudaVersion, '11.8') }}: + value: '11' + ${{ if eq(parameters.CudaVersion, '12.2') }}: + value: '12' + - name: CUDA_VERSION + value: ${{ parameters.CudaVersion }} + - name: linux_trt_version + ${{ if eq(parameters.CudaVersion, '11.8') }}: + value: ${{ variables.linux_trt_version_cuda11 }} + ${{ if eq(parameters.CudaVersion, '12.2') }}: + value: ${{ variables.linux_trt_version_cuda12 }} + steps: + - checkout: self + clean: true + submodules: recursive + - template: ../templates/get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/default/cuda${{ variables.CUDA_VERSION_MAJOR }}/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/x86_64/default/cuda${{ variables.CUDA_VERSION_MAJOR }} + DockerBuildArgs: " + --build-arg TRT_VERSION=${{ variables.linux_trt_version }} + --build-arg BUILD_UID=$( id -u ) + " + Repository: onnxruntimecuda${{ variables.CUDA_VERSION_MAJOR }}xtrt86build + - template: ../templates/set-version-number-variables-step.yml + + - script: $(Build.SourcesDirectory)/tools/ci_build/github/linux/build_nodejs_package.sh + workingDirectory: $(Build.SourcesDirectory) + displayName: 'Build Node.js binding Package' + + - template: ../templates/nodejs-artifacts-package-and-publish-steps-posix.yml + parameters: + arch: 'x64' + os: 'linux' + artifactName: 'drop-onnxruntime-nodejs-linux-x64' + + - template: ../templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/stages/nodejs-win-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nodejs-win-packaging-stage.yml new file mode 100644 index 0000000000000..73e650eb07992 --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/stages/nodejs-win-packaging-stage.yml @@ -0,0 +1,192 @@ +parameters: + BuildCommand: '' + StageName: 'Windows_Nodejs_Packaging' + ArtifactName: 'drop-onnxruntime-nodejs-win' + DoEsrp: 'false' + BuildArch: 'x64' # Optional. Options: x86, x64 + sln_platform: 'x64' # Options: Win32, x64, arm, arm64 + AgentDemands: [] + BuildConfigurations: ['RelWithDebInfo'] # Options: Debug, RelWithDebInfo + EnableLto: true + # Controls whether unreleased onnx opsets are allowed. Default is set to 1 + AllowReleasedOpsetOnly: '0' + IsReleaseBuild: false + PublishWebGpuBuildTools: false + WebGpuBuildToolsArtifactName: 'Windows_WebGPU_BuildTools_x64' + DependsOnStageName: '' + +stages: +- stage: ${{ parameters.StageName }} + dependsOn: + - Setup + - ${{ if ne(parameters.DependsOnStageName, '') }}: + - ${{ parameters.DependsOnStageName }} + + jobs: + - job: ${{ parameters.StageName }} + timeoutInMinutes: 200 + strategy: + maxParallel: 2 + matrix: + ${{ each BuildConfiguration in parameters.BuildConfigurations }}: + ${{ BuildConfiguration }}: + BuildConfig: ${{ BuildConfiguration }} + workspace: + clean: all + pool: + name: onnxruntime-Win-CPU-2022 + demands: ${{ parameters.AgentDemands }} + variables: + buildDirectory: '$(Build.BinariesDirectory)' + OnnxRuntimeBuildDirectory: '$(Build.BinariesDirectory)' + runCodesignValidationInjection: ${{ parameters. DoEsrp}} #For the others, code sign is in a separated job + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: ${{ parameters.AllowReleasedOpsetOnly }} + BuildDate : $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Date.BuildDate']] + BuildTime : $[stageDependencies.Setup.Set_Variables.outputs['Set_Build_Time.BuildTime']] + BuildCommandExtra: '' + ${{ if eq(parameters.EnableLto, true) }}: + build_py_lto_flag: --enable_lto + + steps: + - checkout: self + clean: true + submodules: none + + - powershell: | + if($env:TELEMETRYGUID) + { + $length = $env:TELEMETRYGUID.length + $fileContent = "#define TraceLoggingOptionMicrosoftTelemetry() \ + TraceLoggingOptionGroup("+$env:TELEMETRYGUID.substring(1, $length-2)+")" + New-Item -Path "$(Build.SourcesDirectory)\include\onnxruntime\core\platform\windows\TraceLoggingConfigPrivate.h" -ItemType "file" -Value "$fileContent" -Force + Write-Output "Enabling TELEMETRY" + } + displayName: 'Create TraceLoggingConfigPrivate.h For WinML Telemetry' + env: + TELEMETRYGUID: $(TELEMETRYGUID) + + - task: NodeTool@0 + inputs: + versionSpec: '20.x' + + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + addToPath: true + architecture: ${{ parameters.BuildArch }} + + # need to set PROCESSOR_ARCHITECTURE so the x86 SDK is installed correctly + - task: UseDotNet@2 + inputs: + version: 8.x + env: + PROCESSOR_ARCHITECTURE: ${{ parameters.BuildArch }} + + - task: BatchScript@1 + displayName: 'Setup VS2022 env vars' + inputs: + filename: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat' + arguments: ${{ parameters.BuildArch }} + modifyEnvironment: true + + - ${{ if and(ne(parameters.WebGpuBuildToolsArtifactName, ''), eq(parameters.sln_platform, 'arm64')) }}: + - task: DownloadPipelineArtifact@2 + displayName: 'Download WebGPU build tools from x64 build' + inputs: + artifactName: '${{ parameters.WebGpuBuildToolsArtifactName }}' + targetPath: '$(Build.BinariesDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }}' + - script: | + @echo ##vso[task.setvariable variable=LLVM_TABLEGEN_PATH]$(Build.BinariesDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }}\llvm-tblgen.exe + @echo ##vso[task.setvariable variable=CLANG_TABLEGEN_PATH]$(Build.BinariesDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }}\clang-tblgen.exe + displayName: 'Set tablegen paths' + - powershell: | + Write-Host "Using LLVM_TABLEGEN_PATH: $(LLVM_TABLEGEN_PATH)" + Write-Host "Using CLANG_TABLEGEN_PATH: $(CLANG_TABLEGEN_PATH)" + Write-Host "##vso[task.setvariable variable=BuildCommandExtra]--cmake_extra_defines LLVM_TABLEGEN=$(LLVM_TABLEGEN_PATH) CLANG_TABLEGEN=$(CLANG_TABLEGEN_PATH)" + displayName: 'Set build flags for WebGPU cross-compilation' + + - powershell: | + python tools\ci_build\build.py --build_dir $(Build.BinariesDirectory) ${{ parameters.BuildCommand }} $(BuildCommandExtra) --use_binskim_compliant_compile_flags --parallel --build --update --config $(BuildConfig) --msbuild_extra_options IncludeMobileTargets=false ${{ variables.build_py_lto_flag }} + + - ${{ if notIn(parameters['sln_platform'], 'Win32', 'x64') }}: + # Use cross-compiled protoc + - script: | + @echo ##vso[task.setvariable variable=ProtocDirectory]$(Build.BinariesDirectory)\installed\bin + + # The Configuration variable is required to build C# + - script: | + @echo ##vso[task.setvariable variable=Configuration]$(BuildConfig) + displayName: 'Set Configuration variable' + + # Node.js Publish + - task: BatchScript@1 + displayName: 'Setup VS env vars' + inputs: + filename: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat' + arguments: ${{ parameters.BuildArch }} + modifyEnvironment: true + - task: CopyFiles@2 + displayName: 'Copy DirectML binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\$(BuildConfig)\$(BuildConfig)' + Contents: 'DirectML.dll' + TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}' + - powershell: | + $dxcZipUrl = "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2502/dxc_2025_02_20.zip" + $dxcZipPath = "$(Build.BinariesDirectory)\dxc.zip" + $dxcExtractPath = "$(Build.BinariesDirectory)\dxc_extracted" + $targetArch = "${{ parameters.sln_platform }}" + + # Download the DXC package + Write-Host "Downloading DXC release from $dxcZipUrl" + Invoke-WebRequest -Uri $dxcZipUrl -OutFile $dxcZipPath + + # Create extraction directory + if (-not (Test-Path $dxcExtractPath)) { + New-Item -Path $dxcExtractPath -ItemType Directory -Force + } + + # Extract the zip file + Write-Host "Extracting DXC package to $dxcExtractPath" + Expand-Archive -Path $dxcZipPath -DestinationPath $dxcExtractPath -Force + + # Copy the necessary DLLs to the target directory + $sourcePath = Join-Path $dxcExtractPath "bin\$targetArch" + $targetPath = "$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\$targetArch" + + Write-Host "Copying dxil.dll and dxcompiler.dll from $sourcePath to $targetPath" + Copy-Item -Path "$sourcePath\dxil.dll" -Destination $targetPath -Force + Copy-Item -Path "$sourcePath\dxcompiler.dll" -Destination $targetPath -Force + + Write-Host "DXC DLLs successfully copied to the target directory" + displayName: 'Download and Copy DXC Binaries' + - template: ../templates/win-esrp-dll.yml + parameters: + FolderPath: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}' + DisplayName: 'ESRP - Sign Node.js binding binaries' + DoEsrp: ${{ parameters.DoEsrp }} + Pattern: '*.dll,*.node' + + - script: | + del /Q $(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}\CodeSignSummary-*.* + call npm pack + copy $(Build.SourcesDirectory)\js\node\onnxruntime-*.tgz $(Build.ArtifactStagingDirectory) + workingDirectory: '$(Build.SourcesDirectory)\js\node' + displayName: 'Create NPM Package' + + - task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\${{ parameters.sln_platform }}' + artifactName: ${{ parameters.ArtifactName }} + + - ${{ if and(eq(parameters.PublishWebGpuBuildTools, true), eq(parameters.sln_platform, 'x64')) }}: + - script: | + mkdir $(Build.ArtifactStagingDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }} + copy $(Build.BinariesDirectory)\$(BuildConfig)\_deps\dawn-build\third_party\dxc\RelWithDebInfo\bin\llvm-tblgen.exe $(Build.ArtifactStagingDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }} + copy $(Build.BinariesDirectory)\$(BuildConfig)\_deps\dawn-build\third_party\dxc\RelWithDebInfo\bin\clang-tblgen.exe $(Build.ArtifactStagingDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }} + displayName: 'Copy WebGPU build tools' + - task: 1ES.PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)\${{ parameters.WebGpuBuildToolsArtifactName }}' + artifactName: ${{ parameters.WebGpuBuildToolsArtifactName }} diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml index 893bf3f1ec394..a4fe78a7088e3 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml @@ -39,6 +39,11 @@ stages: buildJava: ${{ parameters.buildJava }} buildNodejs: ${{ parameters.buildNodejs }} +- ${{ if eq(parameters.buildNodejs, 'true') }}: + - template: nodejs-linux-packaging-stage.yml + parameters: + CudaVersion: ${{ parameters.CudaVersion }} + - template: nuget-win-cuda-packaging-stage.yml parameters: RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml index 8560817331475..e36fe98fe0ac2 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml @@ -32,9 +32,7 @@ stages: parameters: Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/default/cuda${{ variables.CUDA_VERSION_MAJOR }}/Dockerfile Context: tools/ci_build/github/linux/docker/inference/x86_64/default/cuda${{ variables.CUDA_VERSION_MAJOR }} - DockerBuildArgs: " - --build-arg BUILD_UID=$( id -u ) - " + DockerBuildArgs: " --build-arg BUILD_UID=$( id -u )" Repository: onnxruntimecuda${{ variables.CUDA_VERSION_MAJOR }}build - script: $(Build.SourcesDirectory)/tools/ci_build/github/linux/build_cuda_c_api_package.sh @@ -113,13 +111,6 @@ stages: nativeLibraryName: 'libonnxruntime4j_jni.so' is1ES: true - - ${{ if eq(parameters.buildNodejs, 'true') }}: - - template: ../templates/nodejs-artifacts-package-and-publish-steps-posix.yml - parameters: - arch: 'x64' - os: 'linux' - artifactName: 'drop-onnxruntime-nodejs-linux-x64-tensorrt' - - template: ../templates/c-api-artifacts-package-and-publish-steps-posix.yml parameters: buildConfig: 'Release' diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index bb789edc1cf21..9b1d7b705e741 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -182,10 +182,10 @@ stages: buildArch: x64 msbuildPlatform: arm64 packageName: arm64 - buildparameter: --build_nodejs --arm64 ${{ parameters.AdditionalBuildFlags }} ${{ parameters.AdditionalWinBuildFlags}} + buildparameter: --arm64 ${{ parameters.AdditionalBuildFlags }} ${{ parameters.AdditionalWinBuildFlags}} runTests: false buildJava: false - buildNodejs: true + buildNodejs: false - template: win-ci.yml parameters: @@ -194,10 +194,10 @@ stages: buildArch: x64 msbuildPlatform: x64 packageName: x64 - buildparameter: --build_java --build_nodejs ${{ parameters.AdditionalBuildFlags }} ${{ parameters.AdditionalWinBuildFlags}} + buildparameter: --build_java ${{ parameters.AdditionalBuildFlags }} ${{ parameters.AdditionalWinBuildFlags}} runTests: ${{ parameters.RunOnnxRuntimeTests }} buildJava: true - buildNodejs: true + buildNodejs: false - stage: Jar_Packaging dependsOn: @@ -506,14 +506,11 @@ stages: - stage: Nodejs_Packaging dependsOn: - - Windows_CI_GPU_DML_Dev - - Windows_CI_GPU_DML_Dev_arm64 + - Windows_Nodejs_Packaging_x64 + - Windows_Nodejs_Packaging_arm64 + - Linux_Nodejs_Packaging_x64 - Linux_C_API_Packaging_CPU - - Linux_C_API_Packaging_GPU - MacOS_C_API_Package_Publish - - Windows_Packaging_CPU_x86_${{ parameters.BuildVariant }} - - Windows_Packaging_CPU_x64_${{ parameters.BuildVariant }} - - Windows_Packaging_CPU_arm64_${{ parameters.BuildVariant }} condition: succeeded() jobs: - job: Nodejs_Packaging @@ -544,74 +541,78 @@ stages: # Node.js binding artifacts preparation # # This stage prepares Node.js binding artifacts for publishing. The artifacts support the following platforms: - # - Windows x64 with DML support - # - Windows arm64 with DML support - # - Linux x64 with TensorRT support + # - Windows x64 (CPU, DML, WebGPU) + # - Windows arm64 (CPU, DML, WebGPU) + # - Linux x64 (CPU, CUDA, TensorRT, WebGPU) # - Linux arm64 (CPU only) - # - macOS x64 (CPU only) - # - macOS arm64 (CPU only) + # - macOS x64 (CPU, CoreML, WebGPU) + # - macOS arm64 (CPU, CoreML, WebGPU) + # + # File manifest: + # - Windows x64 (CPU, DML, WebGPU): + # dependency: Windows_Nodejs_Packaging_x64 (drop-onnxruntime-nodejs-win-x64) + # files: + # - onnxruntime_binding.node + # - onnxruntime.dll + # - DirectML.dll + # - dxil.dll + # - dxcompiler.dll + # + # - Windows arm64 (CPU, DML, WebGPU): + # dependency: Windows_Nodejs_Packaging_arm64 (drop-onnxruntime-nodejs-win-arm64) + # files: + # - onnxruntime_binding.node + # - onnxruntime.dll + # - DirectML.dll + # - dxil.dll + # - dxcompiler.dll # - # ORT Node.js binding artifacts contain 2 parts: - # 1. ONNX Runtime native shared libraries and their dependencies - # - Windows (x64, arm64): - # - onnxruntime.dll - # - DirectML.dll - # - Linux (x64, arm64): - # - libonnxruntime.so{.version} - # - libonnxruntime_providers_shared.so - # - libonnxruntime_providers_{provider}.so - # - macOS (x64, arm64): - # - libonnxruntime.dylib - # 2. ONNX Runtime Node.js binding - # - onnxruntime_binding.node + # - Linux x64 (CPU, CUDA, TensorRT, WebGPU): + # dependency: Linux_Nodejs_Packaging_x64 (drop-onnxruntime-nodejs-linux-x64) + # files: + # - onnxruntime_binding.node + # - libonnxruntime.so.1 + # - libonnxruntime_providers_shared.so + # - libonnxruntime_providers_cuda.so + # - libonnxruntime_providers_tensorrt.so # - # For windows platform, the artifact is named as 'onnxruntime-nodejs-win-x64-dml' for x64, and - # 'onnxruntime-nodejs-win-arm64-dml' for arm64. Each artifact contains both (1) and (2). + # - Linux arm64 (CPU only): + # dependency: Linux_C_API_Packaging_CPU_aarch64 (drop-onnxruntime-nodejs-linux-aarch64) + # files: + # - onnxruntime_binding.node + # - libonnxruntime.so.1 # - # For Linux and macOS platforms, (1) and (2) are packed into separate artifacts. - # The following artifacts contain (1): - # - onnxruntime-osx - # - onnxruntime-linux-x64-tensorrt - # - onnxruntime-linux-aarch64 - # The following artifacts contain (2): - # - drop-onnxruntime-nodejs-linux-x64-tensorrt - # - drop-onnxruntime-nodejs-linux-aarch64 - # - drop-onnxruntime-nodejs-osx-x86_64 - # - drop-onnxruntime-nodejs-osx-arm64 + # - macOS x64 (CPU, CoreML, WebGPU): + # dependency: MacOS_C_API_Packaging_CPU_x86_64 (drop-onnxruntime-nodejs-osx-x86_64) + # files: + # - onnxruntime_binding.node + # - libonnxruntime.{version}.dylib # - # All binary artifacts will eventually be put into folder before packaging 'onnxruntime-node': + # - macOS arm64 (CPU, CoreML, WebGPU): + # dependency: MacOS_C_API_Packaging_CPU_arm64 (drop-onnxruntime-nodejs-osx-arm64) + # files: + # - onnxruntime_binding.node + # - libonnxruntime.{version}.dylib + # + # The following files will be excluded from the further packaging because they are too large to be included in the + # NPM package: + # - linux/x64/libonnxruntime_providers_cuda.so + # + # Rest binary artifacts will eventually be put into folder before packaging 'onnxruntime-node': # $(Build.SourcesDirectory)\js\node\bin\napi-v3\{os}\{cpu_arch}\ # # {os} is one of 'win32', 'darwin', 'linux' and {cpu_arch} is one of 'x64', 'arm64'. - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet (OSX)' - inputs: - artifactName: 'onnxruntime-osx' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet (Linux x64)' - inputs: - artifactName: 'onnxruntime-linux-x64-tensorrt' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet (Linux aarch64)' - inputs: - artifactName: 'onnxruntime-linux-aarch64' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact' - - task: DownloadPipelineArtifact@0 displayName: 'Download Pipeline Artifact - Nodejs (Win x64)' inputs: - artifactName: 'drop-onnxruntime-nodejs-win-x64-dml' + artifactName: 'drop-onnxruntime-nodejs-win-x64' targetPath: '$(Build.BinariesDirectory)/nodejs-artifacts/win32/x64/' - task: DownloadPipelineArtifact@0 displayName: 'Download Pipeline Artifact - Nodejs (Win ARM64)' inputs: - artifactName: 'drop-onnxruntime-nodejs-win-arm64-dml' + artifactName: 'drop-onnxruntime-nodejs-win-arm64' targetPath: '$(Build.BinariesDirectory)/nodejs-artifacts/win32/arm64/' - task: DownloadPipelineArtifact@0 @@ -629,7 +630,7 @@ stages: - task: DownloadPipelineArtifact@0 displayName: 'Download Pipeline Artifact - Nodejs (Linux x64)' inputs: - artifactName: 'drop-onnxruntime-nodejs-linux-x64-tensorrt' + artifactName: 'drop-onnxruntime-nodejs-linux-x64' targetPath: '$(Build.BinariesDirectory)/nodejs-artifacts/linux/x64/' - task: DownloadPipelineArtifact@0 @@ -638,15 +639,9 @@ stages: artifactName: 'drop-onnxruntime-nodejs-linux-aarch64' targetPath: '$(Build.BinariesDirectory)/nodejs-artifacts/linux/arm64/' - - task: PowerShell@2 - displayName: 'PowerShell Script' - inputs: - targetType: filePath - filePath: $(Build.SourcesDirectory)\tools\ci_build\github\windows\extract_nuget_files.ps1 - - script: | - dir - workingDirectory: '$(Build.BinariesDirectory)/nuget-artifact' + dir /S + workingDirectory: '$(Build.BinariesDirectory)/nodejs-artifacts' displayName: 'List artifacts' - script: | @@ -683,61 +678,43 @@ stages: TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\win32\arm64' # Node.js binding linux/x64 - - task: CopyFiles@2 - displayName: 'Copy nuget binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\x64\' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-linux-x64-tensorrt\lib' - Contents: | - libonnxruntime.so.1 - libonnxruntime_providers_shared.so - TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\x64' - task: CopyFiles@2 displayName: 'Copy nodejs binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\x64\' inputs: SourceFolder: '$(Build.BinariesDirectory)\nodejs-artifacts\linux\x64' - Contents: '*.node' + Contents: | + libonnxruntime.so.1 + *.node TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\x64' # Node.js binding linux/arm64 - - task: CopyFiles@2 - displayName: 'Copy nuget binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64\' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-linux-aarch64\lib' - Contents: 'libonnxruntime.so.1' - TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64' - task: CopyFiles@2 displayName: 'Copy nodejs binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64\' inputs: SourceFolder: '$(Build.BinariesDirectory)\nodejs-artifacts\linux\arm64' - Contents: '*.node' + Contents: | + libonnxruntime.so.1 + *.node TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\linux\arm64' # Node.js binding darwin/x64 - - task: CopyFiles@2 - displayName: 'Copy nuget binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\x64\' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-osx-x86_64\lib' - Contents: 'libonnxruntime.*.dylib' - TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\x64' - task: CopyFiles@2 displayName: 'Copy nodejs binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\x64\' inputs: SourceFolder: '$(Build.BinariesDirectory)\nodejs-artifacts\darwin\x64' - Contents: '*.node' + Contents: | + libonnxruntime.*.dylib + *.node TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\x64' # Node.js binding darwin/arm64 - - task: CopyFiles@2 - displayName: 'Copy nuget binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\arm64\' - inputs: - SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\nuget-artifacts\onnxruntime-osx-arm64\lib' - Contents: 'libonnxruntime.*.dylib' - TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\arm64' - task: CopyFiles@2 displayName: 'Copy nodejs binaries to: $(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\arm64\' inputs: SourceFolder: '$(Build.BinariesDirectory)\nodejs-artifacts\darwin\arm64' - Contents: '*.node' + Contents: | + libonnxruntime.*.dylib + *.node TargetFolder: '$(Build.SourcesDirectory)\js\node\bin\napi-v3\darwin\arm64' - task: PowerShell@2 diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-cpu-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/templates/linux-cpu-packaging-pipeline.yml index 7ac2e3a8addb6..fb1c63e1f8a24 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-cpu-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-cpu-packaging-pipeline.yml @@ -34,7 +34,7 @@ stages: PoolName: 'onnxruntime-Ubuntu2204-AMD-CPU' ArtifactNamePrefix: ${{ parameters.ArtifactNamePrefix }} PackageJava: ${{ parameters.PackageJava }} - PackageNodeJS: ${{ parameters.PackageNodeJS }} + PackageNodeJS: false - template: c-api-linux-cpu.yml parameters: diff --git a/tools/ci_build/github/linux/build_nodejs_package.sh b/tools/ci_build/github/linux/build_nodejs_package.sh new file mode 100755 index 0000000000000..29ee91a122e39 --- /dev/null +++ b/tools/ci_build/github/linux/build_nodejs_package.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e -x +mkdir -p $HOME/.onnx +docker run -e SYSTEM_COLLECTIONURI --rm --volume /data/onnx:/data/onnx:ro --volume $BUILD_SOURCESDIRECTORY:/onnxruntime_src --volume $BUILD_BINARIESDIRECTORY:/build \ +--volume /data/models:/build/models:ro --volume $HOME/.onnx:/home/onnxruntimedev/.onnx -e NIGHTLY_BUILD onnxruntimecuda${CUDA_VERSION_MAJOR}xtrt86build \ +/bin/bash -c "/usr/bin/python3 /onnxruntime_src/tools/ci_build/build.py --build_dir /build --config Release --skip_tests --skip_submodule_sync --parallel --use_binskim_compliant_compile_flags --build_shared_lib --build_nodejs --use_webgpu --use_tensorrt --cuda_version=$CUDA_VERSION --cuda_home=/usr/local/cuda-$CUDA_VERSION --cudnn_home=/usr --tensorrt_home=/usr --cmake_extra_defines 'CMAKE_CUDA_ARCHITECTURES=60-real;70-real;75-real;80-real;90' --use_vcpkg --use_vcpkg_ms_internal_asset_cache && cd /build/Release && make install DESTDIR=/build/installed" From a4976e33ec9538c5a881f082c090a774af4a7a44 Mon Sep 17 00:00:00 2001 From: Sushanth Rajasankar <44513542+sushraja-msft@users.noreply.github.com> Date: Fri, 4 Apr 2025 15:43:38 -0700 Subject: [PATCH 235/266] Add support for uint8_t as data type for GatherBlockQuantized (#24239) ### Description This change adds support for GatherBlockQuantized to use uin8_t as data's type with the same semantics as MatMulNBits. Zero_Points and Gather Axis other than 0 are not yet supported, in order to keep the change scoped. ### Motivation and Context With the newer llama models like Phi4 trained with shared embeddings, the weights of the lm_head matrix and the embeddings table are exactly the same. These embeddings are huge, unquantized embeddings are 1.2GB in Phi4 mini instruct, at int4 quantization the weights are still 300MB. We can go a step further and have these two ops the lm_head matmulnbits and GatherBlockQuantized share the same weights, that would save 300MB on the model size. The two things that hinder that are the shape expectations for GatherBlockQuantized and the data type supported for data in GatherBlockQuantized. The shape can be solved via a simple reshape op, but the data type needs code changes and that is what this change does. Here is Phi4 modified with shared weights between lm_head and matmulnbits, this model is just 2.1GB on disk. image --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- docs/ContribOperators.md | 5 +- docs/OperatorKernels.md | 2 +- .../contrib_ops/cpu/cpu_contrib_kernels.cc | 4 + .../quantization/gather_block_quantized.cc | 45 +++++++++-- .../core/graph/contrib_ops/contrib_defs.cc | 21 ++++- .../gather_block_quantized_op_test.cc | 81 ++++++++++++++++++- 6 files changed, 142 insertions(+), 16 deletions(-) diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index f582abca34706..0308b5c79c508 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -2039,10 +2039,11 @@ This version of the operator has been available since version 1 of the 'com.micr 1. Input `data` is a constant. It is quantized block-wise along attribute `quantize_axis` with block size specified by attribute `block_size`. `block_size must` be a power of 2 and not smaller than 16, like 16, 32, 64, 128, .. 2. Input `data`'s scale and zero point are specified by input `scales` and `zero_points`. `scales` and `zero_points` are also constants. - If `zero_points` is not provided, 0 is the zero point. + If `zero_points` is not provided, 0 is the zero point except when data is uint8 type then the default zero point is 8. 3. During the op execution, `data` and `indices` are first used to generate the quantized output. Then, `scales` and `zero_points` are used to dequantize the output. 4. The `output` and `scales` have the same type. The `data` and `zero_points` have the same type. + 5. For uint8 data, the `gather_axis` must be 0. #### Version @@ -2082,7 +2083,7 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T1 : tensor(int4), tensor(uint4)
+
T1 : tensor(int4), tensor(uint4), tensor(uint8)
Constrain quantized types.
T2 : tensor(float), tensor(float16), tensor(bfloat16)
Constrain dequantized types.
diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 60d9e8e747eeb..a20333e2340c4 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -515,7 +515,7 @@ Do not modify directly.* |FusedConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*in* Z:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedGemm|*in* A:**T**
*in* B:**T**
*in* C:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| -|GatherBlockQuantized|*in* data:**T1**
*in* indices:**Tind**
*in* scales:**T2**
*in* zero_points:**T1**
*out* output:**T2**|1+|**T1** = tensor(int4), tensor(uint4)
**T2** = tensor(float), tensor(float16)
**Tind** = tensor(int32), tensor(int64)| +|GatherBlockQuantized|*in* data:**T1**
*in* indices:**Tind**
*in* scales:**T2**
*in* zero_points:**T1**
*out* output:**T2**|1+|**T1** = tensor(int4), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)
**Tind** = tensor(int32), tensor(int64)| |GatherND|*in* data:**T**
*in* indices:**Tind**
*out* output:**T**|1+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |GreedySearch|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*out* sequences:**I**|1+|**T** = tensor(float)| diff --git a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc index 345b5e793a764..1a737f3a9d251 100644 --- a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc @@ -38,6 +38,8 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, Fused class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, MatMulNBits); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MLFloat16, MatMulNBits); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MatMulBnb4); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, uint8_t, int32_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, uint8_t, int64_t, GatherBlockQuantized); class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, UInt4x2, int32_t, GatherBlockQuantized); class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, UInt4x2, int64_t, GatherBlockQuantized); class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, Int4x2, int32_t, GatherBlockQuantized); @@ -318,6 +320,8 @@ Status RegisterCpuContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc b/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc index 5935663f114a3..b83164d806ffc 100644 --- a/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc +++ b/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc @@ -16,6 +16,21 @@ namespace onnxruntime { namespace contrib { +namespace { +template +int32_t GetDataElement(const T1* data_ptr, int64_t data_idx) { + return static_cast(data_ptr[data_idx >> 1].GetElem(narrow(data_idx & 1))); +} + +template <> +int32_t GetDataElement(const uint8_t* data_ptr, int64_t data_idx) { + const uint8_t data_val_u8 = data_ptr[data_idx >> 1]; + // Weights are stored as (nibble2)(nibble1) in uint8_t. + auto data_val = static_cast((data_idx & 1) ? ((data_val_u8 >> 4) & 0x0F) : (data_val_u8 & 0x0F)); + return data_val; +} +} // namespace + template class GatherBlockQuantized : public OpKernel { public: @@ -98,6 +113,12 @@ Status GatherBlockQuantized::PrepareForCompute(OpKernelContext* contex for (int64_t i = p.gather_axis + 1; i < static_cast(data_rank); ++i) shape.push_back(data_shape[narrow(i)]); + // When data is stored as uint8_t, each element has two int4 values. + // The shape in the onnx model reflects that by having the last dimension be half the number of values. + // Ex: For a true data size of 2000x3072, the onnx model would have data of shape 2000x1536. + // However the outputs still need to be of size 2000x3072. Therefore we x2 the last dimension here. + uint32_t components = (std::is_same_v) ? 2 : 1; + shape[shape.size() - 1] = shape.back() * components; p.output_tensor = context->Output(0, TensorShape(std::move(shape))); // validate quantization parameters @@ -106,7 +127,7 @@ Status GatherBlockQuantized::PrepareForCompute(OpKernelContext* contex "data and scales must have the same rank."); for (size_t i = 0; i < data_shape.NumDimensions(); ++i) { ORT_RETURN_IF_NOT(i == static_cast(p.quantize_axis) - ? (data_shape[i] + block_size_ - 1) / block_size_ == scales_shape[i] + ? (data_shape[i] * components + block_size_ - 1) / block_size_ == scales_shape[i] : data_shape[i] == scales_shape[i], "data and scales do not match shapes."); } @@ -165,16 +186,22 @@ Status GatherBlockQuantized::CopyDataAndDequantize(const T1* data_ptr, int64_t output_idx = output_idx_base; int64_t data_idx = data_idx_base; for (int64_t i = 0; i < gather_block; ++i, ++output_idx, ++data_idx) { - auto data_val = static_cast(data_ptr[data_idx >> 1].GetElem(narrow(data_idx & 1))); + auto data_val = GetDataElement(data_ptr, data_idx); int64_t x = data_idx / quantize_full_block; int64_t y = data_idx % quantize_full_block / quantize_N; int64_t z = data_idx % quantize_N; int64_t scale_idx = x * scale_full_block + y / block_size_ * quantize_N + z; auto scale_val = static_cast(scales_ptr[scale_idx]); - auto zp_val = static_cast(zero_points_ptr - ? zero_points_ptr[scale_idx >> 1].GetElem(narrow(scale_idx & 1)) - : 0); + int32_t zp_val; + if constexpr (std::is_same_v) { + // The default zero point for uint8 weights as stored by MatMulNBits op is 8. + zp_val = 8; + } else { + zp_val = static_cast(zero_points_ptr + ? zero_points_ptr[scale_idx >> 1].GetElem(narrow(scale_idx & 1)) + : 0); + } output_ptr[output_idx] = static_cast(static_cast(data_val - zp_val) * scale_val); } @@ -205,7 +232,7 @@ template Status GatherBlockQuantized::Compute(OpKernelContext* context) const { Prepare p; ORT_RETURN_IF_ERROR(PrepareForCompute(context, p)); - + auto components = (std::is_same_v) ? 2 : 1; const auto& data_shape = p.data_tensor->Shape(); // re-shape the data tensor to [gather_M, gather_axis_dim, gather_block] // re-shape the indices tensor to [gather_N] @@ -215,7 +242,7 @@ Status GatherBlockQuantized::Compute(OpKernelContext* context) const { // 2> block is picked from data based on value from indices: axis_i = indices[blk_i % gather_N], // 3> get the corresponding block in data tensor: data_blk = data[blk_i / gather_N, axis_i, :], // 4> pick the element from the block: value_i = data_blk[blk_ele_i] - const int64_t gather_block = data_shape.SizeFromDimension(SafeInt(p.gather_axis) + 1); + const int64_t gather_block = data_shape.SizeFromDimension(SafeInt(p.gather_axis) + 1) * components; const int64_t gather_axis_dim = data_shape[narrow(p.gather_axis)]; const int64_t gather_M = data_shape.SizeToDimension(narrow(p.gather_axis)); const int64_t gather_N = p.indices_tensor->Shape().Size(); @@ -229,7 +256,7 @@ Status GatherBlockQuantized::Compute(OpKernelContext* context) const { // data_i % (quantize_axis_dim * quantize_N) / quantize_N, // data_i % quantize_N) // 4> get scale index: (x, y / block_size_, z) - const int64_t quantize_axis_dim = data_shape[narrow(p.quantize_axis)]; + const int64_t quantize_axis_dim = data_shape[narrow(p.quantize_axis)] * components; const int64_t quantize_N = data_shape.SizeFromDimension(SafeInt(p.quantize_axis) + 1); concurrency::ThreadPool* tp = context->GetOperatorThreadPool(); @@ -273,6 +300,8 @@ Status GatherBlockQuantized::Compute(OpKernelContext* context) const { .TypeConstraint("Tind", DataTypeImpl::GetTensorType()), \ GatherBlockQuantized); +REGISTER_GATHERBLOCKQUANTIZED(uint8_t, int32_t); +REGISTER_GATHERBLOCKQUANTIZED(uint8_t, int64_t); REGISTER_GATHERBLOCKQUANTIZED(UInt4x2, int32_t); REGISTER_GATHERBLOCKQUANTIZED(UInt4x2, int64_t); REGISTER_GATHERBLOCKQUANTIZED(Int4x2, int32_t); diff --git a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc index 7b4a45ce8aa0f..d87688a62040c 100644 --- a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc @@ -3571,10 +3571,11 @@ GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (h 1. Input `data` is a constant. It is quantized block-wise along attribute `quantize_axis` with block size specified by attribute `block_size`. `block_size must` be a power of 2 and not smaller than 16, like 16, 32, 64, 128, .. 2. Input `data`'s scale and zero point are specified by input `scales` and `zero_points`. `scales` and `zero_points` are also constants. - If `zero_points` is not provided, 0 is the zero point. + If `zero_points` is not provided, 0 is the zero point except when data is uint8 type then the default zero point is 8. 3. During the op execution, `data` and `indices` are first used to generate the quantized output. Then, `scales` and `zero_points` are used to dequantize the output. 4. The `output` and `scales` have the same type. The `data` and `zero_points` have the same type. + 5. For uint8 data, the `gather_axis` must be 0. )DOC"; ONNX_CONTRIB_OPERATOR_SCHEMA(GatherBlockQuantized) @@ -3602,7 +3603,7 @@ GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (h .Input(2, "scales", "quantization scale", "T2") .Input(3, "zero_points", "quantization zero points", "T1", OpSchema::Optional) .Output(0, "output", "Dequantized output tensor of rank q + (r - 1).", "T2") - .TypeConstraint("T1", {"tensor(int4)", "tensor(uint4)"}, "Constrain quantized types.") + .TypeConstraint("T1", {"tensor(int4)", "tensor(uint4)", "tensor(uint8)"}, "Constrain quantized types.") .TypeConstraint("T2", {"tensor(float)", "tensor(float16)", "tensor(bfloat16)"}, "Constrain dequantized types.") .TypeConstraint("Tind", {"tensor(int32)", "tensor(int64)"}, "Constrain indices to integer types.") .TypeAndShapeInferenceFunction([](ONNX_NAMESPACE::InferenceContext& ctx) { @@ -3637,14 +3638,19 @@ GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (h gather_axis = (gather_axis + r) % r; quantize_axis = (quantize_axis + r) % r; + if ((ctx.getInputType(0)->tensor_type().elem_type() == onnx::TensorProto_DataType_UINT8) && gather_axis != 0) { + fail_shape_inference("gather_axis must be 0, for uint8 data"); + } + if (scales_shape.dim_size() != r) { fail_shape_inference("scales must have the same rank as data"); } + uint32_t components = ctx.getInputType(0)->tensor_type().elem_type() == onnx::TensorProto_DataType_UINT8 ? 2 : 1; for (int i = 0; i < r; ++i) { if (!data_shape.dim(i).has_dim_value() || !scales_shape.dim(i).has_dim_value() || - (i == quantize_axis && (data_shape.dim(i).dim_value() + block_size - 1) / block_size != scales_shape.dim(i).dim_value()) || + (i == quantize_axis && (data_shape.dim(i).dim_value() * components + block_size - 1) / block_size != scales_shape.dim(i).dim_value()) || (i != quantize_axis && data_shape.dim(i).dim_value() != scales_shape.dim(i).dim_value())) { fail_shape_inference("data shape and scales shape do not match"); } @@ -3652,6 +3658,10 @@ GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (h // validate zero point shape if (ctx.hasInput(3)) { + if (ctx.getInputType(0)->tensor_type().elem_type() == onnx::TensorProto_DataType_UINT8) { + fail_type_inference("zero_points are not supported for uint8_t data type"); + } + if (!hasInputShape(ctx, 3)) { fail_shape_inference("zero_points shape must be known"); } @@ -3675,12 +3685,15 @@ GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (h ctx.getOutputType(0)->mutable_tensor_type()->mutable_shape(); } for (int i = 0; i < out_rank; ++i) { + // For uint8_t data type the last dimension needs to be expanded back to actual dimension, + // because the data 2 int4s are stored packed in a single uint8_t. + auto last_dimension_components = (i == out_rank - 1) ? components : 1; *ctx.getOutputType(0)->mutable_tensor_type()->mutable_shape()->add_dim() = (i < gather_axis) ? data_shape.dim(i) : (i >= gather_axis && i < gather_axis + q) ? indices_shape.dim(i - gather_axis) - : data_shape.dim(i - q + 1); + : data_shape.dim(i - q + 1) * last_dimension_components; } }); diff --git a/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc b/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc index c4536fc56a22f..0dfe194e893e2 100644 --- a/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc +++ b/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc @@ -15,6 +15,27 @@ namespace onnxruntime { namespace test { +// When uint8_t data type is used GatherBlockQuantize applies MatMulNBit's conventions for storing the data. +// That is when no zero points are specified a default zero point of 8 is used. This convertor hence +// compensates for that by adding 8 to the data values, so that the outputs match the results that +// we be seen with non uint8_t data types. +template +void PackDataForUint8TypeIfNecessary(std::vector& data, std::vector& data_shape) { + if (!std::is_same_v) { + return; + } + // For uint8_t, we need to pack each pair of values (after adding 8) into a single uint8_t + std::vector packed_data; + for (size_t i = 0; i < data.size(); i += 2) { + int low_nibble = (data[i] + 8) & 0xF; + int high_nibble = ((i + 1) < data.size()) ? ((data[i + 1] + 8) & 0xF) : 0; + int packed = (high_nibble << 4) | low_nibble; + packed_data.push_back(packed); + } + data = packed_data; + data_shape[data_shape.size() - 1] = (data_shape[data_shape.size() - 1] + 1) / 2; +} + // Combinations: types, gather_axis, quantize_axis, block_size, indices, scale shape vs data shape template void RunGatherBlockQuantized(const std::vector& data, @@ -96,6 +117,7 @@ void Test_Fail_WithZeroPoints(int64_t gather_axis, 4, 5, 6, 7, -4, -3, -2, -1}; std::vector data_shape = {2, 3, 4}; + PackDataForUint8TypeIfNecessary(data, data_shape); std::vector indices = {1}; std::vector indices_shape = {1}; std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; @@ -123,7 +145,6 @@ void Test_Fail_WithZeroPoints(int64_t gather_axis, TEST(GatherBlockQuantizedOpTest, UnsupportedTypes) { Test_Fail_WithZeroPoints(0, 2, 16); - Test_Fail_WithZeroPoints(0, 2, 16); Test_Fail_WithZeroPoints(0, 2, 16); Test_Fail_WithZeroPoints(0, 2, 16); Test_Fail_WithZeroPoints(0, 2, 16); @@ -134,21 +155,70 @@ TEST(GatherBlockQuantizedOpTest, UnsupportedTypes) { Test_Fail_WithZeroPoints(0, 2, 16); Test_Fail_WithZeroPoints(0, 2, 16); Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); +} + +template +void Test_Fail_WithoutZeroPoints(int64_t gather_axis, + int64_t quantize_axis, + int64_t block_size) { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + PackDataForUint8TypeIfNecessary(data, data_shape); + std::vector indices = {1}; + std::vector indices_shape = {1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {2, 3, 1}; + std::vector output = {8.f, 10.f, 12.f, 14.f, + 3.f, 4.f, 5.f, 6.f, + -6.f, -4.f, -2.f, 0.f}; + std::vector output_shape = {1, 3, 4}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + {}, + gather_axis, + quantize_axis, + block_size, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectFailure); +} + +TEST(GatherBlockQuantizedOpTest, UnsupportedUInt8DataType) { + // T1 uint8_t with zero points is not yet supported. + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + // Gather on axis other than 0 is not supported with uint8_t + Test_Fail_WithoutZeroPoints(1, 2, 16); + Test_Fail_WithoutZeroPoints(1, 2, 16); } TEST(GatherBlockQuantizedOpTest, InvalidBlockSize) { Test_Fail_WithZeroPoints(0, 2, 8); Test_Fail_WithZeroPoints(0, 2, 17); + Test_Fail_WithZeroPoints(0, 2, 17); } TEST(GatherBlockQuantizedOpTest, InvalidGatherAxis) { Test_Fail_WithZeroPoints(3, 2, 16); Test_Fail_WithZeroPoints(-4, 2, 16); + Test_Fail_WithZeroPoints(-4, 2, 16); } TEST(GatherBlockQuantizedOpTest, InvalidQuantizeAxis) { Test_Fail_WithZeroPoints(0, 3, 16); Test_Fail_WithZeroPoints(0, -4, 16); + Test_Fail_WithZeroPoints(0, -4, 16); } template @@ -160,6 +230,7 @@ void Test_ShapeMismatch_WithZeroPoints() { 4, 5, 6, 7, -4, -3, -2, -1}; std::vector data_shape = {2, 3, 4}; + PackDataForUint8TypeIfNecessary(data, data_shape); std::vector indices = {1}; std::vector indices_shape = {1}; std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f}; @@ -188,6 +259,7 @@ void Test_ShapeMismatch_WithZeroPoints() { TEST(GatherBlockQuantizedOpTest, ShapeMismatch) { Test_ShapeMismatch_WithZeroPoints(); Test_ShapeMismatch_WithZeroPoints(); + Test_ShapeMismatch_WithZeroPoints(); } template @@ -199,6 +271,7 @@ void Test_InvalidIndices_WithZeroPoints() { 4, 5, 6, 7, -4, -3, -2, -1}; std::vector data_shape = {2, 3, 4}; + PackDataForUint8TypeIfNecessary(data, data_shape); std::vector indices = {2}; std::vector indices_shape = {1}; std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; @@ -227,6 +300,7 @@ void Test_InvalidIndices_WithZeroPoints() { TEST(GatherBlockQuantizedOpTest, InvalidIndices) { Test_InvalidIndices_WithZeroPoints(); Test_InvalidIndices_WithZeroPoints(); + Test_InvalidIndices_WithZeroPoints(); } template @@ -298,6 +372,7 @@ void Test_GatherAxis0_NoZeroPoints() { 4, 5, 6, 7, -4, -3, -2, -1}; std::vector data_shape = {2, 3, 4}; + PackDataForUint8TypeIfNecessary(data, data_shape); std::vector indices = {1}; std::vector indices_shape = {1}; std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; @@ -340,6 +415,10 @@ TEST(GatherBlockQuantizedOpTest, GatherAxis0NoZeroPoints) { Test_GatherAxis0_NoZeroPoints(); Test_GatherAxis0_NoZeroPoints(); Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); } template From 9102aaee3db864a4b38a4f7ddca3437f1aef0efd Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Fri, 4 Apr 2025 16:46:38 -0700 Subject: [PATCH 236/266] [Native WebGPU] Add Conv, ConTranspose and FusedConv (#24186) ### Description Add Conv, ConvTranspose, and FusedConv to the WebGPU execution provider. ### Motivation and Context Required for operator coverage. --- onnxruntime/contrib_ops/webgpu/fused_conv.cc | 33 ++ .../webgpu/webgpu_contrib_kernels.cc | 2 +- .../core/optimizer/conv_activation_fusion.cc | 2 +- .../core/optimizer/graph_transformer_utils.cc | 26 +- .../core/providers/webgpu/math/matmul.cc | 72 +++-- .../core/providers/webgpu/math/matmul.h | 12 +- .../providers/webgpu/math/matmul_packed.cc | 291 +++++++++++------- .../providers/webgpu/math/matmul_packed.h | 41 ++- .../providers/webgpu/nn/activation_util.cc | 25 ++ .../providers/webgpu/nn/activation_util.h | 15 + onnxruntime/core/providers/webgpu/nn/conv.cc | 273 ++++++++++++++++ onnxruntime/core/providers/webgpu/nn/conv.h | 34 ++ .../providers/webgpu/nn/conv2d_mm_webgpu.cc | 232 ++++++++++++++ .../providers/webgpu/nn/conv2d_mm_webgpu.h | 61 ++++ .../webgpu/nn/conv_backprop_webgpu.cc | 191 ++++++++++++ .../webgpu/nn/conv_backprop_webgpu.h | 49 +++ .../providers/webgpu/nn/conv_transpose.cc | 132 ++++++++ .../core/providers/webgpu/nn/conv_transpose.h | 27 ++ .../core/providers/webgpu/nn/conv_utils.cc | 22 ++ .../core/providers/webgpu/nn/conv_utils.h | 15 + .../core/providers/webgpu/nn/fuse_utils.cc | 79 +++++ .../core/providers/webgpu/nn/fuse_utils.h | 51 +++ .../core/providers/webgpu/nn/grouped_conv.cc | 93 ++++++ .../core/providers/webgpu/nn/grouped_conv.h | 36 +++ .../webgpu/webgpu_execution_provider.cc | 30 +- .../core/providers/webgpu/webgpu_utils.cc | 24 ++ .../core/providers/webgpu/webgpu_utils.h | 5 + onnxruntime/core/session/inference_session.cc | 7 +- .../test/contrib_ops/fused_conv_test.cc | 19 +- .../test/optimizer/graph_transform_test.cc | 19 ++ .../test/providers/cpu/nn/conv_op_test.cc | 8 +- .../cpu/nn/conv_transpose_op_test.cc | 4 +- 32 files changed, 1747 insertions(+), 183 deletions(-) create mode 100644 onnxruntime/contrib_ops/webgpu/fused_conv.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/activation_util.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/activation_util.h create mode 100644 onnxruntime/core/providers/webgpu/nn/conv.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/conv.h create mode 100644 onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.h create mode 100644 onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.h create mode 100644 onnxruntime/core/providers/webgpu/nn/conv_transpose.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/conv_transpose.h create mode 100644 onnxruntime/core/providers/webgpu/nn/conv_utils.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/conv_utils.h create mode 100644 onnxruntime/core/providers/webgpu/nn/fuse_utils.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/fuse_utils.h create mode 100644 onnxruntime/core/providers/webgpu/nn/grouped_conv.cc create mode 100644 onnxruntime/core/providers/webgpu/nn/grouped_conv.h create mode 100644 onnxruntime/core/providers/webgpu/webgpu_utils.cc diff --git a/onnxruntime/contrib_ops/webgpu/fused_conv.cc b/onnxruntime/contrib_ops/webgpu/fused_conv.cc new file mode 100644 index 0000000000000..e6b7ac3ec24d4 --- /dev/null +++ b/onnxruntime/contrib_ops/webgpu/fused_conv.cc @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/nn/conv.h" +#include "contrib_ops/webgpu/webgpu_contrib_kernels.h" +#include "core/providers/webgpu/nn/fuse_utils.h" + +namespace onnxruntime { +namespace contrib { +namespace webgpu { +using onnxruntime::webgpu::Conv; +template +class FusedConv final : public Conv { + public: + FusedConv(const OpKernelInfo& info) : Conv(info) { + ORT_ENFORCE(GetFusedActivationAttr(info, Conv::activation_).IsOK()); + } +}; + +ONNX_OPERATOR_KERNEL_EX( + FusedConv, + kMSDomain, + 1, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", onnxruntime::webgpu::WebGpuSupportedFloatTypes()), + FusedConv); + +} // namespace webgpu +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc b/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc index 6e63ba3a0caa4..4136477a1d88c 100644 --- a/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc @@ -40,7 +40,7 @@ Status RegisterWebGpuContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/core/optimizer/conv_activation_fusion.cc b/onnxruntime/core/optimizer/conv_activation_fusion.cc index ea9d8605e2417..71c8667a89b1d 100644 --- a/onnxruntime/core/optimizer/conv_activation_fusion.cc +++ b/onnxruntime/core/optimizer/conv_activation_fusion.cc @@ -121,7 +121,7 @@ class ConvActivationSelector : public NodeSelector { if (!graph_utils::IsSupportedOptypeVersionAndDomain(*next_node, "Relu", {6, 13, 14})) { return std::nullopt; } - } else if (node_ep.empty() || node_ep == kCpuExecutionProvider || node_ep == kJsExecutionProvider) { + } else if (node_ep.empty() || node_ep == kCpuExecutionProvider || node_ep == kJsExecutionProvider || node_ep == kWebGpuExecutionProvider) { if (!is_supported_non_cuda_rocm_ep_activation(*next_node) && !graph_utils::IsSupportedOptypeVersionAndDomain(*next_node, "HardSigmoid", {6})) { return std::nullopt; diff --git a/onnxruntime/core/optimizer/graph_transformer_utils.cc b/onnxruntime/core/optimizer/graph_transformer_utils.cc index 9684394da0520..eae2a464cef7e 100644 --- a/onnxruntime/core/optimizer/graph_transformer_utils.cc +++ b/onnxruntime/core/optimizer/graph_transformer_utils.cc @@ -296,17 +296,19 @@ InlinedVector> GenerateTransformers( onnxruntime::kCudaExecutionProvider, onnxruntime::kRocmExecutionProvider, onnxruntime::kDmlExecutionProvider}; - const InlinedHashSet cpu_rocm_acl_armnn_js_eps = {onnxruntime::kCpuExecutionProvider, - onnxruntime::kRocmExecutionProvider, - onnxruntime::kAclExecutionProvider, - onnxruntime::kArmNNExecutionProvider, - onnxruntime::kJsExecutionProvider}; - const InlinedHashSet cpu_cuda_rocm_acl_armnn_js_eps = {onnxruntime::kCpuExecutionProvider, - onnxruntime::kCudaExecutionProvider, - onnxruntime::kRocmExecutionProvider, - onnxruntime::kAclExecutionProvider, - onnxruntime::kArmNNExecutionProvider, - onnxruntime::kJsExecutionProvider}; + const InlinedHashSet cpu_rocm_acl_armnn_js_webgpu_eps = {onnxruntime::kCpuExecutionProvider, + onnxruntime::kRocmExecutionProvider, + onnxruntime::kAclExecutionProvider, + onnxruntime::kArmNNExecutionProvider, + onnxruntime::kJsExecutionProvider, + onnxruntime::kWebGpuExecutionProvider}; + const InlinedHashSet cpu_cuda_rocm_acl_armnn_js_webgpu_eps = {onnxruntime::kCpuExecutionProvider, + onnxruntime::kCudaExecutionProvider, + onnxruntime::kRocmExecutionProvider, + onnxruntime::kAclExecutionProvider, + onnxruntime::kArmNNExecutionProvider, + onnxruntime::kJsExecutionProvider, + onnxruntime::kWebGpuExecutionProvider}; const InlinedHashSet cpu_dml_acl_eps = {onnxruntime::kCpuExecutionProvider, onnxruntime::kDmlExecutionProvider, onnxruntime::kAclExecutionProvider}; @@ -338,7 +340,7 @@ InlinedVector> GenerateTransformers( transformers.emplace_back(std::make_unique(cpu_dml_acl_eps)); transformers.emplace_back(std::make_unique(cpu_acl_eps)); - transformers.emplace_back(std::make_unique(cpu_rocm_acl_armnn_js_eps)); + transformers.emplace_back(std::make_unique(cpu_rocm_acl_armnn_js_webgpu_eps)); transformers.emplace_back(std::make_unique(cpu_acl_cuda_dml_rocm_eps, level)); transformers.emplace_back(std::make_unique(cpu_acl_cuda_dml_rocm_eps, level)); diff --git a/onnxruntime/core/providers/webgpu/math/matmul.cc b/onnxruntime/core/providers/webgpu/math/matmul.cc index 9b447d5fdb59a..cdd3909874e7f 100644 --- a/onnxruntime/core/providers/webgpu/math/matmul.cc +++ b/onnxruntime/core/providers/webgpu/math/matmul.cc @@ -6,8 +6,9 @@ #include "core/providers/cpu/tensor/utils.h" #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_supported_types.h" - +#include "core/providers/webgpu/nn/fuse_utils.h" #include "core/providers/webgpu/data_transfer.h" + namespace onnxruntime { namespace webgpu { @@ -54,11 +55,12 @@ Status MatMulNaiveProgram::GenerateShaderCode(ShaderHelper& shader) const { std::string process_bias; if (has_bias_) { shader.AddInput("bias", ShaderUsage::UseUniform); - process_bias = "value += output_value_t(bias[row + i]);"; + process_bias = is_channels_last_ ? "value += output_value_t(bias[col])" : "value += output_value_t(bias[row + i]);"; } + std::string apply_activation = GetActivationSnippet(activation_, "output_value_t", "output_element_t"); const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | - ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); const auto& batch_dims = shader.AddIndices("batch_dims"); int a_components = a.NumComponents(); @@ -90,6 +92,7 @@ Status MatMulNaiveProgram::GenerateShaderCode(ShaderHelper& shader) const { << "for (var i = 0u; i < " << output_number_ << "u; i++) {\n" << " var value = values[i];\n" << process_bias << "\n" + << apply_activation << "\n" << " let cur_indices = output_indices_t(batch, row + i, col/ " << components << ");\n" << " let offset = " << output.IndicesToOffset("cur_indices") << ";\n" << output.SetByOffset("offset", "value") @@ -127,7 +130,7 @@ Status MatMul::ComputeInternal(ComputeContext& context) const { const int64_t a_rows = a->Shape().NumDimensions() > 1 ? a->Shape()[a->Shape().NumDimensions() - 2] : 1; TensorShape output_shape_shader({batch_size, a_rows, helper.N() / components}); - MatMulNaiveProgram program{output_rank, output_number, has_bias}; + MatMulNaiveProgram program{Activation(), output_rank, output_number, has_bias}; program .CacheHint(std::to_string(components), std::to_string(a_components), std::to_string(output_number)) @@ -147,11 +150,32 @@ Status MatMul::ComputeInternal(ComputeContext& context) const { return context.RunProgram(program); } - int64_t batchA = a->Shape().SizeToDimension(a->Shape().NumDimensions() - 2); - int64_t batchB = b->Shape().SizeToDimension(b->Shape().NumDimensions() - 2); + std::vector inputs(has_bias ? 3 : 2); + inputs[0] = a; + inputs[1] = b; + if (has_bias) { + const auto* bias = context.Input(2); + inputs.push_back(bias); + } + auto program = CreateMatMulProgram(Activation(), inputs, output_tensor, false); + + return context.RunProgram(program); +} + +MatMulProgram CreateMatMulProgram(const Activation& activation, std::vector& inputs, Tensor* output_tensor, bool is_channels_last, + const TensorShape& input_a_reshape, + const TensorShape& input_b_reshape) { + const auto* a = inputs[0]; + const auto* b = inputs[1]; + bool has_bias = inputs.size() > 2; + TensorShape a_shape = input_a_reshape.NumDimensions() > 0 ? input_a_reshape : a->Shape(); + TensorShape b_shape = input_b_reshape.NumDimensions() > 0 ? input_b_reshape : b->Shape(); + + MatMulComputeHelper helper; + ORT_THROW_IF_ERROR(helper.Compute(a_shape, b_shape)); + int64_t batchA = a_shape.SizeToDimension(a_shape.NumDimensions() - 2); + int64_t batchB = b_shape.SizeToDimension(b_shape.NumDimensions() - 2); - TensorShape a_shape = a->Shape(); - TensorShape b_shape = b->Shape(); TensorShape output_shape = helper.OutputShape(); const int64_t dim_output_outer = output_shape[output_shape.NumDimensions() - 2]; @@ -184,9 +208,9 @@ Status MatMul::ComputeInternal(ComputeContext& context) const { const int64_t batch_size = outer_dims.Size(); // Get dimensions for matrix multiplication from TensorShape - const int32_t dim_a_outer = narrow(a_shape[a_shape.NumDimensions() - 2]); // left matrix second dimension - const int32_t dim_inner = narrow(a_shape[a_shape.NumDimensions() - 1]); // left matrix first dimension - const int32_t dim_b_outer = narrow(b_shape[b_shape.NumDimensions() - 1]); // right matrix first dimension + const uint32_t dim_a_outer = narrow(a_shape[a_shape.NumDimensions() - 2]); // left matrix second dimension + const uint32_t dim_inner = narrow(a_shape[a_shape.NumDimensions() - 1]); // left matrix first dimension + const uint32_t dim_b_outer = narrow(b_shape[b_shape.NumDimensions() - 1]); // right matrix first dimension const bool is_vec4 = dim_inner % 4 == 0 && dim_b_outer % 4 == 0; @@ -194,34 +218,36 @@ Status MatMul::ComputeInternal(ComputeContext& context) const { ? InlinedVector({4, 1, 1}) : InlinedVector({4, 4, 1}); - const uint32_t dispatch_x = narrow((dim_b_outer + MATMUL_PACKED_WORKGROUP_SIZE_X * elements_per_thread[0] - 1) / - (MATMUL_PACKED_WORKGROUP_SIZE_X * elements_per_thread[0])); - const uint32_t dispatch_y = narrow((dim_a_outer + MATMUL_PACKED_WORKGROUP_SIZE_Y * elements_per_thread[1] - 1) / - (MATMUL_PACKED_WORKGROUP_SIZE_Y * elements_per_thread[1])); - const uint32_t dispatch_z = narrow((static_cast(batch_size) + MATMUL_PACKED_WORKGROUP_SIZE_Z * elements_per_thread[2] - 1) / - (MATMUL_PACKED_WORKGROUP_SIZE_Z * elements_per_thread[2])); + const uint32_t dispatch_x = narrow((dim_b_outer + MatMul::MATMUL_PACKED_WORKGROUP_SIZE_X * elements_per_thread[0] - 1) / + (MatMul::MATMUL_PACKED_WORKGROUP_SIZE_X * elements_per_thread[0])); + const uint32_t dispatch_y = narrow((dim_a_outer + MatMul::MATMUL_PACKED_WORKGROUP_SIZE_Y * elements_per_thread[1] - 1) / + (MatMul::MATMUL_PACKED_WORKGROUP_SIZE_Y * elements_per_thread[1])); + const uint32_t dispatch_z = narrow((static_cast(batch_size) + MatMul::MATMUL_PACKED_WORKGROUP_SIZE_Z * elements_per_thread[2] - 1) / + (MatMul::MATMUL_PACKED_WORKGROUP_SIZE_Z * elements_per_thread[2])); const int components = is_vec4 ? 4 : 1; const TensorShape a_shape_temp = CreateMatMulIntermediateShape(outer_dims_a, dim_a_outer, dim_inner, components); const TensorShape b_shape_temp = CreateMatMulIntermediateShape(outer_dims_b, dim_inner, dim_b_outer, components); const TensorShape output_shape_temp = TensorShape({batch_size, dim_a_outer, dim_b_outer / components}); - MatMulProgram program{has_bias, is_vec4, elements_per_thread}; + MatMulProgram program{activation, has_bias, is_vec4, elements_per_thread, is_channels_last}; program - .CacheHint(absl::StrJoin(elements_per_thread, "-"), std::to_string(is_vec4)) + .CacheHint(activation.ToString(), absl::StrJoin(elements_per_thread, "-"), std::to_string(is_vec4)) .AddInputs({{a, ProgramTensorMetadataDependency::TypeAndRank, a_shape_temp, components}, {b, ProgramTensorMetadataDependency::TypeAndRank, b_shape_temp, components}}) .AddOutputs({{output_tensor, ProgramTensorMetadataDependency::Rank, output_shape_temp, components}}) .AddUniformVariables({{dim_a_outer}, {dim_b_outer}, {dim_inner}}) .AddIndices(outer_dims) .SetDispatchGroupSize(dispatch_x, dispatch_y, dispatch_z) - .SetWorkgroupSize(MATMUL_PACKED_WORKGROUP_SIZE_X, MATMUL_PACKED_WORKGROUP_SIZE_Y, MATMUL_PACKED_WORKGROUP_SIZE_Z); + .SetWorkgroupSize(MatMul::MATMUL_PACKED_WORKGROUP_SIZE_X, MatMul::MATMUL_PACKED_WORKGROUP_SIZE_Y, MatMul::MATMUL_PACKED_WORKGROUP_SIZE_Z); if (has_bias) { - const auto* bias = context.Input(2); - program.AddInput({bias, ProgramTensorMetadataDependency::Rank, 1}); + auto bias_components = is_channels_last ? components : 1; + const auto* bias = inputs[2]; + TensorShape reduced_bias_shape = ReduceShapeByComponents(bias->Shape(), bias_components); + program.AddInput({bias, ProgramTensorMetadataDependency::Rank, reduced_bias_shape, bias_components}); } - return context.RunProgram(program); + return program; } } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/math/matmul.h b/onnxruntime/core/providers/webgpu/math/matmul.h index 789e824383189..91216d8e25eec 100644 --- a/onnxruntime/core/providers/webgpu/math/matmul.h +++ b/onnxruntime/core/providers/webgpu/math/matmul.h @@ -9,16 +9,20 @@ #include "core/providers/webgpu/math/matmul_utils.h" #include "core/providers/webgpu/math/matmul_packed.h" #include "core/providers/webgpu/webgpu_utils.h" +#include "core/providers/webgpu/nn/fuse_utils.h" namespace onnxruntime { namespace webgpu { +MatMulProgram CreateMatMulProgram(const Activation& activation, std::vector& inputs, Tensor* output, bool is_channels_last, + const TensorShape& input_a_reshape = TensorShape(), + const TensorShape& input_b_reshape = TensorShape()); + class MatMul final : public WebGpuKernel { public: MatMul(const OpKernelInfo& info) : WebGpuKernel{info} {} Status ComputeInternal(ComputeContext& context) const override; - constexpr static uint32_t MATMUL_PACKED_WORKGROUP_SIZE_X = 8; constexpr static uint32_t MATMUL_PACKED_WORKGROUP_SIZE_Y = 8; constexpr static uint32_t MATMUL_PACKED_WORKGROUP_SIZE_Z = 1; @@ -26,8 +30,8 @@ class MatMul final : public WebGpuKernel { class MatMulNaiveProgram final : public Program { public: - MatMulNaiveProgram(const size_t output_rank, int64_t output_number, bool has_bias) - : Program{"MatMulNaive"}, output_rank_(output_rank), output_number_(output_number), has_bias_{has_bias} { + MatMulNaiveProgram(const Activation& activation, const size_t output_rank, int64_t output_number, bool has_bias, bool is_channels_last = false) + : Program{"MatMulNaive"}, activation_(activation), output_rank_(output_rank), output_number_(output_number), has_bias_{has_bias}, is_channels_last_(is_channels_last) { } Status GenerateShaderCode(ShaderHelper& sh) const override; @@ -38,9 +42,11 @@ class MatMulNaiveProgram final : public Program { {"K", ProgramUniformVariableDataType::Uint32}); private: + const Activation& activation_; const size_t output_rank_; const int64_t output_number_; const bool has_bias_; + const bool is_channels_last_; }; } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/math/matmul_packed.cc b/onnxruntime/core/providers/webgpu/math/matmul_packed.cc index 2e5cff923f442..36510eec0cd3b 100644 --- a/onnxruntime/core/providers/webgpu/math/matmul_packed.cc +++ b/onnxruntime/core/providers/webgpu/math/matmul_packed.cc @@ -5,7 +5,7 @@ #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_supported_types.h" #include "core/providers/webgpu/webgpu_utils.h" - +#include namespace onnxruntime { namespace webgpu { @@ -13,7 +13,8 @@ void MatMulProgram::MatMulReadWriteFnSource(ShaderHelper& shader, const ShaderVariableHelper& a, const ShaderVariableHelper& b, const ShaderVariableHelper& output, - const ShaderIndicesHelper& batch_dims) const { + const ShaderIndicesHelper& batch_dims, + std::string activation_snippet) const { int components = is_vec4_ ? 4 : 1; const std::string data_type = "a_element_t"; const std::string type_string = MakeScalarOrVectorType(components, data_type); @@ -23,7 +24,7 @@ void MatMulProgram::MatMulReadWriteFnSource(ShaderHelper& shader, << "fn mm_readA(batch: i32, row: i32, colIn: i32, batch_indices: batch_dims_indices_t) -> " << type_string << " {\n" << " var value = " << type_string << "(0.0);\n" << " let col = colIn * " << components << ";\n" - << " if(row < uniforms.dim_a_outer && col < uniforms.dim_inner) {\n" + << " if(row < i32(uniforms.dim_a_outer) && col < i32(uniforms.dim_inner)) {\n" << " var a_indices: a_indices_t;\n" << ConvertOutputBatchIndicesToInputBatchIndices("a", a, a.Rank() - 2, batch_dims.Rank(), "batch_indices") << a.IndicesSet("a_indices", a.Rank() - 2, "u32(row)") << "\n" @@ -38,7 +39,7 @@ void MatMulProgram::MatMulReadWriteFnSource(ShaderHelper& shader, << "fn mm_readB(batch: i32, row: i32, colIn: i32, batch_indices: batch_dims_indices_t) -> " << type_string << " {\n" << " var value = " << type_string << "(0.0);\n" << " let col = colIn * " << components << ";\n" - << " if(row < uniforms.dim_inner && col < uniforms.dim_b_outer) {\n" + << " if(row < i32(uniforms.dim_inner) && col < i32(uniforms.dim_b_outer)) {\n" << " var b_indices: b_indices_t;\n" << ConvertOutputBatchIndicesToInputBatchIndices("b", b, b.Rank() - 2, batch_dims.Rank(), "batch_indices") << b.IndicesSet("b_indices", b.Rank() - 2, "u32(row)") << "\n" @@ -52,14 +53,16 @@ void MatMulProgram::MatMulReadWriteFnSource(ShaderHelper& shader, shader.AdditionalImplementation() << "fn mm_write(batch: i32, row: i32, colIn: i32, valueIn: " << type_string << ") {\n" << " let col = colIn * " << components << ";\n" - << " if (row < uniforms.dim_a_outer && col < uniforms.dim_b_outer) {\n" + << " if (row < i32(uniforms.dim_a_outer) && col < i32(uniforms.dim_b_outer)) {\n" << " var value = valueIn;\n" << " let coords = vec3(batch, row, colIn);\n"; if (has_bias_) { - shader.AdditionalImplementation() << " value = value + " << type_string << "(bias[row]);\n"; + shader.AdditionalImplementation() << " value = value + " << (is_channels_last_ ? "bias[colIn]" : type_string + "(bias[row])") << ";\n"; } + shader.AdditionalImplementation() << " " << activation_snippet << "\n"; + shader.AdditionalImplementation() << output.SetByIndices("vec3(coords)", "value") << "\n" << " }\n" @@ -67,29 +70,36 @@ void MatMulProgram::MatMulReadWriteFnSource(ShaderHelper& shader, } Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, - const ShaderIndicesHelper& batch_dims, const InlinedVector& elements_per_thread, uint32_t workgroup_size_x, - uint32_t workgroup_size_y) { + uint32_t workgroup_size_y, + const std::string& data_type, + const ShaderIndicesHelper* batch_dims, + bool transpose_a, + uint32_t tile_inner, + bool split_k, + uint32_t splitted_dim_inner) { + ORT_UNUSED_PARAMETER(split_k); + ORT_UNUSED_PARAMETER(splitted_dim_inner); + std::string write_data_to_sub_a_vec4_snippet = + transpose_a ? std::string("mm_Asub[inputRow][inputCol] = mm_readA(batch, kStart + inputRow, globalRowStart / innerElementSize + inputCol") + (batch_dims ? ", batchIndices" : "") + ");\n" + : std::string("mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRow + innerRow, kStart / innerElementSize + inputCol") + (batch_dims ? ", batchIndices" : "") + ");\n"; // elements per thread const auto elements_per_thread_x = elements_per_thread[0]; const auto elements_per_thread_y = elements_per_thread[1]; - const decltype(elements_per_thread_x) tile_inner = 32; const auto tile_a_outer = workgroup_size_y * elements_per_thread_y; const auto tile_b_outer = workgroup_size_x * elements_per_thread_x; - const auto tile_a_width = tile_inner; - - const auto tile_a_height = tile_a_outer; + const auto tile_a_width = transpose_a ? tile_a_outer : tile_inner; + const auto tile_a_height = transpose_a ? tile_inner : tile_a_outer; const auto inner_elements_size = tile_a_width / workgroup_size_x; const auto row_per_thread_b = tile_inner / workgroup_size_y; - const std::string data_type = "a_element_t"; - - if (!((inner_elements_size == 3 || inner_elements_size == 4) && - tile_a_width % workgroup_size_x == 0 && - tile_inner % workgroup_size_y == 0 && - elements_per_thread_x == 4)) { + if (!((transpose_a && inner_elements_size == 4 && elements_per_thread[1] == 4) || + (!transpose_a && (inner_elements_size == 3 || inner_elements_size == 4))) && + tile_a_width % workgroup_size_x == 0 && + tile_inner % workgroup_size_y == 0 && + elements_per_thread_x == 4) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Invalid matrix multiplication configuration inner_elements_size: ", inner_elements_size, " must be 3 or 4. tile_a_width: ", tile_a_width, " must be divisible by WorkgroupSizeX: ", @@ -112,7 +122,7 @@ Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, << " let globalRow = i32(global_id.y) * rowPerThread;\n" << " let globalCol = i32(global_id.x);\n" << " let batch = i32(global_id.z);\n" - << " let batchIndices = " << batch_dims.OffsetToIndices("u32(batch)") << ";\n" + << (nullptr != batch_dims ? " let batchIndices = " + batch_dims->OffsetToIndices("u32(batch)") + ";\n" : "") << " let globalRowStart = i32(workgroup_id.y) * " << tile_a_outer << ";\n" << " let num_tiles = (uniforms.dim_inner - 1) / tileInner + 1;\n" << " var kStart = 0;\n" @@ -121,14 +131,14 @@ Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, // Loop over shared dimension. shader.MainFunctionBody() << " let tileRowB = localRow * " << row_per_thread_b << ";\n" - << " for (var t = 0; t < num_tiles; t = t + 1) {\n"; + << " for (var t = 0; t < i32(num_tiles); t = t + 1) {\n"; // Load one tile of A into local memory. shader.MainFunctionBody() << " for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" << " let inputRow = tileRow + innerRow;\n" << " let inputCol = tileCol;\n" - << " mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRow + innerRow, kStart / innerElementSize + inputCol, batchIndices);\n" + << " " << write_data_to_sub_a_vec4_snippet << " }\n"; // Load one tile of B into local memory. @@ -136,7 +146,7 @@ Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, << " for (var innerRow = 0; innerRow < " << row_per_thread_b << "; innerRow = innerRow + 1) {\n" << " let inputRow = tileRowB + innerRow;\n" << " let inputCol = tileCol;\n" - << " mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol, batchIndices);\n" + << " mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol" << (nullptr != batch_dims ? ", batchIndices" : "") << ");\n" << " }\n" << " kStart = kStart + tileInner;\n" << " workgroupBarrier();\n"; @@ -152,15 +162,29 @@ Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, shader.MainFunctionBody() << " let BCached3 = mm_Bsub[k * innerElementSize + 3][tileCol];\n"; } - shader.MainFunctionBody() - << " for (var i = 0; i < rowPerThread; i = i + 1) {\n" - << " let ACached = mm_Asub[tileRow + i][k];\n" - << " acc[i] = BCached0 * ACached.x + acc[i];\n" - << " acc[i] = BCached1 * ACached.y + acc[i];\n" - << " acc[i] = BCached2 * ACached.z + acc[i];\n" - << " " << (inner_elements_size == 3 ? "" : "acc[i] = BCached3 * ACached.w + acc[i];") << "\n" - << " }\n"; - + if (transpose_a) { + shader.MainFunctionBody() + << " let Acached0 = mm_Asub[k * innerElementSize][localRow];\n" + << " let Acached1 = mm_Asub[k * innerElementSize + 1][localRow];\n" + << " let Acached2 = mm_Asub[k * innerElementSize + 2][localRow];\n" + << (inner_elements_size == 3 ? "" : " let Acached3 = mm_Asub[k * innerElementSize + 3][localRow];\n") + << " for (var i = 0; i < rowPerThread; i = i + 1) {\n" + << " let ACached = mm_Asub[tileCol][i];\n" + << " acc[i] = BCached0 * ACached0[i] + acc[i];\n" + << " acc[i] = BCached1 * ACached1[i] + acc[i];\n" + << " acc[i] = BCached2 * ACached2[i] + acc[i];\n" + << " " << (inner_elements_size == 3 ? "" : "acc[i] = BCached3 * ACached3[i] + acc[i];") << "\n" + << " }\n"; + } else { + shader.MainFunctionBody() + << " for (var i = 0; i < rowPerThread; i = i + 1) {\n" + << " let ACached = mm_Asub[tileRow + i][k];\n" + << " acc[i] = BCached0 * ACached.x + acc[i];\n" + << " acc[i] = BCached1 * ACached.y + acc[i];\n" + << " acc[i] = BCached2 * ACached.z + acc[i];\n" + << " " << (inner_elements_size == 3 ? "" : "acc[i] = BCached3 * ACached.w + acc[i];") << "\n" + << " }\n"; + } shader.MainFunctionBody() << " workgroupBarrier();\n" << " }\n"; // main for loop @@ -174,13 +198,22 @@ Status MatMulProgram::MakeMatMulPackedVec4Source(ShaderHelper& shader, return Status::OK(); } -Status MatMulProgram::MakeMatMulPackedSource(ShaderHelper& shader, const ShaderIndicesHelper& batch_dims, +Status MatMulProgram::MakeMatMulPackedSource(ShaderHelper& shader, const InlinedVector& elements_per_thread, uint32_t workgroup_size_x, - uint32_t workgroup_size_y) { + uint32_t workgroup_size_y, + const std::string& data_type, + const ShaderIndicesHelper* batch_dims, + bool transpose_a, + uint32_t tile_inner, + bool split_k, + uint32_t splitted_dim_inner, + bool sequentially_access_by_threads) { + ORT_UNUSED_PARAMETER(split_k); + ORT_UNUSED_PARAMETER(splitted_dim_inner); + const auto elements_per_thread_x = elements_per_thread[0]; const auto elements_per_thread_y = elements_per_thread[1]; - const decltype(elements_per_thread_x) tile_inner = 32; const auto tile_a_outer = workgroup_size_y * elements_per_thread_y; const auto tile_b_outer = workgroup_size_x * elements_per_thread_x; @@ -194,12 +227,11 @@ Status MatMulProgram::MakeMatMulPackedSource(ShaderHelper& shader, const ShaderI ", tile_inner: ", tile_inner, " must be divisible by WorkgroupSizeY: ", workgroup_size_y); } - const std::string data_type = "a_element_t"; - const auto row_per_thread_a = tile_a_height / workgroup_size_y; const auto col_per_thread_a = tile_a_width / workgroup_size_x; const auto row_per_thread_b = tile_inner / workgroup_size_y; - + std::string write_data_to_sub_a_snippet = transpose_a ? std::string("mm_Asub[inputRow][inputCol] = mm_readA(batch, kStart + inputRow, globalRowStart + inputCol") + (batch_dims ? ", batchIndices" : "") + ");\n" + : std::string("mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRowStart + inputRow, kStart + inputCol") + (batch_dims ? ", batchIndices" : "") + ");\n"; shader.AdditionalImplementation() << "var mm_Asub: array, " << tile_a_height << ">;\n" << "var mm_Bsub: array, " << tile_inner << ">;\n" @@ -208,93 +240,142 @@ Status MatMulProgram::MakeMatMulPackedSource(ShaderHelper& shader, const ShaderI << "const tileInner = " << tile_inner << ";\n"; shader.MainFunctionBody() << " let batch = i32(global_id.z);\n" - << " let batchIndices = " << batch_dims.OffsetToIndices("u32(batch)") << ";\n" + << (nullptr != batch_dims ? " let batchIndices = " + batch_dims->OffsetToIndices("u32(batch)") + ";\n" : "") << " let num_tiles = (uniforms.dim_inner - 1) / tileInner + 1;\n" << " var kStart = 0;\n" << " var acc: array, rowPerThread>;\n"; - shader.MainFunctionBody() - << "let tileRow = i32(local_id.y) * rowPerThread;\n" - << "let tileCol = i32(local_id.x) * colPerThread;\n" - << "let globalRow = i32(global_id.y) * rowPerThread;\n" - << "let globalCol = i32(global_id.x) * colPerThread;\n" - << "let globalRowStart = i32(workgroup_id.y) * " << tile_a_outer << ";\n" - << "let tileRowA = i32(local_id.y) * " << row_per_thread_a << ";\n" - << "let tileColA = i32(local_id.x) * " << col_per_thread_a << ";\n" - << "let tileRowB = i32(local_id.y) * " << row_per_thread_b << ";\n"; - - // Loop over shared dimension. - shader.MainFunctionBody() - << "for (var t = 0; t < num_tiles; t = t + 1) {\n"; - - // Load one tile of A into local memory. - shader.MainFunctionBody() - << " for (var innerRow = 0; innerRow < " << row_per_thread_a << "; innerRow = innerRow + 1) {\n" - << " for (var innerCol = 0; innerCol < " << col_per_thread_a << "; innerCol = innerCol + 1) {\n" - << " let inputRow = tileRowA + innerRow;\n" - << " let inputCol = tileColA + innerCol;\n" - << " mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRowStart + inputRow, kStart + inputCol, batchIndices);\n" - << " }\n" - << " }\n"; - - // Load one tile of B into local memory. - shader.MainFunctionBody() - << " for (var innerRow = 0; innerRow < " << row_per_thread_b << "; innerRow = innerRow + 1) {\n" - << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" - << " let inputRow = tileRowB + innerRow;\n" - << " let inputCol = tileCol + innerCol;\n" - << " mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol + innerCol, batchIndices);\n" - << " }\n" - << " }\n" - << " kStart = kStart + tileInner;\n" - << " workgroupBarrier();\n"; - - // Compute acc values for a single thread. - shader.MainFunctionBody() - << "var BCached: array<" << data_type << ", colPerThread>;\n" - << " for (var k = 0; k < tileInner; k = k + 1) {\n" - << " for (var inner = 0; inner < colPerThread; inner = inner + 1) {\n" - << " BCached[inner] = mm_Bsub[k][tileCol + inner];\n" - << " }\n" - << " for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" - << " let ACached = mm_Asub[tileRow + innerRow][k];\n" - << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" - << " acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol];\n" - << " }\n" - << " }\n" - << " }\n" - << " workgroupBarrier();\n" - << "}\n"; - - // Write the results to the output buffer - shader.MainFunctionBody() - << "for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" - << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" - << " mm_write(batch, globalRow + innerRow, globalCol + innerCol, acc[innerRow][innerCol]);\n" - << " }\n" - << "}\n"; - + if (sequentially_access_by_threads) { + shader.MainFunctionBody() << "let localRow = i32(local_id.y);\n" + << "let localCol = i32(local_id.x);\n" + << "let globalRowStart = i32(workgroup_id.y) * " << tile_a_outer << ";\n" + << "let globalColStart = i32(workgroup_id.x) * " << tile_b_outer << ";\n" + << "\n" + << "// Loop over shared dimension.\n" + << "for (var t = 0; t < i32(num_tiles); t = t + 1) {\n" + << " // Load one tile of A into local memory.\n" + << " for (var inputRow = localRow; inputRow < " << tile_a_height << "; inputRow = inputRow + " << workgroup_size_y << ") {\n" + << " for (var inputCol = localCol; inputCol < " << tile_a_width << "; inputCol = inputCol + " << workgroup_size_x << ") {\n" + << " " << write_data_to_sub_a_snippet << "\n" + << " }\n" + << " }\n" + << " // Load one tile of B into local memory.\n" + << " for (var inputRow = localRow; inputRow < " << tile_inner << "; inputRow = inputRow + " << workgroup_size_y << ") {\n" + << " for (var inputCol = localCol; inputCol < " << tile_b_outer << "; inputCol = inputCol + " << workgroup_size_x << ") {\n" + << " mm_Bsub[inputRow][inputCol] = mm_readB(batch,\n" + << " kStart + inputRow,\n" + << " globalColStart + inputCol" << (batch_dims ? ", batchIndices" : "") << ");\n " + << " }\n" + << " }\n" + << " kStart = kStart + tileInner;\n" + << " workgroupBarrier();\n" + << "\n" + << " // Compute acc values for a single thread.\n" + << " var BCached : array<" << data_type << ", colPerThread>;\n" + << " for (var k = 0; k < tileInner; k = k + 1) {\n" + << " for (var inner = 0; inner < colPerThread; inner = inner + 1) {\n" + << " BCached[inner] = mm_Bsub[k][localCol + inner * " << workgroup_size_x << "];\n" + << " }\n" + << " for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" + << " let ACached = " << (transpose_a ? "mm_Asub[k][localCol + innerRow * " + std::to_string(workgroup_size_y) + "];" : "mm_Asub[localRow + innerRow * " + std::to_string(workgroup_size_y) + "][k];") << "\n" + << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" + << " acc[innerRow][innerCol] = acc[innerRow][innerCol] +\n" + << " ACached * BCached[innerCol];\n" + << " }\n" + << " }\n" + << " }\n" + << " workgroupBarrier();\n" + << "}\n" + << "for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n" + << " let gRow = globalRowStart + localRow + innerRow * " << workgroup_size_y << ";\n" + << " for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n" + << " let gCol = globalColStart + localCol + innerCol * " << workgroup_size_x << ";\n" + << " mm_write(batch, gRow, gCol, acc[innerRow][innerCol]);\n" + << " }\n" + << "}\n"; + } else { + shader.MainFunctionBody() + << "let tileRow = i32(local_id.y) * rowPerThread;\n" + << "let tileCol = i32(local_id.x) * colPerThread;\n" + << "let globalRow = i32(global_id.y) * rowPerThread;\n" + << "let globalCol = i32(global_id.x) * colPerThread;\n" + << "let globalRowStart = i32(workgroup_id.y) * " << tile_a_outer << ";\n" + << "let tileRowA = i32(local_id.y) * " << row_per_thread_a << ";\n" + << "let tileColA = i32(local_id.x) * " << col_per_thread_a << ";\n" + << "let tileRowB = i32(local_id.y) * " << row_per_thread_b << ";\n"; + + // Loop over shared dimension. + shader.MainFunctionBody() + << "for (var t = 0; t < i32(num_tiles); t = t + 1) {\n"; + + // Load one tile of A into local memory. + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < i32(" << row_per_thread_a << "); innerRow = innerRow + 1) {\n" + << " for (var innerCol = 0; innerCol < i32(" << col_per_thread_a << "); innerCol = innerCol + 1) {\n" + << " let inputRow = tileRowA + innerRow;\n" + << " let inputCol = tileColA + innerCol;\n" + << " " << write_data_to_sub_a_snippet << "\n" + << " }\n" + << " }\n"; + + // Load one tile of B into local memory. + shader.MainFunctionBody() + << " for (var innerRow = 0; innerRow < i32(" << row_per_thread_b << "); innerRow = innerRow + 1) {\n" + << " for (var innerCol = 0; innerCol < i32(colPerThread); innerCol = innerCol + 1) {\n" + << " let inputRow = tileRowB + innerRow;\n" + << " let inputCol = tileCol + innerCol;\n" + << " mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol + innerCol" << (nullptr != batch_dims ? ", batchIndices" : "") << ");\n" + << " }\n" + << " }\n" + << " kStart = kStart + tileInner;\n" + << " workgroupBarrier();\n"; + + // Compute acc values for a single thread. + shader.MainFunctionBody() + << "var BCached: array<" << data_type << ", colPerThread>;\n" + << " for (var k = 0; k < tileInner; k = k + 1) {\n" + << " for (var inner = 0; inner < i32(colPerThread); inner = inner + 1) {\n" + << " BCached[inner] = mm_Bsub[k][tileCol + inner];\n" + << " }\n" + << " for (var innerRow = 0; innerRow < i32(rowPerThread); innerRow = innerRow + 1) {\n" + << " let ACached = mm_Asub[tileRow + innerRow][k];\n" + << " for (var innerCol = 0; innerCol < i32(colPerThread); innerCol = innerCol + 1) {\n" + << " acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol];\n" + << " }\n" + << " }\n" + << " }\n" + << " workgroupBarrier();\n" + << "}\n"; + + // Write the results to the output buffer + shader.MainFunctionBody() + << "for (var innerRow = 0; innerRow < i32(rowPerThread); innerRow = innerRow + 1) {\n" + << " for (var innerCol = 0; innerCol < i32(colPerThread); innerCol = innerCol + 1) {\n" + << " mm_write(batch, globalRow + innerRow, globalCol + innerCol, acc[innerRow][innerCol]);\n" + << " }\n" + << "}\n"; + } return Status::OK(); } Status MatMulProgram::GenerateShaderCode(ShaderHelper& shader) const { const auto& a = shader.AddInput("a", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); const auto& b = shader.AddInput("b", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); - const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); const auto& batch_dims = shader.AddIndices("batch_dims", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias); if (has_bias_) { shader.AddInput("bias", ShaderUsage::UseUniform); } - + std::string apply_activation = GetActivationSnippet(activation_, "output_value_t", "output_element_t"); // declare the read and write functions - MatMulReadWriteFnSource(shader, a, b, output, batch_dims); - + MatMulReadWriteFnSource(shader, a, b, output, batch_dims, apply_activation); + std::string data_type = "a_element_t"; // generate the main function if (is_vec4_) { - ORT_RETURN_IF_ERROR(MakeMatMulPackedVec4Source(shader, batch_dims, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY())); + ORT_RETURN_IF_ERROR(MakeMatMulPackedVec4Source(shader, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY(), data_type, &batch_dims)); } else { - ORT_RETURN_IF_ERROR(MakeMatMulPackedSource(shader, batch_dims, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY())); + ORT_RETURN_IF_ERROR(MakeMatMulPackedSource(shader, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY(), data_type, &batch_dims)); } return Status::OK(); } diff --git a/onnxruntime/core/providers/webgpu/math/matmul_packed.h b/onnxruntime/core/providers/webgpu/math/matmul_packed.h index ea76468944066..d3a68ff8a57fa 100644 --- a/onnxruntime/core/providers/webgpu/math/matmul_packed.h +++ b/onnxruntime/core/providers/webgpu/math/matmul_packed.h @@ -7,38 +7,53 @@ #include "core/providers/webgpu/program.h" #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/math/matmul_utils.h" +#include "core/providers/webgpu/nn/fuse_utils.h" namespace onnxruntime { namespace webgpu { class MatMulProgram final : public Program { public: - MatMulProgram(bool bias, bool is_vec4, const gsl::span& elements_per_thread) : Program{"MatMul"}, - has_bias_{bias}, - is_vec4_{is_vec4}, - elements_per_thread_(elements_per_thread.begin(), elements_per_thread.end()) {} + MatMulProgram(const Activation& activation, bool bias, bool is_vec4, const gsl::span& elements_per_thread, bool is_channels_last = false) : Program{"MatMul"}, + activation_(activation), + has_bias_{bias}, + is_vec4_{is_vec4}, + elements_per_thread_(elements_per_thread.begin(), elements_per_thread.end()), + is_channels_last_(is_channels_last) {} Status GenerateShaderCode(ShaderHelper& sh) const override; - WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"dim_a_outer", ProgramUniformVariableDataType::Int32}, - {"dim_b_outer", ProgramUniformVariableDataType::Int32}, - {"dim_inner", ProgramUniformVariableDataType::Int32}); + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"dim_a_outer", ProgramUniformVariableDataType::Uint32}, + {"dim_b_outer", ProgramUniformVariableDataType::Uint32}, + {"dim_inner", ProgramUniformVariableDataType::Uint32}); static Status MakeMatMulPackedVec4Source(ShaderHelper& shader, - const ShaderIndicesHelper& batch_dims, const InlinedVector& elements_per_thread, uint32_t workgroup_size_x, - uint32_t workgroup_size_y); + uint32_t workgroup_size_y, + const std::string& data_type, + const ShaderIndicesHelper* batch_dims, + bool transpose_a = false, + uint32_t tile_inner = 32, + bool split_k = false, + uint32_t splitted_dim_inner = 32); static Status MakeMatMulPackedSource(ShaderHelper& shader, - const ShaderIndicesHelper& batch_dims, const InlinedVector& elements_per_thread, uint32_t workgroup_size_x, - uint32_t workgroup_size_y); + uint32_t workgroup_size_y, + const std::string& data_type, + const ShaderIndicesHelper* batch_dims, + bool transpose_a = false, + uint32_t tile_inner = 32, + bool split_k = false, + uint32_t splitted_dim_inner = 32, + bool sequentially_access_by_threads = false); private: + const Activation& activation_; const bool has_bias_; const bool is_vec4_; const InlinedVector elements_per_thread_; - - void MatMulReadWriteFnSource(ShaderHelper& shader, const ShaderVariableHelper& a, const ShaderVariableHelper& b, const ShaderVariableHelper& output, const ShaderIndicesHelper& batch_dims) const; + bool is_channels_last_ = false; + void MatMulReadWriteFnSource(ShaderHelper& shader, const ShaderVariableHelper& a, const ShaderVariableHelper& b, const ShaderVariableHelper& output, const ShaderIndicesHelper& batch_dims, std::string apply_activation) const; }; } // namespace webgpu diff --git a/onnxruntime/core/providers/webgpu/nn/activation_util.cc b/onnxruntime/core/providers/webgpu/nn/activation_util.cc new file mode 100644 index 0000000000000..b5c31d98cda93 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/activation_util.cc @@ -0,0 +1,25 @@ +#include "core/providers/webgpu/nn/activation_util.h" +#include "core/common/common.h" +namespace onnxruntime { +namespace webgpu { +std::string TypeSnippet(uint32_t component, std::string data_type) { + switch (component) { + case 1: + return data_type; + case 2: + return "vec2<" + data_type + ">"; + case 3: + return "vec3<" + data_type + ">"; + case 4: + return "vec4<" + data_type + ">"; + default: + ORT_THROW("Component ", component, " is not supported."); + } +} + +std::string BiasSnippet(bool has_bias) { + return has_bias ? "value = value + getBiasByOutputCoords(coords);" : ""; +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/activation_util.h b/onnxruntime/core/providers/webgpu/nn/activation_util.h new file mode 100644 index 0000000000000..1c9fd93e35384 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/activation_util.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include + +namespace onnxruntime { +namespace webgpu { + +extern std::string TypeSnippet(uint32_t component, std::string data_type); +extern std::string BiasSnippet(bool has_bias); + +} // namespace webgpu +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/webgpu/nn/conv.cc b/onnxruntime/core/providers/webgpu/nn/conv.cc new file mode 100644 index 0000000000000..0edad3eebe2ea --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv.cc @@ -0,0 +1,273 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "core/providers/webgpu/nn/conv.h" +#include "core/providers/webgpu/nn/conv2d_mm_webgpu.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/tensor/transpose.h" +#include "core/providers/webgpu/nn/grouped_conv.h" +#include "core/providers/webgpu/webgpu_utils.h" +#include "core/providers/webgpu/math/matmul.h" +namespace onnxruntime { +namespace webgpu { + +Status TransposeKernel(ComputeContext& context, const Tensor* kernel, const TensorShape& kernel_shape, Tensor* transposed_kernel, const InlinedVector& perm) { + // Transpose weights + auto rank = kernel_shape.NumDimensions(); + TensorShapeVector transposed_kernel_shape_vector(rank); + for (size_t i = 0; i < rank; ++i) { + transposed_kernel_shape_vector[i] = kernel_shape[perm[i]]; + } + uint32_t output_size = onnxruntime::narrow(kernel_shape.Size()); + TensorShape transposed_kernel_shape(transposed_kernel_shape_vector); + *transposed_kernel = context.CreateGPUTensor(kernel->DataType(), transposed_kernel_shape); + bool use_shared = false; + TransposeProgram program{perm, use_shared}; + program + .CacheHint(absl::StrJoin(perm, "-")) + .AddInput({kernel, ProgramTensorMetadataDependency::TypeAndRank, kernel_shape, 1}) + .AddOutput({transposed_kernel, ProgramTensorMetadataDependency::TypeAndRank}) + .AddUniformVariable({output_size}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE); + return context.RunProgram(program); +} + +template +Status Conv::ComputeInternal(ComputeContext& context) const { + bool has_bias = context.InputCount() > 2; + const auto* input = context.Input(0); + const auto* kernel = context.Input(1); + const auto* bias = has_bias ? context.Input(2) : nullptr; + TensorShape input_shape = input->Shape(); + TensorShape kernel_shape = kernel->Shape(); + ConvAttributes::ConvPadVector local_pads(conv_attrs_.pads.begin(), conv_attrs_.pads.end()); + TensorShapeVector local_dilations(conv_attrs_.dilations.begin(), conv_attrs_.dilations.end()); + TensorShapeVector local_strides(conv_attrs_.strides.begin(), conv_attrs_.strides.end()); + TensorShapeVector kernel_spacial_shape_vector; + ORT_RETURN_IF_ERROR(conv_attrs_.ComputeKernelShape(kernel_shape, kernel_spacial_shape_vector, false)); + if (local_pads.empty()) { + local_pads.resize(kernel_spacial_shape_vector.size() * 2, 0); + } + if (local_dilations.empty()) { + local_dilations.resize(kernel_spacial_shape_vector.size(), 1); + } + if (local_strides.empty()) { + local_strides.resize(kernel_spacial_shape_vector.size(), 1); + } + TensorShapeVector input_shape_vector = input_shape.AsShapeVector(); + auto batch = input_shape[0]; + TensorShapeVector output_shape_vector = {batch}; + TensorShape input_spacial_shape = is_channels_last ? TensorShape(TensorShapeVector(std::next(input_shape_vector.begin()), std::prev(input_shape_vector.end()))) : input_shape.Slice(2); + ORT_RETURN_IF_ERROR(conv_attrs_.InferPadsAndOutputShape(input_spacial_shape, kernel_spacial_shape_vector, local_strides, local_dilations, local_pads, output_shape_vector)); + auto output_channels = kernel_shape[0]; + if (is_channels_last) { + output_shape_vector.push_back(output_channels); + } else { + output_shape_vector.insert(output_shape_vector.begin() + 1, output_channels); + } + auto output_shape = TensorShape(output_shape_vector); + auto* output = context.Output(0, output_shape); + std::vector strides; + std::vector pads; + std::vector dilations; + auto transform_dim = [](int64_t dim) { return static_cast(dim); }; + std::transform(local_pads.begin(), local_pads.end(), std::back_inserter(pads), transform_dim); + std::transform(local_strides.begin(), local_strides.end(), std::back_inserter(strides), transform_dim); + std::transform(local_dilations.begin(), local_dilations.end(), std::back_inserter(dilations), transform_dim); + auto rank = input_shape.NumDimensions(); + const InlinedVector perm = {2, 3, 1, 0}; + if (rank > 4) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Only Conv1d and Conv2d are supported."); + } else if (rank == 4) { + // Conv2D + } else if (rank == 3) { + // Conv1D + TensorShapeVector kernel_shape_vector = kernel_shape.AsShapeVector(); + input_shape_vector.insert(input_shape_vector.begin() + (is_channels_last ? 1 : 2), 1, 1); + output_shape_vector.insert(output_shape_vector.begin() + (is_channels_last ? 1 : 2), 1, 1); + kernel_shape_vector.insert(kernel_shape_vector.begin() + 2, 1); + input_shape = TensorShape(input_shape_vector); + kernel_shape = TensorShape(kernel_shape_vector); + pads.insert(pads.begin(), 0); + pads.insert(pads.begin() + 2, 0); + strides.insert(strides.begin(), 1); + dilations.insert(dilations.begin(), 1); + } else { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input and kernel tensors must have at least 3 dimensions"); + } + std::vector inputs(has_bias ? 3 : 2); + inputs[0] = input; + inputs[1] = kernel; + if (has_bias) { + inputs[2] = bias; + } + std::vector modified_input_output_shapes = {input_shape, kernel_shape}; + if (has_bias) { + modified_input_output_shapes.push_back(bias->Shape()); + } + modified_input_output_shapes.push_back(TensorShape(output_shape_vector)); + uint32_t auto_pad_adjust = conv_attrs_.auto_pad == AutoPadType::SAME_LOWER ? 1 : 0; + auto pad0 = conv_attrs_.auto_pad == AutoPadType::NOTSET ? pads[0] : (pads[0] + pads[2] + auto_pad_adjust) / 2; + auto pad1 = conv_attrs_.auto_pad == AutoPadType::NOTSET ? pads[1] : (pads[1] + pads[3] + auto_pad_adjust) / 2; + std::vector updated_pads{pad0, pad1}; + if (conv_attrs_.group > 1) { + Tensor transposed_kernel; + if (is_channels_last) { + ORT_RETURN_IF_ERROR(TransposeKernel(context, kernel, kernel_shape, &transposed_kernel, perm)); + inputs[1] = &transposed_kernel; + modified_input_output_shapes[1] = transposed_kernel.Shape(); + } + auto output_channels_per_group = output_channels / conv_attrs_.group; + auto components = static_cast(is_channels_last && output_channels_per_group >= 4 ? GetMaxComponents(output_channels) : 1); + auto output_size = output_shape.Size() / components; + GroupedConvProgram program(activation_, has_bias, is_channels_last); + auto reduced_kernel_shape = ReduceShapeByComponents(modified_input_output_shapes[1], components); + auto reduced_output_shape = ReduceShapeByComponents(modified_input_output_shapes[has_bias ? 3 : 2], components); + program.CacheHint(activation_.ToString(), std::to_string(components), std::to_string(is_channels_last)) + .AddInput({inputs[0], ProgramTensorMetadataDependency::TypeAndRank, modified_input_output_shapes[0], 1}) + .AddInput({inputs[1], ProgramTensorMetadataDependency::TypeAndRank, reduced_kernel_shape, components}) + .AddOutput({output, ProgramTensorMetadataDependency::TypeAndRank, reduced_output_shape, components}) + .AddUniformVariables({{static_cast(output_size)}, {dilations}, {strides}, {updated_pads}, {static_cast(output_channels_per_group)}, {static_cast(components)}}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE); + if (has_bias) { + auto reduced_bias_shape = ReduceShapeByComponents(modified_input_output_shapes[2], components); + program.AddInput({inputs[2], ProgramTensorMetadataDependency::TypeAndRank, reduced_bias_shape, components}); + } + return context.RunProgram(program); + } + const auto input_height = input_shape[is_channels_last ? 1 : 2]; + const auto input_width = input_shape[is_channels_last ? 2 : 3]; + const auto input_channels = input_shape[is_channels_last ? 3 : 1]; + const auto kernel_height = kernel_shape[2]; + const auto kernel_width = kernel_shape[3]; + const auto output_height = output_shape_vector[is_channels_last ? 1 : 2]; + const auto output_width = output_shape_vector[is_channels_last ? 2 : 3]; + + const auto same_size = is_channels_last && input_height == kernel_height && input_width == kernel_width && pads[0] == 0 && pads[1] == 0; + if (same_size || (kernel_height == 1 && kernel_width == 1 && pads[0] == 0 && pads[1] == 0 && strides[0] == 1 && strides[1] == 1)) { + Tensor transposed_kernel; + TensorShape input_reshape; + TensorShape kernel_reshape; + TensorShape matmul_output_shape; + std::vector matmul_inputs; + std::vector matmul_input_reshapes; + if (is_channels_last) { + // Transpose weights + + ORT_RETURN_IF_ERROR(TransposeKernel(context, kernel, kernel_shape, &transposed_kernel, perm)); + inputs[1] = &transposed_kernel; + if (same_size) { + const auto shared_dim = input_height * input_width * input_channels; + input_reshape = TensorShape({1, batch, shared_dim}); + kernel_reshape = TensorShape({1, shared_dim, output_channels}); + matmul_output_shape = TensorShape({1, batch, output_channels}); + } else { + input_reshape = TensorShape({batch, input_height * input_width, input_channels}); + kernel_reshape = TensorShape({1, input_channels, output_channels}); + matmul_output_shape = TensorShape({batch, output_height * output_width, output_channels}); + } + matmul_inputs.push_back(input); + matmul_inputs.push_back(&transposed_kernel); + matmul_input_reshapes.push_back(input_reshape); + matmul_input_reshapes.push_back(kernel_reshape); + } else { + input_reshape = TensorShape({batch, input_channels, input_height * input_width}); + kernel_reshape = TensorShape({1, output_channels, input_channels}); + matmul_output_shape = TensorShape({batch, output_channels, output_height * output_width}); + matmul_inputs.push_back(kernel); + matmul_inputs.push_back(input); + matmul_input_reshapes.push_back(kernel_reshape); + matmul_input_reshapes.push_back(input_reshape); + } + if (has_bias) { + matmul_inputs.push_back(bias); + } + auto N = matmul_output_shape[2]; + auto matmul_first_input_numdims = matmul_input_reshapes[0].NumDimensions(); + auto K = matmul_input_reshapes[0].GetDims()[matmul_first_input_numdims - 1]; + if (N < 8 && K < 8) { + const auto components = GetMaxComponents(N); + const auto a_components = GetMaxComponents(K); + const auto output_number = GetMaxComponents(output_shape[1]); + uint32_t output_size = static_cast(output_shape.Size() / components / output_number); + const size_t output_rank = matmul_output_shape.NumDimensions(); + TensorShape outer_dims = output_rank > 2 ? matmul_output_shape.Slice(0, output_rank - 2) : TensorShape({}); + MatMulNaiveProgram program(activation_, output_rank, output_number, has_bias); + program + .CacheHint(std::to_string(components), std::to_string(a_components), std::to_string(output_number)) + .AddInputs({{matmul_inputs[0], ProgramTensorMetadataDependency::TypeAndRank, ReduceShapeByComponents(matmul_input_reshapes[0], a_components), int(a_components)}, + {matmul_inputs[1], ProgramTensorMetadataDependency::TypeAndRank, ReduceShapeByComponents(matmul_input_reshapes[1], components), int(components)}}); + if (has_bias) { + program.AddInput({bias, ProgramTensorMetadataDependency::Rank, bias->Shape(), components}); + } + program + .AddOutputs({{output, ProgramTensorMetadataDependency::None, ReduceShapeByComponents(matmul_output_shape, components), int(components)}}) + .SetDispatchGroupSize(static_cast((output_size + 63) / 64)) + .AddIndices(outer_dims) + .AddUniformVariables({{output_size}, {static_cast(matmul_output_shape[1])}, {static_cast(matmul_output_shape[2])}, {static_cast(K)}}); + return context.RunProgram(program); + } else { + MatMulProgram program = CreateMatMulProgram(activation_, matmul_inputs, output, is_channels_last, matmul_input_reshapes[0], matmul_input_reshapes[1]); + return context.RunProgram(program); + } + } + const bool sequentially_access_by_threads = true; + // Transpose weights + Tensor transposed_kernel; + ORT_RETURN_IF_ERROR(TransposeKernel(context, kernel, kernel_shape, &transposed_kernel, perm)); + auto dim_a_outer = static_cast(is_channels_last ? output_height * output_width : output_channels); + auto dim_b_outer = static_cast(is_channels_last ? output_channels : output_height * output_width); + auto dim_inner = static_cast(kernel_height * kernel_width * input_channels); + inputs[1] = &transposed_kernel; + TensorShape transposed_kernel_shape = transposed_kernel.Shape(); + modified_input_output_shapes[1] = transposed_kernel.Shape(); + Conv2dMMProgram conv2d_mm_program = CreateConv2dMMProgram(activation_, inputs, pads, strides, dilations, output, dim_a_outer, dim_b_outer, dim_inner, is_channels_last, sequentially_access_by_threads, modified_input_output_shapes); + return context.RunProgram(conv2d_mm_program); +} + +// Explicit template instantiation for FusedConv +template class Conv; +template class Conv; +template class Conv; +template class Conv; + +#define WEBGPU_ONNX_CONV_OPERATOR_KERNEL(VERSION_FROM) \ + ONNX_OPERATOR_KERNEL_EX( \ + Conv, \ + kMSInternalNHWCDomain, \ + VERSION_FROM, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), \ + Conv); \ + \ + ONNX_OPERATOR_KERNEL_EX( \ + Conv, \ + kOnnxDomain, \ + VERSION_FROM, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), \ + Conv); + +#define WEBGPU_ONNX_CONV_OPERATOR_VERSIONED_KERNEL(VERSION_FROM, VERSION_TO) \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX( \ + Conv, \ + kOnnxDomain, \ + VERSION_FROM, VERSION_TO, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), \ + Conv); \ + \ + ONNX_OPERATOR_VERSIONED_KERNEL_EX( \ + Conv, \ + kMSInternalNHWCDomain, \ + VERSION_FROM, VERSION_TO, \ + kWebGpuExecutionProvider, \ + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), \ + Conv); + +WEBGPU_ONNX_CONV_OPERATOR_VERSIONED_KERNEL(1, 10) +WEBGPU_ONNX_CONV_OPERATOR_VERSIONED_KERNEL(11, 21) +WEBGPU_ONNX_CONV_OPERATOR_KERNEL(22) + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv.h b/onnxruntime/core/providers/webgpu/nn/conv.h new file mode 100644 index 0000000000000..cafaa272c0613 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv.h @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/optional.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/cpu/nn/conv_attributes.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/nn/fuse_utils.h" + +namespace onnxruntime { +namespace webgpu { + +template +class Conv : public WebGpuKernel { + public: + Conv(const OpKernelInfo& info) : WebGpuKernel(info), conv_attrs_(info) { + if (is_fused) { + ORT_ENFORCE(GetFusedActivationAttr(info, activation_).IsOK()); + } + } + Status ComputeInternal(ComputeContext& context) const override; + + protected: + ConvAttributes conv_attrs_; + Activation activation_; +}; + +Status TransposeKernel(ComputeContext& context, const Tensor* kernel, const TensorShape& kernel_shape, Tensor* transposed_kernel, const InlinedVector& perm); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.cc b/onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.cc new file mode 100644 index 0000000000000..24e49304cf532 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.cc @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include +#include +#include +#include +#include "core/providers/webgpu/nn/conv2d_mm_webgpu.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/nn/activation_util.h" +#include "core/providers/webgpu/math/matmul_packed.h" +#include "core/providers/webgpu/nn/conv_utils.h" +#include "core/providers/webgpu/nn/fuse_utils.h" +#include "core/providers/webgpu/webgpu_utils.h" + +namespace onnxruntime { +namespace webgpu { +std::string Conv2dMMProgram::Conv2dCommonSnippet(const ShaderVariableHelper& x, const ShaderVariableHelper& w, const Activation& activation, std::string data_type, uint32_t inner_element_size_x, uint32_t inner_element_size_w, uint32_t inner_element_size) const { + auto get_x_snippet = [&](int32_t inner_element_size) -> std::string { + switch (inner_element_size) { + case 1: + return "resData = " + x.GetByOffset("xIndex") + ";"; + case 3: + return "resData = vec3(" + x.GetByOffset("xIndex") + ", " + x.GetByOffset("xIndex + 1") + ", " + x.GetByOffset("xIndex + 2") + ");"; + case 4: + return "resData = " + x.GetByOffset("xIndex") + ";\n "; + default: + ORT_THROW("inner_element_size", inner_element_size, " is not supported."); + } + }; + auto get_w_snippet = [&](int32_t inner_element_size) -> std::string { + switch (inner_element_size) { + case 1: + return "return " + w.GetByOffset("row * i32(uniforms.w_shape[3]) + colIn") + ";\n"; + case 4: + return "return " + w.GetByOffset("row * i32(uniforms.w_shape[3]) + colIn") + ";\n"; + default: + ORT_THROW("inner_element_size ", inner_element_size, " is not supported."); + } + }; + const std::string coord_a_snippet = is_channels_last_ ? "let coord = vec4(batch, xRow, xCol, xCh / " + std::to_string(inner_element_size_x == 3 ? 4 : inner_element_size_x) + ");" : "let coord = vec4(batch, xCh, xRow, xCol);"; + const std::string coord_res_snippet = is_channels_last_ ? "let coords = vec4(batch, row / outWidth, row % outWidth, col / " + std::to_string(inner_element_size) + ");" : "let coords = vec4(batch, row, col / outWidth, col % outWidth);"; + + const std::string xHeight = is_channels_last_ ? "i32(uniforms.x_shape[1])" : "i32(uniforms.x_shape[2])"; + const std::string xWidth = is_channels_last_ ? "i32(uniforms.x_shape[2])" : "i32(uniforms.x_shape[3])"; + const std::string row = is_channels_last_ ? "row" : "col"; + const std::string col = is_channels_last_ ? "col" : "row"; + std::stringstream read_x_snippet; + read_x_snippet + << "let inChannels = i32(uniforms.w_shape[2]);\n" + << "let outWidth = " << (is_channels_last_ ? "i32(uniforms.result_shape[2])" : "i32(uniforms.result_shape[3])") << ";\n" + << "let outRow = " << row << " / outWidth;\n " + << "let outCol = " << row << " % outWidth;\n" + << "let WRow = " << col << " / (i32(uniforms.w_shape[1]) * inChannels);\n" + << "let WCol = " << col << " / inChannels % i32(uniforms.w_shape[1]);\n" + << "let xRow = outRow * i32(uniforms.strides[0]) + i32(uniforms.dilations[0]) * WRow - i32(uniforms.pads[0]);\n" + << "let xCol = outCol * i32(uniforms.strides[1]) + i32(uniforms.dilations[1]) * WCol - i32(uniforms.pads[1]);\n" + << "let xCh = " << col << " % inChannels;\n" + << "var resData = " << TypeSnippet(inner_element_size_x, data_type) << "(0.0);\n " + << "// The bounds checking is always needed since we use it to pad zero for\n" + << "// the \" same \" padding type.\n" + << "if (xRow >= 0 && xRow < " << xHeight << " && xCol >= 0 && xCol < " << xWidth << ") {\n" + << " " << coord_a_snippet << "\n" + << " let xIndex = getIndexFromCoords4D(coord, vec4(uniforms.x_shape));\n" + << " " << get_x_snippet(inner_element_size_x) + << "}\n" + << "return resData;"; + std::stringstream sample_x; + if (is_channels_last_) { + if (fit_a_outer_ && fit_inner_) { + sample_x << "let col = colIn * " << inner_element_size_x << ";\n" + << read_x_snippet.str(); + } else { + sample_x << "let col = colIn * " << inner_element_size_x << ";\n" + << "if(row < i32(uniforms.dim_a_outer) && col < i32(uniforms.dim_inner)) {\n" + << " " << read_x_snippet.str() << "\n" + << "}\n" + << "return " << TypeSnippet(inner_element_size_x, data_type) << "(0.0);\n"; + } + } else { + if (fit_inner_ && fit_b_outer_) { + sample_x << "let col = colIn * " << inner_element_size_x << ";\n" + << read_x_snippet.str(); + } else { + sample_x << "let col = colIn * " << inner_element_size_x << ";\n" + << "if (row < i32(uniforms.dim_inner) && col < i32(uniforms.dim_b_outer)) {\n" + << " " << read_x_snippet.str() << "\n" + << "}\n" + << "return " << TypeSnippet(inner_element_size_x, data_type) << "(0.0);\n"; + } + } + std::stringstream sample_w; + if (is_channels_last_) { + if (fit_inner_ && fit_b_outer_) { + sample_w << get_w_snippet(inner_element_size_w); + } else { + sample_w << "let col = colIn * " << inner_element_size_w << ";\n" + << "if(row < i32(uniforms.dim_inner) && col < i32(uniforms.dim_b_outer)) {\n" + << " " << get_w_snippet(inner_element_size_w) << "\n" + << "}\n" + << "return " << TypeSnippet(inner_element_size_w, data_type) << "(0.0);\n"; + } + } else { + sample_w << "let col = colIn * " << inner_element_size_w << ";\n" + << "if (row < i32(uniforms.dim_inner) && col < i32(uniforms.dim_b_outer)) {\n" + << " " << get_w_snippet(inner_element_size_w) << "\n" + << "}\n" + << "return " << TypeSnippet(inner_element_size_w, data_type) << "(0.0);\n"; + } + const std::string res_type = TypeSnippet(inner_element_size, data_type); + const std::string a_type = is_channels_last_ ? TypeSnippet(inner_element_size_x, data_type) : TypeSnippet(inner_element_size_w, data_type); + const std::string b_type = is_channels_last_ ? TypeSnippet(inner_element_size_w, data_type) : TypeSnippet(inner_element_size_x, data_type); + const std::string apply_activation = GetActivationSnippet(activation, res_type, data_type); + std::stringstream user_code; + user_code << "fn mm_readA(batch : i32, row : i32, colIn : i32) -> " << a_type << " {\n" + << (is_channels_last_ ? sample_x.str() : sample_w.str()) + << "}\n" + << "\n" + << "fn mm_readB(batch : i32, row : i32, colIn : i32) -> " << b_type << " {\n" + << (is_channels_last_ ? sample_w.str() : sample_x.str()) + << "}\n" + << "\n" + << "fn mm_write(batch : i32, row : i32, colIn : i32, valueIn : " << res_type << ") {\n" + << " let col = colIn * " << inner_element_size << ";\n" + << " if(row < i32(uniforms.dim_a_outer) && col < i32(uniforms.dim_b_outer)) {\n" + << " var value = valueIn;\n" + << " let outWidth = " << (is_channels_last_ ? " i32(uniforms.result_shape[2]) " : " i32(uniforms.result_shape[3]) ") << ";\n" + << " " << coord_res_snippet << "\n" + << " " << BiasSnippet(has_bias_) << "\n" + << " " << apply_activation << "\n" + << " setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value);\n" + << " }\n" + << "}\n"; + return user_code.str(); +} + +Status Conv2dMMProgram::GenerateShaderCode(ShaderHelper& shader) const { + std::stringstream declaration_functions; + declaration_functions << "fn setOutputAtIndex(flatIndex : i32, value : " << (is_vec4_ ? "vec4" : "x_element_t") << ") {\n" + << " result[flatIndex] = " << (is_vec4_ ? "vec4" : "x_element_t") << "(value);\n" + << "}\n" + << "fn setOutputAtCoords(d0 : i32, d1 : i32, d2 : i32, d3 : i32, value : " << (is_vec4_ ? "vec4" : "x_element_t") << "){\n" + << " let flatIndex = getOutputIndexFromCoords(vec4(d0, d1, d2, d3));\n" + << " setOutputAtIndex(flatIndex, value);\n" + << "}\n"; + const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseShapeAndStride | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& w = shader.AddInput("w", ShaderUsage::UseUniform | ShaderUsage::UseShapeAndStride | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + std::vector inputs = {&x, &w}; + ORT_IGNORE_RETURN_VALUE(shader.AddOutput("result", ShaderUsage::UseUniform | ShaderUsage::UseShapeAndStride | ShaderUsage::UseIndicesTypeAlias)); + if (has_bias_) { + const auto& bias = shader.AddInput("bias", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + inputs.push_back(&bias); + declaration_functions << "fn getBiasByOutputCoords(coords : vec4) -> bias_value_t {" << "\n" + << " return bias[" << (is_channels_last_ ? "coords.w" : "coords.y") << "];\n" + << "}"; + } + shader.AdditionalImplementation() + << UtilFunctions("uniforms.result_stride") + << declaration_functions.str() + << Conv2dCommonSnippet(x, w, activation_, "x_element_t", element_size_[0], element_size_[1], element_size_[2]); + std::string data_type = "x_element_t"; + return is_vec4_ ? MatMulProgram::MakeMatMulPackedVec4Source(shader, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY(), data_type, /* batch_dims = */ nullptr, /* transpose_a = */ !is_channels_last_, tile_inner_) : MatMulProgram::MakeMatMulPackedSource(shader, elements_per_thread_, WorkgroupSizeX(), WorkgroupSizeY(), data_type, /* batch_dims = */ nullptr, false, tile_inner_, false, 0, sequentially_access_by_threads_); +} + +Conv2dMMProgram CreateConv2dMMProgram(const Activation& activation, const std::vector& inputs, const std::vector& pads, const std::vector& strides, const std::vector& dilations, Tensor* output, uint32_t dim_a_outer, uint32_t dim_b_outer, uint32_t dim_inner, bool is_channels_last, bool sequentially_access_by_threads, const std::vector& input_output_shapes) { + const auto* input = inputs[0]; + const auto* weight = inputs[1]; + bool has_bias = inputs.size() > 2; + const auto* bias = has_bias ? inputs[2] : nullptr; + const auto& input_shape = input_output_shapes[0]; + auto in_channels = is_channels_last ? input_shape[3] : input_shape[1]; + const auto& output_shape = has_bias ? input_output_shapes[3] : input_output_shapes[2]; + auto batch_size = output_shape[0]; + const auto output_width = is_channels_last ? output_shape[2] : output_shape[3]; + const auto output_height = is_channels_last ? output_shape[1] : output_shape[2]; + const auto output_channels = is_channels_last ? output_shape[3] : output_shape[1]; + // TODO: enable vec4 for NCHW + const bool is_vec4 = is_channels_last && (in_channels % 4 == 0 || in_channels % 3 == 0) && output_channels % 4 == 0; + + // TODO: fine tune size + const auto dispatch_x = is_channels_last ? output_channels : output_width * output_height; + const auto dispatch_y = is_channels_last ? output_width * output_height : output_channels; + std::vector workgroup_size = {8, 8, 1}; + InlinedVector elements_per_thread = {4, static_cast(dim_a_outer <= 8 ? 1 : 4), 1}; + auto integer_ceil = [](int64_t a, int64_t b) -> int64_t { return (a + b - 1) / b; }; + + const std::vector dispatch = { + static_cast(integer_ceil(integer_ceil(dispatch_x, workgroup_size[0]), elements_per_thread[0])), + static_cast(integer_ceil(integer_ceil(dispatch_y, workgroup_size[1]), elements_per_thread[1])), + static_cast(integer_ceil(integer_ceil(batch_size, workgroup_size[2]), elements_per_thread[2])), + }; + + uint32_t inner_element_size = is_vec4 ? (is_channels_last && in_channels % 4 != 0 ? 3 : 4) : 1; + auto tile_a_outer = static_cast(workgroup_size[1] * elements_per_thread[1]); + auto tile_b_outer = static_cast(workgroup_size[0] * elements_per_thread[0]); + auto tile_inner = std::max(workgroup_size[0] * inner_element_size, workgroup_size[1]); + bool fit_a_outer = dim_a_outer % tile_a_outer == 0; + bool fit_b_outer = dim_b_outer % tile_b_outer == 0; + bool fit_inner = dim_inner % tile_inner == 0; + std::vector element_size = {is_vec4 ? inner_element_size : 1, static_cast(is_vec4 ? 4 : 1), static_cast(is_vec4 ? 4 : 1)}; + const auto components = is_vec4 ? 4 : 1; + const auto input_components = static_cast(inner_element_size == 3 ? 1 : inner_element_size); + Conv2dMMProgram program(activation, tile_inner, fit_a_outer, fit_b_outer, fit_inner, is_channels_last, is_vec4, has_bias, std::move(element_size), std::move(elements_per_thread), sequentially_access_by_threads); + TensorShape reduced_input_shape = ReduceShapeByComponents(input_output_shapes[0], input_components); + TensorShape reduced_weight_shape = ReduceShapeByComponents(input_output_shapes[1], components); + TensorShape reduced_output_shape = ReduceShapeByComponents(input_output_shapes[has_bias ? 3 : 2], components); + program.AddInputs({{input, ProgramTensorMetadataDependency::TypeAndRank, reduced_input_shape, input_components}, {weight, ProgramTensorMetadataDependency::TypeAndRank, reduced_weight_shape, components}}); + if (has_bias) { + TensorShape reduced_bias_shape = ReduceShapeByComponents(input_output_shapes[2], components); + program.AddInput({bias, ProgramTensorMetadataDependency::TypeAndRank, reduced_bias_shape, components}); + } + const auto stringify = [](const std::vector& vec) -> std::string { + std::ostringstream oss; + std::transform(vec.begin(), vec.end(), std::ostream_iterator(oss, ","), [](uint32_t i) { return std::to_string(i); }); + return oss.str(); + }; + program.CacheHint(activation.ToString(), stringify({inner_element_size, static_cast(is_vec4 ? 1 : 0), fit_a_outer, fit_b_outer, fit_inner, tile_a_outer, tile_a_outer, tile_inner, static_cast(components)})) + .AddOutput({output, ProgramTensorMetadataDependency::TypeAndRank, reduced_output_shape, components}) + .SetDispatchGroupSize(dispatch[0], dispatch[1], dispatch[2]) + .SetWorkgroupSize(workgroup_size[0], workgroup_size[1], workgroup_size[2]) + .AddUniformVariables({{static_cast(dim_a_outer)}, + {static_cast(dim_b_outer)}, + {static_cast(dim_inner)}, + {pads}, + {strides}, + {dilations}}); + + return program; +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.h b/onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.h new file mode 100644 index 0000000000000..0087d11db179d --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv2d_mm_webgpu.h @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include +#include +#include "core/common/inlined_containers.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/framework/tensor_shape.h" +#include "core/framework/tensor.h" +#include "core/providers/webgpu/nn/fuse_utils.h" +#include "core/providers/webgpu/shader_helper.h" + +namespace onnxruntime { +namespace webgpu { +class Conv2dMMProgram final : public Program { + public: + Conv2dMMProgram(const Activation& activation, uint32_t tile_inner, bool fit_a_outer, bool fit_b_outer, bool fit_inner, bool is_channels_last, bool is_vec4, bool has_bias, std::vector&& element_size, InlinedVector&& elements_per_thread, bool sequentially_access_by_threads) : Program("Conv2dMM"), + activation_(activation), + tile_inner_(tile_inner), + fit_a_outer_(fit_a_outer), + fit_b_outer_(fit_b_outer), + fit_inner_(fit_inner), + is_channels_last_(is_channels_last), + is_vec4_(is_vec4), + has_bias_(has_bias), + element_size_(std::move(element_size)), + elements_per_thread_(std::move(elements_per_thread)), + sequentially_access_by_threads_(sequentially_access_by_threads) {} + + std::string Conv2dCommonSnippet(const ShaderVariableHelper& x, const ShaderVariableHelper& w, const Activation& activation, std::string data_type, uint32_t inner_element_size_x = 4, uint32_t inner_element_size_w = 4, uint32_t inner_element_size = 4) const; + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( + {"dim_a_outer", ProgramUniformVariableDataType::Uint32}, + {"dim_b_outer", ProgramUniformVariableDataType::Uint32}, + {"dim_inner", ProgramUniformVariableDataType::Uint32}, + {"pads", ProgramUniformVariableDataType::Uint32}, + {"strides", ProgramUniformVariableDataType::Uint32}, + {"dilations", ProgramUniformVariableDataType::Uint32}); + + private: + const Activation& activation_; + uint32_t tile_inner_; + bool fit_a_outer_; + bool fit_b_outer_; + bool fit_inner_; + bool is_channels_last_; + bool is_vec4_; + bool has_bias_; + std::vector element_size_; + InlinedVector elements_per_thread_; + bool sequentially_access_by_threads_; +}; + +Conv2dMMProgram CreateConv2dMMProgram(const Activation& activation, const std::vector& inputs, const std::vector& pads, const std::vector& strides, const std::vector& dilations, Tensor* output, uint32_t dim_a_outer, uint32_t dim_b_outer, uint32_t dim_inner, bool is_channels_last, bool sequentially_access_by_threads, const std::vector& modified_input_output_shapes); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc b/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc new file mode 100644 index 0000000000000..aa3ef5b96db54 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc @@ -0,0 +1,191 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include +#include +#include +#include "core/common/inlined_containers.h" +#include "core/providers/webgpu/nn/conv_backprop_webgpu.h" +#include "core/providers/webgpu/webgpu_utils.h" +namespace onnxruntime { +namespace webgpu { + +Status ConvTranspose2DProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& dy = shader.AddInput("dy", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& w = shader.AddInput("w", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + if (has_bias_) { + shader.AddInput("bias"); + } + auto row_dim = is_channels_last_ ? 1 : 2; + auto col_dim = is_channels_last_ ? 2 : 3; + auto channel_dim = is_channels_last_ ? 3 : 1; + auto calculate_result = [&]() -> std::string { + std::stringstream ss; + if (pack_input_as4_) { + if (a_components_ == 4) { + ss << "let xValue = " << dy.GetByOffset("x_offset") << ";\n" + << "let wValue = " << w.GetByOffset("w_offset") << ";\n" + << "dotProd = dotProd + dot(xValue, wValue);\n" + << "x_offset += 1;\n" + << "w_offset += 1;\n"; + } else if (a_components_ == 2) { + ss << "let xValue = vec4(" << dy.GetByOffset("x_offset") << ", " << dy.GetByOffset("x_offset + 1") << ");\n" + << "let wValue = vec4(" << w.GetByOffset("w_offset") << ", " << w.GetByOffset("w_offset + 1u") << ");\n" + << "dotProd = dotProd + dot(xValue, wValue);\n" + << "x_offset += 2;\n" + << "w_offset += 2;\n"; + } else if (a_components_ == 1) { + ss << "let xValue = vec4(" << dy.GetByOffset("x_offset") << ", " << dy.GetByOffset("x_offset + 1u") << ", " << dy.GetByOffset("x_offset + 2u") << ", " << dy.GetByOffset("x_offset + 3u") << ");\n" + << "let wValue = vec4(" << w.GetByOffset("x_offset") << ", " << w.GetByOffset("x_offset + 1u") << ", " << w.GetByOffset("x_offset + 2u") << ", " << w.GetByOffset("x_offset + 3u") << ");\n" + << "dotProd = dotProd + dot(xValue, wValue);\n" + << "x_offset += 4;\n" + << "w_offset += 4;\n"; + } + } else { + if (is_channels_last_) { + ss << "let xValue = " << dy.GetByIndices("dy_indices_t(batch, idyR, idyC, inputChannel / " + std::to_string(a_components_)) << ");\n"; + } else { + ss << "let xValue = " << dy.GetByIndices("dy_indices_t(batch, inputChannel, idyR, idyC)") << ";\n"; + } + if (a_components_ == 1) { + ss << "let wValue = " << w.GetByIndices("w_indices_t(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)") << ";\n" + << "dotProd = dotProd + xValue * wValue;\n"; + } else if (a_components_ == b_components_ && components_ == 1) { + ss << "let wValue = " << w.GetByIndices("w_indices_t(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)") << ";\n" + << "dotProd = dotProd + dot(xValue, wValue);\n"; + } else { + for (uint32_t i = 0; i < a_components_; ++i) { + ss << "let w_indices" << i << " = w_indices_t(u32(wRPerm), u32(wCPerm), inputChannel + d2 + " << i << ", wOutChannel);\n " + << "let w_offset" << i << " = " << w.IndicesToOffset("w_indices" + std::to_string(i)) << ";\n" + << "let wValue" << i << " = " << w.GetByIndices("w_indices" + std::to_string(i)) << ";\n" + << "dotProd = dotProd + xValue[" << i << "] * wValue" << i << ";\n"; + } + } + } + return ss.str(); + }; + auto calculate_remainder = [&]() -> std::string { + std::stringstream ss; + if (input_channels_remainder_ > 0) { + ORT_ENFORCE(pack_input_as4_, "Invalid input_channels_remainder: ", input_channels_remainder_); + if (a_components_ == 1) { + for (uint32_t i = 0; i < input_channels_remainder_; ++i) { + ss << "dotProd = dotProd + " << dy.GetByOffset("x_offset + " + std::to_string(i)) << ";\n"; + } + } else if (a_components_ == 2) { + if (input_channels_remainder_ != 2) { + ORT_THROW("Invalid input_channels_remainder: ", input_channels_remainder_); + } + ss << "let xValue = " << dy.GetByOffset("x_offset") << ";\n" + << "let wValue = " << w.GetByOffset("w_offset") << ";\n" + << "dotProd = dotProd + dot(xValue, wValue);\n"; + } + } + return ss.str(); + }; + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "let outputIndices = " << output.OffsetToIndices("global_idx") << ";\n" + << "let batch = " << output.IndicesGet("outputIndices", 0) << ";\n" + << "let d1 = " << output.IndicesGet("outputIndices", channel_dim) << ";\n" + << "let r = " << output.IndicesGet("outputIndices", row_dim) << ";\n" + << "let c = " << output.IndicesGet("outputIndices", col_dim) << ";\n" + << "let dyCorner = vec2(i32(r), i32(c)) - vec2(uniforms.pads);\n" + << "let dyRCorner = dyCorner.x;\n" + << "let dyCCorner = dyCorner.y;\n" + << "let groupId = d1 / (uniforms.output_channels_per_group / " << components_ << ");\n" + << "let wOutChannel = d1 - groupId * (uniforms.output_channels_per_group / " << components_ << ");\n" + << "// Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1).\n" + << "// ? = to be determined. : = across all values in that axis.\n" + << "var dotProd = output_value_t(0.0);\n" + << "var wR: u32 = 0;\n" + << "if (uniforms.dilations.x == 1) {\n" + << " // Minimum wR >= 0 that satisfies (dyRCorner + wR) % (uniforms.strides.x) == 0\n" + << " wR = u32(((dyRCorner + i32(uniforms.strides.x) - 1) / i32(uniforms.strides.x)) * i32(uniforms.strides.x) - dyRCorner);\n" + << "}\n" + << "for (; wR < uniforms.effective_filter_dims.x; wR = wR + 1) {\n" + << " if (wR % uniforms.dilations.x != 0) {\n" + << " continue;\n" + << " }\n" + << " let dyR = (dy_element_t(dyRCorner) + dy_element_t(wR)) / dy_element_t(uniforms.strides[0]);\n" + << " let wRPerm = uniforms.filter_dims.x - 1 - wR / uniforms.dilations.x;\n" + << " if (dyR < 0.0 || dyR >= dy_element_t(uniforms.dy_shape[" << row_dim << "]) || fract(dyR) > 0.0 || wRPerm < 0) {\n" + << " continue;\n" + << " }\n" + << " let idyR: u32 = u32(dyR);\n" + << " var wC: u32 = 0;\n" + << " if (uniforms.dilations.y == 1) {\n" + << " // Minimum wC >= 0 that satisfies (dyCCorner + wC) % (uniforms.strides.y) == 0\n" + << " wC = u32(((dyCCorner + i32(uniforms.strides.y) - 1) / i32(uniforms.strides.y)) * i32(uniforms.strides.y) - dyCCorner);\n" + << " }\n" + << " for (; wC < uniforms.effective_filter_dims.y; wC = wC + 1) {\n" + << " if (wC % uniforms.dilations.y != 0) {" + << " continue;\n" + << " }\n" + << " let dyC = (dy_element_t(dyCCorner) + dy_element_t(wC)) / dy_element_t(uniforms.strides.y);\n" + << " let wCPerm = uniforms.filter_dims.y - 1 - wC / uniforms.dilations.y;\n" + << " if (dyC < 0.0 || dyC >= dy_element_t(uniforms.dy_shape[" << col_dim << "]) ||\n" + << " fract(dyC) > 0.0 || wCPerm < 0) {\n" + << " continue;\n" + << " }\n" + << " let idyC: u32 = u32(dyC);\n" + << " var inputChannel = groupId * uniforms.input_channels_per_group;\n"; + if (pack_input_as4_) { + shader.MainFunctionBody() << " let dy_indices = dy_indices_t(batch, idyR, idyC, inputChannel);\n" + << " let w_indices = w_indices_t(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel);\n" + << " var x_offset = " << dy.IndicesToOffset("dy_indices") << ";\n" + << " var w_offset = " << w.IndicesToOffset("w_indices") << ";\n"; + } + + shader.MainFunctionBody() << " for (var d2: u32 = 0; d2 < uniforms.input_channels_per_group_int; d2 = d2 + " << (pack_input_as4_ ? 4 : a_components_) << ") {\n" + << " " << calculate_result() << "\n" + << " inputChannel = inputChannel + " << (pack_input_as4_ ? 4 : 1) << ";\n" + << " }\n" + << " " << calculate_remainder() << "\n" + << " wC = wC + uniforms.strides.y - 1;\n" + << " }\n" + << " wR = wR + uniforms.strides.x - 1;\n" + << "}\n" + << "let value = dotProd" << (has_bias_ ? " + bias[d1]" : "") << ";\n" + << output.SetByOffset("global_idx", "value") << "\n"; + return Status::OK(); +} + +ConvTranspose2DProgram CreateConvTranspose2DProgram(const std::vector& inputs, const std::vector& pads, const std::vector& strides, const std::vector& dilations, Tensor* output, bool is_channels_last, const std::vector& modified_input_output_shapes, uint32_t groups) { + bool has_bias = inputs.size() > 2; + const auto* input = inputs[0]; + const auto* weight = inputs[1]; + const auto& input_shape = modified_input_output_shapes[0]; + const auto& weight_shape = modified_input_output_shapes[1]; + const auto& output_shape = modified_input_output_shapes[has_bias ? 3 : 2]; + auto input_channels_per_group = weight_shape[2] / groups; + auto output_channels_per_group = weight_shape[3]; + auto a_components = is_channels_last ? GetMaxComponents(input_channels_per_group) : 1; + bool pack_input_as4 = is_channels_last && output_channels_per_group == 1 && input_channels_per_group >= 4; + auto input_channels_per_group_int = pack_input_as4 ? ((input_channels_per_group + 3) / 4) * 4 : (input_channels_per_group / a_components) * a_components; + auto input_channels_remainder = input_channels_per_group - input_channels_per_group_int; + auto components = is_channels_last ? GetMaxComponents(output_channels_per_group) : 1; + auto b_components = is_channels_last ? (output_channels_per_group == 1 ? a_components : components) : 1; + TensorShape reduced_input_shape = ReduceShapeByComponents(input_shape, a_components); + TensorShape reduced_weight_shape = ReduceShapeByComponents(weight_shape, b_components); + TensorShape reduced_output_shape = ReduceShapeByComponents(output_shape, components); + auto output_size = reduced_output_shape.Size(); + std::vector kernel_dims = {static_cast(weight_shape[0]), static_cast(weight_shape[1])}; + std::vector effective_kernel_dims = {kernel_dims[0] + ((dilations[0] <= 1) ? 0 : ((kernel_dims[0] - 1) * (dilations[0] - 1))), kernel_dims[1] + ((dilations[1] <= 1) ? 0 : ((kernel_dims[1] - 1) * (dilations[1] - 1)))}; + std::vector local_pads = {effective_kernel_dims[0] - 1 - pads[0], effective_kernel_dims[1] - 1 - pads[1]}; + ConvTranspose2DProgram program(is_channels_last, has_bias, components, a_components, b_components, uint32_t(input_channels_remainder), pack_input_as4); + program.AddInputs({{input, ProgramTensorMetadataDependency::TypeAndRank, reduced_input_shape, a_components}, {weight, ProgramTensorMetadataDependency::TypeAndRank, reduced_weight_shape, b_components}}); + if (has_bias) { + const auto* bias = inputs[2]; + const auto& bias_shape = modified_input_output_shapes[2]; + TensorShape reduced_bias_shape = ReduceShapeByComponents(bias_shape, components); + program.AddInput({bias, ProgramTensorMetadataDependency::TypeAndRank, reduced_bias_shape, components}); + } + program.AddOutput({output, ProgramTensorMetadataDependency::Rank, reduced_output_shape, components}) + .AddUniformVariables({{static_cast(output_size)}, {strides}, {kernel_dims}, {dilations}, {effective_kernel_dims}, {local_pads}, {static_cast(input_channels_per_group_int)}, {static_cast(input_channels_per_group)}, {static_cast(output_channels_per_group)}}) + .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE); + + return program; +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.h b/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.h new file mode 100644 index 0000000000000..6c784e4825a65 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.h @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include "core/common/inlined_containers.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/webgpu/program.h" +#include "core/framework/tensor_shape.h" +#include "core/framework/tensor.h" + +namespace onnxruntime { +namespace webgpu { + +class ConvTranspose2DProgram : public Program { + public: + ConvTranspose2DProgram(bool is_channels_last, bool has_bias, uint32_t components, uint32_t a_components, uint32_t b_components, uint32_t input_channels_remainder, bool pack_input_as4) : Program("ConvTranspose2D"), is_channels_last_(is_channels_last), has_bias_(has_bias), components_(components), a_components_(a_components), b_components_(b_components), input_channels_remainder_(input_channels_remainder), pack_input_as4_(pack_input_as4) { + } + + Status GenerateShaderCode(ShaderHelper& sh) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"strides", ProgramUniformVariableDataType::Uint32}, + {"filter_dims", ProgramUniformVariableDataType::Uint32}, + {"dilations", ProgramUniformVariableDataType::Uint32}, + {"effective_filter_dims", ProgramUniformVariableDataType::Uint32}, + {"pads", ProgramUniformVariableDataType::Uint32}, + {"input_channels_per_group_int", ProgramUniformVariableDataType::Uint32}, + {"input_channels_per_group", ProgramUniformVariableDataType::Uint32}, + {"output_channels_per_group", ProgramUniformVariableDataType::Uint32}); + + private: + bool is_channels_last_; + bool has_bias_; + uint32_t components_; + uint32_t a_components_; + uint32_t b_components_; + uint32_t input_channels_remainder_; + bool pack_input_as4_; +}; + +ConvTranspose2DProgram CreateConvTranspose2DProgram(const std::vector& inputs, const std::vector& pads, const std::vector& strides, const std::vector& dilations, Tensor* output, bool is_channels_last, const std::vector& modified_input_output_shapes, uint32_t groups); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv_transpose.cc b/onnxruntime/core/providers/webgpu/nn/conv_transpose.cc new file mode 100644 index 0000000000000..9cd290ef56013 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv_transpose.cc @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "conv.h" +#include "conv_transpose.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/cpu/nn/conv_attributes.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/tensor/transpose.h" +#include "core/providers/webgpu/nn/conv_backprop_webgpu.h" + +namespace onnxruntime { +namespace webgpu { +// kernel shape is the spacial dims of the filter. +// ie. filter shape with batch and channel. kernel shape dimension is 2 less than the filter dimension + +template +Status ConvTranspose::ComputeInternal(ComputeContext& context) const { + const auto* input = context.Input(0); + const auto* filter = context.Input(1); + TensorShape input_shape = input->Shape(); + TensorShape filter_shape = filter->Shape(); + const InlinedVector perm = {2, 3, 0, 1}; + TensorShapeVector local_output_padding(conv_transpose_attrs_.output_padding.begin(), conv_transpose_attrs_.output_padding.end()); + ConvAttributes::ConvPadVector local_pads(conv_transpose_attrs_.pads.begin(), conv_transpose_attrs_.pads.end()); + TensorShapeVector local_dilations(conv_transpose_attrs_.dilations.begin(), conv_transpose_attrs_.dilations.end()); + TensorShapeVector local_strides(conv_transpose_attrs_.strides.begin(), conv_transpose_attrs_.strides.end()); + TensorShapeVector kernel_shape_vector; + auto rank = input_shape.NumDimensions(); + TensorShape input_spacial_shape = input_shape.Slice(is_channels_last ? 1 : 2, is_channels_last ? rank - 1 : rank); + local_pads.reserve(2 * (input_spacial_shape.NumDimensions())); + ORT_RETURN_IF_ERROR(conv_transpose_attrs_.ComputeKernelShape(filter_shape, kernel_shape_vector, false)); + if (local_output_padding.empty()) { + local_output_padding.resize(kernel_shape_vector.size(), 0); + } + if (local_pads.empty()) { + local_pads.resize(kernel_shape_vector.size() * 2, 0); + } + if (local_dilations.empty()) { + local_dilations.resize(kernel_shape_vector.size(), 1); + } + if (local_strides.empty()) { + local_strides.resize(kernel_shape_vector.size(), 1); + } + auto group = conv_transpose_attrs_.group; + auto num_output_channels = group * filter_shape[1]; + auto batch_size = input_shape[0]; + TensorShapeVector output_shape_vector; + conv_transpose_attrs_.ComputePadsAndOutputShape(input_spacial_shape, num_output_channels, kernel_shape_vector, local_strides, local_dilations, local_output_padding, batch_size, &local_pads, &output_shape_vector, is_channels_last); + TensorShape computed_output_shape(output_shape_vector); + std::vector strides; + std::vector pads; + std::vector dilations; + auto transform_dim = [](int64_t dim) { return static_cast(dim); }; + std::transform(local_pads.begin(), local_pads.end(), std::back_inserter(pads), transform_dim); + std::transform(local_strides.begin(), local_strides.end(), std::back_inserter(strides), transform_dim); + std::transform(local_dilations.begin(), local_dilations.end(), std::back_inserter(dilations), transform_dim); + + bool has_bias = context.InputCount() > 2; + const auto* bias = has_bias ? context.Input(2) : nullptr; + if (input_shape.NumDimensions() == 3 && filter_shape.NumDimensions() == 3) { + // ConvTranspose1D + TensorShapeVector input_shape_vector = input_shape.AsShapeVector(); + TensorShapeVector filter_shape_vector = filter_shape.AsShapeVector(); + input_shape_vector.insert(input_shape_vector.begin() + (is_channels_last ? 1 : 2), 1, 1); + output_shape_vector.insert(output_shape_vector.begin() + (is_channels_last ? 1 : 2), 1, 1); + filter_shape_vector.insert(filter_shape_vector.begin() + 2, 1); + input_shape = TensorShape(input_shape_vector); + filter_shape = TensorShape(filter_shape_vector); + pads.insert(pads.begin(), 0); + pads.insert(pads.begin() + 2, 0); + strides.insert(strides.begin(), 1); + dilations.insert(dilations.begin(), 1); + } + if (input_shape.NumDimensions() > 4 || filter_shape.NumDimensions() > 4) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Only Conv2d or Conv1d are supported."); + } else if (input_shape.NumDimensions() < 2 || filter_shape.NumDimensions() < 2) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input and kernel tensors must have at least 3 dimensions"); + } + // Transpose weights + Tensor transposed_filter; + ORT_RETURN_IF_ERROR(TransposeKernel(context, filter, filter_shape, &transposed_filter, perm)); + TensorShape output_shape(output_shape_vector); + TensorShape transposed_filter_shape = transposed_filter.Shape(); + std::vector inputs = {input, &transposed_filter}; + std::vector input_output_shapes = {input_shape, transposed_filter_shape}; + if (has_bias) { + inputs.push_back(bias); + input_output_shapes.push_back(bias->Shape()); + } + uint32_t auto_pad_adjust = conv_transpose_attrs_.auto_pad == AutoPadType::SAME_LOWER ? 1 : 0; + auto pad0 = conv_transpose_attrs_.auto_pad == AutoPadType::NOTSET ? pads[0] : (pads[0] + pads[2] + auto_pad_adjust) / 2; + auto pad1 = conv_transpose_attrs_.auto_pad == AutoPadType::NOTSET ? pads[1] : (pads[1] + pads[3] + auto_pad_adjust) / 2; + Tensor* output = context.Output(0, computed_output_shape); + input_output_shapes.push_back(output_shape); + auto program = CreateConvTranspose2DProgram(inputs, {pad0, pad1}, strides, dilations, output, is_channels_last, input_output_shapes, static_cast(conv_transpose_attrs_.group)); + return context.RunProgram(program); +} + +ONNX_OPERATOR_KERNEL_EX( + ConvTranspose, + kMSInternalNHWCDomain, + 11, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), + ConvTranspose); + +ONNX_OPERATOR_KERNEL_EX( + ConvTranspose, + kOnnxDomain, + 11, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), + ConvTranspose); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + ConvTranspose, + kMSInternalNHWCDomain, + 1, 10, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), + ConvTranspose); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + ConvTranspose, + kOnnxDomain, + 1, 10, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()).TypeConstraint("T", WebGpuSupportedFloatTypes()), + ConvTranspose); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv_transpose.h b/onnxruntime/core/providers/webgpu/nn/conv_transpose.h new file mode 100644 index 0000000000000..a97b3f5947303 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv_transpose.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/common.h" + +#include "core/providers/cpu/nn/conv_transpose_attributes.h" +#include "core/providers/webgpu/webgpu_kernel.h" +namespace onnxruntime { +namespace webgpu { + +template +class ConvTranspose final : public WebGpuKernel { + public: + ConvTranspose(const OpKernelInfo& info) : WebGpuKernel(info), conv_transpose_attrs_(info) { + } + Status ComputeInternal(ComputeContext& context) const override; + + protected: + ConvTransposeAttributes conv_transpose_attrs_; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv_utils.cc b/onnxruntime/core/providers/webgpu/nn/conv_utils.cc new file mode 100644 index 0000000000000..233662c10bfb8 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv_utils.cc @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/nn/conv_utils.h" +namespace onnxruntime { +namespace webgpu { +std::string UtilFunctions(std::string stride_string) { + std::stringstream ss; + ss << "fn getIndexFromCoords3D(coords : vec3, shape : vec3) -> i32 {\n" + << " return dot(coords, vec3(shape.y * shape.z, shape.z, 1));\n" + << "}\n" + << "fn getIndexFromCoords4D(coords : vec4, shape : vec4) -> i32 {\n" + << " return dot(coords, vec4(shape.y * shape.z * shape.w, shape.z * shape.w, shape.w, 1));\n" + << "}\n" + << "fn getOutputIndexFromCoords(coords : vec4) -> i32 {\n" + << " return dot(coords, vec4(i32(" << stride_string << ".x), i32(" << stride_string << ".y), i32(" << stride_string << ".z), 1));\n" + << "}\n"; + return ss.str(); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/conv_utils.h b/onnxruntime/core/providers/webgpu/nn/conv_utils.h new file mode 100644 index 0000000000000..ad8aa868ff7f0 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/conv_utils.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include + +namespace onnxruntime { +namespace webgpu { + +std::string UtilFunctions(std::string stride_string); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/fuse_utils.cc b/onnxruntime/core/providers/webgpu/nn/fuse_utils.cc new file mode 100644 index 0000000000000..38db604695a54 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/fuse_utils.cc @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/webgpu/nn/fuse_utils.h" +#include +namespace onnxruntime { +namespace webgpu { + +Status GetFusedActivationAttr(const OpKernelInfo& info, Activation& activation) { + activation.activation_kind_ = ActivationKind::None; + + std::string activation_type; + if (info.GetAttr("activation", &activation_type).IsOK()) { + if (activation_type == "Relu") { + activation.activation_kind_ = ActivationKind::Relu; + } else if (activation_type == "Tanh") { + activation.activation_kind_ = ActivationKind::Tanh; + } else if (activation_type == "Sigmoid") { + activation.activation_kind_ = ActivationKind::Sigmoid; + } else { + // The remaining activation types have additional parameters to be pulled out. + size_t activation_params_count; + if (activation_type == "LeakyRelu") { + activation.activation_kind_ = ActivationKind::LeakyRelu; + activation_params_count = 1; + } else if (activation_type == "Clip") { + activation.activation_kind_ = ActivationKind::Clip; + activation_params_count = 2; + } else if (activation_type == "HardSigmoid") { + activation.activation_kind_ = ActivationKind::HardSigmoid; + activation_params_count = 2; + } else { + return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "unimplemented activation: " + activation_type); + } + + std::vector activation_params; + common::Status status = info.GetAttrs("activation_params", activation_params); + if (!status.IsOK()) { + return status; + } else if (activation_params_count != activation_params.size()) { + return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "activation_params count mismatch"); + } + for (size_t i = 0; i < activation_params_count; i++) { + activation.activation_params_.values_[i] = activation_params[i]; + } + } + } + + return Status::OK(); +} + +std::string GetActivationSnippet(const Activation& activation, std::string value_type, std::string base_type) { + std::string snippet; + auto base_type_cast = [base_type](float value) -> std::string { + return base_type + "(" + std::to_string(value) + ")"; + }; + auto value_type_cast = [base_type_cast, value_type](float f) -> std::string { + return value_type + "(" + base_type_cast(f) + ")"; + }; + switch (activation.activation_kind_) { + case ActivationKind::Relu: + return "value = max(value, " + value_type_cast(0.0) + ");"; + case ActivationKind::Sigmoid: + return "value = " + value_type_cast(1.0) + " / (" + value_type_cast(1.0) + " + exp(-value));"; + case ActivationKind::Clip: + return "value = clamp(value, " + value_type_cast(activation.activation_params_.Clip.minimum_) + ", " + value_type_cast(activation.activation_params_.Clip.maximum_) + ");"; + case ActivationKind::HardSigmoid: + return "value = clamp(" + value_type_cast(activation.activation_params_.HardSigmoid.alpha_) + " * value + " + value_type_cast(activation.activation_params_.HardSigmoid.beta_) + ", 0.0" + ", 1.0" + ");"; + case ActivationKind::LeakyRelu: + return "value = select(" + base_type_cast(activation.activation_params_.LeakyRelu.alpha_) + " * value, value, value >= " + value_type_cast(0.0) + ");"; + case ActivationKind::Tanh: + return "value = tanh(value);"; + default: + return ""; + } +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/fuse_utils.h b/onnxruntime/core/providers/webgpu/nn/fuse_utils.h new file mode 100644 index 0000000000000..f5d2585bb9b45 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/fuse_utils.h @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include +#include "core/providers/webgpu/webgpu_kernel.h" + +#pragma once +namespace onnxruntime { +namespace webgpu { +enum class ActivationKind { + None, + Relu, + Sigmoid, + Clip, + HardSigmoid, + LeakyRelu, + Tanh +}; + +using Activation = struct Activation { + std::string ToString() const { + std::stringstream oss; + oss << "ActivationKind: " << static_cast(activation_kind_) << ";"; + oss << "ActivationParams: " << activation_params_.values_[0] << ";"; + oss << "ActivationParams: " << activation_params_.values_[1] << ";"; + return oss.str(); + } + using ActivationParameters = union ActivationParameters { + struct { + float alpha_; + } LeakyRelu; + struct { + float minimum_; + float maximum_; + } Clip; + struct { + float alpha_; + float beta_; + } HardSigmoid; + float values_[2]; + }; + ActivationParameters activation_params_ = {}; + ActivationKind activation_kind_ = ActivationKind::None; +}; + +Status GetFusedActivationAttr(const OpKernelInfo& info, Activation& activation); +std::string GetActivationSnippet(const Activation& activation, std::string value_type, std::string base_type); +// Status AppendActivationUniformsData(const Activation& activation, std::vector& variables); +// Status AppendActivationUniforms(const Activation& activation, std::vector& data); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/grouped_conv.cc b/onnxruntime/core/providers/webgpu/nn/grouped_conv.cc new file mode 100644 index 0000000000000..4dc0b82cdd7eb --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/grouped_conv.cc @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include +#include "core/providers/webgpu/nn/grouped_conv.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/shader_variable.h" +#include "core/providers/webgpu/nn/fuse_utils.h" + +namespace onnxruntime { +namespace webgpu { + +std::string CanculateResult(const ShaderVariableHelper& x, const ShaderVariableHelper& w, bool is_channels_last) { + std::stringstream ss; + if (is_channels_last) { + ss << "for (var wHeight: u32 = 0u; wHeight < uniforms.w_shape[0]; wHeight++) {\n" + << " let xHeight = xRCCorner.x + wHeight * uniforms.dilations[0];\n" + << " if (xHeight < 0u || xHeight >= uniforms.x_shape[1]) {\n" + << " continue;\n" + << " }\n" + << "" + << " for (var wWidth: u32 = 0u; wWidth < uniforms.w_shape[1]; wWidth++) {\n" + << " let xWidth = xRCCorner.y + wWidth * uniforms.dilations[1];\n" + << " if (xWidth < 0u || xWidth >= uniforms.x_shape[2]) {\n" + << " continue;\n" + << " }\n" + << "" + << " for (var wInChannel: u32 = 0u; wInChannel < uniforms.w_shape[2]; wInChannel++) {\n" + << " let input_channel = in_channel_offset + wInChannel;\n" + << " let x_indices = x_indices_t(batch, xHeight, xWidth, input_channel);\n" + << " let w_indices = w_indices_t(wHeight, wWidth, wInChannel, output_channel);\n" + << " let xVal = " << x.GetByIndices("x_indices") << ";\n" + << " let wVal = " << w.GetByIndices("w_indices") << ";\n" + << " value += xVal * wVal;\n" + << " }\n" + << " }\n" + << "}\n"; + } else { + ss << "for (var wInChannel: u32 = 0u; wInChannel < uniforms.w_shape[1]; wInChannel++) {\n" + << " let input_channel = in_channel_offset + wInChannel;\n" + << " for (var wHeight: u32 = 0u; wHeight < uniforms.w_shape[2]; wHeight++) {\n" + << " let xHeight = xRCCorner.x + wHeight * uniforms.dilations[0];\n" + << "" + << " if (xHeight < 0u || xHeight >= uniforms.x_shape[2]) {\n" + << " continue;\n" + << " }\n" + << "" + << " for (var wWidth: u32 = 0u; wWidth < uniforms.w_shape[3]; wWidth++) {\n" + << " let xWidth = xRCCorner.y + wWidth * uniforms.dilations[1];\n" + << " if (xWidth < 0u || xWidth >= uniforms.x_shape[3]) {\n" + << " continue;\n" + << " }\n" + << "" + << " let x_indices = x_indices_t(batch, input_channel, xHeight, xWidth);\n" + << " let w_indices = w_indices_t(output_channel, wInChannel, wHeight, wWidth);\n" + << " let xVal = " << x.GetByIndices("x_indices") << ";\n" + << " let wVal = " << w.GetByIndices("w_indices") << ";\n" + << " value += xVal * wVal;\n" + << " }\n" + << " }\n" + << "}\n"; + } + return ss.str(); +} + +Status GroupedConvProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseIndicesTypeAlias); + const auto& w = shader.AddInput("w", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseIndicesTypeAlias); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + std::string apply_activation = GetActivationSnippet(activation_, "output_value_t", "output_element_t"); + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "let output_indices = " << output.OffsetToIndices("global_idx") << ";\n" + << "let batch: u32 = output_indices[0];\n" + << "let output_channel: u32 = " << output.IndicesGet("output_indices", is_channels_last_ ? "3" : "1") << ";\n" + << "let xRCCorner_x: u32 = " << output.IndicesGet("output_indices", is_channels_last_ ? "1" : "2") << ";\n" + << "let xRCCorner_y: u32 = " << output.IndicesGet("output_indices", is_channels_last_ ? "2" : "3") << ";\n" + << "let xRCCorner: vec2 = vec2(xRCCorner_x, xRCCorner_y) * uniforms.strides - uniforms.pads;\n" + << "let group_id = output_channel * uniforms.components / uniforms.output_channels_per_group;\n" + << "let in_channel_offset = group_id * " << w.IndicesGet("uniforms.w_shape", is_channels_last_ ? 2 : 1) << ";\n" + << "var value: output_value_t = output_value_t(0);\n" + << CanculateResult(x, w, is_channels_last_); + if (has_bias_) { + const auto& b = shader.AddInput("b", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + shader.MainFunctionBody() << "value += " + b.GetByIndices("output_channel") + ";\n"; + } + shader.MainFunctionBody() << apply_activation << "\n"; + shader.MainFunctionBody() << output.SetByOffset("global_idx", "value"); + return Status::OK(); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/nn/grouped_conv.h b/onnxruntime/core/providers/webgpu/nn/grouped_conv.h new file mode 100644 index 0000000000000..d09f9679eecf5 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/nn/grouped_conv.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/optional.h" +#include "core/providers/webgpu/webgpu_kernel.h" +#include "core/providers/cpu/nn/conv_attributes.h" +#include "core/providers/webgpu/program.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/nn/fuse_utils.h" + +namespace onnxruntime { +namespace webgpu { + +class GroupedConvProgram final : public Program { + public: + GroupedConvProgram(const Activation& activation, bool has_bias, bool is_channels_last) : Program("GroupedConv"), activation_(activation), has_bias_(has_bias), is_channels_last_(is_channels_last) { + } + Status GenerateShaderCode(ShaderHelper& shader) const override; + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES( + {"output_size", ProgramUniformVariableDataType::Uint32}, + {"dilations", ProgramUniformVariableDataType::Uint32}, + {"strides", ProgramUniformVariableDataType::Uint32}, + {"pads", ProgramUniformVariableDataType::Uint32}, + {"output_channels_per_group", ProgramUniformVariableDataType::Uint32}, + {"components", ProgramUniformVariableDataType::Uint32}); + + private: + const Activation& activation_; + bool has_bias_; + bool is_channels_last_; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 2427bf62cc658..eb65e998c81c5 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -250,6 +250,8 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 16, class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 12, Transpose); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 20, Transpose); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, 22, Transpose); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 23, Transpose); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 12, DepthToSpace); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, DepthToSpace); @@ -257,9 +259,11 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInt class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInternalNHWCDomain, 13, DepthToSpace); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, Conv); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, Conv); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 21, Conv); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 22, Conv); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInternalNHWCDomain, 1, 10, Conv); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInternalNHWCDomain, 11, Conv); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInternalNHWCDomain, 11, 21, Conv); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInternalNHWCDomain, 22, Conv); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 1, 10, ConvTranspose); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, ConvTranspose); @@ -578,21 +582,25 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/core/providers/webgpu/webgpu_utils.cc b/onnxruntime/core/providers/webgpu/webgpu_utils.cc new file mode 100644 index 0000000000000..9b16767475c0c --- /dev/null +++ b/onnxruntime/core/providers/webgpu/webgpu_utils.cc @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "core/providers/webgpu/webgpu_utils.h" +namespace onnxruntime { +namespace webgpu { + +TensorShape ReduceShapeByComponents(const TensorShape& shape, int64_t components) { + // Reduce the last dimensions by components creating a new tensor shape. + TensorShapeVector shape_vector = shape.AsShapeVector(); + auto reduce_index = shape_vector.size() - 1; + // Find the last dimension that is divisible by components. + while (shape_vector[reduce_index] % components != 0 && reduce_index > 0) { + ORT_ENFORCE(components % shape_vector[reduce_index] == 0, "The components must divide dims"); + components /= shape_vector[reduce_index]; + shape_vector[reduce_index] = 1; + reduce_index--; + } + ORT_ENFORCE(reduce_index >= 0 && shape_vector[reduce_index] % components == 0, "The last non-unit dimension of the input shape must be divisible by the number of components."); + shape_vector[reduce_index] /= components; + return TensorShape(shape_vector); +} + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_utils.h b/onnxruntime/core/providers/webgpu/webgpu_utils.h index 5f6f18f34b7f5..e02d9266e8a0e 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_utils.h +++ b/onnxruntime/core/providers/webgpu/webgpu_utils.h @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once #include +#include "core/common/common.h" +#include "core/framework/tensor_shape.h" namespace onnxruntime { namespace webgpu { @@ -44,5 +47,7 @@ inline std::string MakeScalarOrVectorType(int components, std::string_view data_ } } +TensorShape ReduceShapeByComponents(const TensorShape& shape, int64_t components); + } // namespace webgpu } // namespace onnxruntime diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index e5ea562ce3535..92eaa68667f0e 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -153,7 +153,7 @@ static bool HasMemcpyNodes(const Graph& graph) { return false; } -static bool AreAllComputeNodesAssignedToCudaOrJsOrDmlEp(const Graph& graph) { +static bool AreAllComputeNodesAssignedToCudaOrJsOrDmlEpWebGpuEp(const Graph& graph) { bool nodes_on_cpu_and_cuda_and_js_and_dml_eps_only = true; for (const auto& node : graph.Nodes()) { @@ -164,6 +164,7 @@ static bool AreAllComputeNodesAssignedToCudaOrJsOrDmlEp(const Graph& graph) { !(node_provider == kCudaExecutionProvider || node_provider == kRocmExecutionProvider || node_provider == kJsExecutionProvider || + node_provider == kWebGpuExecutionProvider || node_provider == kDmlExecutionProvider) && node_provider != kCpuExecutionProvider) { nodes_on_cpu_and_cuda_and_js_and_dml_eps_only = false; @@ -2041,6 +2042,7 @@ common::Status InferenceSession::Initialize() { onnxruntime::kCudaExecutionProvider, onnxruntime::kRocmExecutionProvider, onnxruntime::kJsExecutionProvider, + onnxruntime::kWebGpuExecutionProvider, onnxruntime::kDmlExecutionProvider}; for (auto& it : graph_support_ep_list) { @@ -2063,12 +2065,13 @@ common::Status InferenceSession::Initialize() { if (strcmp(target_ep->Type().c_str(), onnxruntime::kCudaExecutionProvider) == 0 || strcmp(target_ep->Type().c_str(), onnxruntime::kRocmExecutionProvider) == 0 || strcmp(target_ep->Type().c_str(), onnxruntime::kJsExecutionProvider) == 0 || + strcmp(target_ep->Type().c_str(), onnxruntime::kWebGpuExecutionProvider) == 0 || strcmp(target_ep->Type().c_str(), onnxruntime::kDmlExecutionProvider) == 0) { // Ensure that all nodes have been partitioned to CUDA/JS or CPU EP && there are no memcpy nodes // The reasoning behind this logic is that certain shape nodes will be forced onto CPU // and as long as there are no memcpy nodes this is confirmation that no compute nodes have been placed on the CPU EP // which is all we care about. - if (!AreAllComputeNodesAssignedToCudaOrJsOrDmlEp(graph)) { + if (!AreAllComputeNodesAssignedToCudaOrJsOrDmlEpWebGpuEp(graph)) { LOGS(*session_logger_, ERROR) << "This session cannot use the graph capture feature as requested by the user " << " as all compute graph nodes have not been partitioned to the " << target_ep->Type(); diff --git a/onnxruntime/test/contrib_ops/fused_conv_test.cc b/onnxruntime/test/contrib_ops/fused_conv_test.cc index e6fe0ec0e45a3..0dd69a49972e8 100644 --- a/onnxruntime/test/contrib_ops/fused_conv_test.cc +++ b/onnxruntime/test/contrib_ops/fused_conv_test.cc @@ -33,14 +33,16 @@ void TestConvOp(const ConvOpAndTestAttributes& attributes, bool disable_cpu = false, bool disable_cuda = false, bool disable_rocm = false, + bool disable_webgpu = false, bool use_float16 = false, bool weight_is_initializer = false) { bool enable_cuda = HasCudaEnvironment(0) && !use_float16 && !disable_cuda; // Only ROCm EP supports float16. bool enable_rocm = (nullptr != DefaultRocmExecutionProvider().get()) && !disable_rocm; + bool enable_webgpu = (nullptr != DefaultWebGpuExecutionProvider().get()) && !disable_webgpu; bool enable_cpu = (nullptr != DefaultCpuExecutionProvider().get()) && !use_float16 && !disable_cpu; - if (enable_cuda || enable_rocm || enable_cpu) { + if (enable_cuda || enable_rocm || enable_cpu || enable_webgpu) { OpTester test("FusedConv", 1, onnxruntime::kMSDomain); test.AddAttribute("group", attributes.group); test.AddAttribute("kernel_shape", attributes.kernel_shape); @@ -96,6 +98,10 @@ void TestConvOp(const ConvOpAndTestAttributes& attributes, execution_providers.push_back(DefaultRocmExecutionProvider()); } + if (enable_webgpu) { + execution_providers.push_back(DefaultWebGpuExecutionProvider()); + } + if (enable_cpu) { execution_providers.push_back(DefaultCpuExecutionProvider()); } @@ -110,15 +116,16 @@ void RunConvOp(const ConvOpAndTestAttributes& attributes, const vector& expected_output_shape, bool disable_cpu = false, bool disable_cuda = false, - bool disable_rocm = false) { + bool disable_rocm = false, + bool disable_webgpu = false) { bool weight_is_initializer = false; bool use_float16 = false; TestConvOp(attributes, inputs, input_shapes, expected_output, expected_output_shape, - disable_cpu, disable_cuda, disable_rocm, use_float16, weight_is_initializer); + disable_cpu, disable_cuda, disable_rocm, disable_webgpu, use_float16, weight_is_initializer); use_float16 = true; TestConvOp(attributes, inputs, input_shapes, expected_output, expected_output_shape, - disable_cpu, disable_cuda, disable_rocm, use_float16, weight_is_initializer); + disable_cpu, disable_cuda, disable_rocm, disable_webgpu, use_float16, weight_is_initializer); } TEST(FusedConvTest, Conv2D_HardSigmoid) { @@ -139,7 +146,7 @@ TEST(FusedConvTest, Conv2D_HardSigmoid) { vector W_shape = {2, 1, 2, 2}; vector Y_shape = {1, 2, 2, 2}; auto expected_vals = {0.8f, 0.9f, 1.0f, 1.0f, 0.2f, 0.1f, 0.0f, 0.0f}; - RunConvOp(attrs, {X, W}, {X_shape, W_shape}, expected_vals, Y_shape, false, true, true); + RunConvOp(attrs, {X, W}, {X_shape, W_shape}, expected_vals, Y_shape, false, true, true, true); } TEST(FusedConvTest, Conv2D_Relu) { @@ -233,7 +240,7 @@ TEST(FusedConvTest, Cpu_Conv2D_Bias_Z_Relu) { vector Z = {-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; vector Z_shape = {1, 2, 2, 2}; auto expected_vals = {12.0f, 17.0f, 25.0f, 29.0f, 11.0f, 15.0f, 23.0f, 28.0f}; - RunConvOp(attrs, {X, W, B, Z}, {X_shape, W_shape, B_shape, Z_shape}, expected_vals, Y_shape, false, true, true); + RunConvOp(attrs, {X, W, B, Z}, {X_shape, W_shape, B_shape, Z_shape}, expected_vals, Y_shape, false, true, true, true); } #endif diff --git a/onnxruntime/test/optimizer/graph_transform_test.cc b/onnxruntime/test/optimizer/graph_transform_test.cc index a66964de17c72..a33b3148014f1 100755 --- a/onnxruntime/test/optimizer/graph_transform_test.cc +++ b/onnxruntime/test/optimizer/graph_transform_test.cc @@ -2204,6 +2204,10 @@ TEST_F(GraphTransformationTests, FuseCudaConvAddReluIdentity) { for (auto& node : p_model->MainGraph().Nodes()) { node.SetExecutionProviderType(kJsExecutionProvider); } +#elif defined(USE_WEBGPU) + for (auto& node : p_model->MainGraph().Nodes()) { + node.SetExecutionProviderType(kWebGpuExecutionProvider); + } #else for (auto& node : p_model->MainGraph().Nodes()) { node.SetExecutionProviderType(kCpuExecutionProvider); @@ -2232,6 +2236,10 @@ TEST_F(GraphTransformationTests, FuseCudaConvAdd) { for (auto& node : p_model->MainGraph().Nodes()) { node.SetExecutionProviderType(kJsExecutionProvider); } +#elif defined(USE_WEBGPU) + for (auto& node : p_model->MainGraph().Nodes()) { + node.SetExecutionProviderType(kWebGpuExecutionProvider); + } #else for (auto& node : p_model->MainGraph().Nodes()) { node.SetExecutionProviderType(kCpuExecutionProvider); @@ -2330,6 +2338,10 @@ TEST_F(GraphTransformationTests, FuseConvActivation) { for (auto& node : p_model->MainGraph().Nodes()) { node.SetExecutionProviderType(kJsExecutionProvider); } +#elif defined(USE_WEBGPU) + for (auto& node : p_model->MainGraph().Nodes()) { + node.SetExecutionProviderType(kWebGpuExecutionProvider); + } #else for (auto& node : p_model->MainGraph().Nodes()) { node.SetExecutionProviderType(kCpuExecutionProvider); @@ -2351,6 +2363,13 @@ TEST_F(GraphTransformationTests, FuseConvActivation) { } else { ASSERT_TRUE(op_to_count_after_fusion[model.second] == 0); } +#elif defined(USE_WEBGPU) + std::set webgpu_supported = {"Relu", "Clip", "Sigmoid", "Tanh", "LeakyRelu", "HardSigmoid"}; + if (webgpu_supported.find(model.second) == webgpu_supported.end()) { + ASSERT_EQ(op_to_count_before_fusion[model.second], op_to_count_after_fusion[model.second]); + } else { + ASSERT_TRUE(op_to_count_after_fusion[model.second] == 0); + } #else ASSERT_TRUE(op_to_count_after_fusion[model.second] == 0); #endif diff --git a/onnxruntime/test/providers/cpu/nn/conv_op_test.cc b/onnxruntime/test/providers/cpu/nn/conv_op_test.cc index a3a3dd939cbf0..06434d5b59ec6 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_op_test.cc @@ -489,7 +489,7 @@ TEST(ConvTest, Conv3D_1) { vector{1, 1, 1}, // kernel_shape vector{0, 0, 0, 0, 0, 0}, // pads vector{1, 1, 1}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = {-0.43337246775627136f, -0.48385289311408997f, -0.30954962968826294f, @@ -526,7 +526,7 @@ TEST(ConvTest, Conv3D_2) { vector{1, 1, 1}, // kernel_shape vector{2, 2, 2, 2, 2, 2}, // pads vector{2, 2, 2}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = {0.010772407054901123f, -0.43806642293930054f, 0.455391526222229f, -0.28657248616218567f, @@ -569,7 +569,7 @@ TEST(ConvTest, Conv3D_Bias) { vector{2, 2, 2}, // kernel_shape vector{2, 2, 2, 2, 2, 2}, // pads vector{2, 2, 2}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = {0.46796226501464844f, -0.4613912105560303f, 0.33512794971466064f, -0.4010460674762726f, @@ -916,7 +916,7 @@ TEST(ConvTest, ConvDimWithZero) { vector{1, 1}, // kernel_shape vector{0, 0, 0, 0}, // pads vector{1, 1}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = vector(); diff --git a/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc b/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc index 83b27f10fe04f..198fa07ae4ed0 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc @@ -933,7 +933,7 @@ TEST(ConvTransposeTest, DimWithZero) { TestConvTransposeOp(attrs, {X, W}, {X_shape, W_shape}, expected_vals, Y_shape, OpTester::ExpectResult::kExpectSuccess, "", {kCudaNHWCExecutionProvider, kTensorrtExecutionProvider, - kAclExecutionProvider, kQnnExecutionProvider}); + kAclExecutionProvider, kQnnExecutionProvider, kWebGpuExecutionProvider}); } TEST(ConvTransposeTest, ConvTranspose_3D) { @@ -1068,7 +1068,7 @@ TEST(ConvTransposeTest, ConvTranspose_3D) { TestConvTransposeOp(attrs, {X, W, B}, {X_shape, W_shape, B_shape}, expected_vals, Y_shape, OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kCudaExecutionProvider, - kCudaNHWCExecutionProvider, kQnnExecutionProvider}); + kCudaNHWCExecutionProvider, kQnnExecutionProvider, kWebGpuExecutionProvider}); } TEST(ConvTransposeTest, ConvTranspose_1D_AsymmetricPads) { From a7e62d6390ae06265326dc44e74753ffa633cd69 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:59:58 -0700 Subject: [PATCH 237/266] [webgpu][dawn API optimization] reduce number of calls to wgpuDeviceGetQueue (#24313) ### Description This PR is one of a series of changes for optimization of Dawn API usage. See #24281 Optimizes the usage of wgpuDeviceGetQueue. --- onnxruntime/core/providers/webgpu/webgpu_context.cc | 6 ++++-- onnxruntime/core/providers/webgpu/webgpu_context.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 955b54e873261..d9fe967f3047c 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -136,6 +136,8 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi LOGS_DEFAULT(VERBOSE) << "WebGPU EP Context is created for: Instance=" << instance_.Get() << ", Device=" << device_.Get() << "."; + // cache device queue + device_queue_ = device_.GetQueue(); // cache adapter info ORT_ENFORCE(Device().GetAdapterInfo(&adapter_info_)); // cache device limits @@ -404,7 +406,7 @@ Status WebGpuContext::Run(ComputeContext& context, const ProgramBase& program) { } uniform_buffer = buffer_mgr_->Create(uniform_buffer_total_size, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform); - device_.GetQueue().WriteBuffer(uniform_buffer, 0, uniform_data_buffer.data(), uniform_buffer_total_size); + device_queue_.WriteBuffer(uniform_buffer, 0, uniform_data_buffer.data(), uniform_buffer_total_size); } const auto& compute_pass_encoder = GetComputePassEncoder(); @@ -696,7 +698,7 @@ void WebGpuContext::Flush() { } auto command_buffer = current_command_encoder_.Finish(); - Device().GetQueue().Submit(1, &command_buffer); + device_queue_.Submit(1, &command_buffer); BufferManager().RefreshPendingBuffers(); current_command_encoder_ = nullptr; num_pending_dispatches_ = 0; diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 2f044400afee2..0a54b13e31bf7 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -207,6 +207,7 @@ class WebGpuContext final { webgpu::ValidationMode validation_mode_; + wgpu::Queue device_queue_; wgpu::AdapterInfo adapter_info_; wgpu::Limits device_limits_; std::unordered_set device_features_; From 55c1a3b073b50435a15441ffd856a7056be7c336 Mon Sep 17 00:00:00 2001 From: virajwad <84867530+virajwad@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:14:55 -0700 Subject: [PATCH 238/266] Fix 'minimal_power' to 'minimum_power' for DirectML performance selection (perf test) (#24303) In Perf Test for DirectML EP, for the "performance_preference" runtime key we could not select the "minimum_power" value option due to a small bug. This PR fixes it so that "minimum_power" can be used and ran. I will also link the respective issue to this PR I made the change, built onnxruntime, and tested the perf_test.exe + DLLs on a system with Intel Integrated Graphics + Nvidia dGPU. Switching between 'minimum_power' and 'high_performance', I can see the options respectively choose Intel Integrated and Nvidia dGPU as device runtimes respectively (I checked task manager utilization for both devices). Both inferences complete with no problems. I am attaching a reproducer here with the built perf_test and the commands I tried to test it: [DLL_Build_DML_Reproducer.zip](https://github.com/user-attachments/files/19596463/DLL_Build_DML_Reproducer.zip) Issue #24182 @fdwr Hi, I fixed the issue, if you could please review, thank you --- onnxruntime/test/perftest/ort_test_session.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onnxruntime/test/perftest/ort_test_session.cc b/onnxruntime/test/perftest/ort_test_session.cc index 86d04fb4bbc2b..1cc17ea03fa32 100644 --- a/onnxruntime/test/perftest/ort_test_session.cc +++ b/onnxruntime/test/perftest/ort_test_session.cc @@ -421,12 +421,12 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)"); "Select from 'gpu', or 'npu' \n"); } } else if (key == "performance_preference") { - std::set ov_supported_values = {"default", "high_performance", "minimal_power"}; + std::set ov_supported_values = {"default", "high_performance", "minimum_power"}; if (ov_supported_values.find(value) != ov_supported_values.end()) { } else { ORT_THROW( "[ERROR] [DML] You have selected a wrong configuration value for the key 'performance_preference'. " - "Select from 'default', 'high_performance' or 'minimal_power' \n"); + "Select from 'default', 'high_performance' or 'minimum_power' \n"); } } else if (key == "disable_metacommands") { std::set ov_supported_values = {"true", "True", "false", "False"}; From d6df4f29d32ab0632b7b1522aa4f117c36993d7d Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Fri, 4 Apr 2025 23:58:31 -0700 Subject: [PATCH 239/266] Add ConvTranspose cache key (#24317) ### Description ### Motivation and Context --- onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc b/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc index aa3ef5b96db54..74f3e0dcc85f5 100644 --- a/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc +++ b/onnxruntime/core/providers/webgpu/nn/conv_backprop_webgpu.cc @@ -181,6 +181,8 @@ ConvTranspose2DProgram CreateConvTranspose2DProgram(const std::vector(output_size)}, {strides}, {kernel_dims}, {dilations}, {effective_kernel_dims}, {local_pads}, {static_cast(input_channels_per_group_int)}, {static_cast(input_channels_per_group)}, {static_cast(output_channels_per_group)}}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE); From a1186f634188ba17ab22572c031ee64d9178a675 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Mon, 7 Apr 2025 21:36:18 +0800 Subject: [PATCH 240/266] [webgpu] Use 1D dispatch groups for attention (#24228) This PR uses 1d disptach group size and uses workgroup_idx instead of workgroup.x|workgroup.y in case they are normalized. --- .../contrib_ops/webgpu/bert/attention.cc | 70 ++++++++++--------- .../contrib_ops/webgpu/bert/attention.h | 8 ++- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/attention.cc b/onnxruntime/contrib_ops/webgpu/bert/attention.cc index abea94d2e0b50..6e7919f281fb6 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/attention.cc @@ -99,23 +99,24 @@ Status AttentionProbsProgram::GenerateShaderCode(ShaderHelper& shader) const { << "var tileK: array;\n" << "alias f32_val_t = " << (components_ == 4 ? "vec4" : (components_ == 2 ? "vec2" : "f32")) << ";\n"; shader.MainFunctionBody() << "// x holds the N and y holds the M\n" - << "let m = workgroup_id.y * TILE_SIZE;\n" - << "let n = workgroup_id.x * TILE_SIZE;\n" - << "let batch_idx = workgroup_id.z / uniforms.num_heads;\n" - << "let qOffset = workgroup_id.z * uniforms.M * uniforms.K + m * uniforms.K;\n" + << "let m = u32(workgroup_idx / uniforms.num_total_seq_length_tile) % uniforms.num_seq_length_tile * TILE_SIZE;\n" + << "let n = (workgroup_idx % uniforms.num_total_seq_length_tile) * TILE_SIZE;\n" + << "let batch_head_idx = u32(workgroup_idx / (uniforms.num_total_seq_length_tile * uniforms.num_seq_length_tile));\n" + << "let batch_idx = batch_head_idx / uniforms.num_heads;\n" + << "let qOffset = batch_head_idx * uniforms.M * uniforms.K + m * uniforms.K;\n" << "let sequence_length = uniforms.M;\n" << "var total_sequence_length = uniforms.N;\n"; std::ostringstream oss; InitVarStub(oss, seqlen_k_); shader.MainFunctionBody() << oss.str(); - shader.MainFunctionBody() << "let kOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.kv_sequence_length * uniforms.K;\n"; + shader.MainFunctionBody() << "let kOffset = (batch_head_idx / uniforms.n_reps) * uniforms.kv_sequence_length * uniforms.K;\n"; if (has_present_key_) { - shader.MainFunctionBody() << "let presentKeyOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.present_sequence_length * uniforms.K;\n"; + shader.MainFunctionBody() << "let presentKeyOffset = (batch_head_idx / uniforms.n_reps) * uniforms.present_sequence_length * uniforms.K;\n"; } shader.MainFunctionBody() << "var value = f32_val_t(0);\n" "for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) {\n" - " if (global_id.y < uniforms.M && w + local_id.x < uniforms.K) {\n" + " if (m + local_id.y < uniforms.M && w + local_id.x < uniforms.K) {\n" " tileQ[TILE_SIZE * local_id.y + local_id.x] = q[qOffset + local_id.y * uniforms.K + w + local_id.x];\n" " }\n" " if (n + local_id.y < uniforms.N && w + local_id.x < uniforms.K) {\n" @@ -123,7 +124,7 @@ Status AttentionProbsProgram::GenerateShaderCode(ShaderHelper& shader) const { if ((feed_past_key_ && has_present_key_) || (past_present_share_buffer_ && !is_first_prompt_)) { shader.MainFunctionBody() << " if (n + local_id.y < past_sequence_length) {\n" - << " let pastKeyOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.past_sequence_length * uniforms.K;\n" + << " let pastKeyOffset = (batch_head_idx / uniforms.n_reps) * uniforms.past_sequence_length * uniforms.K;\n" << " tileK[idx] = " << (past_present_share_buffer_ ? "present_key" : "past_key") << "[pastKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x];\n" << " } else if (n + local_id.y - past_sequence_length < uniforms.kv_sequence_length) {\n" << " tileK[idx] = key[kOffset + (n + local_id.y - past_sequence_length) * uniforms.K + w + local_id.x];\n" @@ -152,9 +153,9 @@ Status AttentionProbsProgram::GenerateShaderCode(ShaderHelper& shader) const { << " workgroupBarrier();\n" << "}\n"; - shader.MainFunctionBody() << "if (global_id.y < uniforms.M && global_id.x < total_sequence_length) {\n" - << " let headOffset = workgroup_id.z * uniforms.M * uniforms.N;\n" - << " let outputIdx = headOffset + global_id.y * uniforms.N + global_id.x;\n" + shader.MainFunctionBody() << "if (m + local_id.y < uniforms.M && n + local_id.x < total_sequence_length) {\n" + << " let headOffset = batch_head_idx * uniforms.M * uniforms.N;\n" + << " let outputIdx = headOffset + m + local_id.y * uniforms.N + n + local_id.x;\n" << " var sum: f32 = " << (components_ == 4 ? "value.x + value.y + value.z + value.w" : (components_ == 2 ? "value.x + value.y" : "value")) << ";\n"; shader.MainFunctionBody() << " output[outputIdx] = output_value_t(sum * uniforms.alpha)"; @@ -199,9 +200,9 @@ Status ComputeAttentionProbs(onnxruntime::webgpu::ComputeContext& context, int o } const uint32_t vectorized_head_size = (parameters.head_size_ + components - 1) / components; - program.SetDispatchGroupSize((total_sequence_length + tile_size - 1) / tile_size, - (parameters.sequence_length_ + tile_size - 1) / tile_size, - parameters.batch_size_ * parameters.num_heads_) + const uint32_t num_total_seq_length_tile = (total_sequence_length + tile_size - 1) / tile_size; + const uint32_t num_seq_length_tile = (parameters.sequence_length_ + tile_size - 1) / tile_size; + program.SetDispatchGroupSize(parameters.batch_size_ * parameters.num_heads_ * num_seq_length_tile * num_total_seq_length_tile) .SetWorkgroupSize(tile_size, tile_size) .CacheHint(std::to_string(tile_size), parameters.past_present_share_buffer_, feed_past_key, has_present_key, has_attention_bias, seqlen_k != nullptr, components, parameters.is_first_prompt_) .AddUniformVariables({{static_cast(parameters.sequence_length_)}, @@ -214,7 +215,9 @@ Status ComputeAttentionProbs(onnxruntime::webgpu::ComputeContext& context, int o {static_cast(parameters.kv_sequence_length_)}, {static_cast(seqlen_k == nullptr ? total_sequence_length : parameters.seqlen_present_kv_cache_)}, {static_cast(parameters.n_reps)}, - {static_cast(parameters.is_first_prompt_ ? 1 : 0)}}) + {static_cast(parameters.is_first_prompt_ ? 1 : 0)}, + {num_total_seq_length_tile}, + {num_seq_length_tile}}) .SetOverridableConstants({{static_cast(tile_size)}}); return context.RunProgram(program); @@ -228,15 +231,15 @@ Status InPlaceSoftmaxProgram::GenerateShaderCode(ShaderHelper& shader) const { shader.AdditionalImplementation() << "var thread_max: array;\n" << "var thread_sum: array;\n" << "alias f32_val_t = " << (components_ == 4 ? "vec4" : (components_ == 2 ? "vec2" : "f32")) << ";\n"; - shader.MainFunctionBody() << "let batch_idx = workgroup_id.z / uniforms.num_heads;\n" - << "let sequence_length = uniforms.sequence_length;\n" + shader.MainFunctionBody() << "let sequence_length = uniforms.sequence_length;\n" + << "let batch_idx = u32(workgroup_idx / sequence_length) / uniforms.num_heads;\n" << "var total_sequence_length = uniforms.total_sequence_length_comp * " << components_ << ";\n"; std::ostringstream oss; InitVarStub(oss, seqlen_k_); shader.MainFunctionBody() << oss.str() << "let local_offset = local_idx * uniforms.elements_per_thread;\n" - << "let offset = (global_idx / " << work_group_size_ << ") * uniforms.total_sequence_length_comp + local_offset;\n" - << "let seq_causal_length = " << (seqlen_k_ ? "past_sequence_length + workgroup_id.y + 1" : "uniforms.total_sequence_length_comp") << ";\n" + << "let offset = workgroup_idx * uniforms.total_sequence_length_comp + local_offset;\n" + << "let seq_causal_length = " << (seqlen_k_ ? "past_sequence_length + workgroup_idx % sequence_length + 1" : "uniforms.total_sequence_length_comp") << ";\n" << "var thread_max_vector = f32_val_t(-3.402823e+38f);\n" << "for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) {\n" << " thread_max_vector = max(f32_val_t(x[offset + i]), thread_max_vector);\n" @@ -292,7 +295,7 @@ Status ComputeInPlaceSoftmax(onnxruntime::webgpu::ComputeContext& context, Tenso } program.AddOutputs({{probs, ProgramTensorMetadataDependency::TypeAndRank, components}}) .CacheHint(work_group_size) - .SetDispatchGroupSize(1, sequence_length, batch_size * num_heads) + .SetDispatchGroupSize(batch_size * num_heads * sequence_length) .SetWorkgroupSize(work_group_size) .AddUniformVariables({{static_cast(batch_size)}, {static_cast(num_heads)}, @@ -321,19 +324,20 @@ Status VxAttentionScoreProgram::GenerateShaderCode(ShaderHelper& shader) const { shader.AdditionalImplementation() << "var tileQ: array;\n" << "var tileK: array;\n"; - shader.MainFunctionBody() << "let head_idx = workgroup_id.z % uniforms.num_heads;\n" - << "let batch_idx = workgroup_id.z / uniforms.num_heads;\n" - << "let m = global_id.y;\n" - << "let n = global_id.x;\n" - << "let offsetA = workgroup_id.z * (uniforms.M * uniforms.K) + m * uniforms.K;\n" + shader.MainFunctionBody() << "let batch_head_idx = u32(workgroup_idx / (uniforms.num_head_size_tile * uniforms.num_seq_length_tile));\n" + << "let head_idx = batch_head_idx % uniforms.num_heads;\n" + << "let batch_idx = batch_head_idx / uniforms.num_heads;\n" + << "let m = (u32(workgroup_idx / uniforms.num_head_size_tile) % uniforms.num_seq_length_tile) * TILE_SIZE + local_id.y;\n" + << "let n = (workgroup_idx % uniforms.num_head_size_tile) * TILE_SIZE + local_id.x;\n" + << "let offsetA = batch_head_idx * (uniforms.M * uniforms.K) + m * uniforms.K;\n" << "let sequence_length = uniforms.M;\n" << "var total_sequence_length = uniforms.K;\n"; std::ostringstream oss; InitVarStub(oss, seqlen_k_); shader.MainFunctionBody() << oss.str(); - shader.MainFunctionBody() << "let vOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.N * uniforms.kv_sequence_length + n;\n"; + shader.MainFunctionBody() << "let vOffset = (batch_head_idx / uniforms.n_reps) * uniforms.N * uniforms.kv_sequence_length + n;\n"; if (has_present_value_) { - shader.MainFunctionBody() << "let presentValueOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.N * uniforms.present_sequence_length + n;\n"; + shader.MainFunctionBody() << "let presentValueOffset = (batch_head_idx / uniforms.n_reps) * uniforms.N * uniforms.present_sequence_length + n;\n"; } shader.MainFunctionBody() << "var value = output_value_t(0);\n" @@ -346,7 +350,7 @@ Status VxAttentionScoreProgram::GenerateShaderCode(ShaderHelper& shader) const { if ((feed_past_value_ && has_present_value_) || (past_present_share_buffer_ && !is_first_prompt_)) { shader.MainFunctionBody() << " if (w + local_id.y < past_sequence_length) {\n" - << " let pastValueOffset = (workgroup_id.z / uniforms.n_reps) * uniforms.N * uniforms.past_sequence_length + n;\n" + << " let pastValueOffset = (batch_head_idx / uniforms.n_reps) * uniforms.N * uniforms.past_sequence_length + n;\n" << " tileK[idx] = " << (past_present_share_buffer_ ? "present_value" : "past_value") << "[pastValueOffset + (w + local_id.y) * uniforms.N];\n" << " } else if (w + local_id.y - past_sequence_length < uniforms.kv_sequence_length) {\n" << " tileK[idx] = v[vOffset + (w + local_id.y - past_sequence_length) * uniforms.N];\n" @@ -414,9 +418,9 @@ Status ComputeVxAttentionScore(onnxruntime::webgpu::ComputeContext& context, int program.AddOutput({present_value, ProgramTensorMetadataDependency::TypeAndRank, components}); } - program.SetDispatchGroupSize((parameters.v_head_size_ + tile_n_size - 1) / tile_n_size, - (parameters.sequence_length_ + tile_size - 1) / tile_size, - parameters.batch_size_ * parameters.num_heads_) + const uint32_t num_head_size_tile = (parameters.v_head_size_ + tile_n_size - 1) / tile_n_size; + const uint32_t num_seq_length_tile = (parameters.sequence_length_ + tile_size - 1) / tile_size; + program.SetDispatchGroupSize(parameters.batch_size_ * parameters.num_heads_ * num_head_size_tile * num_seq_length_tile) .CacheHint(std::to_string(tile_size), parameters.past_present_share_buffer_, feed_past_value, has_present_value, seqlen_k != nullptr, parameters.is_first_prompt_) .SetWorkgroupSize(tile_size, tile_size) .AddUniformVariables({{static_cast(parameters.sequence_length_)}, @@ -429,7 +433,9 @@ Status ComputeVxAttentionScore(onnxruntime::webgpu::ComputeContext& context, int {static_cast(parameters.kv_sequence_length_)}, {static_cast(seqlen_k == nullptr ? total_sequence_length : parameters.seqlen_present_kv_cache_)}, {static_cast(parameters.n_reps)}, - {static_cast(parameters.is_first_prompt_)}}) + {static_cast(parameters.is_first_prompt_)}, + {num_head_size_tile}, + {num_seq_length_tile}}) .SetOverridableConstants({{static_cast(tile_size)}}); return context.RunProgram(program); diff --git a/onnxruntime/contrib_ops/webgpu/bert/attention.h b/onnxruntime/contrib_ops/webgpu/bert/attention.h index 6123d2c47add1..7c0cb40cc7f93 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/attention.h @@ -50,7 +50,9 @@ class AttentionProbsProgram final : public Program { {"kv_sequence_length", ProgramUniformVariableDataType::Uint32}, {"present_sequence_length", ProgramUniformVariableDataType::Uint32}, {"n_reps", ProgramUniformVariableDataType::Uint32}, - {"is_first_prompt", ProgramUniformVariableDataType::Uint32}); + {"is_first_prompt", ProgramUniformVariableDataType::Uint32}, + {"num_total_seq_length_tile", ProgramUniformVariableDataType::Uint32}, + {"num_seq_length_tile", ProgramUniformVariableDataType::Uint32}); WEBGPU_PROGRAM_DEFINE_OVERRIDABLE_CONSTANTS({"TILE_SIZE", ProgramConstantDataType::Uint32}); @@ -105,7 +107,9 @@ class VxAttentionScoreProgram final : public Program { {"kv_sequence_length", ProgramUniformVariableDataType::Uint32}, {"present_sequence_length", ProgramUniformVariableDataType::Uint32}, {"n_reps", ProgramUniformVariableDataType::Uint32}, - {"is_first_prompt", ProgramUniformVariableDataType::Uint32}); + {"is_first_prompt", ProgramUniformVariableDataType::Uint32}, + {"num_head_size_tile", ProgramUniformVariableDataType::Uint32}, + {"num_seq_length_tile", ProgramUniformVariableDataType::Uint32}); WEBGPU_PROGRAM_DEFINE_OVERRIDABLE_CONSTANTS({"TILE_SIZE", ProgramConstantDataType::Uint32}); From 73676fc5eb1c5ddeec0c5be321936d34aeb7452a Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 7 Apr 2025 06:37:00 -0700 Subject: [PATCH 241/266] [webgpu][dawn API optimization] reduce number of calls to buffer APIs (#24315) ### Description This PR is one of a series of changes for optimization of Dawn API usage. See https://github.com/microsoft/onnxruntime/pull/24281 Reduce the calls to wgpuBufferAddRef and wgpuBufferRelease (part 1). --- .../core/providers/webgpu/allocator.cc | 14 +-- .../core/providers/webgpu/buffer_manager.cc | 102 ++++++++++++------ .../core/providers/webgpu/buffer_manager.h | 2 +- .../core/providers/webgpu/webgpu_context.cc | 4 - .../core/providers/webgpu/webgpu_context.h | 3 - 5 files changed, 80 insertions(+), 45 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/allocator.cc b/onnxruntime/core/providers/webgpu/allocator.cc index 91cae111a708a..315d0cd75e946 100644 --- a/onnxruntime/core/providers/webgpu/allocator.cc +++ b/onnxruntime/core/providers/webgpu/allocator.cc @@ -13,15 +13,15 @@ void* GpuBufferAllocator::Alloc(size_t size) { return nullptr; } - WGPUBuffer buffer; - if (!session_initialized_ && context_.SupportsBufferMapExtendedUsages()) { - buffer = context_.BufferManager().CreateUMA(size); - } else { - buffer = context_.BufferManager().Create(size); + stats_.num_allocs++; + +#if !defined(__wasm__) + if (!session_initialized_ && context_.DeviceHasFeature(wgpu::FeatureName::BufferMapExtendedUsages)) { + return context_.BufferManager().CreateUMA(size); } +#endif // !defined(__wasm__) - stats_.num_allocs++; - return buffer; + return context_.BufferManager().Create(size); } void GpuBufferAllocator::Free(void* p) { diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.cc b/onnxruntime/core/providers/webgpu/buffer_manager.cc index adb37f54f2e8f..1d8c689cbd909 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.cc +++ b/onnxruntime/core/providers/webgpu/buffer_manager.cc @@ -56,14 +56,27 @@ class LazyReleaseCacheManager : public IBufferCacheManager { } void ReleaseBuffer(WGPUBuffer buffer) override { - pending_buffers_.emplace_back(wgpu::Buffer::Acquire(buffer)); + pending_buffers_.emplace_back(buffer); } void OnRefresh() override { + Release(); pending_buffers_.clear(); } - std::vector pending_buffers_; + public: + ~LazyReleaseCacheManager() { + Release(); + } + + protected: + void Release() { + for (auto& buffer : pending_buffers_) { + wgpuBufferRelease(buffer); + } + } + + std::vector pending_buffers_; }; class SimpleCacheManager : public IBufferCacheManager { @@ -74,7 +87,7 @@ class SimpleCacheManager : public IBufferCacheManager { WGPUBuffer TryAcquireCachedBuffer(size_t buffer_size) override { auto it = buffers_.find(buffer_size); if (it != buffers_.end() && !it->second.empty()) { - auto buffer = it->second.back().MoveToCHandle(); + auto buffer = it->second.back(); it->second.pop_back(); return buffer; } @@ -87,18 +100,31 @@ class SimpleCacheManager : public IBufferCacheManager { } void ReleaseBuffer(WGPUBuffer buffer) override { - pending_buffers_.emplace_back(wgpu::Buffer::Acquire(buffer)); + pending_buffers_.emplace_back(buffer); } void OnRefresh() override { for (auto& buffer : pending_buffers_) { - buffers_[static_cast(buffer.GetSize())].emplace_back(std::move(buffer)); + buffers_[static_cast(wgpuBufferGetSize(buffer))].emplace_back(buffer); } pending_buffers_.clear(); } - std::map> buffers_; - std::vector pending_buffers_; + public: + ~SimpleCacheManager() { + for (auto& buffer : pending_buffers_) { + wgpuBufferRelease(buffer); + } + for (auto& pair : buffers_) { + for (auto& buffer : pair.second) { + wgpuBufferRelease(buffer); + } + } + } + + protected: + std::map> buffers_; + std::vector pending_buffers_; }; // TODO: maybe use different bucket size for storage and uniform buffers? @@ -155,7 +181,7 @@ class BucketCacheManager : public IBufferCacheManager { WGPUBuffer TryAcquireCachedBuffer(size_t buffer_size) override { auto it = buckets_.find(buffer_size); if (it != buckets_.end() && !it->second.empty()) { - auto buffer = it->second.back().MoveToCHandle(); + auto buffer = it->second.back(); it->second.pop_back(); return buffer; } @@ -167,31 +193,44 @@ class BucketCacheManager : public IBufferCacheManager { } void ReleaseBuffer(WGPUBuffer buffer) override { - pending_buffers_.emplace_back(wgpu::Buffer::Acquire(buffer)); + pending_buffers_.emplace_back(buffer); } void OnRefresh() override { // TODO: consider graph capture. currently not supported for (auto& buffer : pending_buffers_) { - auto buffer_size = static_cast(buffer.GetSize()); + auto buffer_size = static_cast(wgpuBufferGetSize(buffer)); auto it = buckets_.find(buffer_size); if (it != buckets_.end() && it->second.size() < buckets_limit_[buffer_size]) { - it->second.emplace_back(std::move(buffer)); + it->second.emplace_back(buffer); + } else { + wgpuBufferRelease(buffer); } } pending_buffers_.clear(); } + ~BucketCacheManager() { + for (auto& buffer : pending_buffers_) { + wgpuBufferRelease(buffer); + } + for (auto& pair : buckets_) { + for (auto& buffer : pair.second) { + wgpuBufferRelease(buffer); + } + } + } + protected: void Initialize() { buckets_keys_.reserve(buckets_limit_.size()); buckets_.reserve(buckets_limit_.size()); for (const auto& pair : buckets_limit_) { buckets_keys_.push_back(pair.first); - buckets_.emplace(pair.first, std::vector()); + buckets_.emplace(pair.first, std::vector()); } std::sort(buckets_keys_.begin(), buckets_keys_.end()); @@ -205,8 +244,8 @@ class BucketCacheManager : public IBufferCacheManager { #endif } std::unordered_map buckets_limit_; - std::unordered_map> buckets_; - std::vector pending_buffers_; + std::unordered_map> buckets_; + std::vector pending_buffers_; std::vector buckets_keys_; }; @@ -255,11 +294,10 @@ BufferManager::BufferManager(WebGpuContext& context, BufferCacheMode storage_buf void BufferManager::Upload(void* src, WGPUBuffer dst, size_t size) { // If the buffer is mapped, we can directly write to it. - wgpu::Buffer dst_buffer = dst; - auto mapped_data = dst_buffer.GetMappedRange(); + void* mapped_data = wgpuBufferGetMappedRange(dst, 0, WGPU_WHOLE_MAP_SIZE); // ensure the buffer is mapped if (mapped_data) { memcpy(mapped_data, src, size); - dst_buffer.Unmap(); + wgpuBufferUnmap(dst); return; } @@ -288,9 +326,11 @@ void BufferManager::MemCpy(WGPUBuffer src, WGPUBuffer dst, size_t size) { EnforceBufferUnmapped(context_, dst); auto buffer_size = NormalizeBufferSize(size); - ORT_ENFORCE(buffer_size <= wgpuBufferGetSize(src) && buffer_size <= wgpuBufferGetSize(dst), + auto src_size = static_cast(wgpuBufferGetSize(src)); + auto dst_size = static_cast(wgpuBufferGetSize(dst)); + ORT_ENFORCE(buffer_size <= src_size && buffer_size <= dst_size, "Source and destination buffers must have enough space for the copy operation. src_size=", - wgpuBufferGetSize(src), ", dst_size=", wgpuBufferGetSize(dst), ", copy_size=", buffer_size, "."); + src_size, ", dst_size=", dst_size, ", copy_size=", buffer_size, "."); auto& command_encoder = context_.GetCommandEncoder(); context_.EndComputePass(); @@ -298,7 +338,7 @@ void BufferManager::MemCpy(WGPUBuffer src, WGPUBuffer dst, size_t size) { } WGPUBuffer BufferManager::Create(size_t size, wgpu::BufferUsage usage) { - auto& cache = GetCacheManager(static_cast(usage)); + auto& cache = GetCacheManager(usage); auto buffer_size = cache.CalculateBufferSize(size); auto buffer = cache.TryAcquireCachedBuffer(buffer_size); @@ -310,7 +350,6 @@ WGPUBuffer BufferManager::Create(size_t size, wgpu::BufferUsage usage) { wgpu::BufferDescriptor desc{}; desc.size = buffer_size; desc.usage = usage; - // desc.label = std::to_string(xx++).c_str(); buffer = context_.Device().CreateBuffer(&desc).MoveToCHandle(); ORT_ENFORCE(buffer, "Failed to create GPU buffer: size=", buffer_size, ", usage=", uint64_t(usage), "."); @@ -320,14 +359,16 @@ WGPUBuffer BufferManager::Create(size_t size, wgpu::BufferUsage usage) { } WGPUBuffer BufferManager::CreateUMA(size_t size, wgpu::BufferUsage usage) { - ORT_ENFORCE(usage & wgpu::BufferUsage::Storage, "UMA buffer must have storage usage."); - auto& cache = GetCacheManager(static_cast(usage)); + ORT_ENFORCE(usage & wgpu::BufferUsage::Storage, "UMA buffer must be a storage buffer."); + auto& cache = GetCacheManager(usage); auto buffer_size = cache.CalculateBufferSize(size); + // Ensure the buffer is mapped for writing at creation. + usage |= wgpu::BufferUsage::MapWrite; + wgpu::BufferDescriptor desc{}; desc.size = buffer_size; - // Ensure the buffer is mapped for writing at creation. - desc.usage = usage | wgpu::BufferUsage::MapWrite; + desc.usage = usage; desc.mappedAtCreation = true; auto buffer = context_.Device().CreateBuffer(&desc).MoveToCHandle(); @@ -373,12 +414,12 @@ void BufferManager::RefreshPendingBuffers() { default_cache_->OnRefresh(); } -IBufferCacheManager& BufferManager::GetCacheManager(WGPUBufferUsage usage) const { - if (usage & WGPUBufferUsage_Storage) { +IBufferCacheManager& BufferManager::GetCacheManager(wgpu::BufferUsage usage) const { + if (usage & wgpu::BufferUsage::Storage) { return *storage_cache_; - } else if (usage & WGPUBufferUsage_Uniform) { + } else if (usage & wgpu::BufferUsage::Uniform) { return *uniform_cache_; - } else if (usage & WGPUBufferUsage_QueryResolve) { + } else if (usage & wgpu::BufferUsage::QueryResolve) { return *query_resolve_cache_; } else { return *default_cache_; @@ -386,7 +427,8 @@ IBufferCacheManager& BufferManager::GetCacheManager(WGPUBufferUsage usage) const } IBufferCacheManager& BufferManager::GetCacheManager(WGPUBuffer buffer) const { - return GetCacheManager(wgpuBufferGetUsage(buffer)); + auto usage = static_cast(wgpuBufferGetUsage(buffer)); + return GetCacheManager(usage); } std::unique_ptr BufferManagerFactory::Create(WebGpuContext& context, BufferCacheMode storage_buffer_cache_mode, BufferCacheMode uniform_buffer_cache_mode, BufferCacheMode query_resolve_buffer_cache_mode) { diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.h b/onnxruntime/core/providers/webgpu/buffer_manager.h index 6a8ebdd60a1ec..b9028ad5de858 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.h +++ b/onnxruntime/core/providers/webgpu/buffer_manager.h @@ -70,7 +70,7 @@ class BufferManager { void RefreshPendingBuffers(); private: - IBufferCacheManager& GetCacheManager(WGPUBufferUsage usage) const; + IBufferCacheManager& GetCacheManager(wgpu::BufferUsage usage) const; IBufferCacheManager& GetCacheManager(WGPUBuffer buffer) const; WebGpuContext& context_; diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index d9fe967f3047c..2987d3905fe54 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -149,10 +149,6 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi device_features_.insert(supported_features.features[i]); } -#if !defined(__wasm__) - supports_buffer_map_extended_usages_ = device_.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages); -#endif - // create buffer manager buffer_mgr_ = BufferManagerFactory::Create(*this, buffer_cache_config.storage.mode, diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 0a54b13e31bf7..8ebb122103177 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -145,8 +145,6 @@ class WebGpuContext final { Status Run(ComputeContext& context, const ProgramBase& program); void OnRunEnd(); - bool SupportsBufferMapExtendedUsages() const { return supports_buffer_map_extended_usages_; } - private: enum class TimestampQueryType { None = 0, @@ -238,7 +236,6 @@ class WebGpuContext final { #if defined(ENABLE_PIX_FOR_WEBGPU_EP) std::unique_ptr pix_frame_generator_ = nullptr; #endif // ENABLE_PIX_FOR_WEBGPU_EP - bool supports_buffer_map_extended_usages_ = false; }; } // namespace webgpu From 350d140074d9c964b42d5718d47132c9889af885 Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Mon, 7 Apr 2025 10:22:37 -0700 Subject: [PATCH 242/266] Implement load cancellation ability (#24257) ### Description SessionOptions now have a new property - load_cancelation_flag. This flag if set to true causes the model to abort load and initialization for huge models. ### Motivation and Context Some users request an ability to abandon model loading and initialization if that exceeds certain time limits. --- .../NativeMethods.shared.cs | 18 ++++++ .../SessionOptions.shared.cs | 10 ++++ include/onnxruntime/core/common/common.h | 32 +++++++++- include/onnxruntime/core/common/exceptions.h | 47 ++++++++++++++- include/onnxruntime/core/common/status.h | 7 ++- .../core/session/onnxruntime_c_api.h | 19 ++++++ .../core/session/onnxruntime_cxx_api.h | 2 + .../core/session/onnxruntime_cxx_inline.h | 6 ++ .../core/framework/error_code_helper.h | 23 ++++---- .../core/framework/graph_partitioner.cc | 59 ++++++++++++++++--- .../core/framework/graph_partitioner.h | 15 +++++ onnxruntime/core/framework/session_options.h | 15 +++++ onnxruntime/core/framework/session_state.cc | 9 +++ .../core/framework/session_state_utils.cc | 6 ++ onnxruntime/core/graph/graph.cc | 8 +++ onnxruntime/core/graph/model.cc | 19 +++++- onnxruntime/core/graph/model.h | 16 +++++ .../core/optimizer/graph_transformer_mgr.cc | 3 + .../core/optimizer/graph_transformer_mgr.h | 11 ++++ .../core/session/abi_session_options.cc | 8 +++ onnxruntime/core/session/inference_session.cc | 35 ++++++++--- onnxruntime/core/session/inference_session.h | 4 ++ onnxruntime/core/session/onnxruntime_c_api.cc | 40 +++---------- onnxruntime/core/session/ort_apis.h | 3 + .../python/onnxruntime_pybind_state.cc | 6 ++ .../test/framework/inference_session_test.cc | 25 ++++++++ .../providers/cpu/controlflow/loop_test.cc | 5 +- onnxruntime/test/shared_lib/test_inference.cc | 29 +++++++++ 28 files changed, 415 insertions(+), 65 deletions(-) diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs index b64a5c3e5a4a2..77c35aac65b92 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.InteropServices; +using static Microsoft.ML.OnnxRuntime.NativeMethods; namespace Microsoft.ML.OnnxRuntime { @@ -325,6 +326,16 @@ public struct OrtApi public IntPtr CreateLoraAdapterFromArray; public IntPtr ReleaseLoraAdapter; public IntPtr RunOptionsAddActiveLoraAdapter; + public IntPtr SetEpDynamicOptions; + public IntPtr ReleaseValueInfo; + public IntPtr ReleaseNode; + public IntPtr ReleaseGraph; + public IntPtr ReleaseModel; + public IntPtr GetValueInfoName; + public IntPtr GetValueInfoTypeInfo; + public IntPtr GetModelEditorApi; + public IntPtr CreateTensorWithDataAndDeleterAsOrtValue; + public IntPtr SessionOptionsSetLoadCancellationFlag; } internal static class NativeMethods @@ -404,6 +415,7 @@ static NativeMethods() OrtReleaseSessionOptions = (DOrtReleaseSessionOptions)Marshal.GetDelegateForFunctionPointer(api_.ReleaseSessionOptions, typeof(DOrtReleaseSessionOptions)); OrtCloneSessionOptions = (DOrtCloneSessionOptions)Marshal.GetDelegateForFunctionPointer(api_.CloneSessionOptions, typeof(DOrtCloneSessionOptions)); OrtSetSessionExecutionMode = (DOrtSetSessionExecutionMode)Marshal.GetDelegateForFunctionPointer(api_.SetSessionExecutionMode, typeof(DOrtSetSessionExecutionMode)); + OrtSessionOptionsSetLoadCancellationFlag = (DOrtSessionOptionsSetLoadCancellationFlag)Marshal.GetDelegateForFunctionPointer(api_.SessionOptionsSetLoadCancellationFlag, typeof(DOrtSessionOptionsSetLoadCancellationFlag)); OrtSetOptimizedModelFilePath = (DOrtSetOptimizedModelFilePath)Marshal.GetDelegateForFunctionPointer(api_.SetOptimizedModelFilePath, typeof(DOrtSetOptimizedModelFilePath)); OrtEnableProfiling = (DOrtEnableProfiling)Marshal.GetDelegateForFunctionPointer(api_.EnableProfiling, typeof(DOrtEnableProfiling)); OrtDisableProfiling = (DOrtDisableProfiling)Marshal.GetDelegateForFunctionPointer(api_.DisableProfiling, typeof(DOrtDisableProfiling)); @@ -1025,6 +1037,12 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca ExecutionMode execution_mode); public static DOrtSetSessionExecutionMode OrtSetSessionExecutionMode; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtSessionOptionsSetLoadCancellationFlag(IntPtr /*(OrtSessionOptions*)*/ options, + bool value); + public static DOrtSessionOptionsSetLoadCancellationFlag OrtSessionOptionsSetLoadCancellationFlag; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtSetOptimizedModelFilePath(IntPtr /* OrtSessionOptions* */ options, byte[] optimizedModelFilepath); public static DOrtSetOptimizedModelFilePath OrtSetOptimizedModelFilePath; diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs index bd450451a1265..9b0f183f03681 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs @@ -802,6 +802,16 @@ public ExecutionMode ExecutionMode } private ExecutionMode _executionMode = ExecutionMode.ORT_SEQUENTIAL; + /// + /// Sets the load cancellation flag for the session. Default is set to false. + /// Provides an opportunity for the user to cancel model loading. + /// + /// true to request cancellation, false to proceed + public void SetLoadCancellationFlag(bool value) + { + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsSetLoadCancellationFlag(handle, value)); + } + #endregion #region Private Methods diff --git a/include/onnxruntime/core/common/common.h b/include/onnxruntime/core/common/common.h index 0822eba950f50..10f658f52e0d9 100644 --- a/include/onnxruntime/core/common/common.h +++ b/include/onnxruntime/core/common/common.h @@ -148,6 +148,26 @@ void LogRuntimeError(uint32_t session_id, const common::Status& status, const ch abort(); \ } while (false) +#define ORT_THROW_FROM_STATUS(status) \ + do { \ + ::onnxruntime::PrintFinalMessage( \ + ::onnxruntime::OnnxRuntimeException( \ + ORT_WHERE_WITH_STACK, status.ToString()) \ + .what()); \ + abort(); \ + } while (false) + +#define ORT_THROW_WITH_CATEGORY_AND_CODE(category, code, ...) \ + do { \ + ::onnxruntime::PrintFinalMessage( \ + ::onnxruntime::OnnxRuntimeException(ORT_WHERE_WITH_STACK, \ + ::onnxruntime::MakeString(__VA_ARGS__), \ + ::onnxruntime::common::category, \ + ::onnxruntime::common::code) \ + .what()); \ + abort(); \ + } while (false) + #else #define ORT_TRY try @@ -180,6 +200,16 @@ void LogRuntimeError(uint32_t session_id, const common::Status& status, const ch #define ORT_THROW_EX(ex, ...) \ throw ex(__VA_ARGS__) +#define ORT_THROW_FROM_STATUS(status) \ + throw ::onnxruntime::OnnxRuntimeException(ORT_WHERE_WITH_STACK, status.ToString(), status.Category(), \ + static_cast<::onnxruntime::common::StatusCode>(status.Code())) + +#define ORT_THROW_WITH_CATEGORY_AND_CODE(category, code, ...) \ + throw ::onnxruntime::OnnxRuntimeException(ORT_WHERE_WITH_STACK, \ + ::onnxruntime::MakeString(__VA_ARGS__), \ + ::onnxruntime::common::category, \ + ::onnxruntime::common::code) + #endif #define ORT_MAKE_STATUS(category, code, ...) \ @@ -237,7 +267,7 @@ void LogRuntimeError(uint32_t session_id, const common::Status& status, const ch auto _status = (expr); \ if ((!_status.IsOK())) { \ ::onnxruntime::LogRuntimeError(0, _status, __FILE__, static_cast(__FUNCTION__), __LINE__); \ - ORT_THROW(_status); \ + ORT_THROW_FROM_STATUS(_status); \ } \ } while (0) diff --git a/include/onnxruntime/core/common/exceptions.h b/include/onnxruntime/core/common/exceptions.h index 494a770b8db98..6d0f6edd6e7c4 100644 --- a/include/onnxruntime/core/common/exceptions.h +++ b/include/onnxruntime/core/common/exceptions.h @@ -11,6 +11,7 @@ #include #include "core/common/common.h" +#include "core/common/status.h" #include "core/common/code_location.h" namespace onnxruntime { @@ -35,12 +36,44 @@ class OnnxRuntimeException : public std::exception { /** Create a new exception that captures the location it was thrown from. @param location Location in the source code the exception is being thrown from + @param msg Message containing additional information about the exception cause. + @param category Error category + @param code Error code + */ + + OnnxRuntimeException(const CodeLocation& location, + const std::string& message, + common::StatusCategory category, + common::StatusCode code) noexcept + : OnnxRuntimeException(location, nullptr, message, category, code) { + } + + /** + Create a new exception that captures the location it was thrown from. + The instance will be created with ONNXRUNTIME category and FAIL code. + @param location Location in the source code the exception is being thrown from @param failed_condition Optional string containing the condition that failed. e.g. "tensor.Size() == input.Size()". May be nullptr. @param msg Message containing additional information about the exception cause. */ - OnnxRuntimeException(const CodeLocation& location, const char* failed_condition, const std::string& msg) - : location_{location} { + OnnxRuntimeException(const CodeLocation& location, const char* failed_condition, const std::string& msg) noexcept + : OnnxRuntimeException(location, failed_condition, msg, + common::StatusCategory::ONNXRUNTIME, common::StatusCode::FAIL) { + } + + /** + Create a new exception that captures the location it was thrown from. + @param location Location in the source code the exception is being thrown from + @param failed_condition Optional string containing the condition that failed. + e.g. "tensor.Size() == input.Size()". May be nullptr. + @param msg Message containing additional information about the exception cause. + @param category Error category + @param code Error code + */ + OnnxRuntimeException(const CodeLocation& location, const char* failed_condition, const std::string& msg, + common::StatusCategory category, + common::StatusCode code) + : location_{location}, category_(category), code_(code) { std::ostringstream ss; ss << location.ToString(CodeLocation::kFilenameAndPath); // output full path in case just the filename is ambiguous @@ -58,6 +91,14 @@ class OnnxRuntimeException : public std::exception { what_ = ss.str(); } + common::StatusCategory Category() const noexcept { + return category_; + } + + common::StatusCode Code() const noexcept { + return code_; + } + const char* what() const noexcept override { return what_.c_str(); } @@ -66,6 +107,8 @@ class OnnxRuntimeException : public std::exception { const CodeLocation location_; const std::vector stacktrace_; std::string what_; + common::StatusCategory category_; + common::StatusCode code_; }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/common/status.h b/include/onnxruntime/core/common/status.h index 8f171daabbb1e..b222e411d7804 100644 --- a/include/onnxruntime/core/common/status.h +++ b/include/onnxruntime/core/common/status.h @@ -43,7 +43,8 @@ enum StatusCode { MODEL_LOADED = 8, NOT_IMPLEMENTED = 9, INVALID_GRAPH = 10, - EP_FAIL = 11 + EP_FAIL = 11, + MODEL_LOAD_CANCELED = 12, }; constexpr const char* StatusCodeToString(StatusCode status) noexcept { @@ -72,6 +73,8 @@ constexpr const char* StatusCodeToString(StatusCode status) noexcept { return "INVALID_GRAPH"; case StatusCode::EP_FAIL: return "EP_FAIL"; + case StatusCode::MODEL_LOAD_CANCELED: + return "MODEL_LOAD_CANCELED"; default: return "GENERAL ERROR"; } @@ -104,6 +107,8 @@ constexpr HRESULT StatusCodeToHRESULT(StatusCode status) noexcept { return HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT); case StatusCode::EP_FAIL: return HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR); + case StatusCode::MODEL_LOAD_CANCELED: + return HRESULT_FROM_WIN32(ERROR_CANCELLED); default: return E_FAIL; } diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 6d4cc8a1f2fa9..3bf0d5e19c525 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -255,6 +255,7 @@ typedef enum OrtErrorCode { ORT_NOT_IMPLEMENTED, ORT_INVALID_GRAPH, ORT_EP_FAIL, + ORT_MODEL_LOAD_CANCELED, } OrtErrorCode; typedef enum OrtOpAttrType { @@ -4898,6 +4899,24 @@ struct OrtApi { _In_ const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type, _Outptr_ OrtValue** out); + + /** \brief sets load cancellation flag to abort session loading process. + * + * \param[in] options instance that was passed to the session at creation time. + * \param[in] cancel setting this to true after model loading process was initiated will + * attempt to cancel the loading process. If cancellation is successful, CreateSession() + * CreateSessionFromArray() or any other session creation API that take session options as an + * argument will return an OrtStatus indicating that session loading was canceled at user request, + * error code ORT_MODEL_LOAD_CANCELED. + * The APIs above would not return any valid Session instance. This is the best case effort and the result + * is not guaranteed. The session may have already been created and initialized + * before the cancellation request was issued. + * + * \snippet{doc} snippets.dox OrtStatus + * + */ + ORT_API2_STATUS(SessionOptionsSetLoadCancellationFlag, _Inout_ OrtSessionOptions* options, + _In_ bool cancel); }; /* diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 979b478e2fbb4..ce7dc1c45b05e 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -928,6 +928,8 @@ struct SessionOptionsImpl : ConstSessionOptionsImpl { SessionOptionsImpl& SetExecutionMode(ExecutionMode execution_mode); ///< Wraps OrtApi::SetSessionExecutionMode + SessionOptionsImpl& SetLoadCancellationFlag(bool value); ///< Wraps OrtApi::SessionOptionsSetLoadCancellationFlag + SessionOptionsImpl& SetLogId(const char* logid); ///< Wraps OrtApi::SetSessionLogId SessionOptionsImpl& SetLogSeverityLevel(int level); ///< Wraps OrtApi::SetSessionLogSeverityLevel diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 48c5e52e33c53..524e3ecc92936 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -747,6 +747,12 @@ inline SessionOptionsImpl& SessionOptionsImpl::SetExecutionMode(ExecutionM return *this; } +template +inline SessionOptionsImpl& SessionOptionsImpl::SetLoadCancellationFlag(bool value) { + ThrowOnError(GetApi().SessionOptionsSetLoadCancellationFlag(this->p_, value)); + return *this; +} + template inline SessionOptionsImpl& SessionOptionsImpl::SetLogId(const char* logid) { ThrowOnError(GetApi().SetSessionLogId(this->p_, logid)); diff --git a/onnxruntime/core/framework/error_code_helper.h b/onnxruntime/core/framework/error_code_helper.h index 703d183ea5c87..b42c6a9ba3e10 100644 --- a/onnxruntime/core/framework/error_code_helper.h +++ b/onnxruntime/core/framework/error_code_helper.h @@ -17,16 +17,19 @@ Status ToStatus(const OrtStatus* ort_status, common::StatusCategory category = c #ifndef ORT_NO_EXCEPTIONS #define API_IMPL_BEGIN try { -#define API_IMPL_END \ - } \ - catch (const onnxruntime::NotImplementedException& ex) { \ - return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, ex.what()); \ - } \ - catch (const std::exception& ex) { \ - return OrtApis::CreateStatus(ORT_RUNTIME_EXCEPTION, ex.what()); \ - } \ - catch (...) { \ - return OrtApis::CreateStatus(ORT_FAIL, "Unknown Exception"); \ +#define API_IMPL_END \ + } \ + catch (const onnxruntime::OnnxRuntimeException& ex) { \ + return OrtApis::CreateStatus(static_cast(ex.Code()), ex.what()); \ + } \ + catch (const onnxruntime::NotImplementedException& ex) { \ + return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, ex.what()); \ + } \ + catch (const std::exception& ex) { \ + return OrtApis::CreateStatus(ORT_RUNTIME_EXCEPTION, ex.what()); \ + } \ + catch (...) { \ + return OrtApis::CreateStatus(ORT_FAIL, "Unknown Exception"); \ } #else diff --git a/onnxruntime/core/framework/graph_partitioner.cc b/onnxruntime/core/framework/graph_partitioner.cc index ff4d300f665b1..50f14104cfd7a 100644 --- a/onnxruntime/core/framework/graph_partitioner.cc +++ b/onnxruntime/core/framework/graph_partitioner.cc @@ -56,6 +56,7 @@ namespace { // contains some common parameters used by the partitioning helper functions struct PartitionParams { std::reference_wrapper graph; + std::reference_wrapper check_load_cancellation_fn; #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) std::reference_wrapper func_mgr; std::reference_wrapper fused_kernel_registry; @@ -143,6 +144,7 @@ struct GetCapabilityForEPParams { #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) IResourceAccountant* resource_accountant; std::reference_wrapper graph_optimizer_registry; + std::reference_wrapper check_load_cancellation_fn; }; auto get_capabilities = [](const IExecutionProvider& ep, @@ -188,7 +190,12 @@ static Status GetCapabilityForEP(const GetCapabilityForEPParams& params, const l { const GraphViewer graph_viewer(graph); - capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant, graph_optimizer_registry); + capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant, + graph_optimizer_registry); + if (params.check_load_cancellation_fn()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, + "Graph partitioning was canceled by user request"); + } if (capabilities.empty()) { return Status::OK(); @@ -209,6 +216,10 @@ static Status GetCapabilityForEP(const GetCapabilityForEPParams& params, const l // Perform layout transformation on the specific EP assigned graph bool modified = false; ORT_RETURN_IF_ERROR(params.transform_layout(graph, modified, current_ep, params.debug_graph_fn)); + if (params.check_load_cancellation_fn()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, + "GetCapabilities was canceled by user request"); + } // It is possible some new nodes are introduced during transformation. These nodes can be either existing nodes // which are reconstructed to update domain or completely new nodes which are necessary for layout transformation. @@ -226,7 +237,12 @@ static Status GetCapabilityForEP(const GetCapabilityForEPParams& params, const l capabilities.clear(); const GraphViewer graph_viewer(graph); - capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant, graph_optimizer_registry); + capabilities = get_capabilities(current_ep, graph_viewer, kernel_lookup, params.resource_accountant, + graph_optimizer_registry); + if (params.check_load_cancellation_fn()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, + "GetCapabilities was canceled by user request"); + } // all nodes with an index >= first_new_node with domain of kMSInternalNHWCDomain should be in the capabilities InlinedHashSet new_nodes_in_capabilities; @@ -405,6 +421,7 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, int& fused_node_unique_id, const layout_transformation::TransformLayoutFunction& transform_layout_fn, const layout_transformation::DebugGraphFn& debug_graph_fn, + const CheckLoadCancellationFn& check_load_cancellation_fn, const logging::Logger& logger, IResourceAccountant* resource_accountant, const GraphOptimizerRegistry& graph_optimizer_registry) { // handle testing edge case where optimizers or constant lifting results in graph with no nodes. @@ -420,7 +437,10 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, // we pass through the FuncManager from the top level graph ORT_RETURN_IF_ERROR(PartitionOnnxFormatModelImpl(*subgraph, func_mgr, kernel_registry_mgr, fused_kernel_registry, current_ep, mode, fused_node_unique_id, - transform_layout_fn, debug_graph_fn, logger, resource_accountant, graph_optimizer_registry)); + transform_layout_fn, debug_graph_fn, + check_load_cancellation_fn, + logger, resource_accountant, + graph_optimizer_registry)); } } @@ -445,7 +465,8 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, std::cref(transform_layout_fn), std::cref(debug_graph_fn), resource_accountant, - std::ref(graph_optimizer_registry)}; + std::ref(graph_optimizer_registry), + std::cref(check_load_cancellation_fn)}; ORT_RETURN_IF_ERROR(GetCapabilityForEP(get_capability_params, logger)); if (capabilities.empty()) { @@ -532,6 +553,8 @@ static Status PartitionOnnxFormatModelImpl(Graph& graph, FuncManager& func_mgr, } ORT_RETURN_IF_ERROR(current_ep.Compile(nodes_and_viewers, node_compute_funcs)); + ORT_RETURN_IF(check_load_cancellation_fn(), + "Graph partitioning is canceled due to user request."); if (node_compute_funcs.size() != nodes_to_compile.size()) { return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, type, " did not return correct number of compiled functions"); @@ -633,6 +656,7 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide Graph& graph, const GraphOptimizerRegistry& graph_optimizer_registry, const logging::Logger& logger, + const CheckLoadCancellationFn& check_load_cancellation_fn, InlinedHashSet& not_inlined, size_t& inlined_count) { // handle testing edge case where optimizers or constant lifting results in graph with no nodes. @@ -650,6 +674,7 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide *subgraph, graph_optimizer_registry, logger, + check_load_cancellation_fn, not_inlined, inlined_count)); } @@ -673,8 +698,13 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide InlinedHashSet claimed_by_ep; for (const auto& ep : execution_providers) { std::vector> capabilities; - ORT_RETURN_IF_ERROR(GetCapabilityForEPForAotInlining(graph_viewer, kernel_registry_mgr, *ep, graph_optimizer_registry, logger, + ORT_RETURN_IF_ERROR(GetCapabilityForEPForAotInlining(graph_viewer, kernel_registry_mgr, *ep, + graph_optimizer_registry, logger, capabilities)); + if (check_load_cancellation_fn()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, "AOT inlining is canceled due to user request."); + } + for (auto& capability : capabilities) { const auto& nodes = capability->sub_graph->nodes; if (nodes.size() == 1) { @@ -707,6 +737,9 @@ static Status InlineFunctionsAOTImpl(const ExecutionProviders& execution_provide ORT_IGNORE_RETURN_VALUE(not_inlined.insert(std::move(function_id))); } } + if (check_load_cancellation_fn()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, "AOT inlining is canceled due to user request."); + } } return Status::OK(); @@ -846,6 +879,7 @@ static Status PartitionOnnxFormatModel(const PartitionParams& partition_params, auto& fused_kernel_registry = partition_params.fused_kernel_registry.get(); auto& fused_node_unique_id = partition_params.fused_node_unique_id.get(); const auto& transform_layout_function = partition_params.transform_layout_function; + const CheckLoadCancellationFn& check_load_cancellation_fn = partition_params.check_load_cancellation_fn; do { // process full graph with each EP @@ -861,6 +895,7 @@ static Status PartitionOnnxFormatModel(const PartitionParams& partition_params, fused_kernel_registry, *ep, mode, fused_node_unique_id, transform_layout_function, partition_params.debug_graph_fn, + check_load_cancellation_fn, logger, resource_accountant, graph_optimizer_registry)); } @@ -915,7 +950,8 @@ static Status PartitionOrtFormatModelImpl(const PartitionParams& partition_param std::cref(partition_params.debug_graph_fn), #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) nullptr, - std::ref(graph_optimizer_registry) + std::ref(graph_optimizer_registry), + partition_params.check_load_cancellation_fn }; // clang-format on @@ -972,6 +1008,9 @@ static Status PartitionOrtFormatModelImpl(const PartitionParams& partition_param std::vector single_node_compute_func; ORT_RETURN_IF_ERROR(current_ep.Compile({IExecutionProvider::FusedNodeAndGraph{node, *compilation_entry.viewer}}, single_node_compute_func)); + if (partition_params.check_load_cancellation_fn()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, "Graph partitioning is canceled due to user request."); + } ORT_RETURN_IF(single_node_compute_func.empty(), "single_node_compute_func should have 1 element."); auto& func_mgr = partition_params.func_mgr.get(); @@ -1032,6 +1071,8 @@ Status GraphPartitioner::InlineFunctionsAOT(Model& model, return Status::OK(); } + auto check_load_cancellation_fn = [this]() -> bool { return IsLoadCancellationFlagSet(); }; + auto& graph = model.MainGraph(); InlinedHashSet not_inlined; do { @@ -1041,13 +1082,13 @@ Status GraphPartitioner::InlineFunctionsAOT(Model& model, graph, *graph_optimizer_registry_, logger, + check_load_cancellation_fn, not_inlined, inlined_count)); if (inlined_count == 0) { break; } - ORT_RETURN_IF_ERROR(graph.Resolve()); } while (true); @@ -1082,6 +1123,8 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "No provider specified."); } + CheckLoadCancellationFn check_load_cancellation_fn = [this]() -> bool { return IsLoadCancellationFlagSet(); }; + #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) // fused_kernel_registry is preparing the kernels created on the fly for fused sub graph. // It is only visible for current session. @@ -1092,6 +1135,7 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, PartitionParams partition_params{ std::ref(graph), + std::cref(check_load_cancellation_fn), std::ref(func_mgr), std::ref(*fused_kernel_registry), std::ref(fused_node_unique_id), @@ -1105,6 +1149,7 @@ Status GraphPartitioner::Partition(Graph& graph, FuncManager& func_mgr, ORT_UNUSED_PARAMETER(debug_graph_fn); PartitionParams partition_params{ std::ref(graph), + std::cref(check_load_cancellation_fn), }; #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) diff --git a/onnxruntime/core/framework/graph_partitioner.h b/onnxruntime/core/framework/graph_partitioner.h index b9d4022cb5a14..87edc7a64c6b5 100644 --- a/onnxruntime/core/framework/graph_partitioner.h +++ b/onnxruntime/core/framework/graph_partitioner.h @@ -33,6 +33,16 @@ class GraphPartitioner { graph_optimizer_registry_(std::move(graph_optimizer_registry)) { } + GraphPartitioner(KernelRegistryManager& kernel_registry_mgr, + const ExecutionProviders& providers, + std::unique_ptr graph_optimizer_registry, + CheckLoadCancellationFn check_load_cancellation_fn) + : kernel_registry_mgr_(kernel_registry_mgr), + providers_(providers), + graph_optimizer_registry_(std::move(graph_optimizer_registry)), + check_load_cancellation_fn_(std::move(check_load_cancellation_fn)) { + } + // Run partitioning. Status Partition(Graph& graph, FuncManager& func_mgr, const layout_transformation::TransformLayoutFunction& transform_layout_function, @@ -41,6 +51,10 @@ class GraphPartitioner { Mode mode = Mode::kNormal, const layout_transformation::DebugGraphFn& debug_graph_fn = {}) const; + bool IsLoadCancellationFlagSet() const { + return check_load_cancellation_fn_ && check_load_cancellation_fn_(); + } + #ifndef ORT_MINIMAL_BUILD /// // Ahead of Time Function inlining. The main purpose of the function is to inline as many @@ -69,6 +83,7 @@ class GraphPartitioner { KernelRegistryManager& kernel_registry_mgr_; const ExecutionProviders& providers_; std::unique_ptr graph_optimizer_registry_; + CheckLoadCancellationFn check_load_cancellation_fn_; }; } // namespace onnxruntime diff --git a/onnxruntime/core/framework/session_options.h b/onnxruntime/core/framework/session_options.h index 8d4db36106f28..ef323b99b006c 100644 --- a/onnxruntime/core/framework/session_options.h +++ b/onnxruntime/core/framework/session_options.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "core/common/inlined_containers.h" #include "core/framework/config_options.h" @@ -66,6 +67,8 @@ struct FreeDimensionOverride { int64_t dim_value; }; +using CheckLoadCancellationFn = std::function; + /** * Configuration information for a session. */ @@ -184,6 +187,18 @@ struct SessionOptions { // User specified logging func and param OrtLoggingFunction user_logging_function = nullptr; void* user_logging_param = nullptr; + + void SetLoadCancellationFlag(bool value) noexcept { + *load_cancellation_flag = value; + } + + bool IsLoadCancellationFlagSet() const noexcept { + return *load_cancellation_flag; + } + + // Load cancellation flag is necessary to be within shared memory as session_options are + // copied internally and the flag needs to be accessible across all copies. + std::shared_ptr load_cancellation_flag = std::make_shared(false); }; inline std::ostream& operator<<(std::ostream& os, const SessionOptions& session_options) { diff --git a/onnxruntime/core/framework/session_state.cc b/onnxruntime/core/framework/session_state.cc index d174d6cc72ead..6362a3169f3a3 100644 --- a/onnxruntime/core/framework/session_state.cc +++ b/onnxruntime/core/framework/session_state.cc @@ -422,6 +422,10 @@ Status SessionState::PrepackConstantInitializedTensors( auto prepacked_constant_weights = [this, &constant_initializers_use_count, &initializers_to_share_map]( bool should_cache_prepacked_weights_for_shared_initializers) -> Status { for (auto& node : GetGraphViewer().Nodes()) { + if (sess_options_.IsLoadCancellationFlagSet()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, + "Weight pre-packing was canceled due to user request."); + } auto kernel = GetMutableKernel(node.Index()); int input_idx = 0; for (auto& input_def : node.InputDefs()) { @@ -1541,6 +1545,11 @@ Status SessionState::FinalizeSessionStateImpl(const std::basic_stringname(); diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index 39ffc6a5b0cee..334ecb3887d14 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -1268,6 +1268,10 @@ Graph::Graph(const Model& owning_model, #endif } + if (owning_model_.IsLoadCancellationFlagSet()) { + ORT_THROW_WITH_CATEGORY_AND_CODE(ONNXRUNTIME, MODEL_LOAD_CANCELED, "Graph loading canceled due to user request."); + } + // Remove constant nodes as they're replaced with initializers above. const gsl::not_null*> graph_mutable_nodes{graph_proto_->mutable_node()}; graph_mutable_nodes->erase( @@ -1365,6 +1369,10 @@ Graph::Graph(const Model& owning_model, } } + if (owning_model_.IsLoadCancellationFlagSet()) { + ORT_THROW_WITH_CATEGORY_AND_CODE(ONNXRUNTIME, MODEL_LOAD_CANCELED, "Graph loading canceled due to user request."); + } + for (auto& graph_output : graph_proto_->output()) { if (utils::HasName(graph_output) && utils::HasType(graph_output)) { auto& name = graph_output.name(); diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index 7629e40c1b5fe..436af7115eb1a 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -82,7 +82,7 @@ Model::Model(const std::string& graph_name, const std::vector& model_local_functions, const logging::Logger& logger, const ModelOptions& options) - : model_path_(model_path) { + : model_path_(model_path), check_load_cancellation_fn_(options.check_load_cancellation_fn) { model_proto_.set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION); model_proto_.mutable_graph()->set_name(graph_name); model_metadata_ = model_metadata; @@ -161,7 +161,7 @@ Model::Model(const ModelProto& model_proto, const PathString& model_path, Model::Model(ModelProto&& model_proto, const PathString& model_path, const IOnnxRuntimeOpSchemaRegistryList* local_registries, const logging::Logger& logger, const ModelOptions& options) - : model_path_(model_path) { + : model_path_(model_path), check_load_cancellation_fn_(options.check_load_cancellation_fn) { if (!utils::HasGraph(model_proto)) { ORT_THROW("ModelProto does not have a graph."); } @@ -435,6 +435,11 @@ Status Model::Load(const ModelProto& model_proto, ORT_TRY { model = std::make_unique(model_proto, model_path, local_registries, logger, options); } + ORT_CATCH(const OnnxRuntimeException& ex) { + ORT_HANDLE_EXCEPTION([&]() { + status = Status(ex.Category(), ex.Code(), ex.what()); + }); + } ORT_CATCH(const std::exception& ex) { ORT_HANDLE_EXCEPTION([&]() { status = Status(ONNXRUNTIME, INVALID_ARGUMENT, "Failed to load model with error: " + std::string(ex.what())); @@ -474,6 +479,11 @@ Status Model::Load(ModelProto&& model_proto, ORT_TRY { model = std::make_unique(std::move(model_proto), model_path, local_registries, logger, options); } + ORT_CATCH(const OnnxRuntimeException& ex) { + ORT_HANDLE_EXCEPTION([&]() { + status = Status(ex.Category(), ex.Code(), ex.what()); + }); + } ORT_CATCH(const std::exception& ex) { ORT_HANDLE_EXCEPTION([&]() { status = Status(ONNXRUNTIME, INVALID_ARGUMENT, "Failed to load model with error: " + std::string(ex.what())); @@ -509,6 +519,11 @@ static Status LoadModelHelper(const T& file_path, Loader loader) { ORT_TRY { status = loader(fd); } + ORT_CATCH(const OnnxRuntimeException& ex) { + ORT_HANDLE_EXCEPTION([&]() { + status = Status(ex.Category(), ex.Code(), ex.what()); + }); + } ORT_CATCH(const std::exception& ex) { ORT_HANDLE_EXCEPTION([&]() { status = Status(ONNXRUNTIME, FAIL, ex.what()); diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 6fd94c60d6b99..70f82bcfb160b 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -11,6 +11,7 @@ #include "core/common/flatbuffers.h" +#include "core/framework/session_options.h" #include "core/graph/graph_viewer.h" #include "core/graph/ort_format_load_options.h" #include "core/session/onnxruntime_c_api.h" @@ -38,6 +39,14 @@ struct ModelOptions { // be returned. bool strict_shape_type_inference; + CheckLoadCancellationFn check_load_cancellation_fn; + + ModelOptions(bool allow_released_opsets_only, bool strict_shape_type_inference, + CheckLoadCancellationFn check_load_cancellation_fn) + : allow_released_opsets_only(allow_released_opsets_only), + strict_shape_type_inference(strict_shape_type_inference), + check_load_cancellation_fn(std::move(check_load_cancellation_fn)) {} + ModelOptions(bool allow_released_opsets_only, bool strict_shape_type_inference) : allow_released_opsets_only(allow_released_opsets_only), strict_shape_type_inference(strict_shape_type_inference) {} @@ -102,6 +111,11 @@ class Model { #endif // !defined(ORT_MINIMAL_BUILD) + // Check for load cancellation. + bool IsLoadCancellationFlagSet() const noexcept { + return check_load_cancellation_fn_ && check_load_cancellation_fn_(); + } + #if !defined(ORT_MINIMAL_BUILD) // Get model's IR version. // Return if not specified. @@ -343,5 +357,7 @@ class Model { // Main graph of the model. std::unique_ptr graph_; + + CheckLoadCancellationFn check_load_cancellation_fn_; }; } // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/graph_transformer_mgr.cc b/onnxruntime/core/optimizer/graph_transformer_mgr.cc index 039283bb2d4e1..83c3f70799987 100644 --- a/onnxruntime/core/optimizer/graph_transformer_mgr.cc +++ b/onnxruntime/core/optimizer/graph_transformer_mgr.cc @@ -27,6 +27,9 @@ common::Status GraphTransformerManager::ApplyTransformers(Graph& graph, Transfor } for (unsigned step = 0; step < steps_; ++step) { + if (IsLoadCancellationFlagSet()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, "Graph transformation canceled due to user request."); + } bool graph_changed = false; for (const auto& transformer : transformers->second) { if (step > 0 && transformer->ShouldOnlyApplyOnce()) diff --git a/onnxruntime/core/optimizer/graph_transformer_mgr.h b/onnxruntime/core/optimizer/graph_transformer_mgr.h index ed66302434ab2..eab57f12bfcbb 100644 --- a/onnxruntime/core/optimizer/graph_transformer_mgr.h +++ b/onnxruntime/core/optimizer/graph_transformer_mgr.h @@ -24,6 +24,16 @@ class GraphTransformerManager { // Get the maximum number of graph transformation steps common::Status GetSteps(unsigned& steps) const; + // Set the cancellation flag ptr from session_options + void SetLoadCancellationFn(CheckLoadCancellationFn check_load_cancellation_fn) { + check_load_cancellation_fn_ = std::move(check_load_cancellation_fn); + } + + // Get the cancellation flag ptr + bool IsLoadCancellationFlagSet() const noexcept { + return check_load_cancellation_fn_ && check_load_cancellation_fn_(); + } + // Register a transformer with a level. common::Status Register(std::unique_ptr transformer, TransformerLevel level); @@ -38,5 +48,6 @@ class GraphTransformerManager { InlinedHashMap>> level_to_transformer_map_; InlinedHashMap transformers_info_; + CheckLoadCancellationFn check_load_cancellation_fn_; }; } // namespace onnxruntime diff --git a/onnxruntime/core/session/abi_session_options.cc b/onnxruntime/core/session/abi_session_options.cc index 2e733f67a888c..e50ee5738c30e 100644 --- a/onnxruntime/core/session/abi_session_options.cc +++ b/onnxruntime/core/session/abi_session_options.cc @@ -340,3 +340,11 @@ ORT_API_STATUS_IMPL(OrtApis::SetDeterministicCompute, _Inout_ OrtSessionOptions* return nullptr; API_IMPL_END } + +ORT_API_STATUS_IMPL(OrtApis::SessionOptionsSetLoadCancellationFlag, _Inout_ OrtSessionOptions* options, + _In_ bool is_cancel) { + API_IMPL_BEGIN + options->value.SetLoadCancellationFlag(is_cancel); + return nullptr; + API_IMPL_END +} diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index 92eaa68667f0e..0cb361bae563b 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -384,6 +384,7 @@ void InferenceSession::ConstructorCommon(const SessionOptions& session_options, #if !defined(ORT_MINIMAL_BUILD) // Update the number of steps for the graph transformer manager using the "finalized" session options ORT_THROW_IF_ERROR(graph_transformer_mgr_.SetSteps(session_options_.max_num_graph_transformation_steps)); + graph_transformer_mgr_.SetLoadCancellationFn(this->check_load_cancellation_fn_); #endif #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) @@ -1005,11 +1006,13 @@ common::Status InferenceSession::LoadOnnxModel(const PathString& model_uri) { std::copy(std::begin(interop_domains_), std::end(interop_domains_), std::back_inserter(domain_ptrs)); ORT_RETURN_IF_ERROR(AddCustomOpDomains(domain_ptrs)); #endif + const bool strict_shape_type_inference = session_options_.config_options.GetConfigOrDefault( kOrtSessionOptionsConfigStrictShapeTypeInference, "0") == "1"; return onnxruntime::Model::Load(model_location_, model, HasLocalSchema() ? &custom_schema_registries_ : nullptr, *session_logger_, - ModelOptions(true, strict_shape_type_inference)); + ModelOptions(true, strict_shape_type_inference, + check_load_cancellation_fn_)); }; common::Status st = LoadWithLoader(loader, "model_loading_uri"); @@ -1102,7 +1105,8 @@ common::Status InferenceSession::Load(const void* model_data, int model_data_len return onnxruntime::Model::Load(std::move(model_proto), model_location_, model, HasLocalSchema() ? &custom_schema_registries_ : nullptr, *session_logger_, - ModelOptions(true, strict_shape_type_inference)); + ModelOptions(true, strict_shape_type_inference, + check_load_cancellation_fn_)); }; return LoadWithLoader(loader, "model_loading_array"); @@ -1140,7 +1144,8 @@ common::Status InferenceSession::LoadOnnxModel(ModelProto model_proto) { // This call will move model_proto to the constructed model instance return onnxruntime::Model::Load(std::move(model_proto), model_location_, model, HasLocalSchema() ? &custom_schema_registries_ : nullptr, *session_logger_, - ModelOptions(true, strict_shape_type_inference)); + ModelOptions(true, strict_shape_type_inference, + check_load_cancellation_fn_)); }; return LoadWithLoader(loader, "model_loading_proto"); @@ -1173,7 +1178,8 @@ common::Status InferenceSession::Load(std::istream& model_istream, bool allow_re const bool strict_shape_type_inference = session_options_.config_options.GetConfigOrDefault( kOrtSessionOptionsConfigStrictShapeTypeInference, "0") == "1"; ModelOptions model_opts(allow_released_opsets_only, - strict_shape_type_inference); + strict_shape_type_inference, + check_load_cancellation_fn_); std::string external_data_folder_path = session_options_.config_options.GetConfigOrDefault( kOrtSessionOptionsModelExternalInitializersFileFolderPath, ""); @@ -1212,7 +1218,8 @@ common::Status InferenceSession::Load() { // Pass on ownership of the parsed ModelProto to the Model instance (its job here is done by this stage) return Model::Load(std::move(this->model_proto_), model_location_, model, HasLocalSchema() ? &custom_schema_registries_ : nullptr, *session_logger_, - ModelOptions(allow_released_opsets_only, strict_shape_type_inference)); + ModelOptions(allow_released_opsets_only, strict_shape_type_inference, + check_load_cancellation_fn_)); }; return LoadWithLoader(loader, "model_loading_from_saved_proto"); @@ -1240,7 +1247,8 @@ common::Status InferenceSession::Load(const OrtModel& model_editor_api_model) { std::unique_ptr tmp_model; ORT_RETURN_IF_ERROR(Model::LoadFromModelEditorApiModel(model_editor_api_model, HasLocalSchema() ? &custom_schema_registries_ : nullptr, - ModelOptions(true, strict_shape_type_inference), + ModelOptions(true, strict_shape_type_inference, + check_load_cancellation_fn_), *session_logger_, tmp_model)); model_ = std::move(tmp_model); @@ -1284,7 +1292,8 @@ common::Status InferenceSession::TransformGraph(onnxruntime::Graph& graph, bool auto graph_optimizer_registry = std::make_unique(&session_options_, execution_providers_.Get(onnxruntime::kCpuExecutionProvider), session_logger_); - GraphPartitioner partitioner(kernel_registry_manager_, execution_providers_, std::move(graph_optimizer_registry)); + GraphPartitioner partitioner(kernel_registry_manager_, execution_providers_, std::move(graph_optimizer_registry), + check_load_cancellation_fn_); // Run Ahead Of time function inlining if (const bool disable_aot_function_inlining = @@ -1712,7 +1721,8 @@ Status PartitionOrtFormatModel(onnxruntime::Graph& graph, providers.Get(onnxruntime::kCpuExecutionProvider), &logger); - GraphPartitioner partitioner(kernel_registry_manager, providers, std::move(graph_optimizer_registry)); + GraphPartitioner partitioner(kernel_registry_manager, providers, std::move(graph_optimizer_registry), + [&sess_options]() -> bool { return sess_options.IsLoadCancellationFlagSet(); }); ORT_RETURN_IF_ERROR(partitioner.Partition(graph, session_state.GetMutableFuncMgr(), transform_layout_fn, @@ -1785,6 +1795,11 @@ common::Status InferenceSession::HasInvalidCombinationOfExecutionProviders() con #pragma warning(disable : 26117) #endif common::Status InferenceSession::Initialize() { + if (session_options_.IsLoadCancellationFlagSet()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, + "Session initialization canceled due to user request."); + } + Status status = Status::OK(); TimePoint tp; if (session_profiler_.IsEnabled()) { @@ -2010,6 +2025,10 @@ common::Status InferenceSession::Initialize() { // now that all the transforms are done, call Resolve on the main graph. this will recurse into the subgraphs. ORT_RETURN_IF_ERROR_SESSIONID_(graph.Resolve()); + if (session_options_.IsLoadCancellationFlagSet()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, MODEL_LOAD_CANCELED, + "Session initialization canceled due to user request."); + } // Currently graph capture is only considered by CUDA EP, TRT EP, ROCM EP and JS EP. // diff --git a/onnxruntime/core/session/inference_session.h b/onnxruntime/core/session/inference_session.h index 5b484103c9ecf..7b5d98c38a0fa 100644 --- a/onnxruntime/core/session/inference_session.h +++ b/onnxruntime/core/session/inference_session.h @@ -781,6 +781,10 @@ class InferenceSession { // the session options are released after the individual operators are destroyed. SessionOptions session_options_; + CheckLoadCancellationFn check_load_cancellation_fn_ = [this]() { + return session_options_.IsLoadCancellationFlagSet(); + }; + /// Logging manager if provided. logging::LoggingManager* logging_manager_; diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 0e23d7a791bec..ac67a3ce5c1a2 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -720,22 +720,11 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSession, _In_ const OrtEnv* env, _In_ const O _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out) { API_IMPL_BEGIN std::unique_ptr sess; - OrtStatus* status = nullptr; *out = nullptr; - - ORT_TRY { - ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, model_path, nullptr, 0, sess)); - ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); - - *out = reinterpret_cast(sess.release()); - } - ORT_CATCH(const std::exception& e) { - ORT_HANDLE_EXCEPTION([&]() { - status = OrtApis::CreateStatus(ORT_FAIL, e.what()); - }); - } - - return status; + ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, model_path, nullptr, 0, sess)); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); + *out = reinterpret_cast(sess.release()); + return nullptr; API_IMPL_END } @@ -743,22 +732,10 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSessionFromArray, _In_ const OrtEnv* env, _In size_t model_data_length, _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out) { API_IMPL_BEGIN std::unique_ptr sess; - OrtStatus* status = nullptr; - *out = nullptr; - - ORT_TRY { - ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, nullptr, model_data, model_data_length, sess)); - ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); - - *out = reinterpret_cast(sess.release()); - } - ORT_CATCH(const std::exception& e) { - ORT_HANDLE_EXCEPTION([&]() { - status = OrtApis::CreateStatus(ORT_FAIL, e.what()); - }); - } - - return status; + ORT_API_RETURN_IF_ERROR(CreateSessionAndLoadModel(options, env, nullptr, model_data, model_data_length, sess)); + ORT_API_RETURN_IF_ERROR(InitializeSession(options, *sess)); + *out = reinterpret_cast(sess.release()); + return nullptr; API_IMPL_END } @@ -2810,6 +2787,7 @@ static constexpr OrtApi ort_api_1_to_22 = { &OrtApis::GetModelEditorApi, &OrtApis::CreateTensorWithDataAndDeleterAsOrtValue, + &OrtApis::SessionOptionsSetLoadCancellationFlag, }; // OrtApiBase can never change as there is no way to know what version of OrtApiBase is returned by OrtGetApiBase. diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h index 9d8aeb18a782f..0a87036a0dd1d 100644 --- a/onnxruntime/core/session/ort_apis.h +++ b/onnxruntime/core/session/ort_apis.h @@ -549,4 +549,7 @@ ORT_API_STATUS_IMPL(CreateTensorWithDataAndDeleterAsOrtValue, _In_ OrtAllocator* ONNXTensorElementDataType type, _Outptr_ OrtValue** out); +ORT_API_STATUS_IMPL(SessionOptionsSetLoadCancellationFlag, _Inout_ OrtSessionOptions* options, + _In_ bool is_cancel); + } // namespace OrtApis diff --git a/onnxruntime/python/onnxruntime_pybind_state.cc b/onnxruntime/python/onnxruntime_pybind_state.cc index 975502063ac2a..a069cfa0b4713 100644 --- a/onnxruntime/python/onnxruntime_pybind_state.cc +++ b/onnxruntime/python/onnxruntime_pybind_state.cc @@ -1753,6 +1753,12 @@ Applies to session load, initialization, etc. Default is 0.)pbdoc") options->value.execution_mode = execution_mode; }, R"pbdoc(Sets the execution mode. Default is sequential.)pbdoc") + .def( + "set_load_cancellation_flag", + [](PySessionOptions* options, bool value) -> void { + options->value.SetLoadCancellationFlag(value); + }, + R"pbdoc(Request inference session load cancellation)pbdoc") .def_property( "execution_order", [](const PySessionOptions* options) -> ExecutionOrder { return options->value.execution_order; }, diff --git a/onnxruntime/test/framework/inference_session_test.cc b/onnxruntime/test/framework/inference_session_test.cc index 95101c8075fc2..dc776f74d8758 100644 --- a/onnxruntime/test/framework/inference_session_test.cc +++ b/onnxruntime/test/framework/inference_session_test.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -498,6 +499,30 @@ TEST(InferenceSessionTests, TestModelSerialization) { ASSERT_TRUE(session_object_emptyValidation.Initialize().IsOK()); } +TEST(InferenceSessionTests, RequestLoadCancellation) { + { + // Explicit cancel during load, small model is fine + SessionOptions so; + so.session_logid = "InferenceSessionTests.TestLoadCancellation"; + + const PathString model_uri = ORT_TSTR("testdata/constant_floats.onnx"); + InferenceSession session_object{so, GetEnvironment()}; + so.SetLoadCancellationFlag(true); + ASSERT_FALSE(session_object.Load(model_uri).IsOK()); + } + { + // Explicit cancel during initialize, small model is fine + const PathString model_uri = ORT_TSTR("testdata/constant_floats.onnx"); + SessionOptions so; + so.session_logid = "InferenceSessionTests.TestLoadCancellation"; + so.SetLoadCancellationFlag(false); + InferenceSession session_object{so, GetEnvironment()}; + ASSERT_STATUS_OK(session_object.Load(model_uri)); + so.SetLoadCancellationFlag(true); + ASSERT_FALSE(session_object.Initialize().IsOK()); + } +} + #ifdef ORT_RUN_EXTERNAL_ONNX_TESTS static bool Compare(const InputDefList& f_arg, const InputDefList& s_arg) { if (f_arg.size() != s_arg.size()) { diff --git a/onnxruntime/test/providers/cpu/controlflow/loop_test.cc b/onnxruntime/test/providers/cpu/controlflow/loop_test.cc index 9c0b779870c70..a5fd37361a255 100644 --- a/onnxruntime/test/providers/cpu/controlflow/loop_test.cc +++ b/onnxruntime/test/providers/cpu/controlflow/loop_test.cc @@ -576,11 +576,10 @@ TEST(Loop, InfiniteLoopTermination) { test.Run(OpTester::ExpectResult::kExpectFailure, "Exiting due to terminate flag being set to true", {kTensorrtExecutionProvider, kOpenVINOExecutionProvider}, &session_run_options); // Disable TensorRT on unsupported data type BOOL - // call get to propagate any exception - terminator_result.get(); - // done with the thread terminator_thread.join(); + // call get to propagate any exception + terminator_result.get(); } // Add basic test to trigger types override logic in Graph::InferAndVerifySubgraphTypes as well as diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc index b517ba7032886..e00606af1c086 100644 --- a/onnxruntime/test/shared_lib/test_inference.cc +++ b/onnxruntime/test/shared_lib/test_inference.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -4669,6 +4670,34 @@ TEST(CApiTest, RunBaseLoraModel) { } } +TEST(CApiTest, RequestLoadCancellation) { + constexpr const ORTCHAR_T* model_path = ORT_TSTR("testdata/transformers/tiny_gpt2_beamsearch.onnx"); + Ort::Env env(ORT_LOGGING_LEVEL_WARNING); + Ort::SessionOptions session_options; + + auto terminator = [&session_options]() { + session_options.SetLoadCancellationFlag(true); + return; + }; + + std::packaged_task task{terminator}; + std::future terminator_result = task.get_future(); + std::thread terminator_thread{std::move(task)}; + bool terminated = false; + try { + Ort::Session session(env, model_path, session_options); + } catch (const Ort::Exception& ex) { + terminated = OrtErrorCode::ORT_MODEL_LOAD_CANCELED == ex.GetOrtErrorCode(); + } + // done with the thread + terminator_thread.join(); + + // call get to propagate any exception + terminator_result.get(); + + ASSERT_TRUE(terminated); +} + struct MockGQA : public OrtCustomOp { MockGQA() { OrtCustomOp::GetMayInplace = [](int** input_index, int** output_index) { From ca1b32df6559854f5d3b6636988e470d1c5fd383 Mon Sep 17 00:00:00 2001 From: xhcao Date: Tue, 8 Apr 2025 04:13:21 +0800 Subject: [PATCH 243/266] [webgpu] Fix ROUND_PREFER_CEIL issue of Resize operator (#24229) ### Description ### Motivation and Context Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- onnxruntime/core/providers/webgpu/tensor/resize_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc b/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc index f68ace3c1d8a1..75a7f859c965f 100644 --- a/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc +++ b/onnxruntime/core/providers/webgpu/tensor/resize_impl.cc @@ -122,7 +122,7 @@ void CalcNearestPixel(std::ostream& os, ResizeNearestMode mode) { body = "select(i32(round(x_original)), i32(floor(x_original)), x_original == f32(i32(x_original)) + 0.5)"; break; case ResizeNearestMode::ROUND_PREFER_CEIL: - body = "i32(round(x_original))"; + body = "select(i32(round(x_original)), i32(ceil(x_original)), x_original == f32(i32(x_original)) + 0.5)"; break; case ResizeNearestMode::FLOOR: body = "i32(floor(x_original))"; From b803429a50762e39d774751303b870eed72ac358 Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Mon, 7 Apr 2025 14:56:56 -0700 Subject: [PATCH 244/266] [Native WebGPU] Exclude WebGPU EP from ConvFp16 3D tests. (#24327) ### Description Exclude WebGPU from Conv3D tests ### Motivation and Context Fix failing tests in packaging pipelines. --- onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc b/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc index d1350db8ec12e..1404071928e09 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_fp16_test.cc @@ -518,7 +518,7 @@ TEST(ConvFp16Test, Conv3D_1) { vector{1, 1, 1}, // kernel_shape vector{0, 0, 0, 0, 0, 0}, // pads vector{1, 1, 1}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = { @@ -557,7 +557,7 @@ TEST(ConvFp16Test, Conv3D_2) { vector{1, 1, 1}, // kernel_shape vector{2, 2, 2, 2, 2, 2}, // pads vector{2, 2, 2}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = { @@ -601,7 +601,7 @@ TEST(ConvFp16Test, Conv3D_Bias) { vector{2, 2, 2}, // kernel_shape vector{2, 2, 2, 2, 2, 2}, // pads vector{2, 2, 2}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = { @@ -1082,7 +1082,7 @@ TEST(ConvFp16Test, Pointwise_3D) { vector{1, 1, 1}, // kernel_shape vector{0, 0, 0, 0, 0, 0}, // pads vector{1, 1, 1}, // strides - {} // excluded EPs + {kWebGpuExecutionProvider} // excluded EPs }; vector X = { From 554fb4ad1fcf808304d4758d73d93a8ecc362bf6 Mon Sep 17 00:00:00 2001 From: zz002 Date: Tue, 8 Apr 2025 08:15:40 +0800 Subject: [PATCH 245/266] [VitisAI EP] export InferShapes to VitisAIEP (#23881) ### Description [VitisAI EP] export InferShapes to VitisAIEP --------- Co-authored-by: Wang Chunye Co-authored-by: Zhenze --- .../providers/shared_library/provider_interfaces.h | 3 +++ .../providers/shared_library/provider_wrappedtypes.h | 1 + onnxruntime/core/providers/vitisai/imp/global_api.cc | 9 +++++++++ .../core/providers/vitisai/include/vaip/my_ort.h | 2 ++ .../core/providers/vitisai/include/vaip/vaip_ort_api.h | 10 ++++++++-- onnxruntime/core/session/provider_bridge_ort.cc | 8 ++++++++ 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index 9d5e16caa361d..bc8905c225822 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -611,6 +611,8 @@ struct ProviderHost { virtual int FunctionProto__metadata_props_size(const ONNX_NAMESPACE::FunctionProto* p) = 0; virtual ONNX_NAMESPACE::StringStringEntryProto* FunctionProto__add_metadata_props(ONNX_NAMESPACE::FunctionProto* p) = 0; + virtual void InferShapes(const std::string& m, const std::string& save_path) = 0; + virtual void InferShapes(ONNX_NAMESPACE::ModelProto& m) = 0; virtual void RegisterSchema(const std::string& domain, const OrtCustomOp* op) = 0; virtual void DeregisterSchema(const std::string& domain, const std::string& op_type, int version) = 0; virtual const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) = 0; @@ -1010,6 +1012,7 @@ struct ProviderHost { virtual const Graph* Graph__ParentGraph(const Graph* p) const = 0; virtual Graph* Graph__MutableParentGraph(Graph* p) = 0; virtual const std::string& Graph__Name(const Graph* p) const noexcept = 0; + virtual void Graph__SetName(Graph* p, const std::string& name) const noexcept = 0; virtual const std::filesystem::path& Graph__ModelPath(const Graph* p) const = 0; virtual const std::vector& Graph__GetInputsIncludingInitializers(const Graph* p) const noexcept = 0; virtual bool Graph__IsSubgraph(const Graph* p) = 0; diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index e2af144f455e4..5f0f9ca4c8584 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -1050,6 +1050,7 @@ struct Graph final { const Graph* ParentGraph() const { return g_host->Graph__ParentGraph(this); } Graph* MutableParentGraph() { return g_host->Graph__MutableParentGraph(this); } const std::string& Name() const noexcept { return g_host->Graph__Name(this); } + void SetName(const std::string& name) noexcept { return g_host->Graph__SetName(this, name); } const std::filesystem::path& ModelPath() const { return g_host->Graph__ModelPath(this); } const std::vector& GetInputsIncludingInitializers() const noexcept { return g_host->Graph__GetInputsIncludingInitializers(this); } bool IsSubgraph() const { return g_host->Graph__IsSubgraph(this); } diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index 6547f00cd47c7..33aa8fa2b31b8 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -360,10 +360,19 @@ vaip_core::OrtApiForVaip* create_org_api_hook() { }; the_global_api.graph_nodes_unsafe = [](const Graph& graph) -> auto { return vaip_core::DllSafe(graph.Nodes()); }; the_global_api.graph_get_name = [](const Graph& graph) -> const std::string& { return graph.Name(); }; + the_global_api.graph_set_name = [](Graph& graph, const char* name) -> void { return graph.SetName(std::string(name)); }; the_global_api.graph_reverse_dfs_from = [](const Graph& graph, gsl::span from, const auto& enter, const auto& leave, const auto& stop) { graph.ReverseDFSFrom(from, enter, leave, nullptr, stop); }; + + the_global_api.graph_infer_shapes_from_filepath = [](const std::string& m, const std::string& save_path) -> auto { return Provider_GetHost()->InferShapes(m, save_path); }; + the_global_api.graph_to_graph_proto = [](const Graph& graph) -> ONNX_NAMESPACE::GraphProto* { + return graph.ToGraphProto().release(); + }; + the_global_api.graph_proto_delete = [](ONNX_NAMESPACE::GraphProto* p) { delete p; }; + the_global_api.graph_infer_shapes = [](ONNX_NAMESPACE::ModelProto& m) -> auto { return Provider_GetHost()->InferShapes(m); }; + // node the_global_api.node_get_inputs_unsafe = vaip::node_get_inputs; the_global_api.node_get_output_node_args_unsafe = vaip::node_get_output_node_args; diff --git a/onnxruntime/core/providers/vitisai/include/vaip/my_ort.h b/onnxruntime/core/providers/vitisai/include/vaip/my_ort.h index 85a1262d8489b..6c9c728d8ffad 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/my_ort.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/my_ort.h @@ -20,6 +20,7 @@ struct NodeAttributes; namespace ONNX_NAMESPACE { struct AttributeProto; struct TensorProto; +struct GraphProto; struct ModelProto; #ifndef USE_VITISAI enum TensorProto_DataType : int { @@ -71,6 +72,7 @@ enum AttributeProto_AttributeType : int { namespace vaip_core { class GraphHolder; using ONNX_NAMESPACE::AttributeProto; +using ONNX_NAMESPACE::GraphProto; using ONNX_NAMESPACE::ModelProto; using ONNX_NAMESPACE::TensorProto; using onnxruntime::Graph; diff --git a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h index 0becc41d861f7..d40da70726b43 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h @@ -13,7 +13,7 @@ struct OrtApi; namespace vaip_core { -#define VAIP_ORT_API_MAJOR (14u) +#define VAIP_ORT_API_MAJOR (16u) #define VAIP_ORT_API_MINOR (0u) #define VAIP_ORT_API_PATCH (0u) struct OrtApiForVaip { @@ -249,7 +249,13 @@ struct OrtApiForVaip { const std::function& leave, const std::function& comp, const std::function& - stop); // [103] + stop); // [103] + void (*graph_set_name)(Graph& graph, const char* name); // [104] + void (*graph_infer_shapes_from_filepath)( + const std::string& m, const std::string& save_path); // [105] + GraphProto* (*graph_to_graph_proto)(const Graph& graph); // [106] + void (*graph_proto_delete)(GraphProto* p); // [107] + void (*graph_infer_shapes)(ModelProto& m); // [108] }; #ifndef USE_VITISAI diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index ba90d55a6b8e8..042598535e987 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -43,6 +43,7 @@ #include "core/session/onnxruntime_c_api.h" #include "core/common/string_helper.h" #include +#include "onnx/shape_inference/implementation.h" #ifdef ENABLE_TRAINING #ifdef ENABLE_TRAINING_TORCH_INTEROP @@ -771,6 +772,12 @@ struct ProviderHostImpl : ProviderHost { int FunctionProto__metadata_props_size(const ONNX_NAMESPACE::FunctionProto* p) override { return p->metadata_props_size(); } ONNX_NAMESPACE::StringStringEntryProto* FunctionProto__add_metadata_props(ONNX_NAMESPACE::FunctionProto* p) override { return p->add_metadata_props(); } + void InferShapes(const std::string& m, const std::string& save_path) override { + return ONNX_NAMESPACE::shape_inference::InferShapes(m, save_path); + } + void InferShapes(ONNX_NAMESPACE::ModelProto& m) override { + return ONNX_NAMESPACE::shape_inference::InferShapes(m); + } void RegisterSchema(const std::string& domain, const OrtCustomOp* op) override { auto& domain_instance = ONNX_NAMESPACE::OpSchemaRegistry::DomainToVersionRange::Instance(); const auto& domain_to_version_map = domain_instance.Map(); @@ -1268,6 +1275,7 @@ struct ProviderHostImpl : ProviderHost { const Graph* Graph__ParentGraph(const Graph* p) const override { return p->ParentGraph(); } Graph* Graph__MutableParentGraph(Graph* p) override { return p->MutableParentGraph(); } const std::string& Graph__Name(const Graph* p) const noexcept override { return p->Name(); } + void Graph__SetName(Graph* p, const std::string& name) const noexcept override { return p->SetName(name); } const std::filesystem::path& Graph__ModelPath(const Graph* p) const override { return p->ModelPath(); } const std::vector& Graph__GetInputsIncludingInitializers(const Graph* p) const noexcept override { return p->GetInputsIncludingInitializers(); } bool Graph__IsSubgraph(const Graph* p) override { return p->IsSubgraph(); } From 18f91e55e8cdb8ce264fc773e91adfd725851cd6 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Tue, 8 Apr 2025 23:27:59 +0800 Subject: [PATCH 246/266] [webgpu] Flash attention for generation (#23808) This PR adds the flash decoding support to optimization the generation speed when the total sequence length is large. Previously, when the total sequence length is big enough, the softmax and softmax * v shaders will become the bottleneck since it only uses limited gpu cores. In this changes, we add the flash decoding support to split the present key/value based on the total sequence length, then do reduce to get the final result. On NV RTX 2000 Ada, the TPS becomes 41.4 from 34.4 for 1K tokens for phi4 static kv cache On Meteor Lake, the TPS becomes 19 from 16 for 1K tokens for phi4 static kv cache Side effect of this PR: It adds two extra buffers to store 1) metadata (max and exp_sum in each split), 2) the splited qkv results with shape [B, N, split_k, H], which increase the memory size. TODO: Ideally, there should only be two shaders, which can also reduce the intermediate memory. The computeQKT can be merged into split shader and do the final softmax adjustment in the reduce shader. However, I meet some issues that when the total sequence length exceeds some value, the result will become garbage. Since I can't resolve it in a short time, leave it in as TODO to fix it in future. --- .../webgpu/bert/flash_attention.cc | 441 ++++++++++++++++-- .../contrib_ops/webgpu/bert/flash_attention.h | 58 ++- 2 files changed, 453 insertions(+), 46 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc index 26b08159a3b84..bb5de40eb27c5 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.cc @@ -28,29 +28,28 @@ Status CopyKVCacheProgram::GenerateShaderCode(ShaderHelper& shader) const { // Attention bias is in BN(total_sequence_length) const auto& key = shader.AddInput("key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias | ShaderUsage::UseIndicesTypeAlias); shader.AddInput("value", ShaderUsage::UseUniform); - const auto& present_key = shader.AddOutput("present_key", ShaderUsage::UseUniform); + const auto& present_key = shader.AddOutput("present_key", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias); const auto& present_value = shader.AddOutput("present_value", ShaderUsage::UseUniform); - const auto& valid_present_shape = shader.AddIndices("valid_present_shape"); + const auto& copy_kv_shape = shader.AddIndices("copy_kv_shape"); - shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.valid_present_size") - << " let output_indices = " << valid_present_shape.OffsetToIndices("global_idx") << ";\n" + shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.copy_size") + << " let output_indices = " << copy_kv_shape.OffsetToIndices("global_idx") << ";\n" << " let head_size_id = output_indices[3];\n" " let sequence_id = output_indices[2];\n" " let num_head_id = output_indices[1];\n" - " let batch = output_indices[0];\n" - << " let present_offset = " << (past_present_share_buffer_ ? present_key.IndicesToOffset("output_indices") : "global_idx") << ";\n"; + " let batch = output_indices[0];\n"; if (has_past_) { shader.MainFunctionBody() << "let past_sequence_length = uniforms.past_sequence_length;\n"; if (past_present_share_buffer_) { - shader.MainFunctionBody() << "if (sequence_id >= past_sequence_length) {\n" - << " let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id - past_sequence_length, head_size_id)" : "key_indices_t(batch, sequence_id - past_sequence_length, num_head_id, head_size_id)") << ";\n" + shader.MainFunctionBody() << " let present_offset = " << present_key.IndicesToOffset("present_key_indices_t(batch, num_head_id, past_sequence_length + sequence_id, head_size_id)") << ";\n" + << " let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id, head_size_id)" : "key_indices_t(batch, sequence_id, num_head_id, head_size_id)") << ";\n" << " " << present_key.SetByOffset("present_offset", "key[offset]") << ";\n" - << " " << present_value.SetByOffset("present_offset", "value[offset]") << ";\n" - << "}"; + << " " << present_value.SetByOffset("present_offset", "value[offset]") << ";\n"; } else { const auto& past_key = shader.AddInput("past_key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias | ShaderUsage::UseIndicesTypeAlias); shader.AddInput("past_value", ShaderUsage::UseUniform); - shader.MainFunctionBody() << "if (sequence_id < past_sequence_length) {\n" + shader.MainFunctionBody() << "let present_offset = global_idx;" + << "if (sequence_id < past_sequence_length) {\n" << " let pastOffset = " << past_key.IndicesToOffset("past_key_indices_t(batch, num_head_id, sequence_id, head_size_id)") << ";\n" << " " << present_key.SetByOffset("present_offset", "past_key[pastOffset]") << ";\n" << " " << present_value.SetByOffset("present_offset", "past_value[pastOffset]") << ";\n" @@ -61,7 +60,8 @@ Status CopyKVCacheProgram::GenerateShaderCode(ShaderHelper& shader) const { << "}"; } } else { - shader.MainFunctionBody() << "let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id, head_size_id)" : "key_indices_t(batch, sequence_id, num_head_id, head_size_id)") << ";\n" + shader.MainFunctionBody() << " let present_offset = " << (past_present_share_buffer_ ? present_key.IndicesToOffset("output_indices") : "global_idx") << ";\n" + << "let offset = " << key.IndicesToOffset(kv_BNSH_ ? "key_indices_t(batch, num_head_id, sequence_id, head_size_id)" : "key_indices_t(batch, sequence_id, num_head_id, head_size_id)") << ";\n" << present_key.SetByOffset("present_offset", "key[offset]") << ";\n" << present_value.SetByOffset("present_offset", "value[offset]") << ";\n"; } @@ -75,18 +75,21 @@ Status CopyKVCache(onnxruntime::webgpu::ComputeContext& context, const WebgpuAtt // This makes it so that FlashAttention only needs to look at present key and value, and saves // number of input buffers in the shader, which we run out of (<=8) without this optimization. const int components = parameters.head_size_ % 4 == 0 ? 4 : (parameters.head_size_ % 2 == 0 ? 2 : 1); + bool has_past = (parameters.total_sequence_length_ - parameters.kv_sequence_length_) > 0; // parameters.total_sequence_length_ is past_sequence_length + kv_sequence_length. // parameters.kv_num_heads_ may be smaller than parameters.num_heads_ when parameters.is_gqa_ is true. int num_heads = parameters.is_gqa_ ? parameters.kv_num_heads_ : parameters.num_heads_; - TensorShape valid_present_shape{parameters.batch_size_, num_heads, parameters.total_sequence_length_, parameters.head_size_ / components}; - int64_t valid_kv_size = valid_present_shape.Size(); - bool has_past = (parameters.past_sequence_length_ > 0); + // Only copy the new kv data for static kv cache + int copy_sequence_length = has_past && parameters.past_present_share_buffer_ ? parameters.kv_sequence_length_ : parameters.total_sequence_length_; + TensorShape copy_kv_shape{parameters.batch_size_, num_heads, copy_sequence_length, parameters.head_size_ / components}; + int64_t copy_size = copy_kv_shape.Size(); CopyKVCacheProgram program{"CopyKVCache", has_past, parameters.qkv_format_ == Q_K_V_BSNH_BNSH_BNSH, parameters.past_present_share_buffer_}; if (parameters.qkv_format_ == Q_K_V_BSNH_BNSH_BNSH) { program.AddInputs({{K, ProgramTensorMetadataDependency::TypeAndRank, components}, {V, ProgramTensorMetadataDependency::TypeAndRank, components}}); } else { ORT_ENFORCE(parameters.qkv_format_ == Q_K_V_BSNH, "qkv format ", parameters.qkv_format_, " is not supported yet in CopyKVCache."); + // Reshape (batch_size, kv_sequence_length, kv_hidden_size) to (batch_size, kv_sequence_length, num_head, head_size) TensorShape reshaped_KV_shape{parameters.batch_size_, parameters.kv_sequence_length_, num_heads, parameters.head_size_ / components}; program.AddInputs({{K, ProgramTensorMetadataDependency::TypeAndRank, reshaped_KV_shape, components}, {V, ProgramTensorMetadataDependency::TypeAndRank, reshaped_KV_shape, components}}); @@ -97,11 +100,11 @@ Status CopyKVCache(onnxruntime::webgpu::ComputeContext& context, const WebgpuAtt } program.AddOutputs({{present_key, ProgramTensorMetadataDependency::Rank, components}, {present_value, ProgramTensorMetadataDependency::Rank, components}}) - .AddIndices(std::move(valid_present_shape)); - program.SetDispatchGroupSize(onnxruntime::narrow((valid_kv_size + 63) / 64)) + .AddIndices(std::move(copy_kv_shape)); + program.SetDispatchGroupSize(static_cast((copy_size + 63) / 64)) .SetWorkgroupSize(64) .CacheHint(has_past, parameters.qkv_format_, parameters.past_present_share_buffer_) - .AddUniformVariables({{static_cast(valid_kv_size)}, + .AddUniformVariables({{static_cast(copy_size)}, // Note that when parameters.past_present_share_buffer_ is true, parameters.past_sequence_length_ will become to // max_sequence_length. To get a valid past_sequence_length, we use total_sequence_length - kv_sequence_length. {static_cast(parameters.total_sequence_length_ - parameters.kv_sequence_length_)}}); @@ -425,49 +428,397 @@ Status FlashAttentionProgram::GenerateShaderCode(ShaderHelper& shader) const { return Status::OK(); } -Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, const Tensor* attention_bias, - Tensor* output, const Tensor* past_key, Tensor* present_key, const Tensor* past_value, Tensor* present_value, - const WebgpuAttentionParameters& parameters, onnxruntime::webgpu::ComputeContext& context) { - ORT_RETURN_IF_ERROR(CopyKVCache(context, parameters, K, past_key, present_key, V, past_value, present_value)); +Status FlashAttentionDecodeQKTProgram::GenerateShaderCode(ShaderHelper& shader) const { + shader.AddInput("q", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + shader.AddInput("present_key", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + if (has_attention_bias_) { + shader.AddInput("attention_bias", ShaderUsage::UseUniform); + } + shader.AddOutput("output", ShaderUsage::UseUniform); + shader.AddOutput("metadata", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + // Note that this shader adopts similar algorithm with dp4a generation shader. + // + // This algorithm works to compute dot product of keys with queries parallelly, by processing on the k (head_size) dimension at each step amongst tile_size_k_vec threads, + // and utilizing the remaining threads in the workgroup to process additional rows of |present_key| in parallel (such that the values in shared memory (tile_q) for |q| can be reused). + // For each load of q, the tile_size_k_vec threads also reload |present_key| tile_size/sub_tile_count times to compute partial dot products of other |present_key| rows + // in order to complete all tile_size |present_key| rows in this workgroup and also reusing the loaded in register values of |q|. + constexpr int tile_size_k_vec = 8; - const uint32_t tile_size = 64; - bool has_attention_bias = attention_bias != nullptr; - FlashAttentionProgram program{"FlashAttention", has_attention_bias, parameters.head_size_, parameters.num_heads_}; - program.AddInputs({{Q, ProgramTensorMetadataDependency::TypeAndRank, 4}, - {present_key, ProgramTensorMetadataDependency::TypeAndRank, 4}, - {present_value, ProgramTensorMetadataDependency::TypeAndRank, 4}}); - if (has_attention_bias) { - program.AddInputs({{attention_bias, ProgramTensorMetadataDependency::TypeAndRank}}); + // 1. Each workgroup processes one row of |q| and tile_size rows of |present_key| + // + // 2. Computation Process: + // - Reads [tile_size][tile_size_k_vec] block of |present_key| data at a time + // - Each thread within workgroup computes dot products of 4 A*B elements since each k represents 4 elements of |present_key| + // - Stores intermediate results in shared memory (inner_qk_values) + // - Iterates through columns (head_size_vec) accumulating results in inner_qk_values + // - Performs final reduction sum in inner_qk_values for output + shader.AdditionalImplementation() << "const tile_size = " << tile_size_ << "u;\n" + << "const tile_size_k_vec = " << tile_size_k_vec << "u;\n" + << "const sub_tile_count = " << WorkgroupSizeX() / tile_size_k_vec << "u;\n"; + shader.AdditionalImplementation() << R"ADDNL_FN( +var tile_q: array; +var inner_qk_values: array, tile_size>; +var tile_qk: array; +)ADDNL_FN"; + + if (has_attention_bias_) { + shader.AdditionalImplementation() << R"HELPER_FN( + fn loadAttentionBias(idx: u32) -> q_element_t + { + return attention_bias[idx]; + } + )HELPER_FN"; + } else { + shader.AdditionalImplementation() << R"HELPER_FN( + fn loadAttentionBias(idx: u32) -> q_element_t + { + return q_element_t(0); + } + )HELPER_FN"; } - program.AddOutputs({{output, ProgramTensorMetadataDependency::TypeAndRank, 4}}); + + shader.MainFunctionBody() << R"MAIN_FN( + let local_row = u32(local_idx / tile_size_k_vec); + let local_col = local_idx % tile_size_k_vec; + let total_seq_offset = (workgroup_idx % uniforms.num_total_seq_length_tile) * tile_size; + let head_idx = u32(workgroup_idx / uniforms.num_total_seq_length_tile); + let q_offset = head_idx * uniforms.head_size_vec; + var total_sequence_length = uniforms.total_sequence_length; + let present_offset = u32(head_idx / uniforms.n_reps) * uniforms.present_sequence_length * uniforms.head_size_vec; + for (var k: u32 = 0u; k < uniforms.head_size_vec; k += tile_size_k_vec) { + if (local_idx < tile_size_k_vec && k + local_idx < uniforms.head_size_vec) { + tile_q[local_idx] = q[q_offset + k + local_idx]; + } + workgroupBarrier(); + let q_data = tile_q[local_col]; + if (k + local_col < uniforms.head_size_vec) { + for (var row_offset = 0u; row_offset < tile_size; row_offset += sub_tile_count) { + if (total_seq_offset + row_offset + local_row < total_sequence_length) { + inner_qk_values[row_offset + local_row][local_col] += dot(present_key[present_offset + (total_seq_offset + row_offset + local_row) * uniforms.head_size_vec + k + local_col], q_data); + } + } + } + workgroupBarrier(); + } + + if (local_idx < tile_size && total_seq_offset + local_idx < total_sequence_length) { + var sum = q_element_t(0); + for (var i = 0u; i < tile_size_k_vec; i++) { + sum += inner_qk_values[local_idx][i]; + } + + let output_idx = head_idx * total_sequence_length + total_seq_offset + local_idx; + sum = sum * q_element_t(uniforms.alpha) + loadAttentionBias(output_idx); + tile_qk[local_idx] = sum; + output[output_idx] = sum; + } + workgroupBarrier(); + + if (local_idx == 0u) { + // Calculate the max and sum in current split. + var l_max = f32(-3.402823e+38f); + var l_sum = f32(0); + for (var i = 0u; i < tile_size && (total_seq_offset + i) < total_sequence_length; i++) { + l_max = max(l_max, f32(tile_qk[i])); + } + for (var i = 0u; i < tile_size && (total_seq_offset + i) < total_sequence_length; i++) { + l_sum += exp(f32(tile_qk[i]) - l_max); + } + let meta_offset = head_idx * uniforms.num_total_seq_length_tile + workgroup_idx % uniforms.num_total_seq_length_tile; + metadata[meta_offset] = metadata_value_t(metadata_element_t(l_max), metadata_element_t(l_sum)); + } +)MAIN_FN"; + + return Status::OK(); +} + +Status ComputeFlashAttentionDecodeQKT(onnxruntime::webgpu::ComputeContext& context, const Tensor* Q, + const Tensor* attention_bias, Tensor* output, Tensor* present_key, Tensor* metadata, + const WebgpuAttentionParameters& parameters, uint32_t num_total_seq_length_tile, uint32_t tile_size) { const float alpha = parameters.scale_ == 0.0f ? 1.f / sqrt(static_cast(parameters.head_size_)) : parameters.scale_; - std::string cache_hint = std::to_string(has_attention_bias) + - std::to_string(parameters.head_size_) + - std::to_string(parameters.num_heads_); - const uint32_t num_seq_tile = (parameters.sequence_length_ + tile_size - 1) / tile_size; - program.SetDispatchGroupSize(parameters.num_heads_ * num_seq_tile) - .SetWorkgroupSize(tile_size) - .CacheHint(cache_hint) - .AddUniformVariables({{static_cast(parameters.sequence_length_)}, + + const bool has_attention_bias = attention_bias != nullptr; + const int components = 4; + + FlashAttentionDecodeQKTProgram program{"FlashAttentionDecodeQKT", has_attention_bias, tile_size}; + program.AddInputs({{Q, ProgramTensorMetadataDependency::TypeAndRank, components}, + {present_key, ProgramTensorMetadataDependency::TypeAndRank, components}}); + if (has_attention_bias) { + program.AddInput({attention_bias, ProgramTensorMetadataDependency::TypeAndRank}); + } + program.AddOutputs({{output, ProgramTensorMetadataDependency::Rank}, + {metadata, ProgramTensorMetadataDependency::Rank, 2}}); + + const uint32_t vectorized_head_size = parameters.head_size_ / components; + program.SetDispatchGroupSize(parameters.num_heads_ * num_total_seq_length_tile) + .SetWorkgroupSize(64) + .CacheHint(tile_size, has_attention_bias) + .AddUniformVariables({{static_cast(vectorized_head_size)}, {static_cast(parameters.total_sequence_length_)}, - {static_cast(parameters.past_present_share_buffer_ ? parameters.past_sequence_length_ : parameters.total_sequence_length_)}, - {static_cast(parameters.total_sequence_length_ - parameters.kv_sequence_length_)}, - {static_cast(parameters.is_gqa_ ? 1 : 0)}, + {static_cast(alpha)}, + // present_sequence_length is used to index into the KV cache, for static kv cache it is the max sequence length. + {static_cast(parameters.is_gqa_ ? parameters.seqlen_present_kv_cache_ : parameters.total_sequence_length_)}, {static_cast(parameters.n_reps)}, - {alpha}, - {num_seq_tile}}); + {num_total_seq_length_tile}}); return context.RunProgram(program); } +Status FlashAttentionDecodeSplitVxProgram::GenerateShaderCode(ShaderHelper& shader) const { + shader.AddInput("metadata", ShaderUsage::UseUniform); + shader.AddInput("qk", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); + shader.AddInput("present_value", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + shader.AddOutput("out_split_vx", ShaderUsage::UseUniform); + + // Note that this shader adopts similar algorithm with dp4a generation shader. + // + // This algorithm works to compute dot product of v with qk parallelly, by processing on the head_size dimension at each step amongst tile_size_k_vec threads, + // and utilizing the remaining threads in the workgroup to process additional rows of |present_value| in parallel (such that the values in shared memory (tile_qk) for |qk| can be reused). + // The tile_size_k_vec threads also reload |present_value| tile_size/sub_tile_count times to compute partial dot products of other |present_value| rows + // in order to complete all tile_size |present_value| rows in this workgroup and also reusing the values in tile_qk. + // + // The difference with FlashAttentionDecodeQKTProgram is that the dot products go through the rows (total_sequence_length) of |present_value| instead of columns (head_size_vec). + // And each workgroup only calculate current tile_size's dot products instead of iterating the whole row |total_sequence_length|. + // That's why this shader is a split shader. The final reduce will be done in FlashAttentionDecodeReduceProgram. + constexpr int tile_size_k_vec = 8; + + shader.AdditionalImplementation() << "const head_size_vec = " << head_size_vec_ << "u;\n" + << "const tile_size = " << tile_size_ << "u;\n" + << "const tile_size_k_vec = " << tile_size_k_vec << "u;\n" + << "const sub_tile_count = " << WorkgroupSizeX() / tile_size_k_vec << "u;\n"; + shader.AdditionalImplementation() << R"HELPER_FN( +var tile_qk: array; +var tile_output: array; +var qkv_values: array, sub_tile_count>; + + )HELPER_FN"; + + // TODO: Ideally, there should only be two shaders FlashAttentionDecodeSplitVx and FlashAttentionDecodeVxReduce, which can also reduce the intermediate memory. + // The FlashAttentionDecodeQKT can be merged into split shader and do the final softmax adjustment in the reduce shader. However, some issues are met that when + // the total sequence length exceeds some value, the result will become garbage. Since it can't be resolved in a short time, leave it as TODO to fix it in future. + shader.MainFunctionBody() << R"MAIN_FN( + let local_row = u32(local_idx / tile_size_k_vec); + let local_col = local_idx % tile_size_k_vec; + let total_seq_offset = (workgroup_idx % uniforms.num_total_seq_length_tile) * tile_size; + let head_idx = u32(workgroup_idx / uniforms.num_total_seq_length_tile); + var total_sequence_length = uniforms.total_sequence_length; + let present_offset = u32(head_idx / uniforms.n_reps) * uniforms.head_size_vec * uniforms.present_sequence_length; + + // Calculate the global max and sum in qk. + var g_max = f32(-3.402823e+38f); + for (var i = 0u; i < uniforms.num_total_seq_length_tile; i++) + { + let meta_offset = head_idx * uniforms.num_total_seq_length_tile + i; + g_max = max(g_max, f32(metadata[meta_offset].x)); + } + var g_sum = f32(0); + for (var i = 0u; i < uniforms.num_total_seq_length_tile; i++) + { + let meta_offset = head_idx * uniforms.num_total_seq_length_tile + i; + let m_value = metadata[meta_offset]; + g_sum += exp(f32(m_value.x) - g_max) * f32(m_value.y); + } + + if (total_seq_offset + local_idx < total_sequence_length) { + tile_qk[local_idx] = qk_value_t(exp(f32(qk[head_idx * total_sequence_length + total_seq_offset + local_idx]) - g_max) / g_sum); + } + + for (var k: u32 = 0u; k < uniforms.head_size_vec; k += tile_size_k_vec) { + var value = present_value_value_t(0); + qkv_values[local_row][local_col] = present_value_value_t(0); + workgroupBarrier(); + + if (k + local_col < uniforms.head_size_vec) { + for (var row_offset = 0u; row_offset < tile_size; row_offset += sub_tile_count) { + if (total_seq_offset + row_offset + local_row < total_sequence_length) { + value += present_value[present_offset + (total_seq_offset + row_offset + local_row) * uniforms.head_size_vec + k + local_col] * tile_qk[row_offset + local_row]; + } + } + } + + qkv_values[local_row][local_col] = value; + workgroupBarrier(); + + if (local_idx < tile_size_k_vec) { + for (var i = 0u; i < sub_tile_count; i++) { + tile_output[k + local_idx] += qkv_values[i][local_idx]; + } + } + workgroupBarrier(); + } + + for (var i = local_idx; i < uniforms.head_size_vec; i += workgroup_size_x) { + let out_offset = head_idx * uniforms.num_total_seq_length_tile * uniforms.head_size_vec + (workgroup_idx % uniforms.num_total_seq_length_tile) * uniforms.head_size_vec + i; + out_split_vx[out_offset] = tile_output[i]; + } +)MAIN_FN"; + + return Status::OK(); +} + +Status ComputeFlashAttentionDecodeSplitVxScore(onnxruntime::webgpu::ComputeContext& context, + const Tensor* metadata, + const Tensor* qk, + Tensor* out_split_vx, + Tensor* present_value, + const WebgpuAttentionParameters& parameters, + uint32_t num_total_seq_length_tile, + uint32_t tile_size) { + const int components = 4; + int head_size_vec = parameters.v_head_size_ / components; + FlashAttentionDecodeSplitVxProgram program{"FlashAttentionDecodeSplitVx", tile_size, head_size_vec}; + program.AddInputs({{metadata, ProgramTensorMetadataDependency::TypeAndRank, 2}, + {qk, ProgramTensorMetadataDependency::TypeAndRank}, + {present_value, ProgramTensorMetadataDependency::TypeAndRank, components}}); + program.AddOutputs({{out_split_vx, ProgramTensorMetadataDependency::TypeAndRank, components}}); // [B, N, split_k, head_size] + program.SetDispatchGroupSize(parameters.num_heads_ * num_total_seq_length_tile) + .CacheHint(tile_size, head_size_vec) + .SetWorkgroupSize(64) + .AddUniformVariables({{static_cast(parameters.total_sequence_length_)}, + {static_cast(head_size_vec)}, + {static_cast(parameters.is_gqa_ ? parameters.seqlen_present_kv_cache_ : parameters.total_sequence_length_)}, + {static_cast(parameters.n_reps)}, + num_total_seq_length_tile}); + + return context.RunProgram(program); +} + +Status FlashAttentionDecodeVxReduceProgram::GenerateShaderCode(ShaderHelper& shader) const { + shader.AddInput("input", ShaderUsage::UseUniform); + shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + + // Inputs are splits of the GQA output, split into num_total_seq_length_tiles rows. + // This shader needs to add these splits across the row dimension to arrive at the final result. The column is head size wide. + // The reduction achieves maximum parallelization by splitting this task first into tile_size columns that each workgroup is responsible for. + // Then within each workgroup the task of summation over the num_total_seq_length_tile for the tile_size columns is further split in two ways. + // First across the row dimension to have WORKGROUP_SIZE/TILE_SIZE parallel computations of summation of TILE_SIZE rows. + // Then across the column dimension where each thread is responsible for 1 column of the TILE_SIZE columns the workgroup is resposible for. + shader.AdditionalImplementation() << "const TILE_SIZE = " << tile_size_ << ";\n"; + shader.AdditionalImplementation() << R"HELPER_FN( +var tile_input: array, TILE_SIZE>; + )HELPER_FN"; + + shader.MainFunctionBody() << R"MAIN_FN( + let head_size_offset = (workgroup_idx % uniforms.num_head_size_tile) * TILE_SIZE; + let head_idx = u32(workgroup_idx / uniforms.num_head_size_tile); + let in_offset = head_idx * uniforms.num_total_seq_length_tile * uniforms.head_size_vec; + var value = output_value_t(0); + let local_row = u32(local_idx / TILE_SIZE); + let local_col = local_idx % TILE_SIZE; + + if (head_size_offset + local_col < uniforms.head_size_vec) { + for (var r = 0u; r < uniforms.num_total_seq_length_tile; r += TILE_SIZE) { + if (r + local_row < uniforms.num_total_seq_length_tile) { + value += input[in_offset + (r + local_row) * uniforms.head_size_vec + head_size_offset + local_col]; + } + } + } + + tile_input[local_row][local_col] = value; + workgroupBarrier(); + + if (local_idx < TILE_SIZE && head_size_offset + local_idx < uniforms.head_size_vec) { + value = output_value_t(0); + for (var i = 0u; i < TILE_SIZE; i++) { + value += tile_input[i][local_idx]; + } + let output_id = head_idx * uniforms.head_size_vec + head_size_offset + local_idx; + output[output_id] = value; + } +)MAIN_FN"; + + return Status::OK(); +} + +Status ComputeFlashAttentionDecodeVxReduce(onnxruntime::webgpu::ComputeContext& context, + const Tensor* out_split_vx, + Tensor* output, + const WebgpuAttentionParameters& parameters, + uint32_t num_total_seq_length_tile) { + const int components = 4; + constexpr int tile_size = 8; + int tile_head_size = tile_size * components; + FlashAttentionDecodeVxReduceProgram program{"FlashAttentionDecodeVxReduce", tile_size}; + program.AddInputs({{out_split_vx, ProgramTensorMetadataDependency::TypeAndRank, components}}); + program.AddOutputs({{output, ProgramTensorMetadataDependency::TypeAndRank, components}}); + const uint32_t num_head_size_tile = static_cast((parameters.v_head_size_ + tile_head_size - 1) / tile_head_size); + program.SetDispatchGroupSize(parameters.num_heads_ * num_head_size_tile) + .CacheHint(tile_size) + .SetWorkgroupSize(tile_size * tile_size) + .AddUniformVariables({{static_cast(parameters.v_head_size_ / components)}, + num_total_seq_length_tile, + {num_head_size_tile}}); + + return context.RunProgram(program); +} + +Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, const Tensor* attention_bias, + Tensor* output, const Tensor* past_key, Tensor* present_key, const Tensor* past_value, Tensor* present_value, + const WebgpuAttentionParameters& parameters, onnxruntime::webgpu::ComputeContext& context) { + ORT_RETURN_IF_ERROR(CopyKVCache(context, parameters, K, past_key, present_key, V, past_value, present_value)); + + if (parameters.sequence_length_ > 1) { + const uint32_t tile_size = 64; + bool has_attention_bias = attention_bias != nullptr; + FlashAttentionProgram program{"FlashAttention", has_attention_bias, parameters.head_size_, parameters.num_heads_}; + program.AddInputs({{Q, ProgramTensorMetadataDependency::TypeAndRank, 4}, + {present_key, ProgramTensorMetadataDependency::TypeAndRank, 4}, + {present_value, ProgramTensorMetadataDependency::TypeAndRank, 4}}); + if (has_attention_bias) { + program.AddInputs({{attention_bias, ProgramTensorMetadataDependency::TypeAndRank}}); + } + program.AddOutputs({{output, ProgramTensorMetadataDependency::TypeAndRank, 4}}); + const float alpha = parameters.scale_ == 0.0f ? 1.f / sqrt(static_cast(parameters.head_size_)) + : parameters.scale_; + std::string cache_hint = std::to_string(has_attention_bias) + + std::to_string(parameters.head_size_) + + std::to_string(parameters.num_heads_); + const uint32_t num_seq_tile = (parameters.sequence_length_ + tile_size - 1) / tile_size; + program.SetDispatchGroupSize(parameters.num_heads_ * num_seq_tile) + .SetWorkgroupSize(tile_size) + .CacheHint(cache_hint) + .AddUniformVariables({{static_cast(parameters.sequence_length_)}, + {static_cast(parameters.total_sequence_length_)}, + {static_cast(parameters.past_present_share_buffer_ ? parameters.past_sequence_length_ : parameters.total_sequence_length_)}, + {static_cast(parameters.total_sequence_length_ - parameters.kv_sequence_length_)}, + {static_cast(parameters.is_gqa_ ? 1 : 0)}, + {static_cast(parameters.n_reps)}, + {alpha}, + {num_seq_tile}}); + + return context.RunProgram(program); + } + + const TensorShapeVector qk_dims({parameters.batch_size_, parameters.num_heads_, + parameters.sequence_length_, parameters.total_sequence_length_}); + const TensorShape qk_shape(qk_dims); + Tensor qk = context.CreateGPUTensor(Q->DataType(), qk_shape); + constexpr uint32_t tile_size = 64; + const uint32_t num_total_seq_length_tile = (parameters.total_sequence_length_ + tile_size - 1) / tile_size; + // The metadata is used to store the max and sum of each tile. + const TensorShapeVector metadata_dims({parameters.batch_size_, parameters.num_heads_, + num_total_seq_length_tile, 2}); + const TensorShape metadata_shape(metadata_dims); + Tensor metadata = context.CreateGPUTensor(Q->DataType(), metadata_shape); + ORT_RETURN_IF_ERROR(ComputeFlashAttentionDecodeQKT(context, Q, attention_bias, &qk, present_key, &metadata, + parameters, num_total_seq_length_tile, tile_size)); + + const TensorShapeVector out_split_vx_dims({parameters.batch_size_, parameters.num_heads_, num_total_seq_length_tile, parameters.head_size_}); + const TensorShape out_split_vx_shape(out_split_vx_dims); + Tensor out_split_vx = context.CreateGPUTensor(Q->DataType(), out_split_vx_shape); + ORT_RETURN_IF_ERROR(ComputeFlashAttentionDecodeSplitVxScore(context, &metadata, &qk, &out_split_vx, present_value, parameters, num_total_seq_length_tile, tile_size)); + ORT_RETURN_IF_ERROR(ComputeFlashAttentionDecodeVxReduce(context, &out_split_vx, output, parameters, num_total_seq_length_tile)); + + return Status::OK(); +} + bool CanApplyFlashAttention(const Tensor* bias, const Tensor* present_key, const Tensor* present_value, const WebgpuAttentionParameters& parameters, onnxruntime::webgpu::ComputeContext& context) { return parameters.batch_size_ == 1 && !parameters.is_packed_qkv_ && parameters.head_size_ == parameters.v_head_size_ && bias == nullptr && - parameters.sequence_length_ > 1 && context.HasFeature(wgpu::FeatureName::Subgroups) && present_key != nullptr && present_value != nullptr && present_key->SizeInBytes() > 0 && present_value->SizeInBytes() > 0 && parameters.head_size_ % 4 == 0; diff --git a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h index 8931403641a81..c066d6249c8b2 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h +++ b/onnxruntime/contrib_ops/webgpu/bert/flash_attention.h @@ -23,7 +23,7 @@ class CopyKVCacheProgram final : public Program { Status GenerateShaderCode(ShaderHelper& sh) const override; - WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"valid_present_size", ProgramUniformVariableDataType::Uint32}, + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"copy_size", ProgramUniformVariableDataType::Uint32}, {"past_sequence_length", ProgramUniformVariableDataType::Uint32}); private: @@ -61,6 +61,62 @@ class FlashAttentionProgram final : public Program { int qkv_num_heads_; }; +class FlashAttentionDecodeQKTProgram final : public Program { + public: + FlashAttentionDecodeQKTProgram(const std::string& kernel_name, + bool has_attention_bias, uint32_t tile_size) + : Program{kernel_name}, has_attention_bias_(has_attention_bias), tile_size_(tile_size) { + } + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"head_size_vec", ProgramUniformVariableDataType::Uint32}, + {"total_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"alpha", ProgramUniformVariableDataType::Float32}, + {"present_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"n_reps", ProgramUniformVariableDataType::Uint32}, + {"num_total_seq_length_tile", ProgramUniformVariableDataType::Uint32}); + + private: + bool has_attention_bias_; + uint32_t tile_size_; +}; + +class FlashAttentionDecodeSplitVxProgram final : public Program { + public: + FlashAttentionDecodeSplitVxProgram(const std::string& kernel_name, uint32_t tile_size, int head_size_vec) + : Program{kernel_name}, tile_size_(tile_size), head_size_vec_(head_size_vec) { + } + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"total_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"head_size_vec", ProgramUniformVariableDataType::Uint32}, + {"present_sequence_length", ProgramUniformVariableDataType::Uint32}, + {"n_reps", ProgramUniformVariableDataType::Uint32}, + {"num_total_seq_length_tile", ProgramUniformVariableDataType::Uint32}); + + private: + uint32_t tile_size_; + int head_size_vec_; +}; + +class FlashAttentionDecodeVxReduceProgram final : public Program { + public: + FlashAttentionDecodeVxReduceProgram(const std::string& kernel_name, uint32_t tile_size) + : Program{kernel_name}, tile_size_(tile_size) { + } + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"head_size_vec", ProgramUniformVariableDataType::Uint32}, + {"num_total_seq_length_tile", ProgramUniformVariableDataType::Uint32}, + {"num_head_size_tile", ProgramUniformVariableDataType::Uint32}); + + private: + uint32_t tile_size_; +}; + Status ApplyFlashAttention(const Tensor* Q, const Tensor* K, const Tensor* V, const Tensor* attention_bias, Tensor* output, const Tensor* past_key, Tensor* present_key, const Tensor* past_value, Tensor* present_value, const WebgpuAttentionParameters& parameters, onnxruntime::webgpu::ComputeContext& context); From 04e0b50c9379fe4c89ba3f45f6ced74ecb482076 Mon Sep 17 00:00:00 2001 From: Fanchen Kong Date: Tue, 8 Apr 2025 23:33:26 +0800 Subject: [PATCH 247/266] Use WASM f32x4 relaxed min/max for relaxed simd build (#24324) ### Description Use wasm_f32x4_relaxed_max and wasm_f32x4_relaxed_min in WASM relaxed SIMD build. ### Motivation and Context This PR replaces wasm_f32x4_min/max with the relaxed SIMD counterparts wasm_f32x4_relaxed_min/max in WASM relaxed SIMD build. According to [relaxed SIMD proposal](https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md#relaxed-min-and-max), the wasm_f32x4_relaxed_min/max allow implementation-defined behavior on NaN propagation and -0.0 vs +0.0. This enables WASM runtimes to use minps/maxps on x64 platforms and improves the performance. e.g. for wasm_f32x4_max -> wasm_f32x4_relaxed_max wasm_f32x4_max: [implementation in V8](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.cc;l=231) wasm_f32x4_relaxed_max: maxps This change would affect kernel functions rely on MlasMaximumFloat32x4 and MlasMinimumFloat32x4, including various activations and reduced min/max kernels. In mlas micro bench "COMPUTESOFTMAXINPLACE...", this change provides a performance improvement of up to 60% on x64 devices. --- onnxruntime/core/mlas/lib/mlasi.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/onnxruntime/core/mlas/lib/mlasi.h b/onnxruntime/core/mlas/lib/mlasi.h index 7532f8eeb5a9b..4782e479753a2 100644 --- a/onnxruntime/core/mlas/lib/mlasi.h +++ b/onnxruntime/core/mlas/lib/mlasi.h @@ -1455,6 +1455,9 @@ MlasConvDepthwiseFloat_CHW( #endif #elif defined(MLAS_TARGET_WASM_SIMD) #define MLAS_WASM_SIMD_INTRINSICS +#if defined(MLAS_TARGET_WASM_RELAXED_SIMD) +#define MLAS_WASM_RELAXED_SIMD_INTRINSICS +#endif #elif defined(MLAS_TARGET_LARCH64) #define MLAS_LSX_INTRINSICS #endif @@ -2265,6 +2268,8 @@ MlasMaximumFloat32x4(MLAS_FLOAT32X4 Vector1, MLAS_FLOAT32X4 Vector2) #elif defined(MLAS_VSX_INTRINSICS) // Don't use vec_max to avoid undefined behavior if NAN return vec_sel(Vector2, Vector1, vec_cmpgt(Vector1, Vector2)); +#elif defined(MLAS_WASM_RELAXED_SIMD_INTRINSICS) + return wasm_f32x4_relaxed_max(Vector1, Vector2); #elif defined(MLAS_WASM_SIMD_INTRINSICS) return wasm_f32x4_max(Vector1, Vector2); #elif defined(MLAS_LSX_INTRINSICS) @@ -2285,6 +2290,8 @@ MlasMinimumFloat32x4(MLAS_FLOAT32X4 Vector1, MLAS_FLOAT32X4 Vector2) #elif defined(MLAS_VSX_INTRINSICS) // Don't use vec_min to avoid undefined behavior if NAN return vec_sel(Vector2, Vector1, vec_cmpgt(Vector2, Vector1)); +#elif defined(MLAS_WASM_RELAXED_SIMD_INTRINSICS) + return wasm_f32x4_relaxed_min(Vector1, Vector2); #elif defined(MLAS_WASM_SIMD_INTRINSICS) return wasm_f32x4_min(Vector1, Vector2); #elif defined(MLAS_LSX_INTRINSICS) From f83e661835aeb0d355b99dd834d5f455f4d77341 Mon Sep 17 00:00:00 2001 From: Guenther Schmuelling Date: Tue, 8 Apr 2025 08:38:18 -0700 Subject: [PATCH 248/266] webgpu support for DequantizeLinear (#24268) webgpu support for DequantizeLinear --- onnxruntime/core/providers/webgpu/program.cc | 10 + onnxruntime/core/providers/webgpu/program.h | 5 +- .../webgpu/quantization/quantize_linear.cc | 221 ++++++++++++++++++ .../webgpu/quantization/quantize_linear.h | 52 +++++ .../core/providers/webgpu/shader_helper.cc | 6 + .../core/providers/webgpu/shader_variable.cc | 5 + .../webgpu/webgpu_execution_provider.cc | 36 +-- .../cpu/tensor/quantize_linear_test.cc | 45 +++- 8 files changed, 353 insertions(+), 27 deletions(-) create mode 100644 onnxruntime/core/providers/webgpu/quantization/quantize_linear.cc create mode 100644 onnxruntime/core/providers/webgpu/quantization/quantize_linear.h diff --git a/onnxruntime/core/providers/webgpu/program.cc b/onnxruntime/core/providers/webgpu/program.cc index 73291e1e93ff1..89f547481b6e4 100644 --- a/onnxruntime/core/providers/webgpu/program.cc +++ b/onnxruntime/core/providers/webgpu/program.cc @@ -102,6 +102,9 @@ constexpr std::string_view ProgramVariableDataTypeName[] = { "u8x4", // Uint8x4 "u8x8", // Uint8x8 "u8x16", // Uint8x16 + "i8x4", // Int8x4 + "i8x8", // Int8x8 + "i8x16", // Int8x16 }; std::ostream& operator<<(std::ostream& os, ProgramVariableDataType type) { os << ProgramVariableDataTypeName[std::underlying_type::type(type)]; @@ -129,6 +132,7 @@ int NumberOfComponents(ProgramVariableDataType type) { case ProgramVariableDataType::Float16x4: case ProgramVariableDataType::Boolx4: case ProgramVariableDataType::Uint8x4: + case ProgramVariableDataType::Int8x4: return 4; case ProgramVariableDataType::Uint8x8: return 8; @@ -142,6 +146,10 @@ int NumberOfComponents(ProgramVariableDataType type) { ProgramVariableDataType ToProgramVariableDataType(int32_t element_type, int component /* = 1 */) { if (component == 1) { switch (element_type) { + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: + return ProgramVariableDataType::Uint8x4; // shader needs to be aware that only 1 value is valid + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: + return ProgramVariableDataType::Int8x4; // shader needs to be aware that only 1 value is valid case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: return ProgramVariableDataType::Float32; case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: @@ -174,6 +182,8 @@ ProgramVariableDataType ToProgramVariableDataType(int32_t element_type, int comp switch (element_type) { case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: return ProgramVariableDataType::Uint8x4; + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: + return ProgramVariableDataType::Int8x4; case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: return ProgramVariableDataType::Float32x4; case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: diff --git a/onnxruntime/core/providers/webgpu/program.h b/onnxruntime/core/providers/webgpu/program.h index ea7d8ae5471af..3b0acfa7d0d35 100644 --- a/onnxruntime/core/providers/webgpu/program.h +++ b/onnxruntime/core/providers/webgpu/program.h @@ -197,7 +197,10 @@ enum class ProgramVariableDataType { Boolx4, Uint8x4, Uint8x8, - Uint8x16 + Uint8x16, + Int8x4, + Int8x8, + Int8x16, }; #ifndef NDEBUG std::ostream& operator<<(std::ostream& os, ProgramVariableDataType); diff --git a/onnxruntime/core/providers/webgpu/quantization/quantize_linear.cc b/onnxruntime/core/providers/webgpu/quantization/quantize_linear.cc new file mode 100644 index 0000000000000..866b1debf6dc8 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/quantization/quantize_linear.cc @@ -0,0 +1,221 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include + +#include "core/util/math.h" +#include "core/providers/webgpu/quantization/quantize_linear.h" +#include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/webgpu_supported_types.h" +#include "core/providers/webgpu/webgpu_utils.h" + +namespace onnxruntime { +namespace webgpu { + +Status DequantizeLinearProgram::GenerateShaderCode(ShaderHelper& shader) const { + const auto& x = shader.AddInput("input", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseElementTypeAlias); + const auto& scale = shader.AddInput("scale", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias | ShaderUsage::UseValueTypeAlias); + const auto& output = shader.AddOutput("output", ShaderUsage::UseUniform | ShaderUsage::UseShapeAndStride | ShaderUsage::UseValueTypeAlias); + + shader.MainFunctionBody() + << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") + << "let output_indices = " << output.OffsetToIndices("global_idx") << ";\n"; + + // Get x input + if (packed_) { + std::string unpack = (signed_) ? "unpack4xI8(x)" : "unpack4xU8(x)"; + if (output.NumComponents() == 1) { + shader.MainFunctionBody() + << "let x = " << x.GetByOffset("global_idx / 4") << ";\n" + << "let x_vec = " << unpack << ";\n" + << "let x_value = x_vec[global_idx % 4];\n"; + } else { + shader.MainFunctionBody() + << "let x = " << x.GetByOffset("global_idx") << ";\n" + << "let x_vec = " << unpack << ";\n" + << "let x_value = x_vec;\n"; + } + } else { + shader.MainFunctionBody() + << "let x_value = " << x.GetByOffset("global_idx") << ";\n"; + } + + // Get scaler + if (per_layer_) { + // scale input is a scalar () + shader.MainFunctionBody() + << "let scale_value = " << scale.GetByOffset("0") << ";\n"; + } else if (per_axis_) { + shader.MainFunctionBody() + << "let scale_index = " << output.IndicesGet("output_indices", "uniforms.axis") << ";\n" + << "let scale_value = " << scale.GetByOffset("scale_index") << ";\n"; + } else { + // Block quantization. Scale input rank is same as input/output rank. + shader.MainFunctionBody() + << "var scale_indices: scale_indices_t = output_indices;\n" + << "let index = " << scale.IndicesGet("scale_indices", "uniforms.axis") << "/ uniforms.block_size;\n" + << scale.IndicesSet("scale_indices", "uniforms.axis", "index") << ";\n" + << "let scale_value = " << scale.GetByIndices("scale_indices") << ";\n"; + } + + // Get zero-point + if (has_zeropoint_) { + const auto& zero_point = shader.AddInput("zero_point", ShaderUsage::UseUniform | ShaderUsage::UseIndicesTypeAlias); + + std::string unpack = (signed_) ? "unpack4xI8(zero_point_input)" : "unpack4xU8(zero_point_input)"; + if (per_layer_) { + // zero-point input is a scalar + if (packed_) { + shader.MainFunctionBody() + << "let zero_point_input = " << zero_point.GetByOffset("0") << ";\n" + << "let zero_point_vec = " << unpack << ";\n" + << "let zero_point_value = zero_point_vec[0];\n"; + } else { + shader.MainFunctionBody() + << "let zero_point_value = " << zero_point.GetByOffset("0") << ";\n"; + } + } else if (per_axis_) { + // zero-point input is a 1D tensor + if (packed_) { + shader.MainFunctionBody() + << "let zero_point_index = " << output.IndicesGet("output_indices", "uniforms.axis") << ";\n" + << "let zero_point_input = " << zero_point.GetByOffset("zero_point_index / 4") << ";\n" + << "let zero_point_vec = " << unpack << ";\n" + << "let zero_point_value = zero_point_vec[zero_point_index % 4];\n"; + } else { + shader.MainFunctionBody() + << "let zero_point_index = " << output.IndicesGet("output_indices", "uniforms.axis") << ";\n" + << "let zero_point_value = " << zero_point.GetByOffset("zero_point_index") << ";\n"; + } + } else { + // BlockedQuantization. The zero-point input shape is same as the input shape except along axis. + if (packed_) { + shader.MainFunctionBody() + << "let zero_point_offset = " << scale.GetByIndices("scale_indices") << ";\n" + << "let zero_point_input = " << zero_point.GetByOffset("zero_point_offset / 4") << ";\n" + << "let zero_point_vec = " << unpack << ";\n" + << "let zero_point_value = zero_point_vec[zero_point_offset % 4];\n"; + } else { + shader.MainFunctionBody() + << "let zero_point_value = " << zero_point.GetByIndices("scale_indices") << ";\n"; + } + } + } else { + shader.MainFunctionBody() + << "let zero_point_value = input_element_t(0);\n"; + } + + // compute and write output + shader.MainFunctionBody() + << output.SetByOffset("global_idx", "(output_value_t(x_value) - scale_value_t(zero_point_value)) * scale_value"); + + return Status::OK(); +} + +Status DequantizeLinear::ComputeInternal(ComputeContext& context) const { + const auto* x = context.Input(0); + const auto* x_scale = context.Input(1); + const auto* x_zeropoint = context.Input(2); + const auto x_shape = x->Shape(); + int64_t x_size = x_shape.Size(); + auto* output_tensor = context.Output(0, x_shape); + int64_t x_scale_rank = x_scale->Shape().NumDimensions(); + + bool packed = x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 || x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8; + bool is_signed = x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8; + int64_t axis = (axis_ >= 0) ? axis_ : axis_ + x_shape.NumDimensions(); + + int max_components = GetMaxComponents(x_size); + if (max_components != 4) { + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "DequantizeLinear: components must be 4, but got ", max_components); + } + + // scaler - single scaler for all elements + bool per_layer = x_scale_rank == 0 || (x_scale_rank == 1 && x_scale->Shape()[0] == 1); + + // 1D tensor - 1 scaler for per axis + bool per_axis = per_layer == false && x_scale_rank == 1; + + bool use_components = per_layer && (!packed || max_components == 4); + int components = use_components ? max_components : 1; + int input_component = use_components && !packed ? max_components : 1; + + DequantizeLinearProgram program{packed, is_signed, per_layer, per_axis, x_zeropoint != nullptr}; + + program + .AddInputs({{x, ProgramTensorMetadataDependency::TypeAndRank, input_component}}) + .AddInputs({{x_scale, ProgramTensorMetadataDependency::TypeAndRank}}) + .AddOutput({output_tensor, ProgramTensorMetadataDependency::None, components}) + .SetDispatchGroupSize((x_size / components + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) + .AddUniformVariables({{static_cast(axis)}}) + .AddUniformVariables({{static_cast(block_size_)}}) + .AddUniformVariables({{static_cast(x_size / components)}}) + .CacheHint(std::to_string(axis), std::to_string(is_signed), std::to_string(per_layer), std::to_string(per_axis), std::to_string(block_size_)); + + if (x_zeropoint != nullptr) { + program.AddInputs({{x_zeropoint, ProgramTensorMetadataDependency::TypeAndRank}}); + } + + return context.RunProgram(program); +} + +namespace { +const std::vector& DequantizeLinearConstraints() { + static std::vector types{ + DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType()}; + return types; +} +} // namespace + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + DequantizeLinear, + kOnnxDomain, + 10, 12, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", DequantizeLinearConstraints()), + DequantizeLinear); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + DequantizeLinear, + kOnnxDomain, + 13, 18, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", DequantizeLinearConstraints()), + DequantizeLinear); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + DequantizeLinear, + kOnnxDomain, + 19, 20, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T1", DequantizeLinearConstraints()) + .TypeConstraint("T2", WebGpuSupportedFloatTypes()), + DequantizeLinear); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + DequantizeLinear, + kOnnxDomain, + 21, 22, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T1", DequantizeLinearConstraints()) + .TypeConstraint("T2", WebGpuSupportedFloatTypes()), + DequantizeLinear); + +ONNX_OPERATOR_KERNEL_EX( + DequantizeLinear, + kOnnxDomain, + 23, + kWebGpuExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T1", DequantizeLinearConstraints()) + .TypeConstraint("T2", WebGpuSupportedFloatTypes()), + DequantizeLinear); + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/quantization/quantize_linear.h b/onnxruntime/core/providers/webgpu/quantization/quantize_linear.h new file mode 100644 index 0000000000000..95614998017e9 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/quantization/quantize_linear.h @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/webgpu/webgpu_kernel.h" + +namespace onnxruntime { +namespace webgpu { + +class DequantizeLinearProgram final : public Program { + public: + DequantizeLinearProgram(const bool packed, const bool issigned, const bool per_layer, + const bool per_axis, bool has_zeropoint) : Program{"DequantizeLinear"}, + packed_{packed}, + signed_{issigned}, + per_layer_{per_layer}, + per_axis_{per_axis}, + has_zeropoint_{has_zeropoint} {} + + Status GenerateShaderCode(ShaderHelper& sh) const override; + + WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES({"axis", ProgramUniformVariableDataType::Uint32}, + {"block_size", ProgramUniformVariableDataType::Uint32}, + {"output_size", ProgramUniformVariableDataType::Uint32}); + + private: + bool packed_; + bool signed_; + bool per_layer_; + bool per_axis_; + bool has_zeropoint_; +}; + +class DequantizeLinear final : public WebGpuKernel { + public: + DequantizeLinear(const OpKernelInfo& info) : WebGpuKernel(info) { + axis_ = info.GetAttrOrDefault("axis", 1); + block_size_ = info.GetAttrOrDefault("block_size", 0); + output_dtype_ = info.GetAttrOrDefault("output_dtype", 0); + } + + Status ComputeInternal(ComputeContext& context) const override; + + private: + int64_t axis_; + int64_t block_size_; + int64_t output_dtype_; +}; + +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/shader_helper.cc b/onnxruntime/core/providers/webgpu/shader_helper.cc index db14cb88d1963..bac360c4c270e 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.cc +++ b/onnxruntime/core/providers/webgpu/shader_helper.cc @@ -168,6 +168,12 @@ Status ValidateVariableDataType(int32_t element_type, ProgramVariableDataType va var_type == ProgramVariableDataType::Uint8x16, "Unexpected program variable type ", int(var_type), " for uint8 tensor"); break; + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: + ORT_RETURN_IF_NOT(var_type == ProgramVariableDataType::Int8x4 || + var_type == ProgramVariableDataType::Int8x8 || + var_type == ProgramVariableDataType::Int8x16, + "Unexpected program variable type ", int(var_type), " for int8 tensor"); + break; default: ORT_RETURN_IF(true, "Unsupported data type: ", element_type); // todo: add int4/uint4 diff --git a/onnxruntime/core/providers/webgpu/shader_variable.cc b/onnxruntime/core/providers/webgpu/shader_variable.cc index f8e1e0b3b8d2b..502d03c2c2dd8 100644 --- a/onnxruntime/core/providers/webgpu/shader_variable.cc +++ b/onnxruntime/core/providers/webgpu/shader_variable.cc @@ -32,6 +32,7 @@ constexpr static const std::string_view STORAGE_TYPE_ARRAY[] = { "u32", // Uint8x4 "vec2", // Uint8x8 "vec4", // Uint8x16 + "u32", // Int8x4 }; constexpr static const auto STORAGE_TYPE = details::_to_std_array(STORAGE_TYPE_ARRAY); @@ -54,6 +55,7 @@ constexpr static const std::string_view VALUE_TYPE_ARRAY[] = { "u32", // Uint8x4 (u32 as 4 elements of uint8) "vec2", // Uint8x8 (vec2 as 2x4 elements of uint8) "vec4", // Uint8x16 (vec4 as 4x4 elements of uint8) + "i32", // Int8x4 }; constexpr static const auto VALUE_TYPE = details::_to_std_array(VALUE_TYPE_ARRAY); @@ -76,6 +78,9 @@ constexpr static const std::string_view ELEMENT_TYPE_ARRAY[] = { "u32", // Uint8x4 "u32", // Uint8x8 "u32", // Uint8x16 + "i32", // Int8x4 + "i32", // Int8x8 + "i32", // Int8x16 }; constexpr static const auto ELEMENT_TYPE = details::_to_std_array(ELEMENT_TYPE_ARRAY); diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index eb65e998c81c5..1d4fea09dd4a6 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -391,18 +391,11 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kMSInternalNHWCD class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 11, 13, CumSum); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 14, CumSum); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 10, 12, uint8_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 10, 12, int8_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 10, 12, int32_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 18, uint8_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 18, int8_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 18, int32_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, 20, uint8_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, 20, int8_t, DequantizeLinear); -class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, 20, int32_t, DequantizeLinear); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, uint8_t, DequantizeLinear); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, int8_t, DequantizeLinear); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, int32_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 10, 12, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 13, 18, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 19, 20, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 21, 22, DequantizeLinear); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kWebGpuExecutionProvider, kOnnxDomain, 23, DequantizeLinear); std::unique_ptr RegisterKernels() { auto kernel_registry = std::make_unique(); @@ -723,20 +716,15 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + + KERNEL_CREATE_INFO_VERSIONED(10, 12, DequantizeLinear), + KERNEL_CREATE_INFO_VERSIONED(13, 18, DequantizeLinear), + KERNEL_CREATE_INFO_VERSIONED(19, 20, DequantizeLinear), + KERNEL_CREATE_INFO_VERSIONED(21, 22, DequantizeLinear), + KERNEL_CREATE_INFO(23, DequantizeLinear), + BuildKernelCreateInfo, BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, - // BuildKernelCreateInfo, }; for (auto& function_table_entry : function_table) { diff --git a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc index 51aae0cfd4adf..4e7a6356a5129 100644 --- a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc @@ -156,7 +156,8 @@ TEST(DequantizeLinearOpTest, Scalar) { test.AddInput("x_zero_point", {}, {-10}); test.AddOutput("y", {}, {220.0f}); // Disable Tensorrt EP due to error:node1_quantize_scale_node: out of bounds channel axis 1. Number of input dimensions is 0. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + // Disable WebGPU EP due to error: needs at least component size 4 + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kWebGpuExecutionProvider}); } // dequantize with scalar data @@ -167,7 +168,8 @@ TEST(DequantizeLinearOpMLFloat16Test, Scalar) { test.AddInput("x_zero_point", {}, {-10}); test.AddOutput("y", {}, {MLFloat16(220.0f)}); // Disable Tensorrt EP due to error:node1_quantize_scale_node: out of bounds channel axis 1. Number of input dimensions is 0. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + // Disable WebGPU EP due to error: needs at least component size 4 + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kWebGpuExecutionProvider}); } // dequantize without zero point @@ -176,6 +178,45 @@ TEST(DequantizeLinearOpTest, Without_Zero_Point) { test.AddInput("x", {}, {100}); test.AddInput("x_scale", {}, {2.0f}); test.AddOutput("y", {}, {200.0f}); + // No DQ allowed without corresponding Q. Skip since TRT10 + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kWebGpuExecutionProvider}); +} + +// dequantize without zero point int8 (testing 8 elements for webgpu) +TEST(DequantizeLinearOpTest, No_Zero_Point_int8) { + OpTester test("DequantizeLinear", 10); + test.AddInput("x", {1, 8}, {-10, 50, 100, 120, -9, 49, 99, 119}); + test.AddInput("x_scale", {}, {2.0f}); + test.AddOutput("y", {1, 8}, {-20.0f, 100.0f, 200.0f, 240.0f, -18.0f, 98.0f, 198.0f, 238.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // No DQ allowed without corresponding Q. Skip since TRT10 +} + +// dequantize without zero point uint8 (testing 8 elements for webgpu) +TEST(DequantizeLinearOpTest, No_Zero_Point_uint8) { + OpTester test("DequantizeLinear", 10); + test.AddInput("x", {1, 8}, {10, 50, 100, 180, 9, 49, 99, 179}); + test.AddInput("x_scale", {}, {2.0f}); + test.AddOutput("y", {1, 8}, {20.0f, 100.0f, 200.0f, 360.0f, 18.0f, 98.0f, 198.0f, 358.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // No DQ allowed without corresponding Q. Skip since TRT10 +} + +// dequantize zero point int8 (testing 8 elements for webgpu) +TEST(DequantizeLinearOpTest, Zero_Point_int8) { + OpTester test("DequantizeLinear", 10); + test.AddInput("x", {1, 8}, {-10, 50, 100, 120, -9, 49, 99, 119}); + test.AddInput("x_scale", {}, {2.0f}); + test.AddInput("zero_point", {}, {-10}); + test.AddOutput("y", {1, 8}, {0.0f, 120.0f, 220.0f, 260.0f, 2.0f, 118.0f, 218.0f, 258.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // No DQ allowed without corresponding Q. Skip since TRT10 +} + +// dequantize zero point uint8 (testing 8 elements for webgpu) +TEST(DequantizeLinearOpTest, Zero_Point_uint8) { + OpTester test("DequantizeLinear", 10); + test.AddInput("x", {1, 8}, {10, 50, 100, 180, 9, 49, 99, 119}); + test.AddInput("x_scale", {}, {2.0f}); + test.AddInput("zero_point", {}, {10}); + test.AddOutput("y", {1, 8}, {0.0f, 80.0f, 180.0f, 340.0f, -2.0f, 78.0f, 178.0f, 218.0f}); test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // No DQ allowed without corresponding Q. Skip since TRT10 } From 10e51d2618137de066caf4fef6c51c4c713f476b Mon Sep 17 00:00:00 2001 From: xhcao Date: Tue, 8 Apr 2025 23:40:59 +0800 Subject: [PATCH 249/266] [webgpu] fix the reflect mode issue of Pad (#24202) ### Description ### Motivation and Context --- .../core/providers/webgpu/tensor/pad.cc | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/onnxruntime/core/providers/webgpu/tensor/pad.cc b/onnxruntime/core/providers/webgpu/tensor/pad.cc index f24578a145aae..5adf873be7897 100644 --- a/onnxruntime/core/providers/webgpu/tensor/pad.cc +++ b/onnxruntime/core/providers/webgpu/tensor/pad.cc @@ -5,6 +5,7 @@ #include #include "core/util/math.h" +#include "core/providers/webgpu/string_macros.h" #include "core/providers/webgpu/tensor/pad.h" #include "core/providers/webgpu/shader_helper.h" #include "core/providers/webgpu/webgpu_supported_types.h" @@ -38,38 +39,47 @@ Status PadProgram::GenerateShaderCode(ShaderHelper& shader) const { std::string lower_pads_str = GetElementAt("uniforms.lower_pads", "dim", rank); std::string data_shape_str = "i32(" + GetElementAt("uniforms.data_shape", "dim", rank) + ")"; std::string data_stride_str = rank == 1 ? "" : " * " + GetElementAt("uniforms.data_stride", "dim", rank - 1); - std::string begin_axis_statement = "in_coord = "; - std::string end_axis_statement = "in_coord = "; - std::string in_axis_statement = "in_coord = " + output_indices_str + " - " + lower_pads_str + ";\n"; + SS(axis_body_ss, 1024); switch (mode_) { case Mode::Constant: - begin_axis_statement = "use_pad_value = true;\n"; - end_axis_statement = "use_pad_value = true;\n"; + axis_body_ss << " if (" << output_indices_str << " < " << lower_pads_str << " || " << output_indices_str << " >= " << lower_pads_str << " + " << data_shape_str << ") {\n" + << " use_pad_value = true;\n"; break; case Mode::Edge: - begin_axis_statement += "0;\n"; - end_axis_statement += data_shape_str + " - 1;\n"; + axis_body_ss << " if (" << output_indices_str << " < " << lower_pads_str << ") {\n" + << " in_coord = 0;\n" + << " } else if (" << output_indices_str << " >= " << lower_pads_str << " + " << data_shape_str << ") {\n" + << " in_coord = " << data_shape_str + " - 1;\n"; break; case Mode::Reflect: - begin_axis_statement += lower_pads_str + " - " + output_indices_str + ";\n"; - end_axis_statement += data_shape_str + " - 2 - (" + output_indices_str + - " - (" + lower_pads_str + " + " + data_shape_str + "));\n"; + axis_body_ss << " if (" << output_indices_str << " < " << lower_pads_str << " || " << output_indices_str << " >= " << lower_pads_str << " + " << data_shape_str << ") {\n" + << " in_coord = " << output_indices_str << " - " << lower_pads_str << ";\n" + << " if (in_coord < 0) {\n" + << " in_coord = -in_coord;\n" + << " }\n" + << " {\n" + << " let _2n_1 = 2 * (" << data_shape_str << " - 1);\n" + << " in_coord = in_coord % _2n_1;\n" + << " if(in_coord >= " << data_shape_str << ") {\n" + << " in_coord = _2n_1 - in_coord;\n" + << " }\n" + << " }\n"; break; case Mode::Wrap: - begin_axis_statement += data_shape_str + " + " + output_indices_str + " - " + lower_pads_str + ";\n"; - end_axis_statement += output_indices_str + " - " + lower_pads_str + " - " + data_shape_str + ";\n"; + axis_body_ss << " if (" << output_indices_str << " < " << lower_pads_str << ") {\n" + << " in_coord = " << data_shape_str << " + " << output_indices_str << " - " << lower_pads_str + ";\n" + << " } else if (" << output_indices_str << " >= " << lower_pads_str << " + " << data_shape_str << ") {\n" + << " in_coord = " << output_indices_str << " - " << lower_pads_str << " - " << data_shape_str << ";\n"; break; default: return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported mode type: ", static_cast(mode_)); } + axis_body_ss << " } else {\n" + << " " << "in_coord = " << output_indices_str << " - " << lower_pads_str << ";\n" + << " }\n"; shader.MainFunctionBody() << " for (var dim = 0; dim < " << rank << " && !use_pad_value; dim++) {\n" - << " if (" << output_indices_str << " < " << lower_pads_str << ") {\n" - << " " << begin_axis_statement << " }\n" - << " else if (" << output_indices_str << " >= " << lower_pads_str << " + " << data_shape_str << ") {\n" - << " " << end_axis_statement << " }\n" - << " else {\n" - << " " << in_axis_statement << " }\n" + << SS_GET(axis_body_ss) << " input_index += select(u32(in_coord)" << data_stride_str << ", u32(in_coord), dim == " << rank - 1 << ");\n" << " }\n" << " " << constant_value_str From 4edada600a9a1333876fb363cfa9a1ffb151bcf7 Mon Sep 17 00:00:00 2001 From: Kevin Chen <45886021+kevinch-nv@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:25:50 -0700 Subject: [PATCH 250/266] Remove explicit batch network flag for TRT 10+ (#24298) ### Description `nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH` [has been deprecated since 10.0](https://docs.nvidia.com/deeplearning/tensorrt/latest/_static/c-api/namespacenvinfer1.html#aa8f406be96c14b7dbea548cf19f09a08) and is always implicitly set for versions 10.0+. Change the EP code to only set this flag for TRT versions 8 and below. ### Motivation and Context Removes deprecated API usages in the TRT EP code. Signed-off-by: Kevin Chen --- .../core/providers/tensorrt/tensorrt_execution_provider.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index 2c443cdc33458..ded135bf50ec8 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -2296,8 +2296,9 @@ SubGraphCollection_t TensorrtExecutionProvider::GetSupportedList(SubGraphCollect auto network_flags = 0; #if NV_TENSORRT_MAJOR > 8 network_flags |= fp16_enable_ || int8_enable_ ? 0 : 1U << static_cast(nvinfer1::NetworkDefinitionCreationFlag::kSTRONGLY_TYPED); -#endif +#else network_flags |= 1U << static_cast(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH); +#endif auto trt_network = std::unique_ptr(trt_builder->createNetworkV2(network_flags)); auto trt_parser = tensorrt_ptr::unique_pointer(nvonnxparser::createParser(*trt_network, trt_logger)); @@ -2907,8 +2908,9 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView auto network_flags = 0; #if NV_TENSORRT_MAJOR > 8 network_flags |= fp16_enable_ || int8_enable_ ? 0 : 1U << static_cast(nvinfer1::NetworkDefinitionCreationFlag::kSTRONGLY_TYPED); -#endif +#else network_flags |= 1U << static_cast(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH); +#endif auto trt_network = std::unique_ptr(trt_builder->createNetworkV2(network_flags)); auto trt_config = std::unique_ptr(trt_builder->createBuilderConfig()); auto trt_parser = tensorrt_ptr::unique_pointer(nvonnxparser::createParser(*trt_network, trt_logger)); From 2265613495debbfd2fa2ebada8a7e7b7867265af Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Wed, 9 Apr 2025 01:44:25 +0800 Subject: [PATCH 251/266] [webgpu] Fix bias_split_gelu (#24342) "channels" should be validated before divided by "components". "components" should be passed to program inputs and outputs. Rename "input" to "x" to match "ErfImpl". Correct the last dimension of output shape. --- .../webgpu/bert/bias_split_gelu.cc | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc b/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc index 99cd643423400..4656fc486fccf 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_split_gelu.cc @@ -22,20 +22,21 @@ ONNX_OPERATOR_KERNEL_EX( BiasSplitGelu); Status BiasSplitGeluProgram::GenerateShaderCode(ShaderHelper& shader) const { - const ShaderVariableHelper& input = shader.AddInput("input"); - const ShaderVariableHelper& bias = shader.AddInput("bias"); - const ShaderVariableHelper& output = shader.AddOutput("output"); + const ShaderVariableHelper& x = + shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + const ShaderVariableHelper& bias = shader.AddInput("bias", ShaderUsage::UseUniform); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform); shader.AdditionalImplementation() << ErfImpl; shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") << "const M_SQRT2: f32 = sqrt(2.0);\n" - << "const halfChannels = uniforms.channels / 2u;\n" + << "let halfChannels = uniforms.channels / 2u;\n" << "let biasIdx = global_idx % halfChannels;\n" << "let batchIndex = global_idx / halfChannels;\n" << "let inputOffset = biasIdx + batchIndex * halfChannels * 2;\n" - << "let valueLeft = " << input.GetByOffset("inputOffset") << " + " << bias.GetByOffset("biasIdx") << ";\n" - << "let valueRight = " << input.GetByOffset("inputOffset + halfChannels") << " + " << bias.GetByOffset("biasIdx + halfChannels") << ";\n" + << "let valueLeft = " << x.GetByOffset("inputOffset") << " + " << bias.GetByOffset("biasIdx") << ";\n" + << "let valueRight = " << x.GetByOffset("inputOffset + halfChannels") << " + " << bias.GetByOffset("biasIdx + halfChannels") << ";\n" << "let geluRight = valueRight * 0.5 * (erf_v(valueRight / M_SQRT2) + 1);\n" << output.SetByOffset("global_idx", "valueLeft * geluRight"); @@ -53,25 +54,27 @@ Status BiasSplitGelu::ComputeInternal(onnxruntime::webgpu::ComputeContext& conte } int64_t channels = input_shape[2]; - int64_t components = GetMaxComponents(channels); - channels /= components; input_shape[2] = channels / 2; // for output shape calculation (N,S,D) -> (N,S,D/2) TensorShape bias_shape = bias->Shape(); if (bias_shape.NumDimensions() != 1 || bias_shape[0] != channels) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "BiasSplitGelu bias should have 1 dimension with size equal to the number of channels."); + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "BiasSplitGelu bias should have 1 dimension with size equal to the number of channels."); } + int components = GetMaxComponents(channels); + channels /= components; + auto* output = context.Output(0, input_shape); int64_t output_size = output->Shape().Size() / components; BiasSplitGeluProgram program{}; - program.AddInputs({{input, ProgramTensorMetadataDependency::TypeAndRank}, - {bias}}) - .AddOutput({output}) + program + .AddInputs({{input, ProgramTensorMetadataDependency::None, components}, + {bias, ProgramTensorMetadataDependency::None, components}}) + .AddOutput({output, ProgramTensorMetadataDependency::None, components}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) - .AddUniformVariables({{static_cast(output_size)}, - {static_cast(channels)}}); + .AddUniformVariables({{static_cast(output_size)}, {static_cast(channels)}}); return context.RunProgram(program); } From 34abb8b44320275ee2f6e8cb90ed2bb217d6e89c Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Wed, 9 Apr 2025 01:44:40 +0800 Subject: [PATCH 252/266] [webgpu] fix bias-add (#24336) "channels" should be validated before divided by "components". "components" should be passed to program inputs and outputs. --- .../contrib_ops/webgpu/bert/bias_add.cc | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc index e822f8764b63f..0f2e6d725007f 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc @@ -21,16 +21,16 @@ ONNX_OPERATOR_KERNEL_EX( BiasAdd); Status BiasAddProgram::GenerateShaderCode(ShaderHelper& shader) const { - const ShaderVariableHelper& input = shader.AddInput("input"); - const ShaderVariableHelper& bias = shader.AddInput("bias"); - const ShaderVariableHelper& residual = shader.AddInput("residual"); - const ShaderVariableHelper& output = shader.AddOutput("output"); + const ShaderVariableHelper& input = shader.AddInput("input", ShaderUsage::UseUniform); + const ShaderVariableHelper& bias = shader.AddInput("bias", ShaderUsage::UseUniform); + const ShaderVariableHelper& residual = shader.AddInput("residual", ShaderUsage::UseUniform); + const ShaderVariableHelper& output = shader.AddOutput("output", ShaderUsage::UseUniform); shader.MainFunctionBody() << shader.GuardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size") - << "let value = " << input.GetByOffset("global_idx") + << " let value = " << input.GetByOffset("global_idx") << " + " << bias.GetByOffset("global_idx % uniforms.channels") << " + " << residual.GetByOffset("global_idx") << ";\n" - << output.SetByOffset("global_idx", "value"); + << " " + output.SetByOffset("global_idx", "value"); return Status::OK(); } @@ -47,23 +47,26 @@ Status BiasAdd::ComputeInternal(onnxruntime::webgpu::ComputeContext& context) co } int64_t channels = input_shape[2]; - int64_t components = GetMaxComponents(channels); - channels /= components; - TensorShape bias_shape = bias->Shape(); if (bias_shape.NumDimensions() != 1 || bias_shape[0] != channels) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "BiasAdd bias should have 1 dimension with size equal to the number of channels."); + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, + "BiasAdd bias should have 1 dimension with size equal to the number of channels."); } + int components = GetMaxComponents(channels); + channels /= components; + auto* output = context.Output(0, input_shape); int64_t output_size = output->Shape().Size() / components; BiasAddProgram program{}; - program.AddInputs({{input}, {bias}, {residual}}) - .AddOutput({output}) + program + .AddInputs({{input, ProgramTensorMetadataDependency::None, components}, + {bias, ProgramTensorMetadataDependency::None, components}, + {residual, ProgramTensorMetadataDependency::None, components}}) + .AddOutput({output, ProgramTensorMetadataDependency::None, components}) .SetDispatchGroupSize((output_size + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE) - .AddUniformVariables({{static_cast(output_size)}, - {static_cast(channels)}}); + .AddUniformVariables({{static_cast(output_size)}, {static_cast(channels)}}); return context.RunProgram(program); } From 0acb04887ac8efe91a5c764375ac84b1af6d99e0 Mon Sep 17 00:00:00 2001 From: xhcao Date: Wed, 9 Apr 2025 01:45:14 +0800 Subject: [PATCH 253/266] [webgpu] optimize SkipLayerNormalization operator (#24164) If the sizes of batch_size and sequence_length are ones, split the hidden_size to improve parallelism. ### Description ### Motivation and Context --- .../webgpu/bert/skip_layer_norm.cc | 172 ++++++++++++------ .../contrib_ops/webgpu/bert/skip_layer_norm.h | 6 +- 2 files changed, 121 insertions(+), 57 deletions(-) diff --git a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc index 61f701f7911a7..2126022f8b547 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "core/providers/webgpu/shader_helper.h" +#include "core/providers/webgpu/string_macros.h" #include "core/providers/webgpu/webgpu_utils.h" #include "core/providers/webgpu/webgpu_supported_types.h" #include "contrib_ops/webgpu/webgpu_contrib_kernels.h" @@ -12,7 +13,7 @@ namespace contrib { namespace webgpu { Status SkipLayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { - const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias); + const auto& x = shader.AddInput("x", ShaderUsage::UseUniform | ShaderUsage::UseValueTypeAlias | ShaderUsage::UseElementTypeAlias); shader.AddInput("skip", ShaderUsage::UseUniform); shader.AddInput("gamma", ShaderUsage::UseUniform); if (hasBeta_) { @@ -26,57 +27,112 @@ Status SkipLayerNormProgram::GenerateShaderCode(ShaderHelper& shader) const { shader.AddOutput("input_skip_bias_sum", ShaderUsage::UseUniform); } - int components = x.NumComponents(); - - std::string bias = (hasBias_) ? " + bias[offset1d + i] " : ""; std::string simpl1 = (simplified_) ? "" : "- mean * mean "; - std::string simpl2 = (simplified_) ? "" : "- element_t(mean) "; - std::string beta = (hasBeta_) ? " + beta[offset1d + i] " : ""; - std::string input_skip_bias_sum = (has_input_skip_bias_sum_) ? "input_skip_bias_sum[offset + i] = value;\n" : ""; - - shader.AdditionalImplementation() - << "alias element_t = " << (is_fp16_ ? "f16;\n" : "f32;\n") - << "alias f32_val_t = " << (components == 4 ? "vec4" : (components == 2 ? "vec2" : "f32")) << ";\n" - << "var sum_shared : array;\n" - << "var sum_squared_shared : array;\n"; - - shader.MainFunctionBody() - << "let ix = local_idx;\n" - << "let iy = global_idx / workgroup_size_x;\n" - << "let hidden_size_vectorized: u32 = uniforms.hidden_size / uniforms.components;\n" - << "var stride = hidden_size_vectorized / workgroup_size_x;\n" - << "let offset = ix * stride + iy * hidden_size_vectorized;\n" - << "let offset1d = stride * ix;\n" - << "if (ix == workgroup_size_x - 1) {\n" - << " stride = hidden_size_vectorized - stride * ix;\n" - << "}\n" - << "for (var i: u32 = 0; i < stride; i++) {\n" - << " let skip_value = skip[offset + i];\n" - << " let input_value = x[offset + i];\n" - << " let value = input_value + skip_value" << bias << ";\n" - << " output[offset + i] = value;\n" - << input_skip_bias_sum - << " let f32_value = f32_val_t(value);\n" - << " sum_shared[ix] += f32_value;\n" - << " sum_squared_shared[ix] += f32_value * f32_value;\n" - << "}\n" - << "workgroupBarrier();\n" - << "var reduce_size : u32 = workgroup_size_x;\n" - << "for (var curr_size = reduce_size >> 1; curr_size > 0; curr_size = reduce_size >> 1) {\n" - << " reduce_size = curr_size + (reduce_size & 1);\n" - << " if (ix < curr_size) {\n" - << " sum_shared[ix] += sum_shared[ix + reduce_size];\n" - << " sum_squared_shared[ix] += sum_squared_shared[ix + reduce_size];\n" - << " }\n" - << " workgroupBarrier();\n" - << "}\n" - << "let sum = sum_shared[0];\n" - << "let square_sum = sum_squared_shared[0];\n" - << "let mean = " << SumVector("sum", components) << " / f32(uniforms.hidden_size);\n" - << "let inv_std_dev = inverseSqrt(" << SumVector("square_sum", components) << " / f32(uniforms.hidden_size) " << simpl1 << "+ uniforms.epsilon);\n" - << "for (var i: u32 = 0; i < stride; i++) {\n" - << " output[offset + i] = (output[offset + i] " << simpl2 << ") * element_t(inv_std_dev) * gamma[offset1d + i]" << beta << ";\n" - << "};\n"; + std::string simpl2 = (simplified_) ? "" : "- x_element_t(mean) "; + if (split_hidden_dim_) { + shader.AdditionalImplementation() + << "var sum_shared : array;\n" + << "var sum_squared_shared : array;\n"; + + SS(input_skip_bias_sum_ss, 512); + if (has_input_skip_bias_sum_) { + input_skip_bias_sum_ss + << " let workgroup_half_idx = uniforms.hidden_size / (workgroup_size_x * 4);\n" + << " if (workgroup_idx >= workgroup_half_idx) {\n" + << " offset = (workgroup_idx - workgroup_half_idx) * workgroup_size_x + local_idx;\n" + << " let skip_value = skip[offset];\n" + << " let input_value = x[offset];\n" + << " let value = input_value + skip_value" << (hasBias_ ? " + bias[offset]" : "") << ";\n" + << " input_skip_bias_sum[offset] = value;\n" + << " return;\n" + << " }\n"; + } + + shader.MainFunctionBody() + << " var offset: u32 = 0;\n" + << (has_input_skip_bias_sum_ ? SS_GET(input_skip_bias_sum_ss) : "") + << " var sum_vec4 = vec4(0);\n" + << " var sum_squared_vec4 = vec4(0);\n" + << " var cur_input_skip_bias_sum = x_value_t(0);\n" + << " for (var i: u32 = 0; i < uniforms.hidden_size / (workgroup_size_x * 4); i++) {\n" + << " let input_offset = i * workgroup_size_x + local_idx;\n" + << " let skip_value = skip[input_offset];\n" + << " let input_value = x[input_offset];\n" + << " let value = input_value + skip_value" << (hasBias_ ? " + bias[input_offset]" : "") << ";\n" + << " if (i == workgroup_idx) {\n" + << " cur_input_skip_bias_sum = value;\n" + << " }\n" + << " let f32_value = vec4(value);\n" + << " sum_vec4 += f32_value;\n" + << " sum_squared_vec4 += f32_value * f32_value;\n" + << " }\n" + << " var sum = " << SumVector("sum_vec4", 4) << ";\n" + << " var sum_squared = " << SumVector("sum_squared_vec4", 4) << ";\n" + << " sum_shared[local_idx] = sum;\n" + << " sum_squared_shared[local_idx] = sum_squared;\n" + << " workgroupBarrier();\n" + << " var reduce_size : u32 = workgroup_size_x;\n" + << " for (var curr_size = reduce_size >> 1; curr_size > 0; curr_size = reduce_size >> 1) {\n" + << " reduce_size = curr_size + (reduce_size & 1);\n" + << " if (local_idx < curr_size) {\n" + << " sum_shared[local_idx] += sum_shared[local_idx + reduce_size];\n" + << " sum_squared_shared[local_idx] += sum_squared_shared[local_idx + reduce_size];\n" + << " }\n" + << " workgroupBarrier();\n" + << " }\n" + << " let mean = sum_shared[0] / f32(uniforms.hidden_size);\n" + << " let inv_std_dev = inverseSqrt(sum_squared_shared[0] / f32(uniforms.hidden_size) " << simpl1 << "+ uniforms.epsilon);\n" + << " offset = workgroup_idx * workgroup_size_x + local_idx;\n" + << " output[offset] = ((cur_input_skip_bias_sum " << simpl2 << ") * x_element_t(inv_std_dev) * gamma[offset]" << (hasBeta_ ? " + beta[offset] " : "") << ");\n"; + } else { + int components = x.NumComponents(); + std::string bias = (hasBias_) ? " + bias[offset1d + i] " : ""; + std::string beta = (hasBeta_) ? " + beta[offset1d + i] " : ""; + std::string input_skip_bias_sum = (has_input_skip_bias_sum_) ? "input_skip_bias_sum[offset + i] = value;\n" : ""; + + shader.AdditionalImplementation() + << "alias f32_val_t = " << (components == 4 ? "vec4" : (components == 2 ? "vec2" : "f32")) << ";\n" + << "var sum_shared : array;\n" + << "var sum_squared_shared : array;\n"; + + shader.MainFunctionBody() + << "let ix = local_idx;\n" + << "let iy = global_idx / workgroup_size_x;\n" + << "let hidden_size_vectorized: u32 = uniforms.hidden_size / uniforms.components;\n" + << "var stride = hidden_size_vectorized / workgroup_size_x;\n" + << "let offset = ix * stride + iy * hidden_size_vectorized;\n" + << "let offset1d = stride * ix;\n" + << "if (ix == workgroup_size_x - 1) {\n" + << " stride = hidden_size_vectorized - stride * ix;\n" + << "}\n" + << "for (var i: u32 = 0; i < stride; i++) {\n" + << " let skip_value = skip[offset + i];\n" + << " let input_value = x[offset + i];\n" + << " let value = input_value + skip_value" << bias << ";\n" + << " output[offset + i] = value;\n" + << input_skip_bias_sum + << " let f32_value = f32_val_t(value);\n" + << " sum_shared[ix] += f32_value;\n" + << " sum_squared_shared[ix] += f32_value * f32_value;\n" + << "}\n" + << "workgroupBarrier();\n" + << "var reduce_size : u32 = workgroup_size_x;\n" + << "for (var curr_size = reduce_size >> 1; curr_size > 0; curr_size = reduce_size >> 1) {\n" + << " reduce_size = curr_size + (reduce_size & 1);\n" + << " if (ix < curr_size) {\n" + << " sum_shared[ix] += sum_shared[ix + reduce_size];\n" + << " sum_squared_shared[ix] += sum_squared_shared[ix + reduce_size];\n" + << " }\n" + << " workgroupBarrier();\n" + << "}\n" + << "let sum = sum_shared[0];\n" + << "let square_sum = sum_squared_shared[0];\n" + << "let mean = " << SumVector("sum", components) << " / f32(uniforms.hidden_size);\n" + << "let inv_std_dev = inverseSqrt(" << SumVector("square_sum", components) << " / f32(uniforms.hidden_size) " << simpl1 << "+ uniforms.epsilon);\n" + << "for (var i: u32 = 0; i < stride; i++) {\n" + << " output[offset + i] = (output[offset + i] " << simpl2 << ") * x_element_t(inv_std_dev) * gamma[offset1d + i]" << beta << ";\n" + << "};\n"; + } return Status::OK(); } @@ -100,14 +156,15 @@ Status SkipLayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeCo return Status::OK(); } - const bool is_fp16 = x->GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16; const uint32_t hidden_size = onnxruntime::narrow(x_shape[x_shape.NumDimensions() - 1]); const int components = GetMaxComponents(hidden_size); const bool has_input_skip_bias_sum = input_skip_bias_sum != nullptr; + const uint32_t norm_count = onnxruntime::narrow(x_shape.SizeToDimension(x_shape.NumDimensions() - 1)); + const bool split_hidden_dim = hidden_size % 512 == 0 && norm_count == 1; - SkipLayerNormProgram program{beta != nullptr, bias != nullptr, epsilon_, hidden_size, has_input_skip_bias_sum, is_fp16, simplified}; + SkipLayerNormProgram program{beta != nullptr, bias != nullptr, epsilon_, hidden_size, has_input_skip_bias_sum, simplified, split_hidden_dim}; program - .CacheHint(simplified, has_input_skip_bias_sum) + .CacheHint(simplified, has_input_skip_bias_sum, split_hidden_dim) .AddInputs({{x, ProgramTensorMetadataDependency::Type, components}}) .AddInputs({{skip, ProgramTensorMetadataDependency::Type, components}}) .AddInputs({{gamma, ProgramTensorMetadataDependency::Type, components}}) @@ -123,6 +180,13 @@ Status SkipLayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeCo {static_cast(epsilon_)}, }); + if (split_hidden_dim) { + const uint32_t workgroup_size_x = 128; + const uint32_t dispatch_size_x = (has_input_skip_bias_sum ? 2 : 1) * hidden_size / (workgroup_size_x * components); + program.SetDispatchGroupSize(dispatch_size_x, 1, 1) + .SetWorkgroupSize(workgroup_size_x); + } + if (beta != nullptr) { program.AddInput({beta, ProgramTensorMetadataDependency::Type, components}); } diff --git a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.h b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.h index 03de1a4b568b9..73f02f0ad8ec0 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.h +++ b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.h @@ -15,7 +15,7 @@ using onnxruntime::webgpu::ComputeContext; class SkipLayerNormProgram final : public Program { public: - SkipLayerNormProgram(bool hasBeta, bool hasBias, float epsilon, uint32_t hidden_size, bool has_input_skip_bias_sum, bool is_fp16, bool simplified) : Program{"SkipLayerNorm"} { + SkipLayerNormProgram(bool hasBeta, bool hasBias, float epsilon, uint32_t hidden_size, bool has_input_skip_bias_sum, bool simplified, bool split_hidden_dim) : Program{"SkipLayerNorm"} { epsilon_ = epsilon; hasBeta_ = hasBeta; hasBias_ = hasBias; @@ -23,7 +23,7 @@ class SkipLayerNormProgram final : public Program { hidden_size_ = hidden_size; has_input_skip_bias_sum_ = has_input_skip_bias_sum; simplified_ = simplified; - is_fp16_ = is_fp16; + split_hidden_dim_ = split_hidden_dim; } Status GenerateShaderCode(ShaderHelper& sh) const override; @@ -39,8 +39,8 @@ class SkipLayerNormProgram final : public Program { float epsilon_; uint32_t hidden_size_; bool has_input_skip_bias_sum_; - bool is_fp16_; bool simplified_; + bool split_hidden_dim_; }; template From d7a38a57efc7bc0716c88114e914963fe03434dc Mon Sep 17 00:00:00 2001 From: Jagadish Krishnamoorthy Date: Tue, 8 Apr 2025 12:13:21 -0700 Subject: [PATCH 254/266] ROCm: Remove -Wno-interference-size compiler flag (#24326) hipClang does not support -Wno-interference-size. Hence remove the option to avoid build error. --- cmake/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index b81df151562dc..b8c9abcf344e5 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1267,6 +1267,7 @@ function(onnxruntime_set_compile_flags target_name) # Unsupported by Clang 18 yet. list(REMOVE_ITEM ORT_HIP_WARNING_FLAGS -Wno-dangling-reference) + list(REMOVE_ITEM ORT_HIP_WARNING_FLAGS -Wno-interference-size) # float16.h:90:12: error: ‘tmp’ is used uninitialized list(APPEND ORT_HIP_WARNING_FLAGS -Wno-uninitialized) list(APPEND ORT_HIP_WARNING_FLAGS -Wno-deprecated-copy) From 39e585ff2bf8c91739424aacabbab027f4d9aa17 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 8 Apr 2025 13:17:41 -0700 Subject: [PATCH 255/266] [web] revise flag `ort.env.wasm.simd` (#24314) ### Description This PR revised the flag `ort.env.wasm.simd` to enhance its usage so that more use scenarios are covered. - Allow setting to `false` explicitly to disable SIMD checking. resolves #24292 (@Eldow) - Allow setting to `'relaxed'` to enable Relaxed SIMD checking. Relaxed SIMD is introduced first in #22794 (@jing-bao) - Behavior is not changed when not setting (ie. `undefined`) or setting to `true` - Added a warning message when setting to unknown value, and reset to `false` in this case --- js/common/lib/env.ts | 16 +++++++++----- js/web/lib/backend-wasm.ts | 7 ++++--- js/web/lib/wasm/wasm-factory.ts | 37 ++++++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/js/common/lib/env.ts b/js/common/lib/env.ts index d6d9f7fa48790..112c8a1f78851 100644 --- a/js/common/lib/env.ts +++ b/js/common/lib/env.ts @@ -41,16 +41,22 @@ export declare namespace Env { numThreads?: number; /** - * set or get a boolean value indicating whether to enable SIMD. If set to false, SIMD will be forcely disabled. + * set a value indicating whether to enable SIMD. + * + * ONNX Runtime will perform feature detection based on the value of this property. Specifically, when the value is + * set to: + * - `undefined`, `true` or `"fixed"`: will check availability of Fixed-width SIMD. + * - `"relaxed"`: will check availability of Relaxed SIMD. + * - `false`: will not perform SIMD feature checking. + * + * Setting this property does not make ONNX Runtime to switch to the corresponding runtime automatically. User need + * to set `wasmPaths` or `wasmBinary` property to load the corresponding runtime. * * This setting is available only when WebAssembly SIMD feature is available in current context. * * @defaultValue `true` - * - * @deprecated This property is deprecated. Since SIMD is supported by all major JavaScript engines, non-SIMD - * build is no longer provided. This property will be removed in future release. */ - simd?: boolean; + simd?: boolean | 'fixed' | 'relaxed'; /** * set or get a boolean value indicating whether to enable trace. diff --git a/js/web/lib/backend-wasm.ts b/js/web/lib/backend-wasm.ts index 5e5f4804aed92..fe8bfaa188ea9 100644 --- a/js/web/lib/backend-wasm.ts +++ b/js/web/lib/backend-wasm.ts @@ -17,12 +17,13 @@ export const initializeFlags = (): void => { env.wasm.initTimeout = 0; } - if (env.wasm.simd === false) { + const simd = env.wasm.simd; + if (typeof simd !== 'boolean' && simd !== undefined && simd !== 'fixed' && simd !== 'relaxed') { // eslint-disable-next-line no-console console.warn( - 'Deprecated property "env.wasm.simd" is set to false. ' + - 'non-SIMD build is no longer provided, and this setting will be ignored.', + `Property "env.wasm.simd" is set to unknown value "${simd}". Reset it to \`false\` and ignore SIMD feature checking.`, ); + env.wasm.simd = false; } if (typeof env.wasm.proxy !== 'boolean') { diff --git a/js/web/lib/wasm/wasm-factory.ts b/js/web/lib/wasm/wasm-factory.ts index 0f49d25040409..23eb2f0978feb 100644 --- a/js/web/lib/wasm/wasm-factory.ts +++ b/js/web/lib/wasm/wasm-factory.ts @@ -64,6 +64,34 @@ const isSimdSupported = (): boolean => { } }; +const isRelaxedSimdSupported = (): boolean => { + try { + // Test for WebAssembly Relaxed SIMD capability (for both browsers and Node.js) + // This typed array is a WebAssembly program containing Relaxed SIMD instructions. + + // The binary data is generated from the following code by wat2wasm: + // (module + // (func (result v128) + // i32.const 1 + // i8x16.splat + // i32.const 2 + // i8x16.splat + // i32.const 3 + // i8x16.splat + // i32x4.relaxed_dot_i8x16_i7x16_add_s + // ) + // ) + return WebAssembly.validate( + new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 19, 1, 17, 0, 65, 1, 253, 15, 65, 2, 253, + 15, 65, 3, 253, 15, 253, 147, 2, 11, + ]), + ); + } catch (e) { + return false; + } +}; + export const initializeWebAssembly = async (flags: Env.WebAssemblyFlags): Promise => { if (initialized) { return Promise.resolve(); @@ -82,7 +110,14 @@ export const initializeWebAssembly = async (flags: Env.WebAssemblyFlags): Promis let numThreads = flags.numThreads!; // ensure SIMD is supported - if (!isSimdSupported()) { + if (flags.simd === false) { + // skip SIMD feature checking as it is disabled explicitly by user + } else if (flags.simd === 'relaxed') { + // check if relaxed SIMD is supported + if (!isRelaxedSimdSupported()) { + throw new Error('Relaxed WebAssembly SIMD is not supported in the current environment.'); + } + } else if (!isSimdSupported()) { throw new Error('WebAssembly SIMD is not supported in the current environment.'); } From 311f77190f67edcaab330f3e26d7a48fc7827a8b Mon Sep 17 00:00:00 2001 From: amarin16 <91211819+amarin16@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:07:54 -0800 Subject: [PATCH 256/266] Cherry-picks into rel-1.21.0 (#23846) Cherry-pick the following changes into [rel-1.21.0](https://github.com/microsoft/onnxruntime/tree/rel-1.21.0). - (#23791) - (#23710) - (#23789) - (#23829) --------- Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com> Co-authored-by: Yifan Li <109183385+yf711@users.noreply.github.com> Co-authored-by: Ankit Maheshkar Co-authored-by: n1harika Co-authored-by: Changming Sun --- cmake/external/emsdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/external/emsdk b/cmake/external/emsdk index 074211759c17c..127ce42cd5f0a 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit 074211759c17c646164d3271ca1d155cc174f78e +Subproject commit 127ce42cd5f0aabe2d9b5d636041ccef7c66d165 From 5f2d93b1c98a839b1fde89aa3c2dac5ea14c2ff9 Mon Sep 17 00:00:00 2001 From: jatinwadhwa921 <110383850+jatinwadhwa921@users.noreply.github.com> Date: Fri, 28 Feb 2025 15:15:30 +0530 Subject: [PATCH 257/266] [OVEP] Config 1 Commits --- .../providers/openvino/backend_manager.cc | 1 + .../core/providers/openvino/backend_utils.cc | 4 +- .../core/providers/openvino/backend_utils.h | 2 +- .../openvino/backends/basic_backend.cc | 43 +++-- .../openvino/openvino_execution_provider.cc | 60 ++++--- .../openvino/openvino_parser_utils.cc | 120 +++++++++++++ .../openvino/openvino_parser_utils.h | 22 +++ .../openvino/openvino_provider_factory.cc | 162 +++++++----------- .../core/providers/openvino/ov_allocator.cc | 29 ++-- .../core/providers/openvino/ov_allocator.h | 5 + .../core/providers/openvino/ov_interface.cc | 42 ++++- .../core/providers/openvino/ov_interface.h | 5 +- .../openvino/ov_versions/data_ops.cc | 3 +- .../qdq_transformations/qdq_stripping.cc | 11 +- .../core/session/provider_bridge_ort.cc | 2 +- .../test/python/onnxruntime_test_python.py | 4 +- .../openvino_wrapper.cc | 2 +- 17 files changed, 345 insertions(+), 172 deletions(-) create mode 100644 onnxruntime/core/providers/openvino/openvino_parser_utils.cc create mode 100644 onnxruntime/core/providers/openvino/openvino_parser_utils.h diff --git a/onnxruntime/core/providers/openvino/backend_manager.cc b/onnxruntime/core/providers/openvino/backend_manager.cc index 2a842b8a1eca8..1ed5ad8a56fd5 100644 --- a/onnxruntime/core/providers/openvino/backend_manager.cc +++ b/onnxruntime/core/providers/openvino/backend_manager.cc @@ -331,6 +331,7 @@ static void DumpOpenVINOEPModel(const std::filesystem::path& onnx_model_path_nam if (dash != std::string::npos) { auto new_name = model_name.stem().string() + subgraph_name.substr(dash, std::string::npos); model_name.replace_filename(new_name); + model_name.replace_extension(".onnx"); } std::fstream dump(model_name, std::ios::out | std::ios::trunc | std::ios::binary); diff --git a/onnxruntime/core/providers/openvino/backend_utils.cc b/onnxruntime/core/providers/openvino/backend_utils.cc index 255154b8788ad..2ee5e9ec3e3a9 100644 --- a/onnxruntime/core/providers/openvino/backend_utils.cc +++ b/onnxruntime/core/providers/openvino/backend_utils.cc @@ -137,14 +137,14 @@ bool IsCILogEnabled() { } std::shared_ptr -CreateOVModel(const std::string model, +CreateOVModel(std::string&& model, const SessionContext& session_context, std::map>& const_outputs_map) { if (IsCILogEnabled()) { std::cout << "CreateNgraphFunc" << std::endl; } try { - auto ov_model = OVCore::Get()->ReadModel(model, session_context.onnx_model_path_name.string()); + auto ov_model = OVCore::Get()->ReadModel(std::move(model), session_context.onnx_model_path_name.string()); // Check for Constant Folding if ((session_context.device_type != "NPU") && !session_context.is_wholly_supported_graph) { diff --git a/onnxruntime/core/providers/openvino/backend_utils.h b/onnxruntime/core/providers/openvino/backend_utils.h index a4e6fc0828f79..f13b1b05ced67 100644 --- a/onnxruntime/core/providers/openvino/backend_utils.h +++ b/onnxruntime/core/providers/openvino/backend_utils.h @@ -62,7 +62,7 @@ void FillOutputBlob(OVTensorPtr outputBlob, Ort::UnownedValue& output_tensor, size_t batch_slice_idx); std::shared_ptr -CreateOVModel(const std::string model, +CreateOVModel(std::string&& model, const SessionContext& session_context, std::map>& const_outputs_map); diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 44b811e6af2c0..04297de038cd3 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -2,6 +2,8 @@ // Licensed under the MIT License #include +#include + #include #include #include @@ -69,14 +71,11 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr subgraph_context_.subgraph_name); model_stream.reset(); // Delete stream after it is no longer needed } else { - std::shared_ptr ov_model; - { - const std::string model = model_proto->SerializeAsString(); - if (!subgraph_context.has_dynamic_input_shape) { - delete model_proto.release(); - } - ov_model = CreateOVModel(model, session_context_, const_outputs_map_); + std::string model = model_proto->SerializeAsString(); + if (!subgraph_context.has_dynamic_input_shape) { + model_proto.reset() } + auto ov_model = CreateOVModel(std::move(model), session_context_, const_outputs_map_); LOGS_DEFAULT(INFO) << log_tag << "IO Buffering Enabled"; exe_network_ = OVCore::Get()->CompileModel( ov_model, remote_context_, subgraph_context_.subgraph_name); @@ -108,14 +107,11 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr subgraph_context_.subgraph_name); } else { // For all other types use ov::ov_core read_model() to generate OV IR // followed by ov::ov_core compile_model() - std::shared_ptr ov_model; - { - const std::string model = model_proto->SerializeAsString(); - if (!subgraph_context.has_dynamic_input_shape) { - delete model_proto.release(); - } - ov_model = CreateOVModel(std::move(model), session_context_, const_outputs_map_); + std::string model = model_proto->SerializeAsString(); + if (!subgraph_context.has_dynamic_input_shape) { + model_proto.reset(); } + auto ov_model = CreateOVModel(std::move(model), session_context_, const_outputs_map_); exe_network_ = OVCore::Get()->CompileModel( ov_model, hw_target, device_config, subgraph_context_.subgraph_name); } @@ -164,10 +160,8 @@ void BasicBackend::PopulateConfigValue(ov::AnyMap& device_config) { if (session_context_.precision.find("FP32") != std::string::npos) { device_config.emplace(ov::hint::inference_precision("f32")); } - if (session_context_.precision.find("ACCURACY") != std::string::npos && - session_context_.device_type.find("GPU") != std::string::npos) { + if (session_context_.precision.find("ACCURACY") != std::string::npos) { if (session_context_.OpenVINO_Version.at(0) >= 2024) { - device_config.emplace(ov::hint::inference_precision(ov::element::undefined)); device_config.emplace(ov::hint::execution_mode(ov::hint::ExecutionMode::ACCURACY)); } else { if (!subgraph_context_.model_precision.empty()) @@ -230,6 +224,15 @@ void BasicBackend::PopulateConfigValue(ov::AnyMap& device_config) { } } } + auto find_device_type_mode = [&](const std::string& device_type) -> std::string { + std::string device_mode = ""; + auto delimiter_pos = device_type.find(':'); + if (delimiter_pos != std::string::npos) { + std::stringstream str_stream(device_type.substr(0, delimiter_pos)); + std::getline(str_stream, device_mode, ','); + } + return device_mode; + }; // Parse device types like "AUTO:CPU,GPU" and extract individual devices auto parse_individual_devices = [&](const std::string& device_type) -> std::vector { @@ -278,8 +281,14 @@ void BasicBackend::PopulateConfigValue(ov::AnyMap& device_config) { if (session_context_.device_type.find("AUTO") == 0 || session_context_.device_type.find("HETERO") == 0 || session_context_.device_type.find("MULTI") == 0) { + //// Parse to get the device mode (e.g., "AUTO:CPU,GPU" -> "AUTO") + std::unordered_set supported_mode = {"AUTO", "HETERO", "MULTI"}; + auto device_mode = find_device_type_mode(session_context_.device_type); + ORT_ENFORCE(supported_mode.find(device_mode)!=supported_mode.end(), " Invalid device mode is passed : " , session_context_.device_type); // Parse individual devices (e.g., "AUTO:CPU,GPU" -> ["CPU", "GPU"]) auto individual_devices = parse_individual_devices(session_context_.device_type); + if (!device_mode.empty()) individual_devices.emplace_back(device_mode); + // Set properties only for individual devices (e.g., "CPU", "GPU") for (const std::string& device : individual_devices) { if (target_config.count(device)) { diff --git a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc index 6482a07ee92bc..da12d7f27d61a 100644 --- a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc +++ b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc @@ -62,36 +62,50 @@ OpenVINOExecutionProvider::OpenVINOExecutionProvider(const ProviderInfo& info, s // to check if target device is available // using OVCore capability GetAvailableDevices to fetch list of devices plugged in if (info.cache_dir.empty()) { - bool device_found = false; - std::vector available_devices = OVCore::Get()->GetAvailableDevices(); + bool all_devices_found = false; // Checking for device_type configuration if (info.device_type != "") { - if (info.device_type.find("HETERO") != std::string::npos || - info.device_type.find("MULTI") != std::string::npos || - info.device_type.find("AUTO") != std::string::npos) { - device_found = true; + std::vector devices_to_check; + if (info.device_type.find("HETERO:") == 0 || + info.device_type.find("MULTI:") == 0 || + info.device_type.find("BATCH:") == 0 || + info.device_type.find("AUTO:") == 0) { + auto delimit = info.device_type.find(":"); + const auto& devices = info.device_type.substr(delimit + 1); + devices_to_check = split(devices, ','); } else { - for (const std::string& device : available_devices) { - if (device.rfind(info.device_type, 0) == 0) { - if (info.device_type.find("GPU") != std::string::npos && (info.precision == "FP32" || - info.precision == "FP16" || - info.precision == "ACCURACY")) { - device_found = true; - break; - } - if (info.device_type == "CPU" && (info.precision == "FP32")) { - device_found = true; - break; - } - if (info.device_type.find("NPU") != std::string::npos) { - device_found = true; - break; - } + devices_to_check.push_back(info.device_type); + } + + // Re-initialize before loop + all_devices_found = true; + for (const auto& device : devices_to_check) { + bool device_found = false; + std::string device_prefix = device; + int device_idx = 0; + // Get the index and remove the index from device_prefix + if (auto delimit = device_prefix.find("."); delimit != std::string::npos) { + try { + device_idx = std::stoi(device_prefix.substr(delimit + 1)); + } catch (std::exception& ex) { + ORT_THROW("[ERROR] [OpenVINO] Wrong index in specified device - " + device + " :", ex.what()); } + device_prefix = device_prefix.substr(0, delimit); + } + std::vector available_devices = OVCore::Get()->GetAvailableDevices(device_prefix); + // If idx is 0, maybe index is not set (e.g. GPU) + // Then the device is found if we have at least one device of the type + if (device_idx == 0 && available_devices.size() >= 1) { + device_found = true; + } else { + // Find full device (e.g GPU.1) in the list + if (std::find(std::begin(available_devices), std::end(available_devices), device) != std::end(available_devices)) + device_found = true; } + all_devices_found = all_devices_found && device_found; } } - if (!device_found) { + if (!all_devices_found) { ORT_THROW("[ERROR] [OpenVINO] Specified device - " + info.device_type + " is not available"); } } diff --git a/onnxruntime/core/providers/openvino/openvino_parser_utils.cc b/onnxruntime/core/providers/openvino/openvino_parser_utils.cc new file mode 100644 index 0000000000000..067076b1f84f2 --- /dev/null +++ b/onnxruntime/core/providers/openvino/openvino_parser_utils.cc @@ -0,0 +1,120 @@ +#include +#include "core/providers/openvino/openvino_parser_utils.h" +#include "core/providers/shared_library/provider_api.h" + +namespace onnxruntime { +namespace openvino_ep { + +std::string OpenVINOParserUtils::ParsePrecision(const ProviderOptions& provider_options, + std::string& device_type, + const std::string& option_name) { + using DeviceName = std::string; + using DefaultValue = std::string; + using ValidValues = std::vector; + using DefaultAndValidPair = std::pair; + using ParserHelper = std::unordered_map; + // {Device prefix, {Default precision, {Supported precisions}}} + ParserHelper helper = { + {"GPU", {"FP16", {"FP16", "FP32", "ACCURACY"}}}, + {"NPU", {"FP16", {"FP16", "ACCURACY"}}}, + {"CPU", {"FP32", {"FP32", "ACCURACY"}}}, + }; + + // If we have multiple device configuration, request precision from user and check it + if ((device_type.find("HETERO:") == 0) || + (device_type.find("MULTI:") == 0) || + (device_type.find("BATCH:") == 0) || + (device_type.find("AUTO:") == 0)) { + if (!provider_options.contains(option_name)) { + LOGS_DEFAULT(INFO) << "[OpenVINO] Precision is not set. Using default OpenVINO precision for " + device_type + ". \n"; + return ""; + } else { + std::unordered_set supported_precisions = {"FP16", "FP32", "ACCURACY"}; + std::string precision = provider_options.at(option_name); + if (supported_precisions.contains(precision)) { + return precision; + } else { + ORT_THROW("[ERROR] [OpenVINO] Unsupported precision for the ", device_type, " device. Device supports only FP16, FP32, ACCURACY.\n"); + } + } + } + + // Deprecated device specification (CPU_FP32, GPU.0_FP32, etc.) + if (auto delimit = device_type.find("_"); delimit != std::string::npos) { + if (provider_options.contains(option_name)) { + ORT_THROW("[ERROR] [OpenVINO] Precision is specified twice, please remove the _precision suffix from device name and only set the precision separately.\n"); + } + LOGS_DEFAULT(WARNING) << "[OpenVINO] Selected 'device_type' " + device_type + " is deprecated. \n" + << "Update the 'device_type' to specified types 'CPU', 'GPU', 'GPU.0', " + << "'GPU.1', 'NPU' or from" + << " HETERO/MULTI/AUTO/BATCH options and set 'precision' separately. \n"; + std::string precision = device_type.substr(delimit + 1); + // Device type is updated in-place + device_type = device_type.substr(0, delimit); + // We have to remove the index (.0, .1, etc.) to use device as key for helper + std::string device_prefix = device_type; + if (auto dot_delimit = device_prefix.find("."); dot_delimit != std::string::npos) { + device_prefix = device_prefix.substr(0, dot_delimit); + } + + if (!helper.contains(device_prefix)) { + ORT_THROW("[ERROR] [OpenVINO] Selected 'device_type' " + device_type + " is not supported with precision suffix. \n"); + } + const auto& valid_values = helper[device_prefix].second; + if (std::find(std::begin(valid_values), std::end(valid_values), precision) != std::end(valid_values)) { + return precision; + } else { + auto value_iter = valid_values.begin(); + std::string valid_values_joined = *value_iter; + // Append 2nd and up, if only one then ++value_iter is same as end() + for (++value_iter; value_iter != valid_values.end(); ++value_iter) { + valid_values_joined += ", " + *value_iter; + } + + ORT_THROW("[ERROR] [OpenVINO] Unsupported inference precision is selected. ", device_type, " only supports ", valid_values_joined, ".\n"); + } + } + + // Deprecated devices are already handled above + // We have to remove the index (.0, .1, etc.) to use device as key for helper + auto device_prefix = device_type; + if (auto dot_delimit = device_prefix.find("."); dot_delimit != std::string::npos) { + device_prefix = device_prefix.substr(0, dot_delimit); + } + + if (provider_options.contains(option_name)) { + std::string precision = provider_options.at(option_name); + + if (helper.contains(device_prefix)) { + auto const& valid_values = helper[device_prefix].second; + if (std::find(std::begin(valid_values), std::end(valid_values), precision) != std::end(valid_values)) { + return precision; // Return precision selected if valid + } else { + auto value_iter = valid_values.begin(); + std::string valid_values_joined = *value_iter; + // Append 2nd and up, if only one then ++value_iter is same as end() + for (++value_iter; value_iter != valid_values.end(); ++value_iter) { + valid_values_joined += ", " + *value_iter; + } + + ORT_THROW("[ERROR] [OpenVINO] Unsupported inference precision is selected. ", device_type, " only supports ", valid_values_joined, ".\n"); + } + } else { + // Not found in helper - custom device, return as is + return precision; + } + } else { + // Precision not set + if (helper.contains(device_prefix)) { + // If found in helper - set the default + return helper[device_prefix].first; + } else { + // Not found in helper - custom device - default precision + LOGS_DEFAULT(INFO) << "[OpenVINO] Precision is not set. Using default OpenVINO precision for " + device_type + ". \n"; + return ""; + } + } +} + +} // namespace openvino_ep +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/openvino_parser_utils.h b/onnxruntime/core/providers/openvino/openvino_parser_utils.h new file mode 100644 index 0000000000000..3e23c9e788463 --- /dev/null +++ b/onnxruntime/core/providers/openvino/openvino_parser_utils.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "core/framework/provider_options.h" + +namespace onnxruntime { +namespace openvino_ep { + +class OpenVINOParserUtils { + public: + static std::string ParsePrecision(const ProviderOptions& provider_options, + std::string& device_type, + const std::string& option_name); +}; + +} // namespace openvino_ep +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc index 87a1dda9a5db1..8005889af23ea 100644 --- a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc +++ b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc @@ -2,6 +2,8 @@ // Licensed under the MIT License #include +#include + #include #include "core/providers/shared_library/provider_api.h" #include "core/providers/openvino/openvino_provider_factory.h" @@ -11,6 +13,7 @@ #include "core/providers/openvino/backend_utils.h" #include "core/session/onnxruntime_session_options_config_keys.h" #include "nlohmann/json.hpp" +#include "core/providers/openvino/openvino_parser_utils.h" namespace onnxruntime { namespace openvino_ep { @@ -55,115 +58,80 @@ bool ParseBooleanOption(const ProviderOptions& provider_options, std::string opt } std::string ParseDeviceType(std::shared_ptr ov_core, const ProviderOptions& provider_options, std::string option_name) { - const std::vector ov_available_devices = ov_core->GetAvailableDevices(); - - std::set ov_supported_device_types = {"CPU", "GPU", - "GPU.0", "GPU.1", "NPU"}; - std::set deprecated_device_types = {"CPU_FP32", "GPU_FP32", - "GPU.0_FP32", "GPU.1_FP32", "GPU_FP16", - "GPU.0_FP16", "GPU.1_FP16"}; - - // Expand set of supported device with OV devices - ov_supported_device_types.insert(ov_available_devices.begin(), ov_available_devices.end()); + // This function normally does not check if the selected device is available, but does some sanity checks + // Only if the device is not standard, then availability is checked. + // Availability is checked for the selected device in the OpenVINOExecutionProvider constructor + std::vector devices_to_check; + std::string selected_device; if (provider_options.contains(option_name)) { - const auto& selected_device = provider_options.at("device_type"); - - if (deprecated_device_types.contains(selected_device)) { - // Deprecated device and precision is handled together at ParsePrecision - return selected_device; - } - - if (!((ov_supported_device_types.contains(selected_device)) || - (selected_device.find("HETERO:") == 0) || - (selected_device.find("MULTI:") == 0) || - (selected_device.find("AUTO:") == 0))) { - ORT_THROW( - "[ERROR] [OpenVINO] You have selected wrong configuration value for the key 'device_type'. " - "Select from 'CPU', 'GPU', 'NPU', 'GPU.x' where x = 0,1,2 and so on or from" - " HETERO/MULTI/AUTO options available. \n"); + selected_device = provider_options.at(option_name); + // If we have multiple device configuration, we need to check all of them + if ((selected_device.find("HETERO:") == 0) || + (selected_device.find("MULTI:") == 0) || + (selected_device.find("BATCH:") == 0) || + (selected_device.find("AUTO:") == 0)) { + auto delimit = selected_device.find(":"); + const auto& devices = selected_device.substr(delimit + 1); + devices_to_check = split(devices, ','); + } else { + devices_to_check.push_back(selected_device); } - LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Choosing Device: " << selected_device; - return selected_device; } else { - std::string default_device; - // Take default behavior from project configuration #if defined OPENVINO_CONFIG_CPU - default_device = "CPU"; + selected_device = "CPU"; + LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Choosing Device: " << selected_device; + return selected_device; #elif defined OPENVINO_CONFIG_GPU - default_device = "GPU"; + selected_device = "GPU"; + LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Choosing Device: " << selected_device; + return selected_device; #elif defined OPENVINO_CONFIG_NPU - default_device = "NPU"; + selected_device = "NPU"; + LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Choosing Device: " << selected_device; + return selected_device; #elif defined OPENVINO_CONFIG_HETERO || defined OPENVINO_CONFIG_MULTI || defined OPENVINO_CONFIG_AUTO - default_device = DEVICE_NAME; - - // Validate that devices passed are valid - int delimit = device_type.find(":"); - const auto& devices = device_type.substr(delimit + 1); - auto device_list = split(devices, ','); - for (const auto& device : devices) { - if (!ov_supported_device_types.contains(device)) { - ORT_THROW("[ERROR] [OpenVINO] Invalid device selected: ", device); - } - } -#endif + selected_device = DEVICE_NAME; - LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Choosing Device: " << default_device; - return default_device; + // Add sub-devices to check-list + int delimit = selected_device.find(":"); + const auto& devices = selected_device.substr(delimit + 1); + devices_to_check = split(devices, ','); +#endif } -} -// Depends on ProviderOptions. -std::string ParsePrecision(const ProviderOptions& provider_options, std::string& device_type, const std::string& option_name) { - using DeviceName = std::string; - using DefaultValue = std::string; - using ValidValues = std::list; - using foo = std::pair; - using ParserHelper = std::map; - ParserHelper helper = { - {"GPU", {"FP16", {"FP16", "FP32"}}}, - {"NPU", {"FP16", {"FP16"}}}, - {"CPU", {"FP32", {"FP32"}}}, - }; - - std::set deprecated_device_types = {"CPU_FP32", "GPU_FP32", - "GPU.0_FP32", "GPU.1_FP32", "GPU_FP16", - "GPU.0_FP16", "GPU.1_FP16"}; - - if (provider_options.contains(option_name)) { - // Start by checking if the device_type is a normal valid one - if (helper.contains(device_type)) { - auto const& valid_values = helper[device_type].second; - const auto& precision = provider_options.at(option_name); - if (precision == "ACCURACY") { - return valid_values.back(); // Return highest supported precision - } else { - if (std::find(valid_values.begin(), valid_values.end(), precision) != valid_values.end()) { - return precision; // Return precision selected if valid - } else { - auto value_iter = valid_values.begin(); - std::string valid_values_joined = *value_iter; - // Append 2nd and up, if only one then ++value_iter is same as end() - for (++value_iter; value_iter != valid_values.end(); ++value_iter) { - valid_values_joined += ", " + *value_iter; - } - - ORT_THROW("[ERROR] [OpenVINO] Unsupported inference precision is selected. ", device_type, " only supports", valid_values_joined, ".\n"); - } + // Devices considered to be supported by default + std::unordered_set supported_device_types = {"CPU", "GPU", "NPU"}; + for (auto device : devices_to_check) { + // Check deprecated device format (CPU_FP32, GPU.0_FP16, etc.) and remove the suffix in place + // Suffix will be parsed in ParsePrecision + if (auto delimit = device.find("_"); delimit != std::string::npos) { + device = device.substr(0, delimit); + } + // Just the device name without .0, .1, etc. suffix + auto device_prefix = device; + // Check if device index is appended (.0, .1, etc.), if so, remove it + if (auto delimit = device_prefix.find("."); delimit != std::string::npos) { + device_prefix = device_prefix.substr(0, delimit); + if (device_prefix == "CPU") + ORT_THROW("[ERROR] [OpenVINO] CPU device is only supported without index, CPU.x is illegal.\n"); + } + // Only device is not supported by default (some exotic device), check if it's available + if (!supported_device_types.contains(device_prefix)) { + std::vector available_devices = ov_core->GetAvailableDevices(); + // Here we need to find the full device name (with .idx, but without _precision) + if (std::find(std::begin(available_devices), std::end(available_devices), device) == std::end(available_devices)) { + ORT_THROW( + "[ERROR] [OpenVINO] You have selected wrong configuration value for the key 'device_type'. " + "Select from 'CPU', 'GPU', 'NPU', 'GPU.x' where x = 0,1,2 and so on or from" + " HETERO/MULTI/AUTO/BATCH options available. \n"); } - } else if (deprecated_device_types.contains(device_type)) { - LOGS_DEFAULT(WARNING) << "[OpenVINO] Selected 'device_type' " + device_type + " is deprecated. \n" - << "Update the 'device_type' to specified types 'CPU', 'GPU', 'GPU.0', " - << "'GPU.1', 'NPU' or from" - << " HETERO/MULTI/AUTO options and set 'precision' separately. \n"; - auto delimit = device_type.find("_"); - device_type = device_type.substr(0, delimit); - return device_type.substr(delimit + 1); } } - // Return default - return helper[device_type].first; + // All devices have passed the check, return selected device + LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Choosing Device: " << selected_device; + return selected_device; } void ParseProviderOptions([[maybe_unused]] ProviderInfo& result, [[maybe_unused]] const ProviderOptions& config_options) {} @@ -227,7 +195,7 @@ struct OpenVINO_Provider : Provider { pi.cache_dir = provider_options.at("cache_dir"); } - pi.precision = ParsePrecision(provider_options, pi.device_type, "precision"); + pi.precision = OpenVINOParserUtils::ParsePrecision(provider_options, pi.device_type, "precision"); if (provider_options.contains("load_config")) { auto parse_config = [&](const std::string& config_str) -> std::map { @@ -249,9 +217,9 @@ struct OpenVINO_Provider : Provider { for (auto& [key, value] : json_config.items()) { ov::AnyMap inner_map; - + std::set valid_ov_devices = {"CPU", "GPU", "NPU", "AUTO", "HETERO", "MULTI"}; // Ensure the key is one of "CPU", "GPU", or "NPU" - if (key != "CPU" && key != "GPU" && key != "NPU") { + if (valid_ov_devices.find(key) == valid_ov_devices.end()) { LOGS_DEFAULT(WARNING) << "Unsupported device key: " << key << ". Skipping entry.\n"; continue; } diff --git a/onnxruntime/core/providers/openvino/ov_allocator.cc b/onnxruntime/core/providers/openvino/ov_allocator.cc index 0e5ff8ff98efb..431f5730c0342 100644 --- a/onnxruntime/core/providers/openvino/ov_allocator.cc +++ b/onnxruntime/core/providers/openvino/ov_allocator.cc @@ -10,12 +10,6 @@ namespace onnxruntime { using namespace openvino_ep; -constexpr size_t default_alignment = 4096; - -static inline size_t align_up(size_t size, size_t pow2_alignment) { - return (size + pow2_alignment - 1) & ~(pow2_alignment - 1); -} - OVRTAllocator::OVRTAllocator(ov::Core& core, OrtDevice::DeviceType device_type, OrtDevice::DeviceId device_id, const char* name) : IAllocator(OrtMemoryInfo(name, OrtAllocatorType::OrtDeviceAllocator, OrtDevice(device_type, OrtDevice::MemType::DEFAULT, device_id), device_id, OrtMemTypeCPUInput)), core_(core) { if (device_type == OrtDevice::NPU) { remote_ctx_ = core_.get_default_context("NPU").as(); @@ -26,16 +20,11 @@ OVRTAllocator::OVRTAllocator(ov::Core& core, OrtDevice::DeviceType device_type, void* OVRTAllocator::Alloc(size_t size) { try { - size_t alloc_size = align_up(size + sizeof(ov::Tensor*) + default_alignment, default_alignment); ov::Tensor* tensor = new ov::Tensor(remote_ctx_.create_host_tensor(ov::element::Type_t::u8, - {alloc_size})); - uintptr_t data_ptr = reinterpret_cast(tensor->data()); - - ov::Tensor** ptr = reinterpret_cast(align_up(data_ptr + sizeof(ov::Tensor*), default_alignment)); - ptr[-1] = tensor; - - return reinterpret_cast(ptr); - + {size})); + std::unique_lock lock(mutex_); + allocated_.insert({tensor->data(), tensor}); + return reinterpret_cast(tensor->data()); } catch (const ov::Exception& e) { ORT_THROW(std::string("Alloc failed: ") + e.what()); } @@ -43,8 +32,14 @@ void* OVRTAllocator::Alloc(size_t size) { void OVRTAllocator::Free(void* p) { try { - ov::Tensor** ptr = reinterpret_cast(p); - delete ptr[-1]; + std::unique_lock lock(mutex_); + auto it = allocated_.find(p); + if (it != allocated_.end()) { + ov::Tensor* tensor = it->second; + allocated_.erase(it); + lock.unlock(); + delete tensor; + } } catch (const ov::Exception& e) { ORT_THROW(std::string("Free failed: ") + e.what()); } diff --git a/onnxruntime/core/providers/openvino/ov_allocator.h b/onnxruntime/core/providers/openvino/ov_allocator.h index 083cfc4d5aed3..f6e87111f47ff 100644 --- a/onnxruntime/core/providers/openvino/ov_allocator.h +++ b/onnxruntime/core/providers/openvino/ov_allocator.h @@ -3,9 +3,12 @@ #ifdef USE_OVEP_NPU_MEMORY #pragma once +#include + #include "core/common/inlined_containers.h" #include "core/framework/allocator.h" #include "openvino/runtime/remote_context.hpp" +#include "core/common/inlined_containers.h" namespace onnxruntime { @@ -18,6 +21,8 @@ class OVRTAllocator : public IAllocator { private: ov::Core& core_; ov::RemoteContext remote_ctx_; + InlinedHashMap allocated_; + std::mutex mutex_; }; } // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index 37f9e1c4e9201..d5d23cf4a11f1 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -46,9 +46,9 @@ void printDebugInfo(const ov::CompiledModel& obj) { } #endif -std::shared_ptr OVCore::ReadModel(const std::string& model, const std::string& model_path) { +std::shared_ptr OVCore::ReadModel(std::string&& model, const std::string& model_path) { try { - std::istringstream modelStringStream(model); + std::istringstream modelStringStream(std::move(model)); std::istream& modelStream = modelStringStream; // Try to load with FrontEndManager ov::frontend::FrontEndManager manager; @@ -164,8 +164,42 @@ OVExeNetwork OVCore::ImportModel(std::shared_ptr model_strea } #endif -std::vector OVCore::GetAvailableDevices() { - auto available_devices = core.get_available_devices(); +std::vector OVCore::GetAvailableDevices() const { + std::vector available_devices = core.get_available_devices(); + return available_devices; +} + +std::vector OVCore::GetAvailableDevices(const std::string& device_type) const { + std::vector available_devices; + std::vector devicesIDs; + // Uses logic from OpenVINO to only return available devices of the specified type (e.g. CPU, NPU or GPU) + try { + devicesIDs = core.get_property(device_type, ov::available_devices); + } catch (const ov::Exception&) { + // plugin is not created by e.g. invalid env + // Empty device list will be returned + } catch (const std::runtime_error&) { + // plugin is not created by e.g. invalid env + // Empty device list will be returned + } catch (const std::exception& ex) { + ORT_THROW("[ERROR] [OpenVINO] An exception is thrown while trying to create the ", + device_type, + " device: ", + ex.what()); + } catch (...) { + ORT_THROW("[ERROR] [OpenVINO] Unknown exception is thrown while trying to create the ", + device_type, + " device"); + } + + if (devicesIDs.size() > 1) { + for (const auto& deviceID : devicesIDs) { + available_devices.push_back(device_type + '.' + deviceID); + } + } else if (!devicesIDs.empty()) { + available_devices.push_back(device_type); + } + return available_devices; } diff --git a/onnxruntime/core/providers/openvino/ov_interface.h b/onnxruntime/core/providers/openvino/ov_interface.h index 0ed51394a6ffa..7e0f3f7d917a9 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.h +++ b/onnxruntime/core/providers/openvino/ov_interface.h @@ -67,7 +67,7 @@ struct OVCore : WeakSingleton { ov::Core core; // OV Interface For Reading Model - std::shared_ptr ReadModel(const std::string& model_stream, const std::string& model_path); + std::shared_ptr ReadModel(std::string&& model_stream, const std::string& model_path); // OV Interface for Compiling OV Model Type OVExeNetwork CompileModel(std::shared_ptr& ie_cnn_network, @@ -92,7 +92,8 @@ struct OVCore : WeakSingleton { OVRemoteContextPtr context, std::string name); #endif - std::vector GetAvailableDevices(); + std::vector GetAvailableDevices() const; + std::vector GetAvailableDevices(const std::string& device_type) const; void SetCache(const std::string& cache_dir_path); void SetStreams(const std::string& device_type, int num_streams); }; diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index f7326642a5544..4e1387d2ef4a9 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -792,7 +792,8 @@ bool DataOps::node_is_supported(const NodeIndex node_idx, bool& has_external_wei if (((device_id_.find("CPU") != std::string::npos) || (device_id_.find("GPU") != std::string::npos)) && ((optype == "Expand") || (optype == "Equal") || (optype == "Slice") || (optype == "Concat") || - (optype == "Shape"))) { + (optype == "Shape") || (optype == "Cast") || + (optype == "Resize"))) { return; } has_unsupported_dimension = true; diff --git a/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc b/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc index a9f6420d6ac3b..effd13abc3e3a 100644 --- a/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc +++ b/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc @@ -346,7 +346,7 @@ static bool CheckQFeedsIntoQuantizedOutput(const NodeUnit& node_unit, auto op_of_quantized_layer = node_unit.Outputs(); for (auto& itr : op_of_quantized_layer) { auto it = graph_op_data_type.find(itr.node_arg.Name()); - if (it != graph_op_data_type.end() && it->second == "tensor(uint8)") { + if (it != graph_op_data_type.end() && (it->second == "tensor(uint8)" || it->second == "tensor(uint16)")) { return true; } } @@ -369,6 +369,11 @@ static bool CheckQRuleSet(const NodeUnit& node_unit, graph_op_data_type[src_graph.GetNodeArg(ops->Name())->Name()] = ops->Type()->data(); } + // check If any quantized node feeds into the src graph output + if (CheckQFeedsIntoQuantizedOutput(node_unit, std::move(graph_op_data_type))) { + return true; + } + // If UInt16 Q, don't keep it if (GetQDQDataType(q_node) == DT_UINT16 || GetQDQDataType(q_node) == DT_INT16) { reason = SkipReason::Int16QDQ; @@ -381,9 +386,7 @@ static bool CheckQRuleSet(const NodeUnit& node_unit, } else if (op_type == "Add") { // Add keeps all Qs return true; - } else if (CheckQFeedsIntoQuantizedOutput(node_unit, std::move(graph_op_data_type))) { - return true; - } else { + } else { // Keep Q of an unsupported Op only if the target that succeeds it is a supported Op in this list return IsNextTargetNodeOfQValid(q_node, &target_node, src_graph, {"Conv", "Add", "MatMul"}, false); } diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 042598535e987..8539394f321bd 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -1992,7 +1992,7 @@ ProviderOptions OrtOpenVINOProviderOptionsToOrtOpenVINOProviderOptionsV2(const O ov_options_converted_map["context"] = context_string.str(); } - ov_options_converted_map["enable_opencl_throttling"] = legacy_ov_options->enable_opencl_throttling; + ov_options_converted_map["enable_opencl_throttling"] = legacy_ov_options->enable_opencl_throttling == 0 ? "true" : "false"; if (legacy_ov_options->enable_dynamic_shapes) { ov_options_converted_map["disable_dynamic_shapes"] = "false"; diff --git a/onnxruntime/test/python/onnxruntime_test_python.py b/onnxruntime/test/python/onnxruntime_test_python.py index 3af6e8ccacfb8..f3ebc92409f77 100644 --- a/onnxruntime/test/python/onnxruntime_test_python.py +++ b/onnxruntime/test/python/onnxruntime_test_python.py @@ -1307,7 +1307,7 @@ def test_session_options_add_external_initializers(self): def test_register_custom_ops_library(self): if sys.platform.startswith("win"): - shared_library = "custom_op_library.dll" + shared_library = os.path.abspath("custom_op_library.dll") if not os.path.exists(shared_library): raise FileNotFoundError(f"Unable to find '{shared_library}'") @@ -1724,7 +1724,7 @@ def test_register_custom_e_ps_library(self): return if sys.platform.startswith("win"): - shared_library = "test_execution_provider.dll" + shared_library = os.path.abspath("test_execution_provider.dll") elif sys.platform.startswith("darwin"): # exclude for macos diff --git a/onnxruntime/test/testdata/custom_op_openvino_wrapper_library/openvino_wrapper.cc b/onnxruntime/test/testdata/custom_op_openvino_wrapper_library/openvino_wrapper.cc index 27d5c59439243..d4ce3320e13ca 100644 --- a/onnxruntime/test/testdata/custom_op_openvino_wrapper_library/openvino_wrapper.cc +++ b/onnxruntime/test/testdata/custom_op_openvino_wrapper_library/openvino_wrapper.cc @@ -35,7 +35,7 @@ static ov::element::Type ConvertONNXToOVType(ONNXTensorElementDataType onnx_type case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: return ov::element::bf16; default: - return ov::element::undefined; + return ov::element::dynamic; } } From 72bf43bc40a63df326d44daed1b5fe461eedc9c6 Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe Date: Tue, 25 Mar 2025 16:58:57 -0800 Subject: [PATCH 258/266] Stateful PoC: Perform stateless -> stateful conversion of ov::Model --- .../providers/openvino/backend_manager.cc | 6 +- .../openvino/backends/basic_backend.cc | 16 +- .../openvino/openvino_provider_factory.cc | 4 +- .../core/providers/openvino/ov_interface.cc | 60 +++- .../openvino/ov_stateful_patch_utils.h | 338 ++++++++++++++++++ 5 files changed, 417 insertions(+), 7 deletions(-) create mode 100644 onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h diff --git a/onnxruntime/core/providers/openvino/backend_manager.cc b/onnxruntime/core/providers/openvino/backend_manager.cc index 1ed5ad8a56fd5..f56a6256395a7 100644 --- a/onnxruntime/core/providers/openvino/backend_manager.cc +++ b/onnxruntime/core/providers/openvino/backend_manager.cc @@ -104,7 +104,8 @@ BackendManager::BackendManager(SessionContext& session_context, subgraph_context_.has_dynamic_input_shape = true; LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Model has symbolic input dims"; if ((session_context_.device_type.find("CPU") != std::string::npos || - session_context_.device_type.find("GPU") != std::string::npos) && + session_context_.device_type.find("GPU") != std::string::npos || + session_context_.device_type.find("NPU") != std::string::npos) && !session_context_.disable_dynamic_shapes) { LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Starting backend initialization. " << "Creating backend Dynamic Shapes"; @@ -474,7 +475,8 @@ void BackendManager::Compute(OrtKernelContext* context) { if (subgraph_context_.has_dynamic_input_shape && !session_context_.disable_dynamic_shapes && (session_context_.device_type.find("CPU") != std::string::npos || - session_context_.device_type.find("GPU") != std::string::npos)) { + session_context_.device_type.find("GPU") != std::string::npos || + session_context_.device_type.find("NPU") != std::string::npos)) { concrete_backend_->Infer(context); } else if (subgraph_context_.has_dynamic_input_shape) { std::vector> tensor_shapes = GetInputTensorShapes(ctx); diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 04297de038cd3..043bced075a43 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -374,6 +374,12 @@ void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferReque } index++; } + + // for the stateful PoC, the ONNX model will have KV cache (past/present) tensors, but + // we internally converted it to stateful, which removed these. So, we just continue here + // to avoid runtime exception. + if (input_name.empty()) continue; + ORT_ENFORCE(!input_name.empty(), log_tag, "Input names mismatch between OpenVINO and ONNX. ", onnx_input_name, " doesn't exist in the list of OpenVINO input tensor names"); @@ -381,7 +387,8 @@ void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferReque if (subgraph_context_.has_dynamic_input_shape && !session_context_.disable_dynamic_shapes && (session_context_.device_type.find("CPU") != std::string::npos || - session_context_.device_type.find("GPU") != std::string::npos)) { + session_context_.device_type.find("GPU") != std::string::npos || + session_context_.device_type.find("NPU") != std::string::npos)) { auto tensor = context.GetInput(subgraph_context_.input_names.at(input_name)); auto tensor_info = tensor.GetTensorTypeAndShapeInfo(); auto tensor_shape = tensor_info.GetShape(); @@ -443,7 +450,9 @@ void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferReque } } // Loop subgraph original input names - if (session_context_.device_type.find("NPU") != std::string::npos) { + // For stateful PoC added '&& false' here to disable it, as we forced it through + // same dynamic shape path above as we do for CPU & GPU. + if (session_context_.device_type.find("NPU") != std::string::npos && false) { // Set the output blob as remote blob auto graph_output_info = exe_network_.Get().outputs(); auto output_idx = 0; @@ -638,7 +647,8 @@ void BasicBackend::CompleteAsyncInference(Ort::KernelContext& context, OVInferRe "list of OpenVINO output tensor names"); } if ((session_context_.device_type.find("CPU") != std::string::npos || - session_context_.device_type.find("GPU") != std::string::npos)) { + session_context_.device_type.find("GPU") != std::string::npos || + session_context_.device_type.find("NPU") != std::string::npos)) { try { graph_output_blob = infer_request->GetTensor(output_name); } catch (const char* msg) { diff --git a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc index 8005889af23ea..2341a716b4180 100644 --- a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc +++ b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc @@ -310,7 +310,9 @@ struct OpenVINO_Provider : Provider { // Always true for NPU plugin or when passed . if (pi.device_type.find("NPU") != std::string::npos) { - pi.disable_dynamic_shapes = true; + // For Stateful PoC, we want control to pass through dynamic shape paths, + // so just force this to false right now. + pi.disable_dynamic_shapes = false; } return std::make_shared(pi, SharedContext::Get()); diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index d5d23cf4a11f1..099dbe27e0bd2 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -8,6 +8,9 @@ #include "core/providers/shared_library/provider_api.h" #include "core/providers/openvino/backend_utils.h" +// for make stateful utility function(s) +#include "core/providers/openvino/ov_stateful_patch_utils.h" + using Exception = ov::Exception; namespace onnxruntime { @@ -77,7 +80,52 @@ OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_netwo const std::string& name) { ov::CompiledModel obj; try { - obj = core.compile_model(ie_cnn_network, hw_target, device_config); + if (true) { + ov::AnyMap config; + + // Create a clone of ie_cnn_network, since it's a const ov::Model, and we need to patch it.. + // Note! With this default path, the model runs but produces garbage (for NPUW). For CPU it's fine. + auto mutable_model = ie_cnn_network->clone(); + + // uncomment to override ov::Model with one produced by OV's ONNX front-end. + // For some reason, this makes it work -- even though model.onnx is the same model read by ORT GenAI. + // auto mutable_model = core.read_model("C:\\Users\\LNL\\Workspace\\ORT\\deepseek_r1_distill_qwen_1.5B_int4_ort_qdq\\model.onnx"); + + std::cout << "stateless model" << std::endl; + logBasicModelInfo(mutable_model); + + std::cout << "making stateful..." << std::endl; + patch_stateful_decoder(mutable_model); + + std::cout << "after stateful transition:" << std::endl; + logBasicModelInfo(mutable_model); + + // This patches the model so that it only produces the logits required for sampling. + // Actually either way that happens within NPUW::LLMCompiledModel creation, but this is + // here mostly to align this behavior for other devices (CPU, GPU). + apply_slice_before_matmul_transformation(mutable_model); + + auto kv_pos = get_kv_axes_pos(mutable_model); + std::cout << "kv_pos.batch = " << kv_pos.batch << std::endl; + std::cout << "kv_pos.seq_len = " << kv_pos.seq_len << std::endl; + + if (hw_target.find("NPU") != std::string::npos) { + KVDesc kv_desc; + kv_desc.max_prompt_len = pop_int_and_cast(device_config, "MAX_PROMPT_LEN").value_or(1024u); + kv_desc.min_response_len = pop_int_and_cast(device_config, "MIN_RESPONSE_LEN").value_or(128u); + + std::cout << "kv_desc.max_prompt_len = " << kv_desc.max_prompt_len << std::endl; + std::cout << "kv_desc.min_response_len = " << kv_desc.min_response_len << std::endl; + + update_npu_config(config, mutable_model, kv_pos, kv_desc); + } + + std::cout << "calling compile on stateful model..." << std::endl; + obj = core.compile_model(mutable_model, hw_target, config); + std::cout << "done calling compile on stateful model..." << std::endl; + } else { + obj = core.compile_model(ie_cnn_network, hw_target, device_config); + } #ifndef NDEBUG printDebugInfo(obj); #endif @@ -245,6 +293,16 @@ std::string OVInferRequest::GetInputTensorName(uint32_t index) { void OVInferRequest::SetTensor(const std::string& name, OVTensorPtr& blob) { try { ovInfReq.set_tensor(name, *(blob.get())); + + if (name == "input_ids") { + // Since we can't seem to set at ORT GenAI layer right now, we just set it here + // as a workaround. + // TODO: Fix this. + ov::Tensor beam_idx = ov::Tensor(ov::element::i32, {1}); + std::fill_n(beam_idx.data(), 1, 0); + ovInfReq.set_tensor("beam_idx", beam_idx); + } + } catch (const Exception& e) { ORT_THROW(log_tag + " Cannot set Remote Blob for output: " + name + e.what()); } catch (...) { diff --git a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h new file mode 100644 index 0000000000000..be8b783bfeb5b --- /dev/null +++ b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h @@ -0,0 +1,338 @@ +// Copyright (C) Intel Corporation +// Licensed under the MIT License + +#pragma once + +// for make stateful utility function(s) +#include "openvino/pass/manager.hpp" +#include "openvino/pass/make_stateful.hpp" +#include "openvino/opsets/opset13.hpp" + +static inline void logBasicModelInfo(const std::shared_ptr& model) { + std::cout << "Model name: " << model->get_friendly_name() << std::endl; + + // Dump information about model inputs/outputs + auto inputs = model->inputs(); + auto outputs = model->outputs(); + + std::cout << "\tInputs: " << std::endl; + for (const ov::Output& input : inputs) { + const std::string name = input.get_any_name(); + const ov::element::Type type = input.get_element_type(); + const ov::PartialShape shape = input.get_partial_shape(); + const ov::Layout layout = ov::layout::get_layout(input); + + std::cout << "\t\t" << name << ", " << type << ", " << shape << ", " << layout.to_string() << std::endl; + } + + std::cout << "\tOutputs: " << std::endl; + for (const ov::Output& output : outputs) { + const std::string name = output.get_any_name(); + const ov::element::Type type = output.get_element_type(); + const ov::PartialShape shape = output.get_partial_shape(); + const ov::Layout layout = ov::layout::get_layout(output); + + std::cout << "\t\t" << name << ", " << type << ", " << shape << ", " << layout.to_string() << std::endl; + } + + return; +} + +static inline bool model_has_input_output_names(std::shared_ptr model, const std::string& name_to_match) { + for (const ov::Output& input : model->inputs()) { + auto& names = input.get_names(); + + for (auto& name : names) { + if (name == name_to_match) { + return true; + } + } + } + + for (const ov::Output& output : model->outputs()) { + auto& names = output.get_names(); + for (auto& name : names) { + if (name == name_to_match) { + return true; + } + } + } + + return false; +} + +static void fuse_cache_reorder(std::shared_ptr ov_model, + std::vector& not_kv_inputs, + const std::vector& key_value_input_names, + int gather_dim) { + if (model_has_input_output_names(ov_model, "beam_idx")) { + throw std::runtime_error("Model already has fused cache"); + } + + std::string main_input_name = "inputs_embeds"; + if (model_has_input_output_names(ov_model, "input_ids")) { + main_input_name = "input_ids"; + } + + auto input_batch = ov_model->input(main_input_name).get_partial_shape()[0]; + + auto beam_idx = std::make_shared(ov::element::i32, ov::PartialShape({input_batch})); + beam_idx->set_friendly_name("beam_idx"); + beam_idx->output(0).get_tensor().add_names({"beam_idx"}); + ov_model->add_parameters({beam_idx}); + not_kv_inputs.push_back(beam_idx->get_friendly_name()); + + // Go over all cache parameters and fuse _reorder_cache with indices provided by the new parameter beam_idx + for (const auto& input_name : key_value_input_names) { + auto parameter_output_port = ov_model->input(input_name); + auto consumers = parameter_output_port.get_target_inputs(); + + auto gather_op = + std::make_shared(parameter_output_port, + beam_idx, + ov::opset13::Constant::create(ov::element::i64, {}, {gather_dim})); + + // Replace the source output for all consumers of the input tensor + for (auto& consumer : consumers) { + consumer.replace_source_output(gather_op->output(0)); + } + } + + // Validate the modified model + ov_model->validate_nodes_and_infer_types(); +} + +static void make_stateful(std::shared_ptr& ov_model, + const std::vector& key_value_input_names, + const std::vector& key_value_output_names) { + std::map input_output_map; + + // Create mapping for KV-cache inputs and outputs + for (size_t i = 0; i < key_value_input_names.size(); ++i) { + input_output_map[key_value_input_names[i]] = key_value_output_names[i]; + } + + // Apply the transformation to make the model stateful + ov::pass::Manager manager; + manager.register_pass(input_output_map); + manager.run_passes(ov_model); +} + +// Converted to C++ from here: +// https://github.com/huggingface/optimum-intel/blob/main/optimum/exporters/openvino/stateful.py#L281 +static void patch_stateful_decoder(std::shared_ptr model) { + std::vector key_value_input_names; + std::vector not_kv_inputs; + for (const ov::Output& input : model->inputs()) { + auto& names = input.get_names(); + + bool found = false; + for (auto& name : names) { + if (name.find("key_values") != std::string::npos) { + key_value_input_names.push_back(name); + found = true; + break; + } + } + + if (!found) { + not_kv_inputs.push_back(input.get_any_name()); + } + } + + std::vector key_value_output_names; + for (const ov::Output& output : model->outputs()) { + auto& names = output.get_names(); + for (auto& name : names) { + if (name.find("present") != std::string::npos) { + key_value_output_names.push_back(name); + break; + } + } + } + + if (key_value_input_names.empty() || key_value_output_names.empty()) { + std::cout << "no key_value_input_names or key_value_output_names found" << std::endl; + return; + } + + // By default, batch is the 0 - th but chatglm uses 1 - st dimension as batch + // TODO: Deduce from a model via ordinal reshape(? ) and topology + // batch_dim = 1 if config.model_type == "chatglm" and not hasattr(config, "rope_ratio") else 0 + auto batch_dim = 0; + + fuse_cache_reorder(model, not_kv_inputs, key_value_input_names, batch_dim); + + make_stateful(model, key_value_input_names, key_value_output_names); +} + +// Some other utility functions copied from OpenVINO GenAI +static bool has_op_with_type(const std::shared_ptr& function, const std::string& type_name) { + for (const auto& op : function->get_ops()) { + if (op->get_type_name() == type_name) { + return true; + } + } + return false; +} + +static std::tuple, int64_t> find_llm_matmul(const std::shared_ptr& model) { + auto last_node = model->output(0).get_node()->input_value(0).get_node_shared_ptr(); + std::shared_ptr matmul = ov::as_type_ptr(last_node); + + // in case of PA all tokens are moved to batch dimension and we have to slice / gather accordingly + const bool pa_based_model = has_op_with_type(model, "PagedAttentionExtension"); + int64_t slice_gather_dim = pa_based_model ? 0 : 1; + + // There are several patterns for matmul we are looking for: + // Matmul -> Result + // Matmul -> Add -> Result + // Matmul -> Transpose -> Result + // MatMul -> Divide -> Tanh -> Multiply -> Result + if (!matmul) { + if (auto add = ov::as_type_ptr(last_node)) { + matmul = ov::as_type_ptr(add->input_value(0).get_node_shared_ptr()); + } else if (auto transpose = ov::as_type_ptr(last_node)) { + matmul = ov::as_type_ptr(transpose->input_value(0).get_node_shared_ptr()); + auto order = ov::as_type_ptr(transpose->input_value(1).get_node_shared_ptr())->get_axis_vector_val(); + slice_gather_dim = order[slice_gather_dim]; + } else if (auto multiply = ov::as_type_ptr(last_node)) { + if (auto tanh = ov::as_type_ptr(multiply->input_value(0).get_node_shared_ptr())) { + if (auto divide = ov::as_type_ptr(tanh->input_value(0).get_node_shared_ptr())) { + matmul = as_type_ptr(divide->input_value(0).get_node_shared_ptr()); + } + } + } + } + return std::make_tuple(matmul, slice_gather_dim); +} + +static void apply_slice_before_matmul_transformation(std::shared_ptr model) { + std::shared_ptr matmul = nullptr; + int64_t slice_gather_dim = -1; + std::tie(matmul, slice_gather_dim) = find_llm_matmul(model); + + if (matmul && matmul->input(0).get_partial_shape().rank().get_length() == 3) { + auto start = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-1}); + auto stop = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-2}); + auto step = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-1}); + auto axis = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{slice_gather_dim}); + auto slice = std::make_shared(matmul->input_value(0), start, stop, step, axis); + matmul->input(0).replace_source_output(slice); + } +} + +static void update_config(ov::AnyMap& config, const std::pair& pair) { + if (config.count(pair.first) == 0) { + config.insert(pair); + } +} + +static std::optional pop_option(ov::AnyMap& config, const std::string& option_name) { + if (auto it = config.find(option_name); it != config.end()) { + std::optional found = std::make_optional(it->second); + config.erase(it); + return found; + } + return std::nullopt; +} + +static void rename_key(ov::AnyMap& config, const std::string& old_key, const std::string& new_key) { + if (config.count(old_key) != 0) { + auto opt_value = pop_option(config, old_key); + config[new_key] = opt_value.value(); + } +} + +struct KVAxesPosition { + size_t batch; + size_t seq_len; +}; + +KVAxesPosition get_kv_axes_pos(std::shared_ptr model) { + // sequence length axis in key/values tensors, for most cases [BATCH_SIZE, num_kv_heads, seq_len, head_size], + // therefore usually seq_length_axis = 2 and batch = 0 + KVAxesPosition kv_pos{0u, 2u}; + + // "ReadValue" node is KV cache representation in stateful model + std::string kv_node_type_name = std::string(ov::op::v6::ReadValue::get_type_info_static().name); + + for (const auto op : model->get_ops()) { + // check input size, as in LoRA adapters case it could be 0 + if (op->get_type_name() != kv_node_type_name || op->get_input_size() < 1) { + continue; + } + + // Shape example: [-1,4,0,64] + auto shape = op->get_input_partial_shape(0); + + for (int64_t i = 0; i < shape.rank().get_length(); i++) { + // Find axis = 0. This would be sequence length axis. + if (shape[i] == 0) { + kv_pos.seq_len = i; + } else if (shape[i].is_dynamic()) { + // Dynamic axis is a batch + kv_pos.batch = i; + } + } + break; + } + + return kv_pos; +} + +struct KVDesc { + uint32_t max_prompt_len; + uint32_t min_response_len; +}; + +static void update_npu_config(ov::AnyMap& config, + const std::shared_ptr& model, + const KVAxesPosition& kv_pos, + const KVDesc& kv_desc) { + update_config(config, {"NPU_USE_NPUW", "YES"}); + update_config(config, {"NPUW_LLM", "YES"}); + + update_config(config, {"NPUW_LLM_BATCH_DIM", kv_pos.batch}); + update_config(config, {"NPUW_LLM_SEQ_LEN_DIM", kv_pos.seq_len}); + + update_config(config, {"NPUW_LLM_MAX_PROMPT_LEN", kv_desc.max_prompt_len}); + update_config(config, {"NPUW_LLM_MIN_RESPONSE_LEN", kv_desc.min_response_len}); + + rename_key(config, "++PREFILL_CONFIG", "++NPUW_LLM_PREFILL_CONFIG"); + rename_key(config, "++GENERATE_CONFIG", "++NPUW_LLM_GENERATE_CONFIG"); + rename_key(config, "PREFILL_CONFIG", "NPUW_LLM_PREFILL_CONFIG"); + rename_key(config, "PREFILL_HINT", "NPUW_LLM_PREFILL_HINT"); + rename_key(config, "GENERATE_CONFIG", "NPUW_LLM_GENERATE_CONFIG"); + rename_key(config, "GENERATE_HINT", "NPUW_LLM_GENERATE_HINT"); +} + +static std::optional pop_option_new(ov::AnyMap& config, const std::string& option_name) { + if (auto it = config.find(option_name); it != config.end()) { + std::optional found = std::make_optional(it->second); + config.erase(it); + return found; + } + return std::nullopt; +} + +static std::optional pop_int_and_cast(ov::AnyMap& config, const std::string& key) { + auto anyopt = pop_option_new(config, key); + if (anyopt.has_value()) { + const auto any = anyopt.value(); + int64_t value; + // NB: Integer value coming from python has int64_t datatype + if (any.is()) { + value = any.as(); + } else if (any.is()) { + value = any.as(); + } else { + OPENVINO_THROW("Failed to extract " + key + ". Type mismatch: expected types: int or int64_t"); + } + if (value < 0) { + OPENVINO_THROW(key + " cannot be negative!"); + } + return std::make_optional(static_cast(value)); + } + return std::nullopt; +} From f4cc9f358b61c4d4ee193bafc6a445c1850efc68 Mon Sep 17 00:00:00 2001 From: ankitm3k Date: Thu, 3 Apr 2025 16:40:11 +0530 Subject: [PATCH 259/266] update: Update enable_causallm provider option for stateful poc --- .../core/providers/openvino/backend_manager.cc | 5 +++-- .../providers/openvino/backends/basic_backend.cc | 15 ++++++++++----- onnxruntime/core/providers/openvino/contexts.h | 1 + .../openvino/openvino_provider_factory.cc | 8 +++++++- .../core/providers/openvino/ov_interface.cc | 7 ++----- .../core/providers/openvino/ov_interface.h | 1 + onnxruntime/core/session/provider_bridge_ort.cc | 1 + onnxruntime/python/onnxruntime_pybind_state.cc | 3 +++ onnxruntime/test/perftest/ort_test_session.cc | 11 ++++++++++- 9 files changed, 38 insertions(+), 14 deletions(-) diff --git a/onnxruntime/core/providers/openvino/backend_manager.cc b/onnxruntime/core/providers/openvino/backend_manager.cc index f56a6256395a7..b73f905a1bb35 100644 --- a/onnxruntime/core/providers/openvino/backend_manager.cc +++ b/onnxruntime/core/providers/openvino/backend_manager.cc @@ -105,7 +105,7 @@ BackendManager::BackendManager(SessionContext& session_context, LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Model has symbolic input dims"; if ((session_context_.device_type.find("CPU") != std::string::npos || session_context_.device_type.find("GPU") != std::string::npos || - session_context_.device_type.find("NPU") != std::string::npos) && + (session_context_.device_type.find("NPU") != std::string::npos && session_context_.enable_causallm)) && !session_context_.disable_dynamic_shapes) { LOGS_DEFAULT(INFO) << "[OpenVINO-EP] Starting backend initialization. " << "Creating backend Dynamic Shapes"; @@ -476,7 +476,8 @@ void BackendManager::Compute(OrtKernelContext* context) { !session_context_.disable_dynamic_shapes && (session_context_.device_type.find("CPU") != std::string::npos || session_context_.device_type.find("GPU") != std::string::npos || - session_context_.device_type.find("NPU") != std::string::npos)) { + (session_context_.device_type.find("NPU") != std::string::npos && + session_context_.enable_causallm))) { concrete_backend_->Infer(context); } else if (subgraph_context_.has_dynamic_input_shape) { std::vector> tensor_shapes = GetInputTensorShapes(ctx); diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 043bced075a43..adb9b68fce61e 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -29,6 +29,9 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr ptr_stream_t& model_stream) : session_context_{session_context}, subgraph_context_{subgraph_context}, shared_context_{shared_context} { std::string& hw_target = session_context_.device_type; + auto enable_causallm = session_context_.enable_causallm; + + std::cout << "CausalLM enabled: " << enable_causallm << std::endl; if (ValidateSubgraph(const_outputs_map_)) return; @@ -95,7 +98,7 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr } else if (!session_context_.has_external_weights && !subgraph_context_.has_dynamic_input_shape && !session_context_.so_context_enable && - auto_unified_compile) { + !enable_causallm && auto_unified_compile) { // Unified OV compile_model is efficient when ov model caching is enabled // Unified OV compile_model API is supported with AUTO from version 2024.3 and above // Inputs with static dimenstions @@ -113,7 +116,7 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr } auto ov_model = CreateOVModel(std::move(model), session_context_, const_outputs_map_); exe_network_ = OVCore::Get()->CompileModel( - ov_model, hw_target, device_config, subgraph_context_.subgraph_name); + ov_model, hw_target, device_config, enable_causallm, subgraph_context_.subgraph_name); } #endif LOGS_DEFAULT(INFO) << log_tag << "Loaded model to the plugin"; @@ -388,7 +391,8 @@ void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferReque !session_context_.disable_dynamic_shapes && (session_context_.device_type.find("CPU") != std::string::npos || session_context_.device_type.find("GPU") != std::string::npos || - session_context_.device_type.find("NPU") != std::string::npos)) { + (session_context_.device_type.find("NPU") != std::string::npos && + session_context_.enable_causallm))) { auto tensor = context.GetInput(subgraph_context_.input_names.at(input_name)); auto tensor_info = tensor.GetTensorTypeAndShapeInfo(); auto tensor_shape = tensor_info.GetShape(); @@ -452,7 +456,7 @@ void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferReque // For stateful PoC added '&& false' here to disable it, as we forced it through // same dynamic shape path above as we do for CPU & GPU. - if (session_context_.device_type.find("NPU") != std::string::npos && false) { + if (session_context_.device_type.find("NPU") != std::string::npos && !session_context_.enable_causallm) { // Set the output blob as remote blob auto graph_output_info = exe_network_.Get().outputs(); auto output_idx = 0; @@ -648,7 +652,8 @@ void BasicBackend::CompleteAsyncInference(Ort::KernelContext& context, OVInferRe } if ((session_context_.device_type.find("CPU") != std::string::npos || session_context_.device_type.find("GPU") != std::string::npos || - session_context_.device_type.find("NPU") != std::string::npos)) { + (session_context_.device_type.find("NPU") != std::string::npos && + session_context_.enable_causallm))) { try { graph_output_blob = infer_request->GetTensor(output_name); } catch (const char* msg) { diff --git a/onnxruntime/core/providers/openvino/contexts.h b/onnxruntime/core/providers/openvino/contexts.h index a1a756a9baef7..c02422b2853b2 100644 --- a/onnxruntime/core/providers/openvino/contexts.h +++ b/onnxruntime/core/providers/openvino/contexts.h @@ -96,6 +96,7 @@ struct ProviderInfo { bool disable_dynamic_shapes{false}; // [disable_dynamic_shapes]: Rewrite dynamic shaped models to // static shape at runtime and execute. bool enable_qdq_optimizer{false}; // Enables QDQ pruning for efficient inference latency with NPU + bool enable_causallm{false}; // Enables Causal LM optimization for NPU/NPUW (ORT GenAI OVEP Pass) bool so_context_enable{false}; // ORT session option bool so_disable_cpu_ep_fallback{false}; // ORT session option bool so_context_embed_mode{false}; // ORT session option diff --git a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc index 2341a716b4180..be99378381794 100644 --- a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc +++ b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc @@ -306,13 +306,19 @@ struct OpenVINO_Provider : Provider { pi.enable_qdq_optimizer = ParseBooleanOption(provider_options, "enable_qdq_optimizer"); + pi.enable_causallm = ParseBooleanOption(provider_options, "enable_causallm"); + pi.disable_dynamic_shapes = ParseBooleanOption(provider_options, "disable_dynamic_shapes"); // Always true for NPU plugin or when passed . if (pi.device_type.find("NPU") != std::string::npos) { // For Stateful PoC, we want control to pass through dynamic shape paths, // so just force this to false right now. - pi.disable_dynamic_shapes = false; + if (pi.enable_causallm) { + pi.disable_dynamic_shapes = false; + } else { + pi.disable_dynamic_shapes = true; + } } return std::make_shared(pi, SharedContext::Get()); diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index 099dbe27e0bd2..41dec7a639d82 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -77,20 +77,17 @@ std::shared_ptr OVCore::ReadModel(std::string&& model, const std::str OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_network, std::string& hw_target, ov::AnyMap& device_config, + bool enable_causallm, const std::string& name) { ov::CompiledModel obj; try { - if (true) { + if (enable_causallm) { ov::AnyMap config; // Create a clone of ie_cnn_network, since it's a const ov::Model, and we need to patch it.. // Note! With this default path, the model runs but produces garbage (for NPUW). For CPU it's fine. auto mutable_model = ie_cnn_network->clone(); - // uncomment to override ov::Model with one produced by OV's ONNX front-end. - // For some reason, this makes it work -- even though model.onnx is the same model read by ORT GenAI. - // auto mutable_model = core.read_model("C:\\Users\\LNL\\Workspace\\ORT\\deepseek_r1_distill_qwen_1.5B_int4_ort_qdq\\model.onnx"); - std::cout << "stateless model" << std::endl; logBasicModelInfo(mutable_model); diff --git a/onnxruntime/core/providers/openvino/ov_interface.h b/onnxruntime/core/providers/openvino/ov_interface.h index 7e0f3f7d917a9..a11628ed370c7 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.h +++ b/onnxruntime/core/providers/openvino/ov_interface.h @@ -73,6 +73,7 @@ struct OVCore : WeakSingleton { OVExeNetwork CompileModel(std::shared_ptr& ie_cnn_network, std::string& hw_target, ov::AnyMap& device_config, + bool enable_causallm, const std::string& name); // OV Interface for Fast Compile OVExeNetwork CompileModel(const std::string& onnx_model, diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 8539394f321bd..c5e845d14fb30 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -2008,6 +2008,7 @@ ProviderOptions OrtOpenVINOProviderOptionsToOrtOpenVINOProviderOptionsV2(const O ov_options_converted_map["load_config"] = ""; ov_options_converted_map["model_priority"] = "DEFAULT"; ov_options_converted_map["enable_qdq_optimizer"] = "false"; + ov_options_converted_map["enable_causallm"] = "false"; return ov_options_converted_map; } diff --git a/onnxruntime/python/onnxruntime_pybind_state.cc b/onnxruntime/python/onnxruntime_pybind_state.cc index a069cfa0b4713..22914c9dec7fe 100644 --- a/onnxruntime/python/onnxruntime_pybind_state.cc +++ b/onnxruntime/python/onnxruntime_pybind_state.cc @@ -1115,6 +1115,9 @@ std::unique_ptr CreateExecutionProviderInstance( } else if (option.first == "enable_qdq_optimizer") { OV_provider_options_map[option.first] = option.second; continue; + } else if (option.first == "enable_causallm") { + OV_provider_options_map[option.first] = option.second; + continue; } else { ORT_THROW("Invalid OpenVINO EP option: ", option.first); } diff --git a/onnxruntime/test/perftest/ort_test_session.cc b/onnxruntime/test/perftest/ort_test_session.cc index 1cc17ea03fa32..2395ea7316b1b 100644 --- a/onnxruntime/test/perftest/ort_test_session.cc +++ b/onnxruntime/test/perftest/ort_test_session.cc @@ -741,6 +741,14 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)"); } else { ORT_THROW("[ERROR] [OpenVINO] The value for the key 'enable_qdq_optimizer' should be a boolean i.e. true or false. Default value is false.\n"); } + } else if (key == "enable_causallm") { + if (value == "true" || value == "True" || + value == "false" || value == "False") { + ov_options[key] = value; + } else { + ORT_THROW("[ERROR] [OpenVINO] The value for the key 'enable_causallm' should be a boolean i.e. true or false." + " Default value is false. This provider option must be used with CausalLM Models viz. LLMs & SLMs only.\n"); + } } else if (key == "disable_dynamic_shapes") { if (value == "true" || value == "True" || value == "false" || value == "False") { @@ -796,7 +804,8 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)"); ORT_THROW( "[ERROR] [OpenVINO] wrong key type entered. Choose from the following runtime key options that are available for OpenVINO." " ['device_type', 'device_id', 'num_of_threads', 'load_config', 'cache_dir', 'num_streams', " - "'enable_opencl_throttling', 'disable_dynamic_shapes', 'enable_qdq_optimizer', 'model_priority'] \n"); + "'enable_opencl_throttling', 'disable_dynamic_shapes', 'enable_qdq_optimizer'," + " 'enable_causallm', 'model_priority'] \n"); } } session_options.AppendExecutionProvider_OpenVINO_V2(ov_options); From cfbfc0c703a7b6b84d1eee4613bea1963826b026 Mon Sep 17 00:00:00 2001 From: ankitm3k Date: Thu, 3 Apr 2025 19:45:29 +0530 Subject: [PATCH 260/266] fix: Refactor Stateful Code --- .../openvino/backends/basic_backend.cc | 2 - .../core/providers/openvino/ov_interface.cc | 43 ++- .../openvino/ov_stateful_patch_utils.cc | 329 +++++++++++++++++ .../openvino/ov_stateful_patch_utils.h | 336 ++---------------- 4 files changed, 387 insertions(+), 323 deletions(-) create mode 100644 onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index adb9b68fce61e..5f5c2bde7206c 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -31,8 +31,6 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr std::string& hw_target = session_context_.device_type; auto enable_causallm = session_context_.enable_causallm; - std::cout << "CausalLM enabled: " << enable_causallm << std::endl; - if (ValidateSubgraph(const_outputs_map_)) return; diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index 41dec7a639d82..13e27337b7184 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -88,38 +88,47 @@ OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_netwo // Note! With this default path, the model runs but produces garbage (for NPUW). For CPU it's fine. auto mutable_model = ie_cnn_network->clone(); - std::cout << "stateless model" << std::endl; - logBasicModelInfo(mutable_model); + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "Stateless OV Model Statistic" << std::endl; + LogBasicModelInfo(mutable_model); + } + LogBasicModelInfo(mutable_model); - std::cout << "making stateful..." << std::endl; - patch_stateful_decoder(mutable_model); + LOGS_DEFAULT(INFO) << log_tag << "Converting from Stateless OV Model to Stateful OV Model" << std::endl; + PatchStatefulDecoder(mutable_model); - std::cout << "after stateful transition:" << std::endl; - logBasicModelInfo(mutable_model); + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "Stateful OV Model Statistic" << std::endl; + LogBasicModelInfo(mutable_model); + } // This patches the model so that it only produces the logits required for sampling. // Actually either way that happens within NPUW::LLMCompiledModel creation, but this is // here mostly to align this behavior for other devices (CPU, GPU). - apply_slice_before_matmul_transformation(mutable_model); + ApplySliceBeforeMatmulTransformation(mutable_model); - auto kv_pos = get_kv_axes_pos(mutable_model); - std::cout << "kv_pos.batch = " << kv_pos.batch << std::endl; - std::cout << "kv_pos.seq_len = " << kv_pos.seq_len << std::endl; + auto kv_pos = GetKVAxesPos(mutable_model); + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "kv_pos.batch = " << kv_pos.batch << std::endl; + std::cout << "kv_pos.seq_len = " << kv_pos.seq_len << std::endl; + } if (hw_target.find("NPU") != std::string::npos) { KVDesc kv_desc; - kv_desc.max_prompt_len = pop_int_and_cast(device_config, "MAX_PROMPT_LEN").value_or(1024u); - kv_desc.min_response_len = pop_int_and_cast(device_config, "MIN_RESPONSE_LEN").value_or(128u); + kv_desc.max_prompt_len = PopIntAndCast(device_config, "MAX_PROMPT_LEN").value_or(1024u); + kv_desc.min_response_len = PopIntAndCast(device_config, "MIN_RESPONSE_LEN").value_or(128u); - std::cout << "kv_desc.max_prompt_len = " << kv_desc.max_prompt_len << std::endl; - std::cout << "kv_desc.min_response_len = " << kv_desc.min_response_len << std::endl; + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "kv_desc.max_prompt_len = " << kv_desc.max_prompt_len << std::endl; + std::cout << "kv_desc.min_response_len = " << kv_desc.min_response_len << std::endl; + } - update_npu_config(config, mutable_model, kv_pos, kv_desc); + UpdateNPUConfig(config, kv_pos, kv_desc); } - std::cout << "calling compile on stateful model..." << std::endl; + std::cout << "Compiling Stateful OV Model..." << std::endl; obj = core.compile_model(mutable_model, hw_target, config); - std::cout << "done calling compile on stateful model..." << std::endl; + std::cout << "Stateful OV Model Compilation Complete" << std::endl; } else { obj = core.compile_model(ie_cnn_network, hw_target, device_config); } diff --git a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc new file mode 100644 index 0000000000000..b634560e58a84 --- /dev/null +++ b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc @@ -0,0 +1,329 @@ +// Copyright (C) Intel Corporation +// Licensed under the MIT License + +#include "ov_stateful_patch_utils.h" + +namespace onnxruntime { +namespace openvino_ep { + + + void LogBasicModelInfo(const std::shared_ptr& model) { + std::cout << "Model Name: " << model->get_friendly_name() << std::endl; + + // Dump information about model inputs/outputs + auto inputs = model->inputs(); + auto outputs = model->outputs(); + + std::cout << "\tInputs: " << std::endl; + for (const ov::Output& input : inputs) { + const std::string name = input.get_any_name(); + const ov::element::Type type = input.get_element_type(); + const ov::PartialShape shape = input.get_partial_shape(); + const ov::Layout layout = ov::layout::get_layout(input); + + std::cout << "\t\t" << name << ", " << type << ", " << shape << ", " << layout.to_string() << std::endl; + } + + std::cout << "\tOutputs: " << std::endl; + for (const ov::Output& output : outputs) { + const std::string name = output.get_any_name(); + const ov::element::Type type = output.get_element_type(); + const ov::PartialShape shape = output.get_partial_shape(); + const ov::Layout layout = ov::layout::get_layout(output); + + std::cout << "\t\t" << name << ", " << type << ", " << shape << ", " << layout.to_string() << std::endl; + } + + return; +} + + bool ModelHasInputOutputNames(std::shared_ptr model, const std::string& name_to_match) { + for (const ov::Output& input : model->inputs()) { + auto& names = input.get_names(); + + for (auto& name : names) { + if (name == name_to_match) { + return true; + } + } + } + + for (const ov::Output& output : model->outputs()) { + auto& names = output.get_names(); + for (auto& name : names) { + if (name == name_to_match) { + return true; + } + } + } + + return false; +} + + void FuseCacheReorder(std::shared_ptr ov_model, + std::vector& not_kv_inputs, + const std::vector& key_value_input_names, + int gather_dim) { + if (ModelHasInputOutputNames(ov_model, "beam_idx")) { + throw std::runtime_error("Model already has fused cache"); + } + + std::string main_input_name = "inputs_embeds"; + if (ModelHasInputOutputNames(ov_model, "input_ids")) { + main_input_name = "input_ids"; + } + + auto input_batch = ov_model->input(main_input_name).get_partial_shape()[0]; + + auto beam_idx = std::make_shared(ov::element::i32, ov::PartialShape({input_batch})); + beam_idx->set_friendly_name("beam_idx"); + beam_idx->output(0).get_tensor().add_names({"beam_idx"}); + ov_model->add_parameters({beam_idx}); + not_kv_inputs.push_back(beam_idx->get_friendly_name()); + + // Go over all cache parameters and fuse _reorder_cache with indices provided by the new parameter beam_idx + for (const auto& input_name : key_value_input_names) { + auto parameter_output_port = ov_model->input(input_name); + auto consumers = parameter_output_port.get_target_inputs(); + + auto gather_op = + std::make_shared(parameter_output_port, + beam_idx, + ov::opset13::Constant::create(ov::element::i64, {}, {gather_dim})); + + // Replace the source output for all consumers of the input tensor + for (auto& consumer : consumers) { + consumer.replace_source_output(gather_op->output(0)); + } + } + + // Validate the modified model + ov_model->validate_nodes_and_infer_types(); +} + + void MakeStateful(std::shared_ptr& ov_model, + const std::vector& key_value_input_names, + const std::vector& key_value_output_names) { + std::map input_output_map; + + // Create mapping for KV-cache inputs and outputs + for (size_t i = 0; i < key_value_input_names.size(); ++i) { + input_output_map[key_value_input_names[i]] = key_value_output_names[i]; + } + + // Apply the transformation to make the model stateful + ov::pass::Manager manager; + manager.register_pass(input_output_map); + manager.run_passes(ov_model); +} + +// Converted to C++ from here: +// https://github.com/huggingface/optimum-intel/blob/main/optimum/exporters/openvino/stateful.py#L281 + void PatchStatefulDecoder(std::shared_ptr model) { + std::vector key_value_input_names; + std::vector not_kv_inputs; + for (const ov::Output& input : model->inputs()) { + auto& names = input.get_names(); + + bool found = false; + for (auto& name : names) { + if (name.find("key_values") != std::string::npos) { + key_value_input_names.push_back(name); + found = true; + break; + } + } + + if (!found) { + not_kv_inputs.push_back(input.get_any_name()); + } + } + + std::vector key_value_output_names; + for (const ov::Output& output : model->outputs()) { + auto& names = output.get_names(); + for (auto& name : names) { + if (name.find("present") != std::string::npos) { + key_value_output_names.push_back(name); + break; + } + } + } + + if (key_value_input_names.empty() || key_value_output_names.empty()) { + std::cout << "no key_value_input_names or key_value_output_names found" << std::endl; + return; + } + + // By default, batch is the 0 - th but chatglm uses 1 - st dimension as batch + // TODO: Deduce from a model via ordinal reshape(? ) and topology + // batch_dim = 1 if config.model_type == "chatglm" and not hasattr(config, "rope_ratio") else 0 + auto batch_dim = 0; + + FuseCacheReorder(model, not_kv_inputs, key_value_input_names, batch_dim); + + MakeStateful(model, key_value_input_names, key_value_output_names); +} + +// Some other utility functions copied from OpenVINO GenAI + bool HasOpWithType(const std::shared_ptr& function, const std::string& type_name) { + for (const auto& op : function->get_ops()) { + if (op->get_type_name() == type_name) { + return true; + } + } + return false; +} + + std::tuple, int64_t> FindLLMMatmul(const std::shared_ptr& model) { + auto last_node = model->output(0).get_node()->input_value(0).get_node_shared_ptr(); + std::shared_ptr matmul = ov::as_type_ptr(last_node); + + // in case of PA all tokens are moved to batch dimension and we have to slice / gather accordingly + const bool pa_based_model = HasOpWithType(model, "PagedAttentionExtension"); + int64_t slice_gather_dim = pa_based_model ? 0 : 1; + + // There are several patterns for matmul we are looking for: + // Matmul -> Result + // Matmul -> Add -> Result + // Matmul -> Transpose -> Result + // MatMul -> Divide -> Tanh -> Multiply -> Result + if (!matmul) { + if (auto add = ov::as_type_ptr(last_node)) { + matmul = ov::as_type_ptr(add->input_value(0).get_node_shared_ptr()); + } else if (auto transpose = ov::as_type_ptr(last_node)) { + matmul = ov::as_type_ptr(transpose->input_value(0).get_node_shared_ptr()); + auto order = ov::as_type_ptr(transpose->input_value(1).get_node_shared_ptr())->get_axis_vector_val(); + slice_gather_dim = order[slice_gather_dim]; + } else if (auto multiply = ov::as_type_ptr(last_node)) { + if (auto tanh = ov::as_type_ptr(multiply->input_value(0).get_node_shared_ptr())) { + if (auto divide = ov::as_type_ptr(tanh->input_value(0).get_node_shared_ptr())) { + matmul = ov::as_type_ptr(divide->input_value(0).get_node_shared_ptr()); + } + } + } + } + return std::make_tuple(matmul, slice_gather_dim); +} + + void ApplySliceBeforeMatmulTransformation(std::shared_ptr model) { + std::shared_ptr matmul = nullptr; + int64_t slice_gather_dim = -1; + std::tie(matmul, slice_gather_dim) = FindLLMMatmul(model); + + if (matmul && matmul->input(0).get_partial_shape().rank().get_length() == 3) { + auto start = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-1}); + auto stop = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-2}); + auto step = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-1}); + auto axis = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{slice_gather_dim}); + auto slice = std::make_shared(matmul->input_value(0), start, stop, step, axis); + matmul->input(0).replace_source_output(slice); + } +} + + void UpdateConfig(ov::AnyMap& config, const std::pair& pair) { + if (config.count(pair.first) == 0) { + config.insert(pair); + } +} + + std::optional PopOption(ov::AnyMap& config, const std::string& option_name) { + if (auto it = config.find(option_name); it != config.end()) { + std::optional found = std::make_optional(it->second); + config.erase(it); + return found; + } + return std::nullopt; +} + + void RenameKey(ov::AnyMap& config, const std::string& old_key, const std::string& new_key) { + if (config.count(old_key) != 0) { + auto opt_value = PopOption(config, old_key); + config[new_key] = opt_value.value(); + } +} + + +KVAxesPosition GetKVAxesPos(std::shared_ptr model) { + // sequence length axis in key/values tensors, for most cases [BATCH_SIZE, num_kv_heads, seq_len, head_size], + // therefore usually seq_length_axis = 2 and batch = 0 + KVAxesPosition kv_pos{0u, 2u}; + + // "ReadValue" node is KV cache representation in stateful model + std::string kv_node_type_name = std::string(ov::op::v6::ReadValue::get_type_info_static().name); + + for (const auto& op : model->get_ops()) { + // check input size, as in LoRA adapters case it could be 0 + if (op->get_type_name() != kv_node_type_name || op->get_input_size() < 1) { + continue; + } + + // Shape example: [-1,4,0,64] + auto shape = op->get_input_partial_shape(0); + + for (int64_t i = 0; i < shape.rank().get_length(); i++) { + // Find axis = 0. This would be sequence length axis. + if (shape[i] == 0) { + kv_pos.seq_len = i; + } else if (shape[i].is_dynamic()) { + // Dynamic axis is a batch + kv_pos.batch = i; + } + } + break; + } + + return kv_pos; +} + +void UpdateNPUConfig(ov::AnyMap& config, const KVAxesPosition& kv_pos, const KVDesc& kv_desc) { + UpdateConfig(config, {"NPU_USE_NPUW", "YES"}); + UpdateConfig(config, {"NPUW_LLM", "YES"}); + + UpdateConfig(config, {"NPUW_LLM_BATCH_DIM", kv_pos.batch}); + UpdateConfig(config, {"NPUW_LLM_SEQ_LEN_DIM", kv_pos.seq_len}); + + UpdateConfig(config, {"NPUW_LLM_MAX_PROMPT_LEN", kv_desc.max_prompt_len}); + UpdateConfig(config, {"NPUW_LLM_MIN_RESPONSE_LEN", kv_desc.min_response_len}); + + RenameKey(config, "++PREFILL_CONFIG", "++NPUW_LLM_PREFILL_CONFIG"); + RenameKey(config, "++GENERATE_CONFIG", "++NPUW_LLM_GENERATE_CONFIG"); + RenameKey(config, "PREFILL_CONFIG", "NPUW_LLM_PREFILL_CONFIG"); + RenameKey(config, "PREFILL_HINT", "NPUW_LLM_PREFILL_HINT"); + RenameKey(config, "GENERATE_CONFIG", "NPUW_LLM_GENERATE_CONFIG"); + RenameKey(config, "GENERATE_HINT", "NPUW_LLM_GENERATE_HINT"); +} + +std::optional PopOptionNew(ov::AnyMap& config, const std::string& option_name) { + if (auto it = config.find(option_name); it != config.end()) { + std::optional found = std::make_optional(it->second); + config.erase(it); + return found; + } + return std::nullopt; +} + +std::optional PopIntAndCast(ov::AnyMap& config, const std::string& key) { + auto anyopt = PopOptionNew(config, key); + if (anyopt.has_value()) { + const auto any = anyopt.value(); + int64_t value; + // NB: Integer value coming from python has int64_t datatype + if (any.is()) { + value = any.as(); + } else if (any.is()) { + value = any.as(); + } else { + OPENVINO_THROW("Failed to extract " + key + ". Type mismatch: expected types: int or int64_t"); + } + if (value < 0) { + OPENVINO_THROW(key + " cannot be negative!"); + } + return std::make_optional(static_cast(value)); + } + return std::nullopt; +} + + +} // namespace openvino_ep +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h index be8b783bfeb5b..2d9ad5506bbc4 100644 --- a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h +++ b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h @@ -3,336 +3,64 @@ #pragma once -// for make stateful utility function(s) +#include +#include +#include +#include +#include +#include +#include + #include "openvino/pass/manager.hpp" #include "openvino/pass/make_stateful.hpp" #include "openvino/opsets/opset13.hpp" -static inline void logBasicModelInfo(const std::shared_ptr& model) { - std::cout << "Model name: " << model->get_friendly_name() << std::endl; - - // Dump information about model inputs/outputs - auto inputs = model->inputs(); - auto outputs = model->outputs(); - - std::cout << "\tInputs: " << std::endl; - for (const ov::Output& input : inputs) { - const std::string name = input.get_any_name(); - const ov::element::Type type = input.get_element_type(); - const ov::PartialShape shape = input.get_partial_shape(); - const ov::Layout layout = ov::layout::get_layout(input); - - std::cout << "\t\t" << name << ", " << type << ", " << shape << ", " << layout.to_string() << std::endl; - } - - std::cout << "\tOutputs: " << std::endl; - for (const ov::Output& output : outputs) { - const std::string name = output.get_any_name(); - const ov::element::Type type = output.get_element_type(); - const ov::PartialShape shape = output.get_partial_shape(); - const ov::Layout layout = ov::layout::get_layout(output); - - std::cout << "\t\t" << name << ", " << type << ", " << shape << ", " << layout.to_string() << std::endl; - } - - return; -} - -static inline bool model_has_input_output_names(std::shared_ptr model, const std::string& name_to_match) { - for (const ov::Output& input : model->inputs()) { - auto& names = input.get_names(); - - for (auto& name : names) { - if (name == name_to_match) { - return true; - } - } - } - - for (const ov::Output& output : model->outputs()) { - auto& names = output.get_names(); - for (auto& name : names) { - if (name == name_to_match) { - return true; - } - } - } - - return false; -} - -static void fuse_cache_reorder(std::shared_ptr ov_model, - std::vector& not_kv_inputs, - const std::vector& key_value_input_names, - int gather_dim) { - if (model_has_input_output_names(ov_model, "beam_idx")) { - throw std::runtime_error("Model already has fused cache"); - } - - std::string main_input_name = "inputs_embeds"; - if (model_has_input_output_names(ov_model, "input_ids")) { - main_input_name = "input_ids"; - } - - auto input_batch = ov_model->input(main_input_name).get_partial_shape()[0]; - - auto beam_idx = std::make_shared(ov::element::i32, ov::PartialShape({input_batch})); - beam_idx->set_friendly_name("beam_idx"); - beam_idx->output(0).get_tensor().add_names({"beam_idx"}); - ov_model->add_parameters({beam_idx}); - not_kv_inputs.push_back(beam_idx->get_friendly_name()); - - // Go over all cache parameters and fuse _reorder_cache with indices provided by the new parameter beam_idx - for (const auto& input_name : key_value_input_names) { - auto parameter_output_port = ov_model->input(input_name); - auto consumers = parameter_output_port.get_target_inputs(); - - auto gather_op = - std::make_shared(parameter_output_port, - beam_idx, - ov::opset13::Constant::create(ov::element::i64, {}, {gather_dim})); - - // Replace the source output for all consumers of the input tensor - for (auto& consumer : consumers) { - consumer.replace_source_output(gather_op->output(0)); - } - } +namespace onnxruntime { +namespace openvino_ep { - // Validate the modified model - ov_model->validate_nodes_and_infer_types(); -} +void LogBasicModelInfo(const std::shared_ptr& model); -static void make_stateful(std::shared_ptr& ov_model, - const std::vector& key_value_input_names, - const std::vector& key_value_output_names) { - std::map input_output_map; +bool ModelHasInputOutputNames(std::shared_ptr model, const std::string& name_to_match); - // Create mapping for KV-cache inputs and outputs - for (size_t i = 0; i < key_value_input_names.size(); ++i) { - input_output_map[key_value_input_names[i]] = key_value_output_names[i]; - } +void FuseCacheReorder(std::shared_ptr ov_model, + std::vector& not_kv_inputs, + const std::vector& key_value_input_names, + int gather_dim); - // Apply the transformation to make the model stateful - ov::pass::Manager manager; - manager.register_pass(input_output_map); - manager.run_passes(ov_model); -} +void MakeStateful(std::shared_ptr& ov_model, + const std::vector& key_value_input_names, + const std::vector& key_value_output_names); -// Converted to C++ from here: -// https://github.com/huggingface/optimum-intel/blob/main/optimum/exporters/openvino/stateful.py#L281 -static void patch_stateful_decoder(std::shared_ptr model) { - std::vector key_value_input_names; - std::vector not_kv_inputs; - for (const ov::Output& input : model->inputs()) { - auto& names = input.get_names(); +void PatchStatefulDecoder(std::shared_ptr model); - bool found = false; - for (auto& name : names) { - if (name.find("key_values") != std::string::npos) { - key_value_input_names.push_back(name); - found = true; - break; - } - } +bool HasOpWithType(const std::shared_ptr& function, const std::string& type_name); - if (!found) { - not_kv_inputs.push_back(input.get_any_name()); - } - } +std::tuple, int64_t> FindLLMMatmul(const std::shared_ptr& model); - std::vector key_value_output_names; - for (const ov::Output& output : model->outputs()) { - auto& names = output.get_names(); - for (auto& name : names) { - if (name.find("present") != std::string::npos) { - key_value_output_names.push_back(name); - break; - } - } - } +void ApplySliceBeforeMatmulTransformation(std::shared_ptr model); - if (key_value_input_names.empty() || key_value_output_names.empty()) { - std::cout << "no key_value_input_names or key_value_output_names found" << std::endl; - return; - } +void UpdateConfig(ov::AnyMap& config, const std::pair& pair); - // By default, batch is the 0 - th but chatglm uses 1 - st dimension as batch - // TODO: Deduce from a model via ordinal reshape(? ) and topology - // batch_dim = 1 if config.model_type == "chatglm" and not hasattr(config, "rope_ratio") else 0 - auto batch_dim = 0; +std::optional PopOption(ov::AnyMap& config, const std::string& option_name); - fuse_cache_reorder(model, not_kv_inputs, key_value_input_names, batch_dim); - - make_stateful(model, key_value_input_names, key_value_output_names); -} - -// Some other utility functions copied from OpenVINO GenAI -static bool has_op_with_type(const std::shared_ptr& function, const std::string& type_name) { - for (const auto& op : function->get_ops()) { - if (op->get_type_name() == type_name) { - return true; - } - } - return false; -} - -static std::tuple, int64_t> find_llm_matmul(const std::shared_ptr& model) { - auto last_node = model->output(0).get_node()->input_value(0).get_node_shared_ptr(); - std::shared_ptr matmul = ov::as_type_ptr(last_node); - - // in case of PA all tokens are moved to batch dimension and we have to slice / gather accordingly - const bool pa_based_model = has_op_with_type(model, "PagedAttentionExtension"); - int64_t slice_gather_dim = pa_based_model ? 0 : 1; - - // There are several patterns for matmul we are looking for: - // Matmul -> Result - // Matmul -> Add -> Result - // Matmul -> Transpose -> Result - // MatMul -> Divide -> Tanh -> Multiply -> Result - if (!matmul) { - if (auto add = ov::as_type_ptr(last_node)) { - matmul = ov::as_type_ptr(add->input_value(0).get_node_shared_ptr()); - } else if (auto transpose = ov::as_type_ptr(last_node)) { - matmul = ov::as_type_ptr(transpose->input_value(0).get_node_shared_ptr()); - auto order = ov::as_type_ptr(transpose->input_value(1).get_node_shared_ptr())->get_axis_vector_val(); - slice_gather_dim = order[slice_gather_dim]; - } else if (auto multiply = ov::as_type_ptr(last_node)) { - if (auto tanh = ov::as_type_ptr(multiply->input_value(0).get_node_shared_ptr())) { - if (auto divide = ov::as_type_ptr(tanh->input_value(0).get_node_shared_ptr())) { - matmul = as_type_ptr(divide->input_value(0).get_node_shared_ptr()); - } - } - } - } - return std::make_tuple(matmul, slice_gather_dim); -} - -static void apply_slice_before_matmul_transformation(std::shared_ptr model) { - std::shared_ptr matmul = nullptr; - int64_t slice_gather_dim = -1; - std::tie(matmul, slice_gather_dim) = find_llm_matmul(model); - - if (matmul && matmul->input(0).get_partial_shape().rank().get_length() == 3) { - auto start = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-1}); - auto stop = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-2}); - auto step = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{-1}); - auto axis = std::make_shared(ov::element::i64, ov::Shape{1}, std::vector{slice_gather_dim}); - auto slice = std::make_shared(matmul->input_value(0), start, stop, step, axis); - matmul->input(0).replace_source_output(slice); - } -} - -static void update_config(ov::AnyMap& config, const std::pair& pair) { - if (config.count(pair.first) == 0) { - config.insert(pair); - } -} - -static std::optional pop_option(ov::AnyMap& config, const std::string& option_name) { - if (auto it = config.find(option_name); it != config.end()) { - std::optional found = std::make_optional(it->second); - config.erase(it); - return found; - } - return std::nullopt; -} - -static void rename_key(ov::AnyMap& config, const std::string& old_key, const std::string& new_key) { - if (config.count(old_key) != 0) { - auto opt_value = pop_option(config, old_key); - config[new_key] = opt_value.value(); - } -} +void RenameKey(ov::AnyMap& config, const std::string& old_key, const std::string& new_key); struct KVAxesPosition { size_t batch; size_t seq_len; }; -KVAxesPosition get_kv_axes_pos(std::shared_ptr model) { - // sequence length axis in key/values tensors, for most cases [BATCH_SIZE, num_kv_heads, seq_len, head_size], - // therefore usually seq_length_axis = 2 and batch = 0 - KVAxesPosition kv_pos{0u, 2u}; - - // "ReadValue" node is KV cache representation in stateful model - std::string kv_node_type_name = std::string(ov::op::v6::ReadValue::get_type_info_static().name); - - for (const auto op : model->get_ops()) { - // check input size, as in LoRA adapters case it could be 0 - if (op->get_type_name() != kv_node_type_name || op->get_input_size() < 1) { - continue; - } - - // Shape example: [-1,4,0,64] - auto shape = op->get_input_partial_shape(0); - - for (int64_t i = 0; i < shape.rank().get_length(); i++) { - // Find axis = 0. This would be sequence length axis. - if (shape[i] == 0) { - kv_pos.seq_len = i; - } else if (shape[i].is_dynamic()) { - // Dynamic axis is a batch - kv_pos.batch = i; - } - } - break; - } - - return kv_pos; -} +KVAxesPosition GetKVAxesPos(std::shared_ptr model); struct KVDesc { uint32_t max_prompt_len; uint32_t min_response_len; }; -static void update_npu_config(ov::AnyMap& config, - const std::shared_ptr& model, - const KVAxesPosition& kv_pos, - const KVDesc& kv_desc) { - update_config(config, {"NPU_USE_NPUW", "YES"}); - update_config(config, {"NPUW_LLM", "YES"}); - - update_config(config, {"NPUW_LLM_BATCH_DIM", kv_pos.batch}); - update_config(config, {"NPUW_LLM_SEQ_LEN_DIM", kv_pos.seq_len}); - - update_config(config, {"NPUW_LLM_MAX_PROMPT_LEN", kv_desc.max_prompt_len}); - update_config(config, {"NPUW_LLM_MIN_RESPONSE_LEN", kv_desc.min_response_len}); - - rename_key(config, "++PREFILL_CONFIG", "++NPUW_LLM_PREFILL_CONFIG"); - rename_key(config, "++GENERATE_CONFIG", "++NPUW_LLM_GENERATE_CONFIG"); - rename_key(config, "PREFILL_CONFIG", "NPUW_LLM_PREFILL_CONFIG"); - rename_key(config, "PREFILL_HINT", "NPUW_LLM_PREFILL_HINT"); - rename_key(config, "GENERATE_CONFIG", "NPUW_LLM_GENERATE_CONFIG"); - rename_key(config, "GENERATE_HINT", "NPUW_LLM_GENERATE_HINT"); -} +void UpdateNPUConfig(ov::AnyMap& config, const KVAxesPosition& kv_pos, const KVDesc& kv_desc); -static std::optional pop_option_new(ov::AnyMap& config, const std::string& option_name) { - if (auto it = config.find(option_name); it != config.end()) { - std::optional found = std::make_optional(it->second); - config.erase(it); - return found; - } - return std::nullopt; -} +std::optional PopOptionNew(ov::AnyMap& config, const std::string& option_name); +std::optional PopIntAndCast(ov::AnyMap& config, const std::string& key); -static std::optional pop_int_and_cast(ov::AnyMap& config, const std::string& key) { - auto anyopt = pop_option_new(config, key); - if (anyopt.has_value()) { - const auto any = anyopt.value(); - int64_t value; - // NB: Integer value coming from python has int64_t datatype - if (any.is()) { - value = any.as(); - } else if (any.is()) { - value = any.as(); - } else { - OPENVINO_THROW("Failed to extract " + key + ". Type mismatch: expected types: int or int64_t"); - } - if (value < 0) { - OPENVINO_THROW(key + " cannot be negative!"); - } - return std::make_optional(static_cast(value)); - } - return std::nullopt; -} +} // namespace openvino_ep +} // namespace onnxruntime From 1ba8b20327ffcf44e24d5f46a77b0e0ba4852ffc Mon Sep 17 00:00:00 2001 From: ankitm3k Date: Fri, 4 Apr 2025 21:22:38 +0530 Subject: [PATCH 261/266] update: Refactor, fix & enable EPContext Import for XML & BIN --- .../openvino/backends/basic_backend.cc | 9 +- .../openvino/openvino_execution_provider.cc | 2 +- .../core/providers/openvino/ov_interface.cc | 161 +++++++++++++----- .../core/providers/openvino/ov_interface.h | 4 + .../openvino/ov_stateful_patch_utils.cc | 45 +++-- .../openvino/ov_stateful_patch_utils.h | 2 + 6 files changed, 154 insertions(+), 69 deletions(-) diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 5f5c2bde7206c..593561bd5c29f 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -85,13 +85,14 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr auto auto_unified_compile = ((hw_target.find("AUTO") == std::string::npos) || (session_context_.OpenVINO_Version.at(0) >= 2024 && session_context_.OpenVINO_Version.at(1) > 2)); - if (subgraph_context_.is_ep_ctx_graph) { + if (subgraph_context_.is_ep_ctx_graph && enable_causallm) { // If the blob is held in an EPContext node, then skip FE+Compile // and directly move on to creating a backend with the executable blob exe_network_ = OVCore::Get()->ImportModel(*model_stream, hw_target, device_config, - subgraph_context_.subgraph_name); + enable_causallm, + session_context_.onnx_model_path_name.string()); model_stream.reset(); // Delete stream after it is no longer needed } else if (!session_context_.has_external_weights && !subgraph_context_.has_dynamic_input_shape && @@ -285,7 +286,7 @@ void BasicBackend::PopulateConfigValue(ov::AnyMap& device_config) { //// Parse to get the device mode (e.g., "AUTO:CPU,GPU" -> "AUTO") std::unordered_set supported_mode = {"AUTO", "HETERO", "MULTI"}; auto device_mode = find_device_type_mode(session_context_.device_type); - ORT_ENFORCE(supported_mode.find(device_mode)!=supported_mode.end(), " Invalid device mode is passed : " , session_context_.device_type); + ORT_ENFORCE(supported_mode.find(device_mode) != supported_mode.end(), " Invalid device mode is passed : ", session_context_.device_type); // Parse individual devices (e.g., "AUTO:CPU,GPU" -> ["CPU", "GPU"]) auto individual_devices = parse_individual_devices(session_context_.device_type); if (!device_mode.empty()) individual_devices.emplace_back(device_mode); @@ -379,7 +380,7 @@ void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferReque // for the stateful PoC, the ONNX model will have KV cache (past/present) tensors, but // we internally converted it to stateful, which removed these. So, we just continue here // to avoid runtime exception. - if (input_name.empty()) continue; + if (input_name.empty() || input_name == "beam_idx") continue; ORT_ENFORCE(!input_name.empty(), log_tag, "Input names mismatch between OpenVINO and ONNX. ", onnx_input_name, diff --git a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc index da12d7f27d61a..122c3c4f0899a 100644 --- a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc +++ b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc @@ -96,7 +96,7 @@ OpenVINOExecutionProvider::OpenVINOExecutionProvider(const ProviderInfo& info, s // If idx is 0, maybe index is not set (e.g. GPU) // Then the device is found if we have at least one device of the type if (device_idx == 0 && available_devices.size() >= 1) { - device_found = true; + device_found = true; } else { // Find full device (e.g GPU.1) in the list if (std::find(std::begin(available_devices), std::end(available_devices), device) != std::end(available_devices)) diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index 13e27337b7184..09b7ff929cfe1 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -74,61 +74,72 @@ std::shared_ptr OVCore::ReadModel(std::string&& model, const std::str } } -OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_network, - std::string& hw_target, - ov::AnyMap& device_config, - bool enable_causallm, - const std::string& name) { - ov::CompiledModel obj; - try { - if (enable_causallm) { - ov::AnyMap config; +OVExeNetwork OVCore::StatefulCompileModel(std::shared_ptr& model, + std::string& hw_target, + const ov::AnyMap& device_config) { + ov::CompiledModel compiled_model; + ov::AnyMap config = device_config; - // Create a clone of ie_cnn_network, since it's a const ov::Model, and we need to patch it.. - // Note! With this default path, the model runs but produces garbage (for NPUW). For CPU it's fine. - auto mutable_model = ie_cnn_network->clone(); + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "Stateless OV Model Statistic:" << std::endl; + LogBasicModelInfo(model); + } - if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { - std::cout << "Stateless OV Model Statistic" << std::endl; - LogBasicModelInfo(mutable_model); - } - LogBasicModelInfo(mutable_model); + LOGS_DEFAULT(INFO) << log_tag << "Converting from Stateless OV Model to Stateful OV Model" << std::endl; + bool status = IsStateful(model); + std::cout << "IsStateful Status:\t" << status << std::endl; + if (!status) { + PatchStatefulDecoder(model); + } - LOGS_DEFAULT(INFO) << log_tag << "Converting from Stateless OV Model to Stateful OV Model" << std::endl; - PatchStatefulDecoder(mutable_model); + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "Stateful OV Model Statistic:" << std::endl; + LogBasicModelInfo(model); + } - if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { - std::cout << "Stateful OV Model Statistic" << std::endl; - LogBasicModelInfo(mutable_model); - } + auto kv_pos = GetKVAxesPos(model); + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "kv_pos.batch = " << kv_pos.batch << std::endl; + std::cout << "kv_pos.seq_len = " << kv_pos.seq_len << std::endl; + } - // This patches the model so that it only produces the logits required for sampling. - // Actually either way that happens within NPUW::LLMCompiledModel creation, but this is - // here mostly to align this behavior for other devices (CPU, GPU). - ApplySliceBeforeMatmulTransformation(mutable_model); + if (hw_target.find("NPU") != std::string::npos) { + KVDesc kv_desc; + kv_desc.max_prompt_len = PopIntAndCast(config, "MAX_PROMPT_LEN").value_or(1024u); + kv_desc.min_response_len = PopIntAndCast(config, "MIN_RESPONSE_LEN").value_or(128u); - auto kv_pos = GetKVAxesPos(mutable_model); - if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { - std::cout << "kv_pos.batch = " << kv_pos.batch << std::endl; - std::cout << "kv_pos.seq_len = " << kv_pos.seq_len << std::endl; - } + if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { + std::cout << "kv_desc.max_prompt_len:\t" << kv_desc.max_prompt_len << std::endl; + std::cout << "kv_desc.min_response_len:\t" << kv_desc.min_response_len << std::endl; + } - if (hw_target.find("NPU") != std::string::npos) { - KVDesc kv_desc; - kv_desc.max_prompt_len = PopIntAndCast(device_config, "MAX_PROMPT_LEN").value_or(1024u); - kv_desc.min_response_len = PopIntAndCast(device_config, "MIN_RESPONSE_LEN").value_or(128u); + UpdateNPUConfig(config, kv_pos, kv_desc); + } else { + // This patches the model so that it only produces the logits required for sampling. + // Actually either way that happens within NPUW::LLMCompiledModel creation, but this is + // here mostly to align this behavior for other devices (CPU, GPU). + ApplySliceBeforeMatmulTransformation(model); + } - if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { - std::cout << "kv_desc.max_prompt_len = " << kv_desc.max_prompt_len << std::endl; - std::cout << "kv_desc.min_response_len = " << kv_desc.min_response_len << std::endl; - } + std::cout << "Compiling Stateful OV Model ..." << std::endl; + compiled_model = OVCore::Get()->core.compile_model(model, hw_target, config); + std::cout << "Stateful OV Model Compilation Complete" << std::endl; - UpdateNPUConfig(config, kv_pos, kv_desc); - } + OVExeNetwork exe(compiled_model); + return exe; +} - std::cout << "Compiling Stateful OV Model..." << std::endl; - obj = core.compile_model(mutable_model, hw_target, config); - std::cout << "Stateful OV Model Compilation Complete" << std::endl; +OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_network, + std::string& hw_target, + ov::AnyMap& device_config, + bool enable_causallm, + const std::string& name) { + ov::CompiledModel obj; + try { + if (enable_causallm) { + auto mutable_model = ie_cnn_network->clone(); + auto compiled_model = OVCore::Get()->StatefulCompileModel(mutable_model, hw_target, device_config); + obj = compiled_model.Get(); } else { obj = core.compile_model(ie_cnn_network, hw_target, device_config); } @@ -166,10 +177,68 @@ OVExeNetwork OVCore::CompileModel(const std::string& onnx_model, OVExeNetwork OVCore::ImportModel(std::istream& model_stream, std::string hw_target, const ov::AnyMap& device_config, + bool enable_causallm, std::string name) { try { ov::CompiledModel obj; - obj = core.import_model(model_stream, hw_target, device_config); + + // Check if it's XML + std::streampos originalPos = model_stream.tellg(); + // Allocate space for "= 5 && name.substr(name.size() - 5) == ".onnx") { + bin_file = name; + bin_file.replace(name.size() - 5, 5, ".bin"); + } else { + throw std::runtime_error("Invalid model name. Make sure *.onnx, *.xml, and *.bin carry the same name."); + } + + // Read the model XML into a string + std::stringstream xml_stream; + xml_stream << model_stream.rdbuf(); + std::string xml_content = xml_stream.str(); + + // Read model.bin into a vector + std::ifstream bin_stream; + bin_stream.open(bin_file, std::ios::binary); + if (!bin_stream.is_open()) { + throw std::runtime_error("Failed to open " + bin_file); + } + + bin_stream.seekg(0, std::ios::end); + std::streamsize size = bin_stream.tellg(); + bin_stream.seekg(0, std::ios::beg); + std::vector bin_data(size); + if (!bin_stream.read(reinterpret_cast(bin_data.data()), size)) { + throw std::runtime_error("Failed to read binary data from " + bin_file); + } + + // Create an ov::Tensor for weights + ov::Tensor weights_tensor(ov::element::u8, {bin_data.size()}, bin_data.data()); + + // Load the model explicitly with XML content and weights + std::shared_ptr model = core.read_model(xml_content, weights_tensor); + + if (enable_causallm) { + auto compiled_model = OVCore::Get()->StatefulCompileModel(model, hw_target, device_config); + obj = compiled_model.Get(); + } else { + obj = core.compile_model(model, hw_target, device_config); + } + } + #ifndef NDEBUG printDebugInfo(obj); #endif diff --git a/onnxruntime/core/providers/openvino/ov_interface.h b/onnxruntime/core/providers/openvino/ov_interface.h index a11628ed370c7..6051eafdf86a0 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.h +++ b/onnxruntime/core/providers/openvino/ov_interface.h @@ -69,6 +69,9 @@ struct OVCore : WeakSingleton { // OV Interface For Reading Model std::shared_ptr ReadModel(std::string&& model_stream, const std::string& model_path); + OVExeNetwork StatefulCompileModel(std::shared_ptr& model, + std::string& hw_target, + const ov::AnyMap& device_config); // OV Interface for Compiling OV Model Type OVExeNetwork CompileModel(std::shared_ptr& ie_cnn_network, std::string& hw_target, @@ -84,6 +87,7 @@ struct OVCore : WeakSingleton { OVExeNetwork ImportModel(std::istream& model_stream, std::string hw_target, const ov::AnyMap& device_config, + bool enable_causallm, std::string name); #ifdef IO_BUFFER_ENABLED OVExeNetwork CompileModel(std::shared_ptr& model, diff --git a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc index b634560e58a84..3961c673a212c 100644 --- a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc +++ b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.cc @@ -6,8 +6,7 @@ namespace onnxruntime { namespace openvino_ep { - - void LogBasicModelInfo(const std::shared_ptr& model) { +void LogBasicModelInfo(const std::shared_ptr& model) { std::cout << "Model Name: " << model->get_friendly_name() << std::endl; // Dump information about model inputs/outputs @@ -37,7 +36,7 @@ namespace openvino_ep { return; } - bool ModelHasInputOutputNames(std::shared_ptr model, const std::string& name_to_match) { +bool ModelHasInputOutputNames(std::shared_ptr model, const std::string& name_to_match) { for (const ov::Output& input : model->inputs()) { auto& names = input.get_names(); @@ -60,10 +59,10 @@ namespace openvino_ep { return false; } - void FuseCacheReorder(std::shared_ptr ov_model, - std::vector& not_kv_inputs, - const std::vector& key_value_input_names, - int gather_dim) { +void FuseCacheReorder(std::shared_ptr ov_model, + std::vector& not_kv_inputs, + const std::vector& key_value_input_names, + int gather_dim) { if (ModelHasInputOutputNames(ov_model, "beam_idx")) { throw std::runtime_error("Model already has fused cache"); } @@ -101,9 +100,9 @@ namespace openvino_ep { ov_model->validate_nodes_and_infer_types(); } - void MakeStateful(std::shared_ptr& ov_model, - const std::vector& key_value_input_names, - const std::vector& key_value_output_names) { +void MakeStateful(std::shared_ptr& ov_model, + const std::vector& key_value_input_names, + const std::vector& key_value_output_names) { std::map input_output_map; // Create mapping for KV-cache inputs and outputs @@ -119,7 +118,7 @@ namespace openvino_ep { // Converted to C++ from here: // https://github.com/huggingface/optimum-intel/blob/main/optimum/exporters/openvino/stateful.py#L281 - void PatchStatefulDecoder(std::shared_ptr model) { +void PatchStatefulDecoder(std::shared_ptr model) { std::vector key_value_input_names; std::vector not_kv_inputs; for (const ov::Output& input : model->inputs()) { @@ -166,7 +165,7 @@ namespace openvino_ep { } // Some other utility functions copied from OpenVINO GenAI - bool HasOpWithType(const std::shared_ptr& function, const std::string& type_name) { +bool HasOpWithType(const std::shared_ptr& function, const std::string& type_name) { for (const auto& op : function->get_ops()) { if (op->get_type_name() == type_name) { return true; @@ -175,7 +174,7 @@ namespace openvino_ep { return false; } - std::tuple, int64_t> FindLLMMatmul(const std::shared_ptr& model) { +std::tuple, int64_t> FindLLMMatmul(const std::shared_ptr& model) { auto last_node = model->output(0).get_node()->input_value(0).get_node_shared_ptr(); std::shared_ptr matmul = ov::as_type_ptr(last_node); @@ -206,7 +205,7 @@ namespace openvino_ep { return std::make_tuple(matmul, slice_gather_dim); } - void ApplySliceBeforeMatmulTransformation(std::shared_ptr model) { +void ApplySliceBeforeMatmulTransformation(std::shared_ptr model) { std::shared_ptr matmul = nullptr; int64_t slice_gather_dim = -1; std::tie(matmul, slice_gather_dim) = FindLLMMatmul(model); @@ -221,13 +220,13 @@ namespace openvino_ep { } } - void UpdateConfig(ov::AnyMap& config, const std::pair& pair) { +void UpdateConfig(ov::AnyMap& config, const std::pair& pair) { if (config.count(pair.first) == 0) { config.insert(pair); } } - std::optional PopOption(ov::AnyMap& config, const std::string& option_name) { +std::optional PopOption(ov::AnyMap& config, const std::string& option_name) { if (auto it = config.find(option_name); it != config.end()) { std::optional found = std::make_optional(it->second); config.erase(it); @@ -236,14 +235,13 @@ namespace openvino_ep { return std::nullopt; } - void RenameKey(ov::AnyMap& config, const std::string& old_key, const std::string& new_key) { +void RenameKey(ov::AnyMap& config, const std::string& old_key, const std::string& new_key) { if (config.count(old_key) != 0) { auto opt_value = PopOption(config, old_key); config[new_key] = opt_value.value(); } } - KVAxesPosition GetKVAxesPos(std::shared_ptr model) { // sequence length axis in key/values tensors, for most cases [BATCH_SIZE, num_kv_heads, seq_len, head_size], // therefore usually seq_length_axis = 2 and batch = 0 @@ -324,6 +322,17 @@ std::optional PopIntAndCast(ov::AnyMap& config, const std::string& key return std::nullopt; } +bool IsStateful(const std::shared_ptr& model) { + for (auto&& ptr : model->get_ordered_ops()) { + if (ov::is_type(ptr) || + ov::is_type(ptr) || + ov::is_type(ptr) || + ov::is_type(ptr)) { + return true; + } + } + return false; +} } // namespace openvino_ep } // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h index 2d9ad5506bbc4..2a4434c282493 100644 --- a/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h +++ b/onnxruntime/core/providers/openvino/ov_stateful_patch_utils.h @@ -62,5 +62,7 @@ void UpdateNPUConfig(ov::AnyMap& config, const KVAxesPosition& kv_pos, const KVD std::optional PopOptionNew(ov::AnyMap& config, const std::string& option_name); std::optional PopIntAndCast(ov::AnyMap& config, const std::string& key); +bool IsStateful(const std::shared_ptr& model); + } // namespace openvino_ep } // namespace onnxruntime From c858abc4a5c938177e8616c291a8f45627a54169 Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe Date: Mon, 7 Apr 2025 04:24:38 -0800 Subject: [PATCH 262/266] Support chat-mode for NPU --- .../openvino/backends/basic_backend.h | 2 +- .../core/providers/openvino/ov_interface.cc | 119 ++++++++++++++---- .../core/providers/openvino/ov_interface.h | 30 ++++- 3 files changed, 118 insertions(+), 33 deletions(-) diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.h b/onnxruntime/core/providers/openvino/backends/basic_backend.h index 7d905f4a1e2f7..4bb6997fb374b 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.h +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.h @@ -78,7 +78,7 @@ class InferRequestsQueue { InferRequestsQueue(OVExeNetwork& net, size_t nireq, std::function initializer) { OVInferRequestPtr infer_request; for (size_t id = 0; id < nireq; id++) { - infer_request = std::make_shared(net.CreateInferRequest()); + infer_request = net.CreateInferRequest(); initializer(infer_request); infer_requests_.push_back(infer_request); } diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index 09b7ff929cfe1..be484f70d5cd2 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -105,7 +105,7 @@ OVExeNetwork OVCore::StatefulCompileModel(std::shared_ptr& model, if (hw_target.find("NPU") != std::string::npos) { KVDesc kv_desc; - kv_desc.max_prompt_len = PopIntAndCast(config, "MAX_PROMPT_LEN").value_or(1024u); + kv_desc.max_prompt_len = PopIntAndCast(config, "MAX_PROMPT_LEN").value_or(3072u); kv_desc.min_response_len = PopIntAndCast(config, "MIN_RESPONSE_LEN").value_or(128u); if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { @@ -125,7 +125,7 @@ OVExeNetwork OVCore::StatefulCompileModel(std::shared_ptr& model, compiled_model = OVCore::Get()->core.compile_model(model, hw_target, config); std::cout << "Stateful OV Model Compilation Complete" << std::endl; - OVExeNetwork exe(compiled_model); + OVExeNetwork exe(compiled_model, hw_target, true); return exe; } @@ -134,19 +134,18 @@ OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_netwo ov::AnyMap& device_config, bool enable_causallm, const std::string& name) { - ov::CompiledModel obj; + OVExeNetwork exe; try { if (enable_causallm) { auto mutable_model = ie_cnn_network->clone(); - auto compiled_model = OVCore::Get()->StatefulCompileModel(mutable_model, hw_target, device_config); - obj = compiled_model.Get(); + exe = OVCore::Get()->StatefulCompileModel(mutable_model, hw_target, device_config); } else { - obj = core.compile_model(ie_cnn_network, hw_target, device_config); + auto obj = core.compile_model(ie_cnn_network, hw_target, device_config); + exe = OVExeNetwork(obj, hw_target); } #ifndef NDEBUG printDebugInfo(obj); #endif - OVExeNetwork exe(obj); return exe; } catch (const Exception& e) { ORT_THROW(log_tag + " Exception while Loading Network for graph: " + name + e.what()); @@ -165,7 +164,7 @@ OVExeNetwork OVCore::CompileModel(const std::string& onnx_model, #ifndef NDEBUG printDebugInfo(obj); #endif - OVExeNetwork exe(obj); + OVExeNetwork exe(obj, hw_target); return exe; } catch (const Exception& e) { ORT_THROW(log_tag + " Exception while Loading Network for graph: " + name + e.what()); @@ -180,7 +179,7 @@ OVExeNetwork OVCore::ImportModel(std::istream& model_stream, bool enable_causallm, std::string name) { try { - ov::CompiledModel obj; + OVExeNetwork exe; // Check if it's XML std::streampos originalPos = model_stream.tellg(); @@ -194,7 +193,8 @@ OVExeNetwork OVCore::ImportModel(std::istream& model_stream, model_stream.seekg(originalPos); if (header != " model = core.read_model(xml_content, weights_tensor); if (enable_causallm) { - auto compiled_model = OVCore::Get()->StatefulCompileModel(model, hw_target, device_config); - obj = compiled_model.Get(); + exe = OVCore::Get()->StatefulCompileModel(model, hw_target, device_config); } else { - obj = core.compile_model(model, hw_target, device_config); + auto obj = core.compile_model(model, hw_target, device_config); + exe = OVExeNetwork(obj, hw_target); } } #ifndef NDEBUG printDebugInfo(obj); #endif - OVExeNetwork exe(obj); return exe; } catch (const Exception& e) { ORT_THROW(log_tag + " Exception while Loading Network for graph: " + name + e.what()); @@ -330,11 +329,16 @@ void OVCore::SetStreams(const std::string& device_type, int num_streams) { core.set_property(device_type, {ov::num_streams(num_streams)}); } -OVInferRequest OVExeNetwork::CreateInferRequest() { +std::shared_ptr OVExeNetwork::CreateInferRequest() { try { auto infReq = obj.create_infer_request(); - OVInferRequest inf_obj(std::move(infReq)); - return inf_obj; + std::shared_ptr ovInfReq; + if (_stateful_llm) { + ovInfReq = std::make_shared(std::move(infReq), _device); + } else { + ovInfReq = std::make_shared(std::move(infReq)); + } + return ovInfReq; } catch (const Exception& e) { ORT_THROW(log_tag + "Exception while creating InferRequest object: " + e.what()); } catch (...) { @@ -368,16 +372,6 @@ std::string OVInferRequest::GetInputTensorName(uint32_t index) { void OVInferRequest::SetTensor(const std::string& name, OVTensorPtr& blob) { try { ovInfReq.set_tensor(name, *(blob.get())); - - if (name == "input_ids") { - // Since we can't seem to set at ORT GenAI layer right now, we just set it here - // as a workaround. - // TODO: Fix this. - ov::Tensor beam_idx = ov::Tensor(ov::element::i32, {1}); - std::fill_n(beam_idx.data(), 1, 0); - ovInfReq.set_tensor("beam_idx", beam_idx); - } - } catch (const Exception& e) { ORT_THROW(log_tag + " Cannot set Remote Blob for output: " + name + e.what()); } catch (...) { @@ -423,5 +417,76 @@ void OVInferRequest::QueryStatus() { std::cout << "ovInfReq.query_state()" << " "; } + +void StatefulOVInferRequest::_pre_infer() { + // Since we can't seem to set at ORT GenAI layer right now, we just set it here + // as a workaround. + // TODO: Fix this. + ov::Tensor beam_idx = ov::Tensor(ov::element::i32, {1}); + std::fill_n(beam_idx.data(), 1, 0); + ovInfReq.set_tensor("beam_idx", beam_idx); + + // For NPU, we need to cache input_ids and position_ids for + // chat-mode support. + if (device.find("NPU") != std::string::npos) { + auto input_ids_tensor = ovInfReq.get_tensor("input_ids"); + + // add input_ids to our cache + { + auto* pData = input_ids_tensor.data(); + for (size_t i = 0; i < input_ids_tensor.get_size(); i++) { + cached_input_ids.push_back(pData[i]); + } + } + + // add position_ids to our cache + { + auto position_ids = ovInfReq.get_tensor("position_ids"); + auto* pData = position_ids.data(); + for (size_t i = 0; i < position_ids.get_size(); i++) { + cached_position_ids.push_back(pData[i]); + } + } + + // if we're about to run prefill model + if (input_ids_tensor.get_size() > 1) { + // if the input_ids size doesn't equal cached size of the input_ids + // then it means that we're running 2nd (or later) prompt. + if (input_ids_tensor.get_shape()[1] != cached_input_ids.size()) { + // set a new input_ids tensor with the content of our cached input_ids + { + auto new_shape = input_ids_tensor.get_shape(); + new_shape[1] = cached_input_ids.size(); + auto new_input_ids = ov::Tensor(input_ids_tensor.get_element_type(), new_shape); + auto* pNewInputIds = new_input_ids.data(); + std::memcpy(pNewInputIds, cached_input_ids.data(), cached_input_ids.size() * sizeof(int64_t)); + ovInfReq.set_tensor("input_ids", new_input_ids); + } + + // set a new position_ids tensor with the content of our cached position_ids + { + auto position_ids_tensor = ovInfReq.get_tensor("position_ids"); + auto new_shape = position_ids_tensor.get_shape(); + new_shape[1] = cached_position_ids.size(); + auto new_position_ids = ov::Tensor(position_ids_tensor.get_element_type(), new_shape); + auto* pNewPositionIds = new_position_ids.data(); + std::memcpy(pNewPositionIds, cached_position_ids.data(), cached_position_ids.size() * sizeof(int64_t)); + ovInfReq.set_tensor("position_ids", new_position_ids); + } + } + } + } +} + +void StatefulOVInferRequest::StartAsync() { + _pre_infer(); + OVInferRequest::StartAsync(); +} + +void StatefulOVInferRequest::Infer() { + _pre_infer(); + OVInferRequest::Infer(); +} + } // namespace openvino_ep } // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/ov_interface.h b/onnxruntime/core/providers/openvino/ov_interface.h index 6051eafdf86a0..cc9aa7677a014 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.h +++ b/onnxruntime/core/providers/openvino/ov_interface.h @@ -105,15 +105,18 @@ struct OVCore : WeakSingleton { class OVExeNetwork { ov::CompiledModel obj; - + std::string _device; + bool _stateful_llm; public: - explicit OVExeNetwork(ov::CompiledModel md) : obj(md) {} + explicit OVExeNetwork(ov::CompiledModel md, std::string device, bool stateful_llm = false) + : obj(md), _device(device), _stateful_llm(stateful_llm) {} OVExeNetwork() : obj(ov::CompiledModel()) {} ov::CompiledModel& Get() { return obj; } - OVInferRequest CreateInferRequest(); + std::shared_ptr CreateInferRequest(); }; class OVInferRequest { + protected: ov::InferRequest ovInfReq; public: @@ -121,8 +124,8 @@ class OVInferRequest { OVTensorPtr GetTensor(const std::string& name); std::string GetInputTensorName(uint32_t index); void SetTensor(const std::string& name, OVTensorPtr& blob); - void StartAsync(); - void Infer(); + virtual void StartAsync(); + virtual void Infer(); void WaitRequest(); void QueryStatus(); explicit OVInferRequest(ov::InferRequest obj) : ovInfReq(std::move(obj)) {} @@ -131,5 +134,22 @@ class OVInferRequest { return ovInfReq; } }; + +class StatefulOVInferRequest : public OVInferRequest { + public: + explicit StatefulOVInferRequest(ov::InferRequest obj, std::string d) : OVInferRequest(std::move(obj)), device(d) {} + + void StartAsync() override; + void Infer() override; + + private: + void _pre_infer(); + std::string device; + + // For NPU, we need to cache input_ids & position_ids to support chat-mode. + std::vector cached_input_ids; + std::vector cached_position_ids; +}; + } // namespace openvino_ep } // namespace onnxruntime From a0c11c7e7f605d62488ffefc71f783d165b6eb67 Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe Date: Mon, 7 Apr 2025 05:13:38 -0800 Subject: [PATCH 263/266] Support KVCache rewind for stateful LLMs via SetEpDynamicOptions --- .../providers/openvino/backend_manager.cc | 6 +++ .../core/providers/openvino/backend_manager.h | 1 + .../openvino/backends/basic_backend.cc | 7 +++ .../openvino/backends/basic_backend.h | 1 + .../core/providers/openvino/ibackend.h | 1 + .../openvino/openvino_execution_provider.cc | 18 +++++++ .../core/providers/openvino/ov_interface.cc | 47 ++++++++++++++++++- .../core/providers/openvino/ov_interface.h | 2 + 8 files changed, 82 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/openvino/backend_manager.cc b/onnxruntime/core/providers/openvino/backend_manager.cc index b73f905a1bb35..a3045640518fc 100644 --- a/onnxruntime/core/providers/openvino/backend_manager.cc +++ b/onnxruntime/core/providers/openvino/backend_manager.cc @@ -550,5 +550,11 @@ void BackendManager::ShutdownBackendManager() { concrete_backend_.reset(); } +void BackendManager::RewindKVCache(size_t index) { + if (concrete_backend_) { + concrete_backend_->RewindKVCache(index); + } +} + } // namespace openvino_ep } // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/backend_manager.h b/onnxruntime/core/providers/openvino/backend_manager.h index cdc27701ec2e6..93c185ab6a3ee 100644 --- a/onnxruntime/core/providers/openvino/backend_manager.h +++ b/onnxruntime/core/providers/openvino/backend_manager.h @@ -30,6 +30,7 @@ class BackendManager { SessionContext& GetSessionContext(); Status ExportCompiledBlobAsEPCtxNode(const onnxruntime::GraphViewer& subgraph); ov::CompiledModel& GetOVCompiledModel(); + void RewindKVCache(size_t index); private: std::unique_ptr GetModelProtoFromFusedNode( diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 593561bd5c29f..65e1694d5b243 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -358,6 +358,13 @@ void BasicBackend::SetNumThreads(ov::AnyMap& device_config) { device_config.emplace(ov::inference_num_threads(session_context_.num_of_threads)); } +void BasicBackend::RewindKVCache(size_t index) { + OVInferRequestPtr infer_request; + infer_request = inferRequestsQueue_->getIdleRequest(); + infer_request->RewindKVCache(index); + inferRequestsQueue_->putIdleRequest(std::move(infer_request)); +} + // Starts an asynchronous inference request for data in slice indexed by batch_slice_idx on // an Infer Request indexed by infer_req_idx void BasicBackend::StartAsyncInference(Ort::KernelContext& context, OVInferRequestPtr infer_request) { diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.h b/onnxruntime/core/providers/openvino/backends/basic_backend.h index 4bb6997fb374b..57405af84122f 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.h +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.h @@ -41,6 +41,7 @@ class BasicBackend : public IBackend { ov::CompiledModel& GetOVCompiledModel() override { return exe_network_.Get(); } + void RewindKVCache(size_t index) override; private: void PopulateCompiledDirectory(std::string, std::string&, std::string&, bool&); diff --git a/onnxruntime/core/providers/openvino/ibackend.h b/onnxruntime/core/providers/openvino/ibackend.h index 04d1f52cbf834..1b6f7936493fe 100644 --- a/onnxruntime/core/providers/openvino/ibackend.h +++ b/onnxruntime/core/providers/openvino/ibackend.h @@ -17,6 +17,7 @@ class IBackend { virtual void Infer(OrtKernelContext* context) = 0; virtual ov::CompiledModel& GetOVCompiledModel() = 0; virtual ~IBackend() = default; + virtual void RewindKVCache(size_t index) {}; }; using ptr_stream_t = std::unique_ptr; class BackendFactory { diff --git a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc index 122c3c4f0899a..5d481edfe056e 100644 --- a/onnxruntime/core/providers/openvino/openvino_execution_provider.cc +++ b/onnxruntime/core/providers/openvino/openvino_execution_provider.cc @@ -295,6 +295,24 @@ common::Status OpenVINOExecutionProvider::SetEpDynamicOptions(gsl::span= 0) { + backend.RewindKVCache(static_cast(index)); + } else { + LOGS_DEFAULT(WARNING) << "kvcache_rewind index is < 0: " << index; + } + } } else { // Handle unknown options LOGS_DEFAULT(WARNING) << "Unknown key/value pair - ignoring " << key << "/" << value; diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index be484f70d5cd2..7d5f09ea5847c 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -105,7 +105,7 @@ OVExeNetwork OVCore::StatefulCompileModel(std::shared_ptr& model, if (hw_target.find("NPU") != std::string::npos) { KVDesc kv_desc; - kv_desc.max_prompt_len = PopIntAndCast(config, "MAX_PROMPT_LEN").value_or(3072u); + kv_desc.max_prompt_len = PopIntAndCast(config, "MAX_PROMPT_LEN").value_or(1024u); kv_desc.min_response_len = PopIntAndCast(config, "MIN_RESPONSE_LEN").value_or(128u); if (onnxruntime::openvino_ep::backend_utils::IsDebugEnabled()) { @@ -488,5 +488,50 @@ void StatefulOVInferRequest::Infer() { OVInferRequest::Infer(); } +void StatefulOVInferRequest::RewindKVCache(size_t index) { + if (device == "NPU") { + std::cout << "RewindKVCache on NPU: Trimming cached input_ids / position_ids to length " + << index << std::endl; + if (cached_input_ids.size() > index) { + cached_input_ids.resize(index); + } + + if (cached_position_ids.size() > index) { + cached_position_ids.resize(index); + } + } else { + std::cout << "OVInferRequest::RewindKVCache: Trimming internal states to length = " + << index << std::endl; + if (index == 0) { + // in this case, since we're trimming *all* of the KVCache, just reset the state. + ovInfReq.reset_state(); + } else { + // retrieve kvcache states, and trim... + // Most of this code was grabbed from here: + // https://github.com/openvinotoolkit/openvino.genai/blob/releases/2025/1/src/cpp/src/utils.cpp#L329 + auto states = ovInfReq.query_state(); + for (auto& state : states) { + ov::Tensor old_tensor = state.get_state(); + // [BATCH_SIZE, num_kv_heads, seq_len, head_size] + auto shape = old_tensor.get_shape(); + + if (shape[2] > index) { + shape[2] = index; + + ov::Coordinate new_shape_begin{0, 0, 0, 0}; + ov::Coordinate new_shape_end{shape}; + + auto trimmed_tensor = ov::Tensor(old_tensor, new_shape_begin, new_shape_end); + + ov::Tensor new_tensor(old_tensor.get_element_type(), shape); + trimmed_tensor.copy_to(new_tensor); + + state.set_state(new_tensor); + } + } + } + } +} + } // namespace openvino_ep } // namespace onnxruntime diff --git a/onnxruntime/core/providers/openvino/ov_interface.h b/onnxruntime/core/providers/openvino/ov_interface.h index cc9aa7677a014..8e356b96cdc77 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.h +++ b/onnxruntime/core/providers/openvino/ov_interface.h @@ -133,6 +133,7 @@ class OVInferRequest { ov::InferRequest& GetNewObj() { return ovInfReq; } + virtual void RewindKVCache(size_t index) {}; }; class StatefulOVInferRequest : public OVInferRequest { @@ -141,6 +142,7 @@ class StatefulOVInferRequest : public OVInferRequest { void StartAsync() override; void Infer() override; + void RewindKVCache(size_t index) override; private: void _pre_infer(); From 7a8dbe2fcb98892b4100b670c38289e9089c6923 Mon Sep 17 00:00:00 2001 From: Ryan Metcalfe <107415876+RyanMetcalfeInt8@users.noreply.github.com> Date: Tue, 8 Apr 2025 01:35:50 -0400 Subject: [PATCH 264/266] ov_interface.cc: Fix compilation errors in Debug build (#642) --- onnxruntime/core/providers/openvino/ov_interface.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index 7d5f09ea5847c..f9e40c782fde2 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -143,9 +143,11 @@ OVExeNetwork OVCore::CompileModel(std::shared_ptr& ie_cnn_netwo auto obj = core.compile_model(ie_cnn_network, hw_target, device_config); exe = OVExeNetwork(obj, hw_target); } + #ifndef NDEBUG - printDebugInfo(obj); + printDebugInfo(exe.Get()); #endif + return exe; } catch (const Exception& e) { ORT_THROW(log_tag + " Exception while Loading Network for graph: " + name + e.what()); @@ -240,7 +242,7 @@ OVExeNetwork OVCore::ImportModel(std::istream& model_stream, } #ifndef NDEBUG - printDebugInfo(obj); + printDebugInfo(exe.Get()); #endif return exe; } catch (const Exception& e) { From 1ff02d1036ea6db56430d403da8b9d40e4175a85 Mon Sep 17 00:00:00 2001 From: Ankit Maheshkar Date: Tue, 8 Apr 2025 20:09:02 +0530 Subject: [PATCH 265/266] fix: disable ep_sdk_version check (#645) --- onnxruntime/core/providers/openvino/backends/basic_backend.cc | 2 +- onnxruntime/core/providers/openvino/onnx_ctx_model_helper.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.cc b/onnxruntime/core/providers/openvino/backends/basic_backend.cc index 65e1694d5b243..e406b1b02259d 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.cc +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.cc @@ -85,7 +85,7 @@ BasicBackend::BasicBackend(std::unique_ptr& model_pr auto auto_unified_compile = ((hw_target.find("AUTO") == std::string::npos) || (session_context_.OpenVINO_Version.at(0) >= 2024 && session_context_.OpenVINO_Version.at(1) > 2)); - if (subgraph_context_.is_ep_ctx_graph && enable_causallm) { + if (subgraph_context_.is_ep_ctx_graph) { // If the blob is held in an EPContext node, then skip FE+Compile // and directly move on to creating a backend with the executable blob exe_network_ = OVCore::Get()->ImportModel(*model_stream, diff --git a/onnxruntime/core/providers/openvino/onnx_ctx_model_helper.cc b/onnxruntime/core/providers/openvino/onnx_ctx_model_helper.cc index 7bd4f8d96cc55..1faf2598780b7 100644 --- a/onnxruntime/core/providers/openvino/onnx_ctx_model_helper.cc +++ b/onnxruntime/core/providers/openvino/onnx_ctx_model_helper.cc @@ -142,7 +142,7 @@ bool EPCtxHandler::CheckForOVEPCtxNode(const Node& node) const { if (node.OpType() == EPCONTEXT_OP) { auto& attrs = node.GetAttributes(); bool result = (attrs.count(SOURCE) == 1) && (attrs.at(SOURCE).s() == kOpenVINOExecutionProvider); - result &= (attrs.count(EP_SDK_VER) == 1) && (attrs.at(EP_SDK_VER).s() == openvino_sdk_version_); + // result &= (attrs.count(EP_SDK_VER) == 1) && (attrs.at(EP_SDK_VER).s() == openvino_sdk_version_); result &= attrs.count(EMBED_MODE) == 1; result &= attrs.count(EP_CACHE_CONTEXT) == 1; return result; From 360ddf59828c8a7d330d0ed593e26e0fc373736e Mon Sep 17 00:00:00 2001 From: Ankit Maheshkar Date: Wed, 9 Apr 2025 22:08:39 +0530 Subject: [PATCH 266/266] fix: Refactor read_model() to accept XML path (#646) --- .../core/providers/openvino/ov_interface.cc | 36 ++++--------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/onnxruntime/core/providers/openvino/ov_interface.cc b/onnxruntime/core/providers/openvino/ov_interface.cc index f9e40c782fde2..8da25e9ef466a 100644 --- a/onnxruntime/core/providers/openvino/ov_interface.cc +++ b/onnxruntime/core/providers/openvino/ov_interface.cc @@ -198,40 +198,18 @@ OVExeNetwork OVCore::ImportModel(std::istream& model_stream, auto obj = core.import_model(model_stream, hw_target, device_config); exe = OVExeNetwork(obj, hw_target); } else { - // Get path to bin file - std::string bin_file; + // If the model is XML, we need to load it with the XML content in read_model() + // where weights from bin file is directly consumed + std::string xml_file_name = name; if (name.size() >= 5 && name.substr(name.size() - 5) == ".onnx") { - bin_file = name; - bin_file.replace(name.size() - 5, 5, ".bin"); + xml_file_name = name; + xml_file_name.replace(name.size() - 5, 5, ".xml"); } else { throw std::runtime_error("Invalid model name. Make sure *.onnx, *.xml, and *.bin carry the same name."); } - // Read the model XML into a string - std::stringstream xml_stream; - xml_stream << model_stream.rdbuf(); - std::string xml_content = xml_stream.str(); - - // Read model.bin into a vector - std::ifstream bin_stream; - bin_stream.open(bin_file, std::ios::binary); - if (!bin_stream.is_open()) { - throw std::runtime_error("Failed to open " + bin_file); - } - - bin_stream.seekg(0, std::ios::end); - std::streamsize size = bin_stream.tellg(); - bin_stream.seekg(0, std::ios::beg); - std::vector bin_data(size); - if (!bin_stream.read(reinterpret_cast(bin_data.data()), size)) { - throw std::runtime_error("Failed to read binary data from " + bin_file); - } - - // Create an ov::Tensor for weights - ov::Tensor weights_tensor(ov::element::u8, {bin_data.size()}, bin_data.data()); - - // Load the model explicitly with XML content and weights - std::shared_ptr model = core.read_model(xml_content, weights_tensor); + // Load the model explicitly with XML contents + std::shared_ptr model = core.read_model(xml_file_name); if (enable_causallm) { exe = OVCore::Get()->StatefulCompileModel(model, hw_target, device_config);
Release notes

Sourced from next's releases.

v15.2.3

[!NOTE]
This release is backporting bug fixes. It does not include all pending features/changes on canary.

Core Changes

  • Update default allowed origins list (#77212)
  • unify allowed origin detection handling (#77053)
  • Add dev warning for cross-origin and stabilize allowedDevOrigins (#77044)
  • Ensure deploymentId is used for CSS preloads (#77210)
  • Update middleware request header (#77201)
  • [metadata] remove the default segement check for metadata rendering (#77119)
  • [ts-hint] fix vscode type hint plugin enabling (#77099)
  • [metadata] re-insert icons to head for streamed metadata (#76915)

Credits

Huge thanks to @​ijjk, @​ztanner, and @​huozhi for helping!

v15.2.2

Core Changes

  • [dev-overlay] fix styling on overflow error messages, add button hover state: #76771
  • Fix: respond 405 status code on OPTIONS request to SSG page: #76767
  • [dev-overlay] Always show relative paths: #76742
  • [metadata] remove the duplicate metadata in the error boundary: #76791
  • Upgrade React from d55cc79b-20250228 to 443b7ff2-20250303: #76804
  • [dev-overlay] Ignore animations on page load: #76834
  • fix: remove useless set-cookie in action-handler: #76839
  • Turbopack: handle task cancelation: #76831
  • Upgrade React from 443b7ff2-20250303 to e03ac20f-20250305: #76842
  • add types for __next_app__ module loading functions: #74566
  • fix duplicated noindex when server action is triggered: #76847
  • fix: don't drop queued actions when navigating: #75362
  • [dev-overlay]: remove dependency on platform for focus trapping: #76849
  • Turbopack: Add turbopack_load_by_url: #76814
  • Add handling of origin in dev mode: #76880
  • [dev-overlay] Stop grouping callstack frames into ignored vs. not ignored: #76861
  • Upgrade React from e03ac20f-20250305 to 029e8bd6-20250306: #76870
  • [dev-overlay] Increase padding if no x button present: #76898
  • fix: prevent incorrect searchParams being applied on certain navs: #76914
  • [dev-overlay] Dim ignore-listed callstack frames when shown: #76862

Example Changes

  • chore(cna): update tailwind styles to be closer to non-tw cna: #76647

Misc Changes

... (truncated)