Index: tool/input_sdk/private/rtti.dart |
diff --git a/tool/input_sdk/private/rtti.dart b/tool/input_sdk/private/rtti.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7f66b9009cb6dd649f97ef41161a1fb100513b34 |
--- /dev/null |
+++ b/tool/input_sdk/private/rtti.dart |
@@ -0,0 +1,164 @@ |
+// Copyright (c) 2015, 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. |
+ |
+/// This library defines the association between runtime objects and |
+/// runtime types. |
+ |
+library dart._rtti; |
+import 'dart:_foreign_helper' show JS, rest; |
+import 'dart:_utils' as utils; |
+import 'dart:_types' show definiteFunctionType, dynamicR, bottom, jsobject; |
+ |
+final defineLazyProperty = JS('', '${utils.defineLazyProperty}'); |
+final defineProperty = JS('', 'Object.defineProperty'); |
+ |
+/// |
+/// Runtime type information. This module defines the mapping from |
+/// runtime objects to their runtime type information. See the types |
+/// module for the definition of how type information is represented. |
+/// |
+/// Runtime objects fall into four main categories: |
+/// |
+/// - Things represented by javascript primitives, such as |
+/// null, numbers, booleans, strings, and symbols. For these |
+/// we map directly from the javascript type (given by typeof) |
+/// to the appropriate class type from core, which serves as their |
+/// rtti. |
+/// |
+/// - Functions, which are represented by javascript functions. |
+/// Representations of Dart functions always have a |
+/// _runtimeType property attached to them with the appropriate |
+/// rtti. |
+/// |
+/// - Objects (instances) which are represented by instances of |
+/// javascript (ES6) classes. Their types are given by their |
+/// classes, and the rtti is accessed by projecting out their |
+/// constructor field. |
+/// |
+/// - Types objects, which are represented as described in the types |
+/// module. Types always have a _runtimeType property attached to |
+/// them with the appropriate rtti. The rtti for these is always |
+/// core.Type. TODO(leafp): consider the possibility that we can |
+/// reliably recognize type objects and map directly to core.Type |
+/// rather than attaching this property everywhere. |
+/// |
+/// |
+ |
+/// |
+///Tag a closure with a type, using one of three forms: |
+/// dart.fn(cls) marks cls has having no optional or named |
+/// parameters, with all argument and return types as dynamic |
+/// dart.fn(cls, func) marks cls with the lazily computed |
+/// runtime type as computed by func() |
+/// dart.fn(cls, rType, argsT, extras) marks cls as having the |
+/// runtime type dart.functionType(rType, argsT, extras) |
+/// |
+/// Note that since we are producing a type for a concrete function, |
+/// it is sound to use the definite arrow type. |
+/// |
+fn(closure, @rest args) => JS('', '''(() => { |
+ // Closure and a lazy type constructor |
+ if ($args.length == 1) { |
+ $defineLazyProperty($closure, $_runtimeType, {get : $args[0]}); |
+ return $closure; |
+ } |
+ let t; |
+ if ($args.length == 0) { |
+ // No type arguments, it's all dynamic |
+ t = $definiteFunctionType( |
+ $dynamicR, Array($closure.length).fill($dynamicR)); |
+ } else { |
+ // We're passed the piecewise components of the function type, |
+ // construct it. |
+ t = $definiteFunctionType.apply(null, $args); |
+ } |
+ tag($closure, t); |
+ return $closure; |
+})()'''); |
+ |
+// TODO(vsm): How should we encode the runtime type? |
+final _runtimeType = JS('', 'Symbol("_runtimeType")'); |
+ |
+checkPrimitiveType(obj) => JS('', '''(() => { |
+ switch (typeof $obj) { |
+ case "undefined": |
+ return $Null; |
+ case "number": |
+ return Math.floor($obj) == $obj ? $int : $double; |
+ case "boolean": |
+ return $bool; |
+ case "string": |
+ return $String; |
+ case "symbol": |
+ return Symbol; |
+ } |
+ // Undefined is handled above. For historical reasons, |
+ // typeof null == "object" in JS. |
+ if ($obj === null) return $Null; |
+ return null; |
+})()'''); |
+ |
+runtimeType(obj) => JS('', '''(() => { |
+ let result = $checkPrimitiveType($obj); |
+ if (result !== null) return result; |
+ return $obj.runtimeType; |
+})()'''); |
+ |
+getFunctionType(obj) => JS('', '''(() => { |
+ // TODO(vsm): Encode this properly on the function for Dart-generated code. |
+ let args = Array($obj.length).fill($dynamicR); |
+ return $definiteFunctionType($bottom, args); |
+})()'''); |
+ |
+/// |
+/// Returns the runtime type of obj. This is the same as `obj.realRuntimeType` |
+/// but will not call an overridden getter. |
+/// |
+/// Currently this will return null for non-Dart objects. |
+/// |
+realRuntimeType(obj) => JS('', '''(() => { |
+ let result = $checkPrimitiveType($obj); |
+ if (result !== null) return result; |
+ // TODO(vsm): Should we treat Dart and JS objects differently here? |
+ // E.g., we can check if obj instanceof core.Object to differentiate. |
+ result = $obj[$_runtimeType]; |
+ if (result) return result; |
+ result = $obj.constructor; |
+ if (result == Function) { |
+ // An undecorated Function should have come from |
+ // JavaScript. Treat as untyped. |
+ return $jsobject; |
+ } |
+ return result; |
+})()'''); |
+ |
+LazyTagged(infoFn) => JS('', '''(() => { |
+ class _Tagged { |
+ get [$_runtimeType]() {return $infoFn();} |
+ } |
+ return _Tagged; |
+})()'''); |
+ |
+read(value) => JS('', '''(() => { |
+ return $value[$_runtimeType]; |
+})()'''); |
+ |
+tag(value, info) => JS('', '''(() => { |
+ $value[$_runtimeType] = $info; |
+})()'''); |
+ |
+tagComputed(value, compute) => JS('', '''(() => { |
+ $defineProperty($value, $_runtimeType, { get: $compute }); |
+})()'''); |
+ |
+tagMemoized(value, compute) => JS('', '''(() => { |
+ let cache = null; |
+ function getter() { |
+ if ($compute == null) return cache; |
+ cache = $compute(); |
+ $compute = null; |
+ return cache; |
+ } |
+ $tagComputed($value, getter); |
+})()'''); |