diff --git a/spec.html b/spec.html index 2125efa52a..f48bc1c160 100644 --- a/spec.html +++ b/spec.html @@ -6136,135 +6136,41 @@

GetGlobalObject ( )

Jobs and Job Queues

-

A Job is an abstract operation that initiates an ECMAScript computation when no other ECMAScript computation is currently in progress. A Job abstract operation may be defined to accept an arbitrary set of job parameters.

-

Execution of a Job can be initiated only when there is no running execution context and the execution context stack is empty. A PendingJob is a request for the future execution of a Job. A PendingJob is an internal Record whose fields are specified in . Once execution of a Job is initiated, the Job always executes to completion. No other Job may be initiated until the currently running Job completes. However, the currently running Job or external events may cause the enqueuing of additional PendingJobs that may be initiated sometime after completion of the currently running Job.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Field Name - - Value - - Meaning -
- [[Job]] - - The name of a Job abstract operation - - This is the abstract operation that is performed when execution of this PendingJob is initiated. -
- [[Arguments]] - - A List - - The List of argument values that are to be passed to [[Job]] when it is activated. -
- [[Realm]] - - A Realm Record - - The Realm Record for the initial execution context when this PendingJob is initiated. -
- [[ScriptOrModule]] - - A Script Record or Module Record - - The script or module for the initial execution context when this PendingJob is initiated. -
- [[HostDefined]] - - Any, default value is *undefined*. - - Field reserved for use by host environments that need to associate additional information with a pending Job. -
-
-

A Job Queue is a FIFO queue of PendingJob records. Each Job Queue has a name and the full set of available Job Queues are defined by an ECMAScript implementation. Every ECMAScript implementation has at least the Job Queues defined in .

Each agent has its own set of named Job Queues. All references to a named job queue in this specification denote the named job queue of the surrounding agent.

- - - - - - - - - - - - - - - - -
- Name - - Purpose -
- ScriptJobs - - Jobs that validate and evaluate ECMAScript |Script| and |Module| source text. See clauses 10 and 15. -
- PromiseJobs - - Jobs that are responses to the settlement of a Promise (see ). -
-
-

A request for the future execution of a Job is made by enqueueing, on a Job Queue, a PendingJob record that includes a Job abstract operation name and any necessary argument values. When there is no running execution context and the execution context stack is empty, the ECMAScript implementation removes the first PendingJob from a Job Queue and uses the information contained in it to create an execution context and starts execution of the associated Job abstract operation.

-

The PendingJob records from a single Job Queue are always initiated in FIFO order. This specification does not define the order in which multiple Job Queues are serviced. An ECMAScript implementation may interweave the FIFO evaluation of the PendingJob records of a Job Queue with the evaluation of the PendingJob records of one or more other Job Queues. An implementation must define what occurs when there are no running execution context and all Job Queues are empty.

- -

Typically an ECMAScript implementation will have its Job Queues pre-initialized with at least one PendingJob and one of those Jobs will be the first to be executed. An implementation might choose to free all resources and terminate if the current Job completes and all Job Queues are empty. Alternatively, it might choose to wait for a some implementation specific agent or mechanism to enqueue new PendingJob requests.

-
-

The following abstract operations are used to create and manage Jobs and Job Queues:

- - -

EnqueueJob ( _queueName_, _job_, _arguments_ )

-

The EnqueueJob abstract operation requires three arguments: _queueName_, _job_, and _arguments_. It performs the following steps:

- - 1. Assert: Type(_queueName_) is String and its value is the name of a Job Queue recognized by this implementation. - 1. Assert: _job_ is the name of a Job. - 1. Assert: _arguments_ is a List that has the same number of elements as the number of parameters required by _job_. - 1. Let _callerContext_ be the running execution context. - 1. Let _callerRealm_ be _callerContext_'s Realm. - 1. Let _callerScriptOrModule_ be _callerContext_'s ScriptOrModule. - 1. Let _pending_ be PendingJob{ [[Job]]: _job_, [[Arguments]]: _arguments_, [[Realm]]: _callerRealm_, [[ScriptOrModule]]: _callerScriptOrModule_, [[HostDefined]]: *undefined* }. - 1. Perform any implementation or host environment defined processing of _pending_. This may include modifying the [[HostDefined]] field or any other field of _pending_. - 1. Add _pending_ at the back of the Job Queue named by _queueName_. - 1. Return NormalCompletion(~empty~). - +

A Job is an abstract operation that initiates an ECMAScript computation when no other ECMAScript computation is currently in progress. A Job abstract operation may be defined to accept an arbitrary set of job parameters.

+ +

The exact normative requirements of evaluating Jobs are governed by the requirements on the HostEnqueueJob abstract operation. Here we explain the conceptual background and intuition in a non-normative fashion.

+ +

A Job Queue is a FIFO queue of PendingJob records, denoted by a String passed as the first argument to HostEnqueueJob. (The FIFO nature of a Job Queue is enforced by the requirements on HostEnqueueJob.) Each Job Queue has such a String name, and the full set of available Job Queues are defined by an ECMAScript implementation.

+ +

Every ECMAScript implementation has at least the Job Queue `"PromiseJobs"`, which are responses to the settlement of a Promise (see ).

+ +

A request for the future execution of a Job is made by performing HostEnqueueJob, giving a Job Queue name, a Job abstract operation, and any necessary argument values. At some time when there is no running execution context and the execution context stack is empty, the ECMAScript implementation will perform the given Job abstract operation and evaluate it with the given arguments.

+ +

The Jobs enqueued on a single Job Queue are always required to be initiated in FIFO order. This specification does not impose requirements on the order in which multiple Job Queues are serviced. An ECMAScript implementation might interweave the FIFO evaluation of the Jobs on a Job Queue with the evaluation of Jobs on one or more other Job Queues. An implementation will define what occurs when there is no running execution context and all Job Queues are empty.

+ + +

HostEnqueueJob ( _queueName_, _job_, _arguments_ )

+ +

HostEnqueueJob is an implementation defined abstract operation that schedules the abstract operation indicated by _job_ to be performed, with the arguments _arguments_, at some future time. The String _queueName_ is used to enforce certain ordering guarantees among enqueued Jobs.

+ +

The implementation of HostEnqueueJob must conform to the following requirements, all of which are scoped to each agent:

+ +
    +
  • At some future point in time, when there is no running execution context and the execution context stack is empty, the implementation must: +
      +
    1. Push an execution context onto the execution context stack.
    2. +
    3. Perform any implementation-defined preparation steps.
    4. +
    5. Perform the abstract operation given by _job_, passing the arguments _arguments_.
    6. +
    7. Perform any implementation-defined cleanup steps.
    8. +
    9. Pop the previously-pushed execution context from the execution context stack.
    10. +
    +
  • +
  • Only one Job may be actively undergoing evaluation at any point in time.
  • +
  • Once evaluation of a Job starts, it must run to completion before evaluation of any other Job starts.
  • +
  • The evaluation of any Jobs enqueued via previous calls to HostEnqueueJob with the same _queueName_ argument must complete before evaluation of the Job starts.
  • +
@@ -6288,32 +6194,6 @@

InitializeHostDefinedRealm ( )

- -

RunJobs ( )

-

The abstract operation RunJobs performs the following steps:

- - 1. Perform ? InitializeHostDefinedRealm(). - 1. In an implementation-dependent manner, obtain the ECMAScript source texts (see clause ) and any associated host-defined values for zero or more ECMAScript scripts and/or ECMAScript modules. For each such _sourceText_ and _hostDefined_, do - 1. If _sourceText_ is the source code of a script, then - 1. Perform EnqueueJob(`"ScriptJobs"`, ScriptEvaluationJob, « _sourceText_, _hostDefined_ »). - 1. Else _sourceText_ is the source code of a module, - 1. Perform EnqueueJob(`"ScriptJobs"`, TopLevelModuleEvaluationJob, « _sourceText_, _hostDefined_ »). - 1. Repeat, - 1. Suspend the running execution context and remove it from the execution context stack. - 1. Assert: The execution context stack is now empty. - 1. Let _nextQueue_ be a non-empty Job Queue chosen in an implementation-defined manner. If all Job Queues are empty, the result is implementation-defined. - 1. Let _nextPending_ be the PendingJob record at the front of _nextQueue_. Remove that record from _nextQueue_. - 1. Let _newContext_ be a new execution context. - 1. Set _newContext_'s Function to *null*. - 1. Set _newContext_'s Realm to _nextPending_.[[Realm]]. - 1. Set _newContext_'s ScriptOrModule to _nextPending_.[[ScriptOrModule]]. - 1. Push _newContext_ onto the execution context stack; _newContext_ is now the running execution context. - 1. Perform any implementation or host environment defined job initialization using _nextPending_. - 1. Let _result_ be the result of performing the abstract operation named by _nextPending_.[[Job]] using the elements of _nextPending_.[[Arguments]] as its arguments. - 1. If _result_ is an abrupt completion, perform HostReportErrors(« _result_.[[Value]] »). - -
-

Agents

@@ -20553,21 +20433,6 @@

Runtime Semantics: GlobalDeclarationInstantiation ( _script_, _env_ )

Unlike explicit var or function declarations, properties that are directly created on the global object result in global bindings that may be shadowed by let/const/class declarations.

- - - -

Runtime Semantics: ScriptEvaluationJob ( _sourceText_, _hostDefined_ )

-

The job ScriptEvaluationJob with parameters _sourceText_ and _hostDefined_ parses, validates, and evaluates _sourceText_ as a |Script|.

- - 1. Assert: _sourceText_ is an ECMAScript source text (see clause ). - 1. Let _realm_ be the current Realm Record. - 1. Let _s_ be ParseScript(_sourceText_, _realm_, _hostDefined_). - 1. If _s_ is a List of errors, then - 1. Perform HostReportErrors(_s_). - 1. Return NormalCompletion(*undefined*). - 1. Return ? ScriptEvaluation(_s_). - -
@@ -21763,26 +21628,6 @@

Runtime Semantics: GetModuleNamespace( _module_ )

- - -

Runtime Semantics: TopLevelModuleEvaluationJob ( _sourceText_, _hostDefined_ )

-

A TopLevelModuleEvaluationJob with parameters _sourceText_ and _hostDefined_ is a job that parses, validates, and evaluates _sourceText_ as a |Module|.

- - 1. Assert: _sourceText_ is an ECMAScript source text (see clause ). - 1. Let _realm_ be the current Realm Record. - 1. Let _m_ be ParseModule(_sourceText_, _realm_, _hostDefined_). - 1. If _m_ is a List of errors, then - 1. Perform HostReportErrors(_m_). - 1. Return NormalCompletion(*undefined*). - 1. Perform ? _m_.ModuleDeclarationInstantiation(). - 1. Assert: All dependencies of _m_ have been transitively resolved and _m_ is ready for evaluation. - 1. Return ? _m_.ModuleEvaluation(). - - -

An implementation may parse a _sourceText_ as a |Module|, analyse it for Early Error conditions, and instantiate it prior to the execution of the TopLevelModuleEvaluationJob for that _sourceText_. An implementation may also resolve, pre-parse and pre-analyse, and pre-instantiate module dependencies of _sourceText_. However, the reporting of any errors detected by these actions must be deferred until the TopLevelModuleEvaluationJob is actually executed.

-
-
-

Runtime Semantics: Evaluation

@@ -22448,18 +22293,6 @@

Error Handling and Language Extensions

An implementation may define behaviour other than throwing *RangeError* for `toFixed`, `toExponential`, and `toPrecision` when the _fractionDigits_ or _precision_ argument is outside the specified range.

- -

HostReportErrors ( _errorList_ )

- -

HostReportErrors is an implementation-defined abstract operation that allows host environments to report parsing errors, early errors, and runtime errors.

- -

An implementation of HostReportErrors must complete normally in all cases. The default implementation of HostReportErrors is to unconditionally return an empty normal completion.

- - -

_errorList_ will be a List of ECMAScript language values. If the errors are parsing errors or early errors, these will always be *SyntaxError* or *ReferenceError* objects. Runtime errors, however, can be any ECMAScript value.

-
-
-

Forbidden Extensions

@@ -35955,7 +35788,7 @@

Promise Resolve Functions

1. Let _thenAction_ be _then_.[[Value]]. 1. If IsCallable(_thenAction_) is *false*, then 1. Return FulfillPromise(_promise_, _resolution_). - 1. Perform EnqueueJob(`"PromiseJobs"`, PromiseResolveThenableJob, « _promise_, _resolution_, _thenAction_ »). + 1. Perform HostEnqueueJob(`"PromiseJobs"`, PromiseResolveThenableJob, « _promise_, _resolution_, _thenAction_ »). 1. Return *undefined*.

The `length` property of a promise resolve function is 1.

@@ -36048,7 +35881,7 @@

TriggerPromiseReactions ( _reactions_, _argument_ )

The abstract operation TriggerPromiseReactions takes a collection of PromiseReactionRecords and enqueues a new Job for each record. Each such Job processes the [[Type]] and [[Handler]] of the PromiseReactionRecord, and if the [[Handler]] is a function, calls it passing the given argument. If the [[Handler]] is *undefined*, the behaviour is determined by the [[Type]].

1. For each _reaction_ in _reactions_, in original insertion order, do - 1. Perform EnqueueJob(`"PromiseJobs"`, PromiseReactionJob, « _reaction_, _argument_ »). + 1. Perform HostEnqueueJob(`"PromiseJobs"`, PromiseReactionJob, « _reaction_, _argument_ »). 1. Return *undefined*.
@@ -36398,12 +36231,12 @@

PerformPromiseThen ( _promise_, _onFulfilled_, _onRejected_, _resultCapabili 1. Append _rejectReaction_ as the last element of the List that is _promise_.[[PromiseRejectReactions]]. 1. Else if _promise_.[[PromiseState]] is `"fulfilled"`, then 1. Let _value_ be _promise_.[[PromiseResult]]. - 1. Perform EnqueueJob(`"PromiseJobs"`, PromiseReactionJob, « _fulfillReaction_, _value_ »). + 1. Perform HostEnqueueJob(`"PromiseJobs"`, PromiseReactionJob, « _fulfillReaction_, _value_ »). 1. Else, 1. Assert: The value of _promise_.[[PromiseState]] is `"rejected"`. 1. Let _reason_ be _promise_.[[PromiseResult]]. 1. If _promise_.[[PromiseIsHandled]] is *false*, perform HostPromiseRejectionTracker(_promise_, `"handle"`). - 1. Perform EnqueueJob(`"PromiseJobs"`, PromiseReactionJob, « _rejectReaction_, _reason_ »). + 1. Perform HostEnqueueJob(`"PromiseJobs"`, PromiseReactionJob, « _rejectReaction_, _reason_ »). 1. Set _promise_.[[PromiseIsHandled]] to *true*. 1. Return _resultCapability_.[[Promise]]. @@ -39097,6 +38930,258 @@

Initializers in ForIn Statement Heads

+ +

Example Host Environment

+ +

This informative annex gives implementations of all of the host-defined abstract operations in this specification, along with supporting infrastructure and an outline for how the environment would be initialized, in order to explain how a simple command-line ECMAScript implementation could work and conform to the various requirements on the host.

+ + +

Jobs and Job Queues

+ +

This implementation uses a PendingJob Record type to track all enqueued jobs. Its fields are given here:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Field Name + + Value + + Meaning +
+ [[Job]] + + A Job abstract operation + + The abstract operation that is performed when execution of this PendingJob is initiated. +
+ [[Arguments]] + + A List + + The List of argument values that are to be passed to [[Job]] when it is activated. +
+ [[Realm]] + + A Realm Record + + The Realm Record for the initial execution context when this PendingJob is initiated. +
+ [[ScriptOrModule]] + + A Script Record or Module Record + + The script or module for the initial execution context when this PendingJob is initiated. +
+
+ +

In addition to the `"PromiseJobs"` Job Queue, this implementation also has a `"ScriptJobs"` Job Queue for validating and evaluating ECMASCript |Script| and |Module| source text. In this implementation each Job Queue has an associated List of PendingJob records.

+ +

This implementation's HostEnqueueJob abstract operation performs the following steps, given the arguments _queueName_, _job_, and _arguments_:

+ + 1. Assert: Type(_queueName_) is String and its value is the name of a Job Queue recognized by this implementation. + 1. Assert: _job_ is the name of a Job. + 1. Assert: _arguments_ is a List that has the same number of elements as the number of parameters required by _job_. + 1. Let _callerContext_ be the running execution context. + 1. Let _callerRealm_ be _callerContext_'s Realm. + 1. Let _pending_ be PendingJob{ [[Job]]: _job_, [[Arguments]]: _arguments_, [[Realm]]: _callerRealm_, [[ScriptOrModule]]: GetActiveScriptOrModule() }. + 1. Add _pending_ to the List of PendingJob records associated with the Job Queue named by _queueName_. + 1. Return NormalCompletion(~empty~). + +
+ + +

Source Text Evaluation

+ +

Source text evaluation in this implementation is performed via ScriptEvaluationJob and TopLevelModuleEvaluationJob. Using Jobs to perform these evaluations is a simple way to ensure that the execution context stack is always empty when any promise jobs run, since any ScriptEvaluationJob or TopLevelModuleEvaluationJob will have run to completion.

+ + +

ScriptEvaluationJob ( _sourceText_ )

+

A ScriptEvaluationJob with parameter _sourceText_ parses, validates, and evaluates _sourceText_ as a |Script|.

+ + 1. Assert: _sourceText_ is an ECMAScript source text (see clause ). + 1. Let _realm_ be the current Realm Record. + 1. Let _s_ be ParseScript(_sourceText_, _realm_, *undefined*). + 1. If _s_ is a List of errors, then + 1. Perform ReportErrors(_s_). + 1. Return NormalCompletion(*undefined*). + 1. Return ? ScriptEvaluation(_s_). + +
+ + +

TopLevelModuleEvaluationJob ( _sourceText_, _filename_ )

+

A TopLevelModuleEvaluationJob with parameters _sourceText_ and _filename_ is a job that parses, validates, and evaluates _sourceText_ as a |Module|.

+ + 1. Assert: _sourceText_ is an ECMAScript source text (see clause ). + 1. Let _realm_ be the current Realm Record. + 1. Let _m_ be ParseModule(_sourceText_, _realm_, _filename_). + 1. If _m_ is a List of errors, then + 1. Perform ReportErrors(_m_). + 1. Return NormalCompletion(*undefined*). + 1. Add ModuleMap{ [[Filename]]: _filename_, [[Module]]: _m_ } to the module map. + 1. Perform ? _m_.ModuleDeclarationInstantiation(). + 1. Assert: All dependencies of _m_ have been transitively resolved and _m_ is ready for evaluation. + 1. Return ? _m_.ModuleEvaluation(). + + +

The implementation might parse a _sourceText_ as a |Module|, analyze it for Early Error conditions, and instantiate it prior to the execution of the TopLevelModuleEvaluationJob for that _sourceText_. It might also resolve, pre-parse and pre-analyze, and pre-instantiate module dependencies of _sourceText_. However, the reporting of any errors detected by these actions will be deferred until the TopLevelModuleEvaluationJob is actually executed.

+
+
+ + +

Module Resolution

+

This implementation uses the [[HostDefined]] field of Source Text Module Records to store the filename from which a module was retrieved. It also maintains a List of ModuleMap Records, known as the module map. This helps enforce the idempotency requirements of HostResolveImportedModule. ModuleMap Records have the fields described here:

+ + + + + + + + + + + + + + + + + + + + + + +
+ Field Name + + Value + + Meaning +
+ [[Filename]] + + A String + + The filename from which this module was created. +
+ [[Module]] + + A Source Text Module Record + + The module record created for this module. +
+
+ +

This implementation's HostResolveImportedModule abstract operation performs the following steps, given the arguments _referencingModule_ and _specifier_:

+ + 1. Let _referencingFilename_ be _referencingModule_.[[HostDefined]]. + 1. Let _realm_ be _referencingModule_.[[Realm]]. + 1. Let _filename_ be the result of resolving _specifier_ against _referencingFilename_ as a filename, according to operating system conventions. + 1. If the module map contains a ModuleMap Record with [[Filename]] equal to _filename_, return that Record's [[Module]] field. + 1. Let _sourceText_ be the result of using the operating system's mechanisms to read the source text of the file located at _filename_. If this fails (e.g. because the file does not exist), throw a *TypeError*. + 1. Let _moduleRecord_ be ? ParseModule(_sourceText_, _realm_, _filename_). + 1. Add ModuleMap{ [[Filename]]: _filename_, [[Module]]: _moduleRecord_ } to the module map. + 1. Return _moduleRecord_. + +
+
+ + +

Initialization and Ongoing Evaluation

+ +

This implementation is initialized by being provided with a set of ECMAScript source texts for zero or more scripts, and zero or more modules; the modules must be provided alongside corresponding filenames. It then performs the following algorithm to evaluate those source texts in appropriate Jobs. If evaluation enqueues any further Jobs, such as promise-related Jobs, the call back to the implementation's HostEnqueueJob abstract operation will ensure those are executed after the ongoing evaluation of the script or module.

+ + + 1. Perform ? InitializeHostDefinedRealm(). + 1. For each supplied ECMAScript source text _sourceText_, + 1. If _sourceText_ is the source code of a script, then + 1. Perform ! HostEnqueueJob(`"ScriptJobs"`, ScriptEvaluationJob, « _sourceText_ »). + 1. Else _sourceText_ is the source code of a module, obtained via the filename _filename_, + 1. Perform ! HostEnqueueJob(`"ScriptJobs"`, TopLevelModuleEvaluationJob, « _sourceText_, _filename_ »). + 1. Repeat, + 1. Suspend the running execution context and remove it from the execution context stack. + 1. Assert: The execution context stack is now empty. + 1. Let _nextQueue_ be a non-empty Job Queue chosen by first prioritizing `"PromiseJobs"`, and then prioritizing `"ScriptJobs"`. If all Job Queues are empty, return; the ECMAScript implementation has finished all evaluation. + 1. Let _nextPending_ be the PendingJob record at the front of _nextQueue_. Remove that record from _nextQueue_. + 1. Let _newContext_ be a new execution context. + 1. Set _newContext_'s Function to *null*. + 1. Set _newContext_'s Realm to _nextPending_.[[Realm]]. + 1. Set _newContext_'s ScriptOrModule to _nextPending_.[[ScriptOrModule]]. + 1. Push _newContext_ onto the execution context stack; _newContext_ is now the running execution context. + 1. Let _result_ be the result of performing the abstract operation named by _nextPending_.[[Job]] using the elements of _nextPending_.[[Arguments]] as its arguments. + 1. If _result_ is an abrupt completion, perform ReportErrors(« _result_.[[Value]] »). + + + +

ReportErrors ( _errorList_ )

+ +

Various algorithms for this implementation require reporting of errors. This is done by passing a list of errors to the ReportErrors abstract operation, which if possible, prints them to the console:

+ + + 1. For each _error_ in _errorList_, + 1. Let _name_ be Get(_error_, `"name"`). + 1. If _name_ is an abrupt completion, return. + 1. Let _message_ be Get(_error_, `"message"`). + 1. If _message_ is an abrupt completion, return. + 1. Print _name_.[[Value]] and _message_.[[Value]] to the console. + + + +

_errorList_ will be a List of ECMAScript language values. If the errors are parsing errors or early errors, these will always be *SyntaxError* or *ReferenceError* objects. Runtime errors, however, can be any ECMAScript value.

+
+
+
+ + +

Other Host-Defined Abstract Operations

+ +

This implementation uses the default implementation of HostEnsureCanCompileStrings.

+ +

This implementation's HostPromiseRejectionTracker abstract operation performs the following steps, given the arguments _promise_ and _operation_:

+ + + 1. Let _reason_ be _promise_.[[PromiseResult]]. + 1. Let _name_ be Get(_reason_, `"name"`). + 1. If _name_ is an abrupt completion, return. + 1. Let _message_ be Get(_reason_, `"message"`). + 1. If _message_ is an abrupt completion, return. + 1. Print _operation_, _name_.[[Value]], and _message_.[[Value]] to the console. + +
+
+

The Strict Mode of ECMAScript