[web] Fix crash on old versions of Chrome (Intl.Segmenter missing) (flutter/engine#41986)

`Chrome < v87` have the `v8BreakIterator` API but don't have `Intl.Segmenter`. This caused crashes for some apps (see b/281377168).

This PR enhances our feature detection to take into account this API mismatch.
This commit is contained in:
Mouad Debbar
2023-05-12 15:59:30 -04:00
committed by GitHub
parent bb93b87e6a
commit e87d7155d2
3 changed files with 48 additions and 3 deletions

View File

@@ -268,4 +268,5 @@ int _detectWebGLVersion() {
}
/// Whether the current browser supports the Chromium variant of CanvasKit.
bool get browserSupportsCanvaskitChromium => domIntl.v8BreakIterator != null;
bool get browserSupportsCanvaskitChromium =>
domIntl.v8BreakIterator != null && domIntl.Segmenter != null;

View File

@@ -1826,17 +1826,22 @@ void _paragraphTests() {
}, skip: isFirefox); // Intended: Headless firefox has no webgl support https://github.com/flutter/flutter/issues/109265
group('getCanvasKitJsFileNames', () {
late dynamic oldV8BreakIterator = v8BreakIterator;
dynamic oldV8BreakIterator = v8BreakIterator;
dynamic oldIntlSegmenter = intlSegmenter;
setUp(() {
oldV8BreakIterator = v8BreakIterator;
oldIntlSegmenter = intlSegmenter;
});
tearDown(() {
v8BreakIterator = oldV8BreakIterator;
intlSegmenter = oldIntlSegmenter;
debugResetBrowserSupportsImageDecoder();
});
test('in Chromium-based browsers', () {
v8BreakIterator = Object(); // Any non-null value.
intlSegmenter = Object(); // Any non-null value.
browserSupportsImageDecoder = true;
expect(getCanvasKitJsFileNames(CanvasKitVariant.full), <String>['canvaskit.js']);
@@ -1847,7 +1852,19 @@ void _paragraphTests() {
]);
});
test('in older versions of Chromium-based browsers', () {
v8BreakIterator = Object(); // Any non-null value.
intlSegmenter = null; // Older versions of Chromium didn't have the Intl.Segmenter API.
browserSupportsImageDecoder = true;
expect(getCanvasKitJsFileNames(CanvasKitVariant.full), <String>['canvaskit.js']);
expect(getCanvasKitJsFileNames(CanvasKitVariant.chromium), <String>['chromium/canvaskit.js']);
expect(getCanvasKitJsFileNames(CanvasKitVariant.auto), <String>['canvaskit.js']);
});
test('in other browsers', () {
intlSegmenter = Object(); // Any non-null value.
v8BreakIterator = null;
browserSupportsImageDecoder = true;
expect(getCanvasKitJsFileNames(CanvasKitVariant.full), <String>['canvaskit.js']);
@@ -1901,3 +1918,9 @@ external dynamic get v8BreakIterator;
@JS('window.Intl.v8BreakIterator')
external set v8BreakIterator(dynamic x);
@JS('window.Intl.Segmenter')
external dynamic get intlSegmenter;
@JS('window.Intl.Segmenter')
external set intlSegmenter(dynamic x);

View File

@@ -157,17 +157,22 @@ void testMain() {
});
group('browserSupportsCanvasKitChromium', () {
late dynamic oldV8BreakIterator = v8BreakIterator;
dynamic oldV8BreakIterator = v8BreakIterator;
dynamic oldIntlSegmenter = intlSegmenter;
setUp(() {
oldV8BreakIterator = v8BreakIterator;
oldIntlSegmenter = intlSegmenter;
});
tearDown(() {
v8BreakIterator = oldV8BreakIterator;
intlSegmenter = oldIntlSegmenter;
debugResetBrowserSupportsImageDecoder();
});
test('Detect browsers that support CanvasKit Chromium', () {
v8BreakIterator = Object(); // Any non-null value.
intlSegmenter = Object(); // Any non-null value.
browserSupportsImageDecoder = true;
expect(browserSupportsCanvaskitChromium, isTrue);
@@ -175,6 +180,7 @@ void testMain() {
test('Detect browsers that do not support image codecs', () {
v8BreakIterator = Object(); // Any non-null value.
intlSegmenter = Object(); // Any non-null value.
browserSupportsImageDecoder = false;
// TODO(mdebbar): we don't check image codecs for now.
@@ -184,6 +190,7 @@ void testMain() {
test('Detect browsers that do not support v8BreakIterator', () {
v8BreakIterator = null;
intlSegmenter = Object(); // Any non-null value.
browserSupportsImageDecoder = true;
expect(browserSupportsCanvaskitChromium, isFalse);
@@ -191,10 +198,18 @@ void testMain() {
test('Detect browsers that support neither', () {
v8BreakIterator = null;
intlSegmenter = Object(); // Any non-null value.
browserSupportsImageDecoder = false;
expect(browserSupportsCanvaskitChromium, isFalse);
});
test('Detect browsers that support v8BreakIterator but no Intl.Segmenter', () {
v8BreakIterator = Object(); // Any non-null value.
intlSegmenter = null;
expect(browserSupportsCanvaskitChromium, isFalse);
});
});
group('OffscreenCanvas', () {
@@ -211,3 +226,9 @@ external dynamic get v8BreakIterator;
@JS('window.Intl.v8BreakIterator')
external set v8BreakIterator(dynamic x);
@JS('window.Intl.Segmenter')
external dynamic get intlSegmenter;
@JS('window.Intl.Segmenter')
external set intlSegmenter(dynamic x);