Stage 1 Draft / January 25, 2022

ECMAScript class brand check proposal

1 ECMAScript Data Types and Values

1.1 ECMAScript Specification Types

1.1.1 The Object Type

1.1.1.1 Object Internal Methods and Internal Slots

All objects have an internal slot named [[ClassBrands]], which is a List of class brand. Initially, it is an empty List.

2 Syntax-Directed Operations

2.1 Contains

2.1.1 Static Semantics: Contains ( symbol: unknown, )

Every grammar production alternative in this specification which is not listed below implicitly has the following default definition of Contains:

  1. For each child node child of this Parse Node, do
    1. If child is an instance of symbol, return true.
    2. If child is an instance of a nonterminal, then
      1. Let contained be the result of child Contains symbol.
      2. If contained is true, return true.
  2. Return false.
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. If symbol is ClassHasInstanceCall, then
    1. If FormalParameters Contains symbol is true, return true.
    2. If FunctionBody of a FunctionDeclaration Contains symbol is true, return true.
    3. If FunctionBody of a FunctionExpression Contains symbol is true, return true.
    4. If GeneratorBody of a GeneratorDeclaration Contains symbol is true, return true.
    5. If GeneratorBody of a GeneratorExpression Contains symbol is true, return true.
    6. If AsyncGeneratorBody of an AsyncGeneratorDeclaration Contains symbol is true, return true.
    7. If AsyncGeneratorBody of an AsyncGeneratorExpression Contains symbol is true, return true.
    8. If AsyncFunctionBody of an AsyncFunctionDeclaration Contains symbol is true, return true.
    9. If AsyncFunctionBody of an AsyncFunctionExpression Contains symbol is true, return true.
  2. Return false.
Note 1

Static semantic rules that depend upon substructure generally do not look into function definitions except for ClassHasInstanceCalls.

ArrowFunction : ArrowParameters => ConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, ClassHasInstanceCall, super or this, return false.
  2. If ArrowParameters Contains symbol is true, return true.
  3. Return ConciseBody Contains symbol.
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, ClassHasInstanceCall, super, or this, return false.
  2. Return AsyncConciseBody Contains symbol.
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, ClassHasInstanceCall, super, or this, return false.
  2. Let head be the AsyncArrowHead that is covered by CoverCallExpressionAndAsyncArrowHead.
  3. If head Contains symbol is true, return true.
  4. Return AsyncConciseBody Contains symbol.
Note 2

Contains is used to detect new.target, class.hasInstance, this, and super usage within an ArrowFunction or AsyncArrowFunction.

2.2 Miscellaneous

2.2.1 Static Semantics: AssignmentTargetType

CallExpression : CoverCallExpressionAndAsyncArrowHead SuperCall ImportCall ClassHasInstanceCall CallExpression Arguments CallExpression TemplateLiteral
  1. Return invalid.

3 Executable Code and Execution Contexts

3.1 Environment Records

3.1.1 The Environment Record Type Hierarchy

3.1.1.1 Class Environment Records

A class Environment Record is a declarative Environment Record that is used to represent the top-level scope of a class, used to perform class.hasInstance meta method invocations from within the class.

Class Environment Records have the additional state fields listed in Table 1.

Table 1: Additional Fields of Class Environment Records
Field Name Value Meaning
[[ClassConstructor]] Object The class constructor whose definition caused this Environment Record to be created.

Class Environment Records support all of the declarative Environment Record methods listed in Table 19 and share the same specifications for all of those methods.

3.1.2 Environment Record Operations

3.1.2.1 NewClassEnvironment ( E )

The abstract operation NewClassEnvironment takes argument E (an Environment Record). It performs the following steps when called:

  1. Let env be a new class Environment Record containing no bindings.
  2. Set env.[[OuterEnv]] to E.
  3. Return env.

3.2 Execution Contexts

3.2.1 GetClassEnvironment ( )

The abstract operation GetClassEnvironment takes no arguments. It finds the Class Environment Record of the nearest containing class. It performs the following steps when called:

  1. Let envRec be the running execution context's LexicalEnvironment.
  2. Repeat,
    1. If envRec is a Class Environment Record, return envRec.
    2. Let envRec be envRec.[[OuterEnv]].

4 Ordinary and Exotic Objects Behaviours

4.1 ECMAScript Function Objects

ECMAScript function objects encapsulate parameterized ECMAScript code closed over a lexical environment and support the dynamic evaluation of that code. An ECMAScript function object is an ordinary object and has the same internal slots and the same internal methods as other ordinary objects. The code of an ECMAScript function object may be either strict mode code (10.2.1) or non-strict code. An ECMAScript function object whose code is strict mode code is called a strict function. One whose code is not strict mode code is called a non-strict function.

In addition to [[Extensible]] and [[Prototype]], ECMAScript function objects also have the internal slots listed in Table 2.

Table 2: Internal Slots of ECMAScript Function Objects
Internal Slot Type Description
[[Environment]] Environment Record The Environment Record that the function was closed over. Used as the outer environment when evaluating the code of the function.
[[PrivateEnvironment]] PrivateEnvironment Record | null The PrivateEnvironment Record for Private Names that the function was closed over. null if this function is not syntactically contained within a class. Used as the outer PrivateEnvironment for inner classes when evaluating the code of the function.
[[FormalParameters]] Parse Node The root parse node of the source text that defines the function's formal parameter list.
[[ECMAScriptCode]] Parse Node The root parse node of the source text that defines the function's body.
[[ConstructorKind]] base | derived Whether or not the function is a derived class constructor.
[[Realm]] Realm Record The realm in which the function was created and which provides any intrinsic objects that are accessed when evaluating the function.
[[ScriptOrModule]] Script Record or Module Record The script or module in which the function was created.
[[ThisMode]] lexical | strict | global Defines how this references are interpreted within the formal parameters and code body of the function. lexical means that this refers to the this value of a lexically enclosing function. strict means that the this value is used exactly as provided by an invocation of the function. global means that a this value of undefined or null is interpreted as a reference to the global object, and any other this value is first passed to ToObject.
[[Strict]] Boolean true if this is a strict function, false if this is a non-strict function.
[[HomeObject]] Object If the function uses super, this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.
[[SourceText]] sequence of Unicode code points The source text that defines the function.
[[Fields]] List of ClassFieldDefinition Records If the function is a class, this is a list of Records representing the non-static fields and corresponding initializers of the class.
[[PrivateMethods]] List of PrivateElements If the function is a class, this is a list representing the non-static private methods and accessors of the class.
[[ClassFieldInitializerName]] String | Symbol | Private Name | empty If the function is created as the initializer of a class field, the name to use for NamedEvaluation of the field; empty otherwise.
[[IsClassConstructor]] Boolean Indicates whether the function is a class constructor. (If true, invoking the function's [[Call]] will immediately throw a TypeError exception.)
[[ClassBrand]] a globally unique value | empty If the function is a class, this might be a globally unique value; empty otherwise.

4.1.1 [[Construct]] ( argumentsList: a List of ECMAScript language values, newTarget: a constructor, )

for
an ECMAScript function object F
  1. Let callerContext be the running execution context.
  2. Let kind be F.[[ConstructorKind]].
  3. If kind is base, then
    1. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%").
  4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  5. Assert: calleeContext is now the running execution context.
  6. If kind is base, then
    1. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
    2. Let initializeResult be InitializeInstanceElements(thisArgument, F).
    3. If initializeResult is an abrupt completion, then
      1. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
      2. Return Completion(initializeResult).
  7. Let constructorEnv be the LexicalEnvironment of calleeContext.
  8. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  9. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  10. If F.[[ClassBrand]] is not empty:
    1. Let currentThis be constructorEnv.GetThisBinding()
    2. If result.[[Type]] is not throw, then append F.[[ClassBrand]] to currentThis.[[ClassBrands]].
  11. If result.[[Type]] is return, then
    1. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
    2. If kind is base, return NormalCompletion(thisArgument).
    3. If result.[[Value]] is not undefined, throw a TypeError exception.
  12. Else, ReturnIfAbrupt(result).
  13. Return ? constructorEnv.GetThisBinding().

4.1.2 OrdinaryFunctionCreate ( functionPrototype, sourceText, ParameterList, Body, thisMode, Scope )

The abstract operation OrdinaryFunctionCreate takes arguments functionPrototype (an Object), sourceText (a sequence of Unicode code points), ParameterList (a Parse Node), Body (a Parse Node), thisMode (either lexical-this or non-lexical-this), and Scope (an Environment Record). sourceText is the source text of the syntactic definition of the function to be created. It performs the following steps when called:

  1. Assert: Type(functionPrototype) is Object.
  2. Let internalSlotsList be the internal slots listed in Table 2.
  3. Let F be ! OrdinaryObjectCreate(functionPrototype, internalSlotsList).
  4. Set F.[[Call]] to the definition specified in 9.2.1.
  5. Set F.[[SourceText]] to sourceText.
  6. Set F.[[FormalParameters]] to ParameterList.
  7. Set F.[[ECMAScriptCode]] to Body.
  8. If the source text matching Body is strict mode code, let Strict be true; else let Strict be false.
  9. Set F.[[Strict]] to Strict.
  10. If thisMode is lexical-this, set F.[[ThisMode]] to lexical.
  11. Else if Strict is true, set F.[[ThisMode]] to strict.
  12. Else, set F.[[ThisMode]] to global.
  13. Set F.[[IsClassConstructor]] to false.
  14. Set F.[[ClassBrand]] to empty.
  15. Set F.[[Environment]] to Scope.
  16. Set F.[[ScriptOrModule]] to GetActiveScriptOrModule().
  17. Set F.[[Realm]] to the current Realm Record.
  18. Set F.[[HomeObject]] to undefined.
  19. Let len be the ExpectedArgumentCount of ParameterList.
  20. Perform ! SetFunctionLength(F, len).
  21. Return F.

5 ECMAScript Language: Expressions

5.1 Left-Hand-Side Expressions

Syntax

CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] ClassHasInstanceCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier ClassHasInstanceCall[Yield, Await] : class . hasInstance ( AssignmentExpression[+In, ?Yield, ?Await] ,opt )

5.1.1 Meta Methods

5.1.1.1 Runtime Semantics: Evalutaion

ClassHasInstanceCall : class . hasInstance ( AssignmentExpression ,opt )
  1. Let inst be the result of AssignmentExpression.
  2. If Type(inst) is not Object.
    1. Return false.
  3. Let envRec be GetClassEnvironment()
  4. Let C be envRec.[[ClassConstructor]].
  5. Assert: C.[[ClassBrand]] is not empty.
  6. If inst.[[ClassBrands]] includes C.[[ClassBrand]], then
    1. Return true.
  7. Else,
    1. Return false.

6 ECMAScript Language: Functions and Classes

6.1 Class Definitions

6.1.1 Static Semantics: Early Errors

ClassTail : ClassHeritageopt { ClassBody }

6.1.2 Static Semantics: ContainsClassHasInstance

ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await]
  1. Return ContainsClassHasInstance of ClassElementList.
ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await]
  1. Return ContainsClassHasInstance of ClassElement.
ClassElementList[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await]
  1. If ContainsClassHasInstance of ClassElement is true, return true.
  2. Return ContainsClassHasInstance of ClassElement.
ClassElement : MethodDefinition static MethodDefinition
  1. Return ContainsClassHasInstance of MethodDefinition.
ClassElement : FieldDefinition static FieldDefinition
  1. Return ContainsClassHasInstance of FieldDefintion.
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. If UniqueFormalParameters Contains ClassHasInstanceCall is true, return true.
  2. Return FunctionBody Contains ClassHasInstanceCall.
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. Return FunctionBody Contains ClassHasInstanceCall.
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. If PropertySetParameterList Contains ClassHasInstanceCall is true, return true.
  2. Return FunctionBody Contains ClassHasInstanceCall.
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. If UniqueFormalParameters Contains ClassHasInstanceCall is true, return true.
  2. Return GeneratorBody Contains ClassHasInstanceCall.
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. If UniqueFormalParameters Contains ClassHasInstanceCall is true, return true.
  2. Return AsyncGeneratorBody Contains ClassHasInstanceCall.
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. If UniqueFormalParameters Contains ClassHasInstanceCall is true, return true.
  2. Return AsyncFunctionBody Contains ClassHasInstanceCall.
FieldDefinition : ClassElementName Initializeropt
  1. If Initializeropt is not preset, return false.
  2. Return ContainsClassHasInstance of Initializer.
Initializer : = AssignmentExpression
  1. Return AssignmentExpression Contains ClassHasInstanceCall

6.1.3 Runtime Semantics: ClassDefinitionEvaluation ( classBinding: unknown, className: unknown, )

Note

For ease of specification, private methods and accessors are included alongside private fields in the [[PrivateElements]] slot of class instances. However, any given object has either all or none of the private methods and accessors defined by a given class. This feature has been designed so that implementations may choose to implement private methods and accessors using a strategy which does not require tracking each method or accessor individually.

For example, an implementation could directly associate instance private methods with their corresponding Private Name and track, for each object, which class constructors have run with that object as their this value. Looking up an instance private method on an object then consists of checking that the class constructor which defines the method has been used to initialize the object, then returning the method associated with the Private Name.

This differs from private fields: because field initializers can throw during class instantiation, an individual object may have some proper subset of the private fields of a given class, and so private fields must in general be tracked individually.

ClassTail : ClassHeritageopt { ClassBodyopt }
  1. Let env be the LexicalEnvironment of the running execution context.
  2. Let classEnv be NewDeclarativeClassEnvironment(env).
  3. If classBinding is not undefined, then
    1. Perform classEnv.CreateImmutableBinding(classBinding, true).
  4. Let outerPrivateEnvironment be the running execution context's PrivateEnvironment.
  5. Let classPrivateEnvironment be NewPrivateEnvironment(outerPrivateEnvironment).
  6. If ClassBodyopt is present, then
    1. For each String dn of the PrivateBoundIdentifiers of ClassBodyopt, do
      1. If classPrivateEnvironment.[[Names]] contains a Private Name whose [[Description]] is dn, then
        1. Assert: This is only possible for getter/setter pairs.
      2. Else,
        1. Let name be a new Private Name whose [[Description]] value is dn.
        2. Append name to classPrivateEnvironment.[[Names]].
  7. If ClassHeritageopt is not present, then
    1. Let protoParent be %Object.prototype%.
    2. Let constructorParent be %Function.prototype%.
  8. Else,
    1. Set the running execution context's LexicalEnvironment to classEnv.
    2. NOTE: The running execution context's PrivateEnvironment is outerPrivateEnvironment when evaluating ClassHeritage.
    3. Let superclassRef be the result of evaluating ClassHeritage.
    4. Set the running execution context's LexicalEnvironment to env.
    5. Let superclass be ? GetValue(superclassRef).
    6. If superclass is null, then
      1. Let protoParent be null.
      2. Let constructorParent be %Function.prototype%.
    7. Else if IsConstructor(superclass) is false, throw a TypeError exception.
    8. Else,
      1. Let protoParent be ? Get(superclass, "prototype").
      2. If Type(protoParent) is neither Object nor Null, throw a TypeError exception.
      3. Let constructorParent be superclass.
  9. Let proto be ! OrdinaryObjectCreate(protoParent).
  10. If ClassBodyopt is not present, let constructor be empty.
  11. Else, let constructor be ConstructorMethod of ClassBody.
  12. Set the running execution context's LexicalEnvironment to classEnv.
  13. Set the running execution context's PrivateEnvironment to classPrivateEnvironment.
  14. If constructor is empty, then
    1. Let defaultConstructor be a new Abstract Closure with no parameters that captures nothing and performs the following steps when called:
      1. Let args be the List of arguments that was passed to this function by [[Call]] or [[Construct]].
      2. If NewTarget is undefined, throw a TypeError exception.
      3. Let F be the active function object.
      4. If F.[[ConstructorKind]] is derived, then
        1. NOTE: This branch behaves similarly to constructor(...args) { super(...args); }. The most notable distinction is that while the aforementioned ECMAScript source text observably calls the @@iterator method on %Array.prototype%, this function does not.
        2. Let func be ! F.[[GetPrototypeOf]]().
        3. If IsConstructor(func) is false, throw a TypeError exception.
        4. Let result be ? Construct(func, args, NewTarget).
      5. Else,
        1. NOTE: This branch behaves similarly to constructor() {}.
        2. Let result be ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%").
      6. Perform ? InitializeInstanceElements(result, F).
      7. Return result.
    2. Let F be ! CreateBuiltinFunction(defaultConstructor, 0, className, « [[ConstructorKind]], [[SourceText]] », the current Realm Record, constructorParent).
  15. Else,
    1. Let constructorInfo be ! DefineMethod of constructor with arguments proto and constructorParent.
    2. Let F be constructorInfo.[[Closure]].
    3. Perform ! MakeClassConstructor(F).
    4. Perform ! SetFunctionName(F, className).
  16. Perform ! MakeConstructor(F, false, proto).
  17. If ClassHeritageopt is present, set F.[[ConstructorKind]] to derived.
  18. Perform ! CreateMethodProperty(proto, "constructor", F).
  19. Set classEnv.[[ClassConstructor]] to F.
  20. If ClassBodyopt is present, then
    1. If ContainsClassHasInstance of ClassBody, Set F.[[ClassBrand]] to a new unique value.
  21. If ClassBodyopt is not present, let elements be a new empty List.
  22. Else, let elements be NonConstructorElements of ClassBody.
  23. Let instancePrivateMethods be a new empty List.
  24. Let staticPrivateMethods be a new empty List.
  25. Let instanceFields be a new empty List.
  26. Let staticElements be a new empty List.
  27. For each ClassElement e of elements, do
    1. If IsStatic of e is false, then
      1. Let element be ClassElementEvaluation of e with argument proto.
    2. Else,
      1. Let element be ClassElementEvaluation of e with argument F.
    3. If element is an abrupt completion, then
      1. Set the running execution context's LexicalEnvironment to env.
      2. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
      3. Return Completion(element).
    4. Set element to element.[[Value]].
    5. If element is a PrivateElement, then
      1. Assert: element.[[Kind]] is either method or accessor.
      2. If IsStatic of e is false, let container be instancePrivateMethods.
      3. Else, let container be staticPrivateMethods.
      4. If container contains a PrivateElement whose [[Key]] is element.[[Key]], then
        1. Let existing be that PrivateElement.
        2. Assert: element.[[Kind]] and existing.[[Kind]] are both accessor.
        3. If element.[[Get]] is undefined, then
          1. Let combined be PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: existing.[[Get]], [[Set]]: element.[[Set]] }.
        4. Else,
          1. Let combined be PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: existing.[[Set]] }.
        5. Replace existing in container with combined.
      5. Else,
        1. Append element to container.
    6. Else if element is a ClassFieldDefinition Record, then
      1. If IsStatic of e is false, append element to instanceFields.
      2. Else, append element to staticElements.
    7. Else if element is a ClassStaticBlockDefinition Record, then
      1. Append element to staticElements.
  28. Set the running execution context's LexicalEnvironment to env.
  29. If classBinding is not undefined, then
    1. Perform classEnv.InitializeBinding(classBinding, F).
  30. Set F.[[PrivateMethods]] to instancePrivateMethods.
  31. Set F.[[Fields]] to instanceFields.
  32. For each PrivateElement method of staticPrivateMethods, do
    1. Perform ! PrivateMethodOrAccessorAdd(F, method).
  33. For each element elementRecord of staticElements, do
    1. If elementRecord is a ClassFieldDefinition Record, then
      1. Let result be DefineField(F, elementRecord).
    2. Else,
      1. Assert: elementRecord is a ClassStaticBlockDefinition Record.
      2. Let result be ? Call(elementRecord.[[BodyFunction]], F).
    3. If result is an abrupt completion, then
      1. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
      2. Return result.
  34. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
  35. Return F.

7 ECMAScript Language: Scripts and Modules

7.1 Scripts

7.1.1 Static Semantics: Early Errors

ScriptBody : StatementList

7.2 Modules

7.2.1 Module Semantics

7.2.1.1 Static Semantics: Early Errors

ModuleBody : ModuleItemList

A Copyright & Software License

Copyright Notice

© 2022 HE Shi-Jun, XU Tian-Yang, Tu Qiang

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.