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 } */