mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
[ddc] Refactor _isInterfaceSubtype
Move the method body out of one giant JS foreign function and into Dart code with small JS foreign function calls inside. * Removes the confusion around what it actually means when we use Dart String interpolation within the JS function template. * Highlights the operations that actually need the JS foreign function. * Allows for syntax highlighting and automatic formatting of this code. * Allows for IDE "jump to definition" for class members that were previously inside the template. These changes were developed by diffing the compiled output to ensure the changes were as minimal and inconsequential as possible. Intentional diffs include: * Add a required message argument to `dart.assertFailed()`. * Add local variables for `varianceType`, `typeArg1`, and `typeArg2`. The only other diff was the loop variable incrementing: `++i` -> `i = i + 1` Change-Id: I76a1522fa4950f05748f905e1aec32c8b7dd4670 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/213526 Commit-Queue: Nicholas Shahan <nshahan@google.com> Reviewed-by: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
parent
d46f474d79
commit
e8cd9f0c44
2 changed files with 43 additions and 37 deletions
|
@ -107,11 +107,13 @@ final mixinOn = JS('', 'Symbol("mixinOn")');
|
|||
@JSExportName('implements')
|
||||
final implements_ = JS('', 'Symbol("implements")');
|
||||
|
||||
/// Either `null` if `clazz` doesn't directly implement any interfaces or a
|
||||
/// list of type objects if it does. Note, indirectly (e.g., via superclass)
|
||||
/// implemented interfaces aren't included here.
|
||||
/// See compiler.dart for when/how it is emitted.
|
||||
List Function()? getImplements(clazz) => JS(
|
||||
/// Returns `null` if [clazz] doesn't directly implement any interfaces or a
|
||||
/// a `Function` that when called produces a `List` of the type objects
|
||||
/// [clazz] implements.
|
||||
///
|
||||
/// Note, indirectly (e.g., via superclass) implemented interfaces aren't
|
||||
/// included here. See compiler.dart for when/how it is emitted.
|
||||
List<Object> Function()? getImplements(clazz) => JS(
|
||||
'',
|
||||
'Object.hasOwnProperty.call(#, #) ? #[#] : null',
|
||||
clazz,
|
||||
|
|
|
@ -1564,55 +1564,59 @@ bool _isSubtype(t1, t2, @notNull bool strictMode) {
|
|||
}
|
||||
|
||||
@notNull
|
||||
bool _isInterfaceSubtype(t1, t2, @notNull bool strictMode) => JS('', '''(() => {
|
||||
bool _isInterfaceSubtype(t1, t2, @notNull bool strictMode) {
|
||||
// Instances of PackageJSType are all subtypes of each other.
|
||||
if (${_jsInstanceOf(t1, PackageJSType)}
|
||||
&& ${_jsInstanceOf(t2, PackageJSType)}) {
|
||||
if (_jsInstanceOf(t1, PackageJSType) && _jsInstanceOf(t2, PackageJSType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($t1 === $t2) {
|
||||
if (JS<bool>('!', '# === #', t1, t2)) {
|
||||
return true;
|
||||
}
|
||||
if (${_equalType(t1, Object)}) {
|
||||
if (_equalType(t1, Object)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Classes cannot subtype `Function` or vice versa.
|
||||
if (${_equalType(t1, Function)} || ${_equalType(t2, Function)}) {
|
||||
if (_equalType(t1, Function) || _equalType(t2, Function)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If t1 is a JS Object, we may not hit core.Object.
|
||||
if ($t1 == null) {
|
||||
return ${_equalType(t2, Object)} || ${_equalType(t2, dynamic)};
|
||||
if (t1 == null) {
|
||||
return _equalType(t2, Object) || _equalType(t2, dynamic);
|
||||
}
|
||||
|
||||
// Check if t1 and t2 have the same raw type. If so, check covariance on
|
||||
// type parameters.
|
||||
let raw1 = $getGenericClass($t1);
|
||||
let raw2 = $getGenericClass($t2);
|
||||
if (raw1 != null && raw1 == raw2) {
|
||||
let typeArguments1 = $getGenericArgs($t1);
|
||||
let typeArguments2 = $getGenericArgs($t2);
|
||||
if (typeArguments1.length != typeArguments2.length) {
|
||||
$assertFailed();
|
||||
var raw1 = getGenericClass(t1);
|
||||
var raw2 = getGenericClass(t2);
|
||||
if (raw1 != null && JS<bool>('!', '# == #', raw1, raw2)) {
|
||||
var typeArguments1 = getGenericArgs(t1);
|
||||
var typeArguments2 = getGenericArgs(t2);
|
||||
if (JS<bool>('!', '#.length != #.length', typeArguments1, typeArguments2)) {
|
||||
assertFailed('Internal type check failure.');
|
||||
}
|
||||
let variances = $getGenericArgVariances($t1);
|
||||
for (let i = 0; i < typeArguments1.length; ++i) {
|
||||
var variances = getGenericArgVariances(t1);
|
||||
for (var i = 0; i < JS<int>('!', '#.length', typeArguments1); ++i) {
|
||||
// When using implicit variance, variances will be undefined and
|
||||
// considered covariant.
|
||||
if (variances === void 0 || variances[i] == ${Variance.covariant}) {
|
||||
if (!$_isSubtype(typeArguments1[i], typeArguments2[i], $strictMode)) {
|
||||
var varianceType = JS('!', '# && #[#]', variances, variances, i);
|
||||
var typeArg1 = JS('!', '#[#]', typeArguments1, i);
|
||||
var typeArg2 = JS('!', '#[#]', typeArguments2, i);
|
||||
if (JS<bool>('!', '# === void 0 || # == #', varianceType, varianceType,
|
||||
Variance.covariant)) {
|
||||
if (!_isSubtype(typeArg1, typeArg2, strictMode)) {
|
||||
return false;
|
||||
}
|
||||
} else if (variances[i] == ${Variance.contravariant}) {
|
||||
if (!$_isSubtype(typeArguments2[i], typeArguments1[i], $strictMode)) {
|
||||
} else if (JS<bool>(
|
||||
'!', '# == #', varianceType, Variance.contravariant)) {
|
||||
if (!_isSubtype(typeArg2, typeArg1, strictMode)) {
|
||||
return false;
|
||||
}
|
||||
} else if (variances[i] == ${Variance.invariant}) {
|
||||
if (!$_isSubtype(typeArguments1[i], typeArguments2[i], $strictMode) ||
|
||||
!$_isSubtype(typeArguments2[i], typeArguments1[i], $strictMode)) {
|
||||
} else if (JS<bool>('!', '# == #', varianceType, Variance.invariant)) {
|
||||
if (!_isSubtype(typeArg1, typeArg2, strictMode) ||
|
||||
!_isSubtype(typeArg2, typeArg1, strictMode)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1620,27 +1624,27 @@ bool _isInterfaceSubtype(t1, t2, @notNull bool strictMode) => JS('', '''(() => {
|
|||
return true;
|
||||
}
|
||||
|
||||
if ($_isInterfaceSubtype(t1.__proto__, $t2, $strictMode)) {
|
||||
if (_isInterfaceSubtype(JS('', '#.__proto__', t1), t2, strictMode)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check mixin.
|
||||
let m1 = $getMixin($t1);
|
||||
if (m1 != null && $_isInterfaceSubtype(m1, $t2, $strictMode)) {
|
||||
var m1 = getMixin(t1);
|
||||
if (m1 != null && _isInterfaceSubtype(m1, t2, strictMode)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check interfaces.
|
||||
let getInterfaces = $getImplements($t1);
|
||||
if (getInterfaces) {
|
||||
for (let i1 of getInterfaces()) {
|
||||
if ($_isInterfaceSubtype(i1, $t2, $strictMode)) {
|
||||
var getInterfaces = getImplements(t1);
|
||||
if (getInterfaces != null) {
|
||||
for (var i1 in getInterfaces()) {
|
||||
if (_isInterfaceSubtype(i1, t2, strictMode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})()''');
|
||||
}
|
||||
|
||||
Object? extractTypeArguments<T>(T instance, Function f) {
|
||||
if (instance == null) {
|
||||
|
|
Loading…
Reference in a new issue