| Index: sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/lib/js_rti.dart (revision 23664)
|
| +++ sdk/lib/_internal/compiler/implementation/lib/js_rti.dart (working copy)
|
| @@ -1,297 +0,0 @@
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -part of _js_helper;
|
| -
|
| -setRuntimeTypeInfo(target, typeInfo) {
|
| - assert(typeInfo == null || typeInfo is JSArray);
|
| - // We have to check for null because factories may return null.
|
| - if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
|
| -}
|
| -
|
| -getRuntimeTypeInfo(target) {
|
| - if (target == null) return null;
|
| - return JS('var', r'#.$builtinTypeInfo', target);
|
| -}
|
| -
|
| -getRuntimeTypeArgument(target, substitution, index) {
|
| - var arguments = substitute(substitution, getRuntimeTypeInfo(target));
|
| - return (arguments == null) ? null : getField(arguments, index);
|
| -}
|
| -
|
| -class TypeImpl implements Type {
|
| - final String _typeName;
|
| -
|
| - TypeImpl(this._typeName);
|
| -
|
| - toString() => _typeName;
|
| -
|
| - // TODO(ahe): This is a poor hashCode as it collides with its name.
|
| - int get hashCode => _typeName.hashCode;
|
| -
|
| - bool operator ==(other) {
|
| - return (other is TypeImpl) && _typeName == other._typeName;
|
| - }
|
| -}
|
| -
|
| -String getClassName(var object) {
|
| - return JS('String', r'#.constructor.builtin$cls', getInterceptor(object));
|
| -}
|
| -
|
| -String getRuntimeTypeAsString(List runtimeType) {
|
| - String className = getConstructorName(runtimeType[0]);
|
| - return '$className${joinArguments(runtimeType, 1)}';
|
| -}
|
| -
|
| -String getConstructorName(type) => JS('String', r'#.builtin$cls', type);
|
| -
|
| -String runtimeTypeToString(type) {
|
| - if (type == null) {
|
| - return 'dynamic';
|
| - } else if (type is JSArray) {
|
| - // A list representing a type with arguments.
|
| - return getRuntimeTypeAsString(type);
|
| - } else {
|
| - // A reference to the constructor.
|
| - return getConstructorName(type);
|
| - }
|
| -}
|
| -
|
| -String joinArguments(var types, int startIndex) {
|
| - if (types == null) return '';
|
| - bool firstArgument = true;
|
| - bool allDynamic = true;
|
| - StringBuffer buffer = new StringBuffer();
|
| - for (int index = startIndex; index < types.length; index++) {
|
| - if (firstArgument) {
|
| - firstArgument = false;
|
| - } else {
|
| - buffer.write(', ');
|
| - }
|
| - var argument = types[index];
|
| - if (argument != null) {
|
| - allDynamic = false;
|
| - }
|
| - buffer.write(runtimeTypeToString(argument));
|
| - }
|
| - return allDynamic ? '' : '<$buffer>';
|
| -}
|
| -
|
| -String getRuntimeTypeString(var object) {
|
| - String className = object is JSArray ? 'List' : getClassName(object);
|
| - var typeInfo = JS('var', r'#.$builtinTypeInfo', object);
|
| - return "$className${joinArguments(typeInfo, 0)}";
|
| -}
|
| -
|
| -Type getRuntimeType(var object) {
|
| - String type = getRuntimeTypeString(object);
|
| - return new TypeImpl(type);
|
| -}
|
| -
|
| -bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
|
| -
|
| -Object invoke(function, arguments) {
|
| - return JS('var', r'#.apply(null, #)', function, arguments);
|
| -}
|
| -
|
| -Object call(target, name) => JS('var', r'#[#]()', target, name);
|
| -
|
| -substitute(var substitution, var arguments) {
|
| - if (substitution is JSArray) {
|
| - arguments = substitution;
|
| - } else if (isJsFunction(substitution)) {
|
| - arguments = invoke(substitution, arguments);
|
| - }
|
| - return arguments;
|
| -}
|
| -
|
| -/**
|
| - * Perform a type check with arguments on the Dart object [object].
|
| - *
|
| - * Parameters:
|
| - * - [isField]: the name of the flag/function to check if the object
|
| - * is of the correct class.
|
| - * - [checks]: the (JavaScript) list of type representations for the
|
| - * arguments to check against.
|
| - * - [asField]: the name of the function that transforms the type
|
| - * arguments of [objects] to an instance of the class that we check
|
| - * against.
|
| - */
|
| -bool checkSubtype(Object object, String isField, List checks, String asField) {
|
| - if (object == null) return false;
|
| - var arguments = getRuntimeTypeInfo(object);
|
| - // Interceptor is needed for JSArray and native classes.
|
| - // TODO(sra): It could be a more specialized interceptor since [object] is not
|
| - // `null` or a primitive.
|
| - // TODO(9586): Move type info for static functions onto an interceptor.
|
| - var interceptor = getInterceptor(object);
|
| - bool isSubclass = getField(interceptor, isField);
|
| - // When we read the field and it is not there, [isSubclass] will be [:null:].
|
| - if (isSubclass == null || !isSubclass) return false;
|
| - // Should the asField function be passed the receiver?
|
| - var substitution = getField(interceptor, asField);
|
| - return checkArguments(substitution, arguments, checks);
|
| -}
|
| -
|
| -String computeTypeName(String isField, List arguments) {
|
| - // Shorten the field name to the class name and append the textual
|
| - // representation of the type arguments.
|
| - int prefixLength = JS_OPERATOR_IS_PREFIX().length;
|
| - return Primitives.formatType(isField.substring(prefixLength, isField.length),
|
| - arguments);
|
| -}
|
| -
|
| -Object subtypeCast(Object object, String isField, List checks, String asField) {
|
| - if (object != null && !checkSubtype(object, isField, checks, asField)) {
|
| - String actualType = Primitives.objectTypeName(object);
|
| - String typeName = computeTypeName(isField, checks);
|
| - throw new CastErrorImplementation(object, typeName);
|
| - }
|
| - return object;
|
| -}
|
| -
|
| -Object assertSubtype(Object object, String isField, List checks,
|
| - String asField) {
|
| - if (object != null && !checkSubtype(object, isField, checks, asField)) {
|
| - String typeName = computeTypeName(isField, checks);
|
| - throw new TypeErrorImplementation(object, typeName);
|
| - }
|
| - return object;
|
| -}
|
| -
|
| -/**
|
| - * Check that the types in the list [arguments] are subtypes of the types in
|
| - * list [checks] (at the respective positions), possibly applying [substitution]
|
| - * to the arguments before the check.
|
| - *
|
| - * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible
|
| - * values for [substitution].
|
| - */
|
| -bool checkArguments(var substitution, var arguments, var checks) {
|
| - return areSubtypes(substitute(substitution, arguments), checks);
|
| -}
|
| -
|
| -bool areSubtypes(List s, List t) {
|
| - // [:null:] means a raw type.
|
| - if (s == null || t == null) return true;
|
| -
|
| - assert(s is JSArray);
|
| - assert(t is JSArray);
|
| - assert(s.length == t.length);
|
| -
|
| - int len = s.length;
|
| - for (int i = 0; i < len; i++) {
|
| - if (!isSubtype(s[i], t[i])) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -getArguments(var type) {
|
| - return type is JSArray ? JS('var', r'#.slice(1)', type) : null;
|
| -}
|
| -
|
| -getField(var object, var name) => JS('var', r'#[#]', object, name);
|
| -
|
| -bool isSubtypeOfNull(type) {
|
| - // `null` means `dynamic`.
|
| - return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME();
|
| -}
|
| -
|
| -/**
|
| - * Tests whether the Dart object [o] is a subtype of the runtime type
|
| - * representation [t], which is a type representation as described in the
|
| - * comment on [isSubtype].
|
| - */
|
| -bool checkSubtypeOfRuntimeType(Object o, var t) {
|
| - if (JS('bool', '# == null', o)) return isSubtypeOfNull(t);
|
| - if (JS('bool', '# == null', t)) return true;
|
| - // Get the runtime type information from the object here, because we may
|
| - // overwrite o with the interceptor below.
|
| - var rti = getRuntimeTypeInfo(o);
|
| - o = getInterceptor(o);
|
| - // We can use the object as its own type representation because we install
|
| - // the subtype flags and the substitution on the prototype, so they are
|
| - // properties of the object in JS.
|
| - var type;
|
| - if (JS('bool', '# != null', rti)) {
|
| - // If the type has type variables (that is, [:rti != null:]), make a copy of
|
| - // the type arguments and insert [o] in the first position to create a
|
| - // compound type representation.
|
| - type = JS('List', '#.slice()', rti);
|
| - JS('', '#.splice(0, 0, #)', type, o);
|
| - } else {
|
| - // Use the object as representation of the raw type.
|
| - type = o;
|
| - }
|
| - return isSubtype(type, t);
|
| -}
|
| -
|
| -Object subtypeOfRuntimeTypeCast(Object object, var type) {
|
| - if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
|
| - String actualType = Primitives.objectTypeName(object);
|
| - throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
|
| - }
|
| - return object;
|
| -}
|
| -
|
| -Object assertSubtypeOfRuntimeType(Object object, var type) {
|
| - if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
|
| - throw new TypeErrorImplementation(object, runtimeTypeToString(type));
|
| - }
|
| - return object;
|
| -}
|
| -
|
| -/**
|
| - * Check whether the type represented by [s] is a subtype of the type
|
| - * represented by [t].
|
| - *
|
| - * Type representations can be:
|
| - * 1) a JavaScript constructor for a class C: the represented type is the raw
|
| - * type C.
|
| - * 2) a Dart object: this is the interceptor instance for a native type.
|
| - * 3) a JavaScript object: this represents a class for which there is no
|
| - * JavaScript constructor, because it is only used in type arguments or it
|
| - * is native. The represented type is the raw type of this class.
|
| - * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
|
| - * subtyping flags and the substitution of the type and the rest of the
|
| - * array are the type arguments.
|
| - * 5) [:null:]: the dynamic type.
|
| - */
|
| -bool isSubtype(var s, var t) {
|
| - // If either type is dynamic, [s] is a subtype of [t].
|
| - if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
|
| - // Subtyping is reflexive.
|
| - if (JS('bool', '# === #', s, t)) return true;
|
| - // Get the object describing the class and check for the subtyping flag
|
| - // constructed from the type of [t].
|
| - var typeOfS = s is JSArray ? s[0] : s;
|
| - var typeOfT = t is JSArray ? t[0] : t;
|
| - // TODO(johnniwinther): replace this with the real function subtype test.
|
| - if (JS('bool', '#.func', s) == true || JS('bool', '#.func', t) == true ) {
|
| - return true;
|
| - }
|
| - // Check for a subtyping flag.
|
| - var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
|
| - if (getField(typeOfS, test) == null) return false;
|
| - // Get the necessary substitution of the type arguments, if there is one.
|
| - var substitution;
|
| - if (JS('bool', '# !== #', typeOfT, typeOfS)) {
|
| - var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
|
| - substitution = getField(typeOfS, field);
|
| - }
|
| - // The class of [s] is a subclass of the class of [t]. If [s] has no type
|
| - // arguments and no substitution, it is used as raw type. If [t] has no
|
| - // type arguments, it used as a raw type. In both cases, [s] is a subtype
|
| - // of [t].
|
| - if ((s is! JSArray && JS('bool', '# == null', substitution)) ||
|
| - t is! JSArray) {
|
| - return true;
|
| - }
|
| - // Recursively check the type arguments.
|
| - return checkArguments(substitution, getArguments(s), getArguments(t));
|
| -}
|
| -
|
| -createRuntimeType(String name) => new TypeImpl(name);
|
|
|