dart-lang / web

Lightweight browser API bindings built around JS static interop.
https://pub.dev/packages/web
BSD 3-Clause "New" or "Revised" License
134 stars 23 forks source link

bug: SpeechRecognition is not a constructor when run the app in release mode #276

Open yeikel16 opened 3 months ago

yeikel16 commented 3 months ago

Hi, I started migrating to use the web package in the speech_to_text plugin, but when I run the example in release mode and try the initialize I get the error Error: k.SpeechRecognition is not a constructor, but in debug mode everything works fine.

I'm looking around the previous version of implementation and the html_dart2js.dart file has this constructor declaration:

  factory SpeechRecognition() {
    return JS('SpeechRecognition',
        'new (window.SpeechRecognition || window.webkitSpeechRecognition)()');
  }

And the new version of web package use extension type

 extension type SpeechRecognition._(JSObject _)
    implements EventTarget, JSObject {
  external factory SpeechRecognition();
  ...
  }

In some examples on the MDN web make reference to

Create a new SpeechRecognition object instance using the SpeechRecognition() constructor.

Run the example here using the branch migrate-web-platform-to-use-web-package.

web: ^1.0.0

Flutter Doctor

[✓] Flutter (Channel stable, 3.22.3, on macOS 14.6 23G80 darwin-arm64, locale es-US) • Flutter version 3.22.3 on channel stable at /Users/yeikel/fvm/versions/3.22.3 • Upstream repository https://github.com/flutter/flutter.git • Framework revision b0850beeb2 (hace 3 semanas), 2024-07-16 21:43:41 -0700 • Engine revision 235db911ba • Dart version 3.4.4 • DevTools version 2.34.3 [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1) • Android SDK at /Users/yeikel/Library/Android/sdk/ • Platform android-34, build-tools 33.0.1 • ANDROID_HOME = /Users/yeikel/Library/Android/sdk/ • Java binary at: /Applications/Android Studio 2.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 15.4) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15F31d • CocoaPods version 1.15.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.2) • Android Studio at /Applications/Android Studio 2.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) [✓] VS Code (version 1.91.1) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.94.0 [✓] Connected device (3 available) • macOS (desktop) • macos • darwin-arm64 • macOS 14.6 23G80 darwin-arm64 • Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 14.6 23G80 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 127.0.6533.89 [✓] Network resources • All expected network resources are available. • No issues found!

srujzs commented 2 months ago

https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition/SpeechRecognition#browser_compatibility

It's pretty unfortunate that it's still under the vendor prefix since Chrome 33. Interop constructors use the name of the type (+ any renaming), so this is indeed broken since new SpeechRecognition() is not valid. A workaround is:

@JS('webkitSpeechRecognition')
extension type _SpeechRecognition._(SpeechRecognition _) implements SpeechRecognition {
  external factory _SpeechRecognition();
}

...

SpeechRecognition createSpeechRecognition() => _SpeechRecognition();

I'm hoping this will be even easier to write once we have static extensions in the language. With that, we could easily add a static extension on SpeechRecognition into the helpers.

yeikel16 commented 2 months ago

Thanks @srujzs, with the workaround run perfect in release mode !!

Just out of curiosity, why not work in release mode and is working in debug mode?

srujzs commented 2 months ago

We have a bunch of polyfills in DDC/debug mode because the way we intercept types for dart:html are a little more brittle there (yet another reason we want to move away from dart:html and to package:web). Here, the polyfill makes it work for DDC but no such polyfill exists in dart2js:

https://github.com/dart-lang/sdk/blob/47180c004b1afb1da8df6dd6eb66bdb5233953ba/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart#L151