Version 2.10.0-60.0.dev
Merge commit 'c47d6b4f36ebd1c5c2b11e01826e00fbe0827f2c' into 'dev'
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
index d0dd4f0..4481354 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -24,6 +24,13 @@
static const int _nullIndex = 2;
static const int _otherIndex = 3;
+ static const int _maxIndex = _otherIndex;
+ static const List<int> _singletonIndices = [
+ _trueIndex,
+ _falseIndex,
+ _nullIndex,
+ ];
+
const PowersetBitsDomain(this._closedWorld);
CommonElements get commonElements => _closedWorld.commonElements;
@@ -36,26 +43,26 @@
int get boolOrNullMask => boolMask | nullMask;
int get nullOrOtherMask => nullMask | otherMask;
int get boolNullOtherMask => boolOrNullMask | otherMask;
+ int get preciseMask => _singletonIndices.fold(
+ powersetBottom, (mask, index) => mask | 1 << index);
int get powersetBottom => 0;
- int get powersetTop => boolNullOtherMask;
+ int get powersetTop => (1 << _maxIndex + 1) - 1;
bool isPotentiallyBoolean(int value) => (value & boolMask) != 0;
- bool isPotentiallyOther(int value) => (value & otherMask) != 0;
bool isPotentiallyNull(int value) => (value & nullMask) != 0;
- bool isPotentiallyBooleanOrNull(int value) => (value & boolOrNullMask) != 0;
- bool isPotentiallyNullOrOther(int value) => (value & nullOrOtherMask) != 0;
+ bool isPotentiallyOther(int value) => (value & otherMask) != 0;
- bool isDefinitelyTrue(int value) => (value & boolNullOtherMask) == trueMask;
- bool isDefinitelyFalse(int value) => (value & boolNullOtherMask) == falseMask;
- bool isDefinitelyNull(int value) => (value & boolNullOtherMask) == nullMask;
+ bool isDefinitelyTrue(int value) => value == trueMask;
+ bool isDefinitelyFalse(int value) => value == falseMask;
+ bool isDefinitelyNull(int value) => value == nullMask;
bool isSingleton(int value) =>
isDefinitelyTrue(value) ||
isDefinitelyFalse(value) ||
isDefinitelyNull(value);
/// Returns `true` if only singleton bits are set and `false` otherwise.
- bool isPrecise(int value) => !isPotentiallyOther(value);
+ bool isPrecise(int value) => value & ~preciseMask == 0;
AbstractBool isOther(int value) =>
AbstractBool.maybeOrFalse(isPotentiallyOther(value));
@@ -115,8 +122,12 @@
return otherMask;
}
- AbstractBool areDisjoint(int a, int b) =>
- AbstractBool.trueOrMaybe(intersection(a, b) == powersetBottom);
+ AbstractBool areDisjoint(int a, int b) {
+ int overlap = intersection(a, b);
+ if (overlap == powersetBottom) return AbstractBool.True;
+ if (isPrecise(overlap)) return AbstractBool.False;
+ return AbstractBool.Maybe;
+ }
int intersection(int a, int b) {
return a & b;
@@ -134,9 +145,11 @@
AbstractBool isBooleanOrNull(int value) => isBoolean(excludeNull(value));
- AbstractBool isBoolean(int value) => isPotentiallyBoolean(value)
- ? AbstractBool.trueOrMaybe(!isPotentiallyNullOrOther(value))
- : AbstractBool.False;
+ AbstractBool isBoolean(int value) {
+ if (!isPotentiallyBoolean(value)) return AbstractBool.False;
+ if (value & ~boolMask == 0) return AbstractBool.True;
+ return AbstractBool.Maybe;
+ }
AbstractBool isDoubleOrNull(int value) => isDouble(excludeNull(value));
@@ -177,10 +190,13 @@
AbstractBool isPrimitiveArray(int value) => isOther(value);
- AbstractBool isPrimitiveBoolean(int value) => isPotentiallyBoolean(value)
- ? AbstractBool.trueOrMaybe(
- isDefinitelyTrue(value) || isDefinitelyFalse(value))
- : AbstractBool.False;
+ AbstractBool isPrimitiveBoolean(int value) {
+ if (isDefinitelyTrue(value) || isDefinitelyFalse(value)) {
+ return AbstractBool.True;
+ }
+ if (!isPotentiallyBoolean(value)) return AbstractBool.False;
+ return AbstractBool.Maybe;
+ }
AbstractBool isPrimitiveNumber(int value) => isOther(value);
@@ -195,8 +211,11 @@
AbstractBool isExact(int value) => AbstractBool.Maybe;
- AbstractBool isEmpty(int value) =>
- AbstractBool.trueOrMaybe(value == powersetBottom);
+ AbstractBool isEmpty(int value) {
+ if (value == powersetBottom) return AbstractBool.True;
+ if (isPrecise(value)) return AbstractBool.False;
+ return AbstractBool.Maybe;
+ }
AbstractBool isInstanceOf(int value, ClassEntity cls) => AbstractBool.Maybe;
@@ -216,7 +235,7 @@
}
int excludeNull(int value) {
- return value & (powersetTop - nullMask);
+ return value & ~nullMask;
}
AbstractBool couldBeTypedArray(int value) => isOther(value);
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 4842c30..9d1ebd6 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1937,13 +1937,13 @@
set formAction(String? value) native;
- String get formEnctype native;
+ String? get formEnctype native;
- set formEnctype(String value) native;
+ set formEnctype(String? value) native;
- String get formMethod native;
+ String? get formMethod native;
- set formMethod(String value) native;
+ set formMethod(String? value) native;
bool get formNoValidate native;
@@ -2120,15 +2120,15 @@
/// The height of this canvas element in CSS pixels.
- int get height native;
+ int? get height native;
- set height(int value) native;
+ set height(int? value) native;
/// The width of this canvas element in CSS pixels.
- int get width native;
+ int? get width native;
- set width(int value) native;
+ set width(int? value) native;
MediaStream captureStream([num? frameRate]) native;
@@ -15994,9 +15994,9 @@
*/
FieldSetElement.created() : super.created();
- bool get disabled native;
+ bool? get disabled native;
- set disabled(bool value) native;
+ set disabled(bool? value) native;
@Returns('HtmlCollection')
@Creates('HtmlCollection')
@@ -21740,34 +21740,34 @@
/// Checks if this type is supported on the current platform.
static bool get supported => Element.isTagSupported('meter');
- num get high native;
+ num? get high native;
- set high(num value) native;
+ set high(num? value) native;
@Unstable()
@Returns('NodeList')
@Creates('NodeList')
List<Node>? get labels native;
- num get low native;
+ num? get low native;
- set low(num value) native;
+ set low(num? value) native;
- num get max native;
+ num? get max native;
- set max(num value) native;
+ set max(num? value) native;
- num get min native;
+ num? get min native;
- set min(num value) native;
+ set min(num? value) native;
- num get optimum native;
+ num? get optimum native;
- set optimum(num value) native;
+ set optimum(num? value) native;
- num get value native;
+ num? get value native;
- set value(num value) native;
+ set value(num? value) native;
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -29170,9 +29170,9 @@
StyleSheet? get sheet native;
- String get type native;
+ String? get type native;
- set type(String value) native;
+ set type(String? value) native;
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 7ffa6e3..cabba39 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -5,9 +5,12 @@
/**
* File, socket, HTTP, and other I/O support for non-web applications.
*
- * **Important:** Browser-based applications can't use this library.
- * Only servers, command-line scripts, and Flutter mobile apps can import
- * and use dart:io.
+ * **Important:** Browser-based apps can't use this library.
+ * Only the following can import and use the dart:io library:
+ * - Servers
+ * - Command-line scripts
+ * - Flutter mobile apps
+ * - Flutter desktop apps
*
* This library allows you to work with files, directories,
* sockets, processes, HTTP servers and clients, and more.
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index f016890..aa97d19 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -683,9 +683,9 @@
AnimatedString get in1 native;
- AnimatedEnumeration get type native;
+ AnimatedEnumeration? get type native;
- AnimatedNumberList get values native;
+ AnimatedNumberList? get values native;
// From SVGFilterPrimitiveStandardAttributes
diff --git a/tests/lib/html/custom/document_register_type_extensions_test.dart b/tests/lib/html/custom/document_register_type_extensions_test.dart
index bbeafb5..7da7cfd 100644
--- a/tests/lib/html/custom/document_register_type_extensions_test.dart
+++ b/tests/lib/html/custom/document_register_type_extensions_test.dart
@@ -60,7 +60,7 @@
CanvasRenderingContext2D context =
this.getContext('2d') as CanvasRenderingContext2D;
context.fillStyle = 'red';
- context.fillRect(0, 0, width, height);
+ context.fillRect(0, 0, width!, height!);
context.fill();
var data = context.getImageData(0, 0, 1, 1).data;
diff --git a/tests/lib/html/url_test.dart b/tests/lib/html/url_test.dart
index 201f523..857f8ae 100644
--- a/tests/lib/html/url_test.dart
+++ b/tests/lib/html/url_test.dart
@@ -17,7 +17,7 @@
var context = canvas.context2D;
context.fillStyle = 'red';
- context.fillRect(0, 0, canvas.width, canvas.height);
+ context.fillRect(0, 0, canvas.width!, canvas.height!);
var dataUri = canvas.toDataUrl('image/png');
var byteString = window.atob(dataUri.split(',')[1]);
diff --git a/tools/VERSION b/tools/VERSION
index 81c8ec6..3b27dbf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 59
+PRERELEASE 60
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/scripts/mdnreader.py b/tools/dom/scripts/mdnreader.py
index b748d1f..9fe43a3 100644
--- a/tools/dom/scripts/mdnreader.py
+++ b/tools/dom/scripts/mdnreader.py
@@ -5,8 +5,15 @@
import json
import os.path
+import re
import sys
+_COMPAT_KEY = '__compat'
+_EXPERIMENTAL_KEY = 'experimental'
+_STATUS_KEY = 'status'
+_SUPPORT_KEY = 'support'
+_VERSION_ADDED_KEY = 'version_added'
+
def _get_browser_compat_data():
current_dir = os.path.dirname(__file__)
@@ -89,17 +96,164 @@
}
if interface in browser_compat_data:
- browser_compat_data[interface].update(metadata)
+ _unify_metadata(browser_compat_data[interface],
+ metadata)
else:
browser_compat_data[interface] = metadata
else:
names[:] = [] # Do not go underneath
+ # Attempts to unify two compatibility infos by taking the union of both, and
+ # for conflicting information, taking the "stricter" of the two versions.
+ # Updates `a` in place to represent the union of `a` and `b`.
+ def _unify_compat(a, b):
+
+ def _has_compat_data(metadata):
+ return _COMPAT_KEY in metadata and _SUPPORT_KEY in metadata[_COMPAT_KEY]
+
+ # Unifies the support statements of both metadata and updates
+ # `support_a` in place. If either metadata do not contain simple support
+ # statements, defaults attribute to not supported.
+ def _unify_support(support_a, support_b):
+ for browser in support_a.keys():
+ if browser in support_b:
+ if _is_simple_support_statement(support_a[browser]) and _is_simple_support_statement(support_b[browser]):
+ support_a[browser][_VERSION_ADDED_KEY] = _unify_versions(
+ support_a[browser][_VERSION_ADDED_KEY],
+ support_b[browser][_VERSION_ADDED_KEY])
+ else:
+ # Only support simple statements for now.
+ support_a[browser] = {_VERSION_ADDED_KEY: None}
+ for browser in support_b.keys():
+ if not browser in support_a:
+ support_a[browser] = support_b[browser]
+
+ if not _has_compat_data(b):
+ return
+ if not _has_compat_data(a):
+ a[_COMPAT_KEY] = b[_COMPAT_KEY]
+ return
+
+ support_a = a[_COMPAT_KEY][_SUPPORT_KEY]
+ support_b = b[_COMPAT_KEY][_SUPPORT_KEY]
+
+ _unify_support(support_a, support_b)
+
+ # Unifies any status info in the two metadata. Modifies `a` in place to
+ # represent the union of both `a` and `b`.
+ def _unify_status(a, b):
+
+ def _has_status(metadata):
+ return _COMPAT_KEY in metadata and _STATUS_KEY in metadata[_COMPAT_KEY]
+
+ # Modifies `status_a` in place to combine "experimental" tags.
+ def _unify_experimental(status_a, status_b):
+ # If either of the statuses report experimental, assume attribute is
+ # experimental.
+ status_a[_EXPERIMENTAL_KEY] = status_a.get(
+ _EXPERIMENTAL_KEY, False) or status_b.get(_EXPERIMENTAL_KEY, False)
+
+ if not _has_status(b):
+ return
+ if not _has_status(a):
+ a[_COMPAT_KEY] = b[_COMPAT_KEY]
+ return
+
+ status_a = a[_COMPAT_KEY][_STATUS_KEY]
+ status_b = b[_COMPAT_KEY][_STATUS_KEY]
+
+ _unify_experimental(status_a, status_b)
+
+ # If there exists multiple definitions of the same interface metadata e.g.
+ # elements, this attempts to unify the compatibilities for the interface as
+ # well as for each attribute.
+ def _unify_metadata(a, b):
+ # Unify the compatibility statement and status of the API or element.
+ _unify_compat(a, b)
+ _unify_status(a, b)
+ # Unify the compatibility statement and status of each attribute.
+ for attr in list(a.keys()):
+ if attr == _COMPAT_KEY:
+ continue
+ if attr in b:
+ _unify_compat(a[attr], b[attr])
+ _unify_status(a[attr], b[attr])
+ for attr in b.keys():
+ if not attr in a:
+ a[attr] = b[attr]
+
os.path.walk(browser_compat_folder, visitor, browser_compat_folder)
return browser_compat_data
+# Given two version values for a given browser, chooses the more strict version.
+def _unify_versions(version_a, version_b):
+ # Given two valid version strings, compares parts of the version string
+ # iteratively.
+ def _greater_version(version_a, version_b):
+ version_a_split = map(int, version_a.split('.'))
+ version_b_split = map(int, version_b.split('.'))
+ for i in range(min(len(version_a_split), len(version_b_split))):
+ if version_a_split[i] > version_b_split[i]:
+ return version_a
+ elif version_a_split[i] < version_b_split[i]:
+ return version_b
+ return version_a if len(version_a_split) > len(
+ version_b_split) else version_b
+
+ # Validate that we can handle the given version.
+ def _validate_version(version):
+ if not version:
+ return False
+ if version is True:
+ return True
+ if isinstance(version, str) or isinstance(version, unicode):
+ pattern = re.compile('^([0-9]+\.)*[0-9]+$')
+ if not pattern.match(version):
+ # It's possible for version strings to look like '<35'. We don't
+ # attempt to parse the conditional logic, and just default to
+ # potentially incompatible.
+ return None
+ return version
+ else:
+ raise ValueError(
+ 'Type of version_a was not handled correctly! type(version) = '
+ + str(type(version)))
+
+ version_a = _validate_version(version_a)
+ version_b = _validate_version(version_b)
+ # If one version reports not supported, default to not supported.
+ if not version_a or not version_b:
+ return False
+ # If one version reports always supported, the other version can only be
+ # more strict.
+ if version_a is True:
+ return version_b
+ if version_b is True:
+ return version_a
+
+ return _greater_version(version_a, version_b)
+
+
+# At this time, we only handle simple support statements due to the complexity
+# and variability around support statements with multiple elements.
+def _is_simple_support_statement(support_statement):
+ if isinstance(support_statement, list): # array_support_statement
+ # TODO(srujzs): Parse this list to determine compatibility. Will
+ # likely require parsing for 'version_removed' keys. Notes about
+ # which browser version enabled this attribute for which
+ # platform also complicates things. For now, we assume it's not
+ # compatible.
+ return False
+ if len(support_statement.keys()) > 1:
+ # If it's anything more complicated than 'version_added', like
+ # 'notes' that specify platform versions, we assume it's not
+ # compatible.
+ return False
+ return True
+
+
class MDNReader(object):
# Statically initialize and treat as constant.
_BROWSER_COMPAT_DATA = _get_browser_compat_data()
@@ -114,40 +268,29 @@
# For now, we will require support for browsers since the last IDL roll.
# TODO(srujzs): Determine if this is too conservative.
browser_version_map = {
- 'chrome': 63,
- 'firefox': 57,
- 'safari': 11,
+ 'chrome': '63',
+ 'firefox': '57',
+ 'safari': '11',
# We still support the latest version of IE.
- 'ie': 11,
- 'opera': 50,
+ 'ie': '11',
+ 'opera': '50',
}
- version_key = 'version_added'
for browser in browser_version_map.keys():
- support_data = compat_data['support']
+ support_data = compat_data[_SUPPORT_KEY]
if browser not in support_data:
return False
support_statement = support_data[browser]
- if isinstance(support_statement, list): # array_support_statement
- # TODO(srujzs): Parse this list to determine compatibility. Will
- # likely require parsing for 'version_removed' keys. Notes about
- # which browser version enabled this attribute for which
- # platform also complicates things. For now, we assume it's not
- # compatible.
+ if not _is_simple_support_statement(support_statement):
return False
- if len(support_statement.keys()) > 1:
- # If it's anything more complicated than 'version_added', like
- # 'notes' that specify platform versions, we assume it's not
- # compatible.
+ version = support_statement[_VERSION_ADDED_KEY]
+ # Compare version strings, target should be the more strict version.
+ target = browser_version_map[browser]
+ if _unify_versions(version, target) != target:
return False
- version = support_statement[version_key]
- if not version or browser_version_map[browser] < float(version):
- # simple_support_statement
- return False
+
# If the attribute is experimental, we assume it's not compatible.
- status_data = compat_data['status']
- experimental_key = 'experimental'
- if experimental_key in status_data and \
- status_data[experimental_key]:
+ status_data = compat_data[_STATUS_KEY]
+ if _EXPERIMENTAL_KEY in status_data and status_data[_EXPERIMENTAL_KEY]:
return False
return True
@@ -169,7 +312,7 @@
return False
elif id_name in interface_dict:
id_data = interface_dict[id_name]
- return self._get_attr_compatibility(id_data['__compat'])
+ return self._get_attr_compatibility(id_data[_COMPAT_KEY])
else:
# Might be an attribute that is defined in a parent interface.
# We defer until attribute emitting to determine if this is the