[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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user