Files
sdk/pkg/dev_compiler/lib/runtime/_rtti.js
T
Leaf Petersen b9c83e0013 Most of this CL just re-organizes the runtime code into multiple sub-libraries. js_utils and loader remain as top level symbols (the former so that it has no dependencies, the latter since it defines the module system that the rest use).
The dart runtime files are roughly split around functional boundaries.  Comments at the top of each file describe the function of the library.  I'm not sure that these are 100% right yet, but they're closer.  We may want to iterate on the organization.

The main dart runtime file just re-exports various symbols from the sub-libraries.  It has hard dependencies on the other runtime files, some of which have soft (lazy) dependencies on SDK files.  The generated code now depends on dart and dartx as a imported libraries, rather than as top level symbols.

This CL also includes some new code to make type representations a bit better.  This is mostly in the new types.js file, which makes all of the non-instance types (dynamic, bottom, void, function types) subtypes of a common representation type.  Among other things, they now have the correct runtime type (core.Type).  Some of the type code has been rationalized around this a bit, but there is more left to do here.  The setSignature code in classes.js now also places the correct runtime type on nominal (instance) types.  There are new tests in the runtime_tests.js file to test for this.

The static object method code that implements the Object methods has not yet been updated to dispatch on type representations.  I will do that in a separate CL.

BUG=
R=jmesserly@google.com, vsm@google.com

Review URL: https://codereview.chromium.org/1182653002
2015-06-12 13:34:39 -07:00

150 lines
4.3 KiB
JavaScript

// 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.
*/
dart_library.library('dart_runtime/_rtti', null, /* Imports */[
], /* Lazy Imports */[
'dart/core',
'dart_runtime/_types'
], function(exports, core, types) {
'use strict';
const defineLazyProperty = dart_utils.defineLazyProperty;
const defineProperty = Object.defineProperty;
const slice = [].slice;
/**
*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)
*/
function fn(closure/* ...args*/) {
// Closure and a lazy type constructor
if (arguments.length == 2) {
defineLazyProperty(closure, _runtimeType, {get : arguments[1]});
return closure;
}
let t;
if (arguments.length == 1) {
// No type arguments, it's all dynamic
let len = closure.length;
let build = () => {
let args = Array.apply(null, new Array(len)).map(() => core.Object);
return types.functionType(core.Object, args);
};
// We could be called before Object is defined.
if (core.Object === void 0) return fn(closure, build);
t = build();
} else {
// We're passed the piecewise components of the function type,
// construct it.
let args = slice.call(arguments, 1);
t = types.functionType.apply(null, args);
}
tag(closure, t);
return closure;
}
exports.fn = fn;
// TODO(vsm): How should we encode the runtime type?
const _runtimeType = Symbol('_runtimeType');
function checkPrimitiveType(obj) {
switch (typeof obj) {
case "undefined":
return core.Null;
case "number":
return Math.floor(obj) == obj ? core.int : core.double;
case "boolean":
return core.bool;
case "string":
return core.String;
case "symbol":
return Symbol;
}
// Undefined is handled above. For historical reasons,
// typeof null == "object" in JS.
if (obj === null) return core.Null;
return null;
}
function runtimeType(obj) {
let result = checkPrimitiveType(obj);
if (result !== null) return result;
return obj.runtimeType;
}
exports.runtimeType = runtimeType;
function getFunctionType(obj) {
// TODO(vsm): Encode this properly on the function for Dart-generated code.
let args = Array.apply(null, new Array(obj.length)).map(() => core.Object);
return types.functionType(types.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.
*/
function realRuntimeType(obj) {
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) {
return getFunctionType(obj);
}
return result;
}
exports.realRuntimeType = realRuntimeType;
function LazyTagged(infoFn) {
class _Tagged {
get [_runtimeType]() {return infoFn();}
}
return _Tagged;
}
exports.LazyTagged = LazyTagged;
function read(value) {
return value[_runtimeType];
}
exports.read = read;
function tag(value, info) {
value[_runtimeType] = info;
}
exports.tag = tag;
function tagComputed(value, compute) {
defineProperty(value, _runtimeType, { get: compute });
}
exports.tagComputed = tagComputed;
function tagMemoized(value, compute) {
let cache = null;
function getter() {
if (compute == null) return cache;
cache = compute();
compute = null;
return cache;
}
tagComputed(value, getter);
}
exports.tagMemoized = tagMemoized;
});