Skip to content

Latest commit

 

History

History

builtins

Folders and files

NameName
Last commit message
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
	}

*/