diff --git a/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc b/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc index 05571fdcee2..52c1470a6ab 100644 --- a/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc +++ b/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc @@ -65,9 +65,6 @@ RuntimeStage::RuntimeStage(std::shared_ptr payload) return; } if (!fb::RuntimeStageBufferHasIdentifier(payload_->GetMapping())) { - VALIDATION_LOG - << "Impeller Runtime stage has invalid magic. Perhaps the stage " - "information is for the incorrect backend or the data is corrupted?"; return; } auto runtime_stage = fb::GetRuntimeStage(payload_->GetMapping()); diff --git a/engine/src/flutter/lib/ui/painting.dart b/engine/src/flutter/lib/ui/painting.dart index 03f08b2030f..4646cdb2390 100644 --- a/engine/src/flutter/lib/ui/painting.dart +++ b/engine/src/flutter/lib/ui/painting.dart @@ -4126,7 +4126,10 @@ class FragmentProgram extends NativeFieldWrapperClass1 { @pragma('vm:entry-point') FragmentProgram._fromAsset(String assetKey) { _constructor(); - _initFromAsset(assetKey); + final String result = _initFromAsset(assetKey); + if (result.isNotEmpty) { + throw result; + } } static void _reinitializeShader(String assetKey) { @@ -4145,7 +4148,10 @@ class FragmentProgram extends NativeFieldWrapperClass1 { return; } - program._initFromAsset(assetKey); + final result = program._initFromAsset(assetKey); + if (result.isNotEmpty) { + throw result; + } } late final int _uniformFloatCount; @@ -4157,8 +4163,8 @@ class FragmentProgram extends NativeFieldWrapperClass1 { @FfiNative, Handle, Bool)>('FragmentProgram::init') external void _init(String sksl, bool debugPrint); - @FfiNative, Handle)>('FragmentProgram::initFromAsset') - external void _initFromAsset(String assetKey); + @FfiNative, Handle)>('FragmentProgram::initFromAsset') + external String _initFromAsset(String assetKey); /// Constructs a [Shader] object suitable for use by [Paint.shader] with /// the given uniforms. diff --git a/engine/src/flutter/lib/ui/painting/fragment_program.cc b/engine/src/flutter/lib/ui/painting/fragment_program.cc index 1a2e0e9ede3..8391383c48d 100644 --- a/engine/src/flutter/lib/ui/painting/fragment_program.cc +++ b/engine/src/flutter/lib/ui/painting/fragment_program.cc @@ -22,18 +22,21 @@ namespace flutter { IMPLEMENT_WRAPPERTYPEINFO(ui, FragmentProgram); -void FragmentProgram::initFromAsset(std::string asset_name) { +std::string FragmentProgram::initFromAsset(std::string asset_name) { std::shared_ptr asset_manager = UIDartState::Current() ->platform_configuration() ->client() ->GetAssetManager(); std::unique_ptr data = asset_manager->GetAsMapping(asset_name); if (data == nullptr) { - Dart_ThrowException(tonic::ToDart("Asset '" + asset_name + "' not found")); - return; + return std::string("Asset '") + asset_name + std::string("' not found"); } auto runtime_stage = impeller::RuntimeStage(std::move(data)); + if (!runtime_stage.IsValid()) { + return std::string("Asset '") + asset_name + + std::string("' does not contain valid shader data."); + } { auto code_mapping = runtime_stage.GetCodeMapping(); auto code_size = code_mapping->GetSize(); @@ -43,10 +46,8 @@ void FragmentProgram::initFromAsset(std::string asset_name) { SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForShader(SkString(sksl, code_size)); if (result.effect == nullptr) { - Dart_ThrowException(tonic::ToDart(std::string("Invalid SkSL:\n") + sksl + - std::string("\nSkSL Error:\n") + - result.errorText.c_str())); - return; + return std::string("Invalid SkSL:\n") + sksl + + std::string("\nSkSL Error:\n") + result.errorText.c_str(); } runtime_effect_ = result.effect; } @@ -84,6 +85,8 @@ void FragmentProgram::initFromAsset(std::string asset_name) { if (Dart_IsError(result)) { Dart_PropagateError(result); } + + return ""; } void FragmentProgram::init(std::string sksl, bool debugPrintSksl) { diff --git a/engine/src/flutter/lib/ui/painting/fragment_program.h b/engine/src/flutter/lib/ui/painting/fragment_program.h index d984410adb5..abdc6d4a8bb 100644 --- a/engine/src/flutter/lib/ui/painting/fragment_program.h +++ b/engine/src/flutter/lib/ui/painting/fragment_program.h @@ -24,7 +24,7 @@ class FragmentProgram : public RefCountedDartWrappable { ~FragmentProgram() override; static void Create(Dart_Handle wrapper); - void initFromAsset(std::string asset_name); + std::string initFromAsset(std::string asset_name); void init(std::string sksl, bool debugPrintSksl); diff --git a/engine/src/flutter/testing/dart/fragment_shader_test.dart b/engine/src/flutter/testing/dart/fragment_shader_test.dart index 4d4d79a1aeb..7cab4f1b71e 100644 --- a/engine/src/flutter/testing/dart/fragment_shader_test.dart +++ b/engine/src/flutter/testing/dart/fragment_shader_test.dart @@ -295,6 +295,30 @@ void main() { await _expectShaderRendersGreen(shader); }); + test('iplr throws an exception on invalid assetKey', () async { + bool throws = false; + try { + final FragmentProgram program = FragmentProgram.fromAsset( + '', + ); + } catch (e) { + throws = true; + } + expect(throws, equals(true)); + }); + + test('iplr throws an exception on invalid data', () async { + bool throws = false; + try { + final FragmentProgram program = FragmentProgram.fromAsset( + 'DashInNooglerHat.jpg', + ); + } catch (e) { + throws = true; + } + expect(throws, equals(true)); + }); + // Test all supported GLSL ops. See lib/spirv/lib/src/constants.dart final Map supportedGLSLOpShaders = _loadShaders( path.join('supported_glsl_op_shaders', 'spirv'),