Repository navigation
builtins
Directory actions
More options
Directory actions
More options
builtins
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
parent directory.. | ||||
Resolution December meeting:
* "intrinsic" is a namespace
* "prototype" is not a namespace
* "intrinsic function" implies final, DontDelete, ReadOnly
* "intrinsic" properties are never dynamic. This implies that intrinsic::NaN references the global NaN
value provided the class or its base classes do not define a property of that name.
* "prototype function" implies DontEnum
* "prototype function" implies that "this" is unconstrained
Resolutions January meeting:
* Primitive (final, non-dynamic) types:
string, boolean, int, uint, double, decimal
* Non-primitive (not final, dynamic) types:
String, Boolean, Number, plus all the others
* Can an intrinsic method be extracted? Yes, no problem -- but it has a bound "this".
* There is a "construct" method attached to classes, generated by the system,
that can be called to create instances of that class.
* These are our methods:
static intrinsic function to() // conversion to type of class
static intrinsic function invoke() // calling class object as fn
intrinsic function invoke() // calling class instance as fn
function get y() // named field getter
function set y() // named field setter
function get *() // any-field getter (see below)
function set *() // any-field setter (ditto)
function invoke *() // any-method caller
The get* and set* are invoked after fixtures lookup but before lookup
on dynamic properties, so will be called for all dynamic properties even
if they already exist. User code would use intrinsic::get("name") to
actually get one of those dynamic properties.
* There is the following magic in the construction of class instances.
(1) The Object and Function constructors are magic.
(2) The class definition machinery adds a "prototype" slot, and
that slot has type "Object".
(2) The class definition machinery creates the prototype object
to be stored in the "prototype" slot, for the class, in the
following way:
(a) the [[Class]] of X.prototype is "X", which is the same
as the [[Class]] of X.
(b) the [[Prototype]] of Object.prototype is null, but the
[[Prototype]] of X.prototype is the initial value of
Object.prototype
* Lars and Brendan agree that subclassing standard classes (String, Array)
and overriding standard methods in the subclasses should not affect non-overridden
methods, ie, if predefined methods of these builtins use other
predefined methods in their implementations then that must not be observable.
Code style:
* Generally put "use namespace intrinsic" at the top of the package
and use public:: or other qualifiers when necessary to invoke
subclassed methods
* Prototype functions should defer to intrinsic functions:
prototype function toString()
this.toString() /* implicitly calls this.intrinsic::toString */
* Use these global, intrinsic-only conversion functions for conversions:
- ToObject
- ToString
- ToInt
- ToUint
- ToDouble
- ToDecimal
- ToBoolean
- ToInteger
- ToPrimitive
Note there is no "ToNumber". Normally you want "ToDouble".
* Use the "magic" namespace for magic things
* Use native functions to access system data and the C library
* Use === and !=== unless there is very good reason to use == or !=.
* To test whether a value v is undefined, use "v === undefined" (or
"v === intrinsic::undefined" if you're not using "use namespace
intrinsic"). Any compiler worth its salt gets this right. Using
"void 0" is legal (and the compiler should get that right too) but
obscure, sort of like shifting for division.
* Use "while (true) { ... }" for infinite loops, not "for (;;) { ... }"
* In declarations, namespace always precedes other modifiers:
intrinsic static const ...
public native function ...
* Use "double" to annotate parameters and variables that are
"Number" in ES3, and use "ToDouble" to convert values to that
representations (not "ToNumber").
* Use "let" or "let const" (rather than "var" or "const") to bind variables
* When factoring out code from multiple API methods into private methods,
use the name "fooHelper" for method "foo".
* Code that is not normative should be flagged with a multiline comment
starting with the word INFORMATIVE in all caps (eg see the date
code)
Formatting style:
* methodNamesAreLikeThis, variable_names_are_like_this
* Don't use tabs
* Indent 4 spaces
* No line longer than 100 characters (not counting linebreak)
* Opening brace for package, class on next line, aligned:
class Bar extends Foo
{
* Opening brace for everything else on the same line
function foo() {
if (fnord > chthulu) {
else {
* Closing brace always on line by itself:
}
else {
* Brace when in doubt:
for (...) {
if (...)
...
}
* Semicolons always (helps Emacs figure things out)
* Expression functions when natural
* Cite the relevant specs for every function
/*
Attempt at modeling ECMA-262 builtin classes using the new ECMA4 language.
Note that these are intended to reflect ECMA-262 behavior, which may omit
common-but-nonstandard extensions used in various implementations (e.g., SpiderMonkey).
Such extensions may be specified using a well-defined namespace:
namespace SpiderMonkey // Mozilla's ECMA-262 implementation
namespace ActionScript // Adobe Flash ActionScript 3.0 implementation
namespace JScriptNET // Microsoft JScript implementation
There is also the ECMA4 namespace, which is designed to allow for higher-performance
early-binding by ECMA4-specific compilers, allowing for potentially better compile-time
error-checking (in strict mode) and runtime performance, but at the expense of some backwards compatibility.
Note that where method implementations are provided, there is no attempt at efficiency;
clarity and simplicity are preferred in all cases.
Some notes on the syntax, which deviates from ECMA4 in a few ways:
-- By default, declared properties inside a class are {DontEnum,DontDelete}, and are part of the
type constraint for the class type, instance type, or prototype that they’re on.
* native: means "provided by the underlying implementation".
* dynamic: means {!DontDelete}, in effect describing the initial state of an object that can change at runtime.
* static: means the property is declared on C itself, not C.prototype or instances of C.
* this:T if given as the first parameter of an unbound (prototype or anonymous) function,
the type of this is constrained to T. Error on bound (instance) functions.
In static functions, use of this is an error.
* anonymous and global functions have this:Object by default
* {DE} = {DontEnum}
* {DD} = {DontDelete}
* {RO} = {ReadOnly}
class C
{
function // {DD,DE,RO} bound to instance, this:C
static function // {DD,DE,RO} bound to C, this causes error
prototype.g = function(this:Object) // generic dynamic prototype function, e.g. Array.slice()
// note that this syntax does not mark the function as {DE},
// but that is almost universally done for prototype functions,
// and is accomplished via a separate call
}
*/