Stage 0 Draft / November 23, 2016

Zones

1Zone Objectslinkpin

A Zone is an object that represents a logical asynchronous context.

1.1Zone Abstract Operationslinkpin

1.1.1CallInZone ( zone, callback, thisArg, argumentsList )linkpin

  1. Let zoneRealm be the value of zone's [[Realm]] internal slot.
  2. Let beforeZone be zoneRealm.[[CurrentZone]].
  3. Set zoneRealm.[[CurrentZone]] to Z.
  4. Let status be Call(callback, thisArg, argumentsList).
  5. Set zoneRealm.[[CurrentZone]] to beforeZone.
  6. Return status.

1.2The Zone Constructorlinkpin

The Zone constructor is the %Zone% intrinsic object and the initial value of the Zone property of the global object. When called as a constructor it creates and initializes a new Zone object. Zone is not intended to be called as a function and will throw an exception when called in that manner.

The Zone constructor is designed to be subclassable. It may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified Zone behaviour must include a super call to the Zone constructor to create and initialize the subclass instance with the internal state necessary to support the Zone and Zone.prototype built-in methods.

1.2.1Zone ( options )linkpin

When the Zone function is called with argument options, the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let functionRealm be ? GetFunctionRealm(the active function object).
  3. Let name be "(unnamed zone)".
  4. Let parent be null.
  5. If options is undefined, set options to ! ObjectCreate(%ObjectPrototype%).
  6. Perform ? RequireObjectCoercible(options).
  7. Let nameOption be ? GetV(options, "name").
  8. If nameOption is not undefined, set name to ? ToString(nameOption).
  9. Let parentOption be ? GetV(options, "parent").
  10. If parentOption is not undefined, set parent to parentOption.
  11. If parent is not null and does not have a [[ParentZone]] internal slot, throw a TypeError exception.
  12. Let zone be ? OrdinaryCreateFromConstructor(NewTarget, "%ZonePrototype", « [[ParentZone]], [[Realm]], [[HostDefined]] »).
  13. Set zone's [[ParentZone]] internal slot to parent.
  14. Set zone's [[Realm]] internal slot to currentRealm.
  15. Perform ! DefinePropertyOrThrow(zone, "name", PropertyDescriptor {[[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).
  16. Perform ? HostSetupZone(zone, options).
  17. Return zone.
Note 1

The Zone constructor is not typically used directly. Instead, anotherZone.fork({ name }) is used to create a new zone that is the child of an existing one. A particular common pattern is Zone.current.fork({ name }).

Note 2

(Spec review note) This is intended to mimic the signature constructor({ name = "(unnamed zone)", parent = null } = {}) { ... }.

1.2.1.1HostSetupZone ( zone, options )linkpin

HostSetupZone is an implementation-defined abstract operation that allows host environments to set up Zone objects based on the developer-supplied options value. Host environments may wish to, for example, store values passed as properties of options in the [[HostDefined]] internal slot of the zone object.

An implementation of HostSetupZone may complete normally or abruptly. Any abrupt completions will be propagated to its callers. The default implementation of HostSetupZone is to unconditionally return an empty normal completion.

Note

zone will be guaranteed to be a Zone object, and options will be guaranteed to have passed RequireObjectCoercible. Implementations are encouraged to follow the pattern of the Zone constructor in using GetV on options and providing default values if and only if the option is undefined.

1.3Properties of the Zone Constructorlinkpin

The value of the [[Prototype]] internal slot of the Zone constructor is the intrinsic object %FunctionPrototype%.

The Zone constructor has the following properties:

1.3.1Zone.prototypelinkpin

The initial value of Zone.prototype is the intrinsic object %ZonePrototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

1.3.2get Zone.currentlinkpin

Zone.current is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let C be the this value.
  2. If IsCallable(C) is false, throw a TypeError exception.
  3. Let thisRealm be ? GetFunctionRealm(C).
  4. Return thisRealm.[[CurrentZone]].

1.4Properties of the Zone Prototype Objectlinkpin

The Zone prototype object is the intrinsic object %ZonePrototype%. The value of the [[Prototype]] internal slot of the Zone prototype object is the intrinsic object %ObjectPrototype%. The Zone prototype object is an ordinary object. It does not have any of the internal slots of Zone instances.

1.4.1get Zone.prototype.parentlinkpin

Zone.prototype.parent is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let Z be the this value.
  2. If Type(Z) is not Object, throw a TypeError exception.
  3. If Z does not have a [[ParentZone]] internal slot, throw a TypeError exception.
  4. Return the value of Z's [[ParentZone]] internal slot.

1.4.2Zone.prototype.fork ( options )linkpin

When the fork method is called with argument options, the following steps are taken:

  1. Let Z be the this value.
  2. If Type(Z) is not Object, throw a TypeError exception.
  3. If Z does not have a [[ParentZone]] internal slot, throw a TypeError exception.
  4. Let name be null.
  5. If options is undefined, set options to ! ObjectCreate(%ObjectPrototype%).
  6. Perform ? RequireObjectCoercible(options).
  7. Let nameOption be ? GetV(options, "name").
  8. If nameOption is undefined,
    1. Let parentName be ? ToString(? Get(Z, "name")).
    2. Set name to the result of concatenating parentName and the string " child".
  9. Otherwise, set name to ? ToString(nameOption).
  10. Let constructorOptions be ! ObjectCreate(%ObjectPrototype%).
  11. Peform ! CreateDataProperty(constructorOptions, "parent", Z).
  12. Perform ! CreateDataProperty(options, "name", name).
  13. Let C be ? Get(Z, "constructor").
  14. Return ? Construct(C, « options »)
Note

(Spec review note) This is intended to mimic the function signature fork({ name = ToString(this.name) + " child" } = {}) { ... }.

1.4.3Zone.prototype.run ( callback )linkpin

When the run method is called with argument callback, the following steps are taken:

  1. Let Z be the this value.
  2. If Type(Z) is not Object, throw a TypeError exception.
  3. If Z does not have a [[ParentZone]] internal slot, throw a TypeError exception.
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Return CallInZone(Z, callback, undefined, « »).

1.4.4Zone.prototype.wrap ( callback )linkpin

When the wrap method is called with argument callback, the following steps are taken:

  1. Let Z be the this value.
  2. If Type(Z) is not Object, throw a TypeError exception.
  3. If Z does not have a [[ParentZone]] internal slot, throw a TypeError exception.
  4. Let wrapped be a new built-in function object as defined in Zone.prototype.wrap Wrapper Functions.
  5. Set the [[Zone]] internal slot of wrapped to Z.
  6. Set the [[Callback]] internal slot of wrapped to callback.
  7. Return wrapped.

1.4.4.1Zone.prototype.wrap Wrapper Functionslinkpin

A Zone.prototype.wrap wrapper function is an anonymous built-in function that is created by the Zone.prototype.wrap method. Each Zone.prototype.wrap wrapper function has [[Zone]] and [[Callback]] internal slots.

When a Zone.prototype.wrap wrapper function F is called with this value thisArg and arguments argumentsList, the following steps are taken:

  1. Assert: F has [[Zone]] and [[Callback]] internal slots.
  2. Let Z be the value of F's [[Zone]] internal slot.
  3. Assert: Z has a [[ParentZone]] internal slot.
  4. Let callback be the value of F's [[Callback]] internal slot.
  5. Assert: IsCallable(callback) is true.
  6. Return CallInZone(Z, callback, thisArg, argumentsList).

1.5Properties of Zone Instanceslinkpin

Zone instances are ordinary objects that inherit properties from the Zone prototype object (the intrinsic, %ZonePrototype%). Zone instances are initially created with the internal slots described in Table 1.

Table 1: Internal Slots of Zone Instances
Internal Slot Description
[[ParentZone]] The zone in which this zone was created.
[[Realm]] The realm of the Zone constructor that created this instance.
[[HostDefined]] Field reserved for use by host environments that need to associate additional information with a zone.

Each Zone instance has the following own property:

1.5.1namelinkpin

The value of the name property is a string that indicates the name of the zone, supplied at construction time. It is used for debugging and tooling purposes and does not affect the zone's behavior.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

2Revisions to Realmslinkpin

The table for Realm Record fields gets a new entry:

Table 2: Realm Record Fields
Field Name Value Meaning
[[CurrentZone]] A Zone object The current zone for this realm

2.1CreateRealm ( )linkpin

The abstract operation CreateRealm with no arguments performs the following steps:

  1. Let realmRec be a new Realm Record.
  2. Perform CreateIntrinsics(realmRec).
  3. Set realmRec.[[GlobalObject]] to undefined.
  4. Set realmRec.[[GlobalEnv]] to undefined.
  5. Set realmRec.[[TemplateMap]] to a new empty List.
  6. Let options be ! ObjectCreate(%ObjectPrototype%).
  7. Perform ! CreateDataProperty(options, "name", "(root zone)").
  8. Set realmRec.[[CurrentZone]] to ! Construct(%Zone%, « options »).
  9. Return realmRec.

3Revisions to Promise Objectslinkpin

3.1PromiseReaction Recordslinkpin

The table for PromiseReaction Record fields gets a new entry:

Table 3: Realm Record Fields
Field Name Value Meaning
[[Zone]] A Zone object The zone associated with this promise reaction

3.2PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability )linkpin

The abstract operation PerformPromiseThen performs the “then” operation on promise using onFulfilled and onRejected as its settlement actions. The result is resultCapability's promise.

  1. Assert: IsPromise(promise) is true.
  2. Assert: resultCapability is a PromiseCapability record.
  3. If IsCallable(onFulfilled) is false, then
    1. Let onFulfilled be "Identity".
  4. If IsCallable(onRejected) is false, then
    1. Let onRejected be "Thrower".
  5. Let currentZone be the value of the current Realm Record's [[CurrentZone]] field.
  6. Let fulfillReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onFulfilled, [[Zone]]: currentZone }.
  7. Let rejectReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onRejected, [[Zone]]: currentZone }.
  8. If the value of promise's [[PromiseState]] internal slot is "pending", then
    1. Append fulfillReaction as the last element of the List that is the value of promise's [[PromiseFulfillReactions]] internal slot.
    2. Append rejectReaction as the last element of the List that is the value of promise's [[PromiseRejectReactions]] internal slot.
  9. Else if the value of promise's [[PromiseState]] internal slot is "fulfilled", then
    1. Let value be the value of promise's [[PromiseResult]] internal slot.
    2. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, « fulfillReaction, value »).
  10. Else,
    1. Assert: The value of promise's [[PromiseState]] internal slot is "rejected".
    2. Let reason be the value of promise's [[PromiseResult]] internal slot.
    3. If the value of promise's [[PromiseIsHandled]] internal slot is false, perform HostPromiseRejectionTracker(promise, "handle").
    4. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, « rejectReaction, reason »).
  11. Set promise's [[PromiseIsHandled]] internal slot to true.
  12. Return resultCapability.[[Promise]].

3.3PromiseReactionJob ( reaction, argument )linkpin

The job PromiseReactionJob with parameters reaction and argument applies the appropriate handler to the incoming value, and uses the handler's return value to resolve or reject the derived promise associated with that handler.

  1. Assert: reaction is a PromiseReaction Record.
  2. Let promiseCapability be reaction.[[Capabilities]].
  3. Let handler be reaction.[[Handler]].
  4. If handler is "Identity", let handlerResult be NormalCompletion(argument).
  5. Else if handler is "Thrower", let handlerResult be Completion{[[Type]]: throw, [[Value]]: argument, [[Target]]: empty}.
  6. Else, let handlerResult be Call(handler, undefined, « argument »).
  7. Else,
    1. Let zone be reaction.[[Zone]].
    2. Let handlerResult be CallInZone(zone, handler, undefined, « argument »).
  8. If handlerResult is an abrupt completion, then
    1. Let status be Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »).
    2. NextJob Completion(status).
  9. Let status be Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »).
  10. NextJob Completion(status).