Updated November 20, 2020
- This document defines formal algorithms for the draft of the TC53 specification
- This document describes some, but not all, of the APIs (additional APIs will be added)
- The intent is to merge these algorithms into the specification
- The style of these algorithms is inspired by ECMA-262, but does not try to follow it
Internal fields are implementation dependent and never accessible outside the implementation. For instance they can be C structure fields, JavaScript private fields, or a combination of both.
Every object conforming to a Class Pattern is expected to have one or several internal fields. This document uses the following operators on internal fields.
- For each internal field of the class being defined
- Let name be the name of the internal field
- Throw if object has no internal field named name
CheckInternalFields throws if an internal field is absent. That can be implicit when internal fields are JavaScript private fields, or can be explicit when internal fields are C structure fields. The purpose of CheckInternalFields is to ensure that object is an instance of the class being defined.
- For each internal field of the class being defined
- Let name be the name of the internal field
- Clear the internal field named name of object
ClearInternalFields zeroes all internal fields. That can be storing null
in JavaScript private fields, or can be storing NULL in C structure fields. The purpose of ClearInternalFields is to ensure that object is in a consistent state when constructed and closed.
- Return the value stored in the internal field named name of object
GetInternalField is trivial for JavaScript private fields, but can involve value conversion for C structure field like converting C NULL
into JavaScript null
.
- Store value in the internal field named name of object
SetInternalField is trivial for JavaScript private fields, but can involve value conversion for C structure field like converting JavaScript null
into C NULL
.
- ClearInternalFields(
this
) - Throw if options is
undefined
ornull
- Let params be an empty object
- For each supported option
- Let name be the name of the supported option
- If HasProperty(options, name)
- Let value be GetProperty(options, name)
- Throw if value is not in the valid range of the supported option
- Else
- Throw if the supported option has no default value
- Let value be the default value of the supported option
- DefineProperty(params, name, value)
- For each supported callback option
- Let name be the name of the supported callback option
- Let callback be GetProperty(params, name)
- If callback is not
null
- SetInternalField(
this
, name, callback)
- SetInternalField(
- Let value be GetProperty(params,
"target"
) - If value is not
undefined
- DefineProperty(
this
,"target"
, value)
- DefineProperty(
- Mark
this
as ineligible for garbage collection
-
Supported options, with their names, default values and valid ranges, are defined by a separate table for every class conforming to the Base Class Pattern.
-
The params object is unobservable. Its purpose in the algorithm is to ensure that properties of the options object are only accessed once and that the options object can be frozen. Local variables can be used instead, for instance:
let pin = 2; if (options !== undefined) { if ("pin" in options)) { pin = options.pin; if ((pin < 0) || (3 < pin)) throw new RangeError(`invalid pin ${pin}`); } }
-
Most classes conforming to the Base Class Pattern are expected to support one or several callbacks. Callbacks are supported options: their default value is
null
, their valid range isnull
or a JavaScript function. Callbacks are stored in internal fields and are always called withthis
set to the constructed object. -
There is only one option that is always supported: its name is
"target"
, its default value isundefined
and its range is any JavaScript value.
- CheckInternalFields(
this
) - Mark
this
as eligible for garbage collection - Cancel any pending callbacks for
this
- ClearInternalFields(
this
)
- Execute steps 1 to 7 of the Base Class Pattern constructor
- Let value be GetProperty(params,
"format"
) - SetInternalField(
this
,"format"
, value) - Try
- Let resources be the hardware resources specified by params
- Throw if resources are unavailable
- Allocate and configure resources
- Throw if allocation or configuration failed
- SetInternalField(this,
"resources"
, resources)
- Catch exception
- Call(
this
, GetProperty(this
, "close"`)); - Throw exception
- Call(
- Execute step 8 of the Base Class Pattern constructor
- Execute step 1 of the Base Class Pattern
close
method - Let resources be GetInternalField(
this
,"resources"
); - Return if resources is null
- Execute steps 2 and 3 of the Base Class Pattern
close
method - Free resources
- Execute step 4 of the Base Class Pattern
close
method
- CheckInternalFields(
this
); - Let resources be GetInternalField(
this
,"resources"
); - Throw if resources is null
- Throw if params are absent but required, or present but not in the valid range
- Let data be undefined
- If resources are readable
- Read from resources into data
- Format data according to GetInternalField(
this
,”format”
)
- Return data.
- CheckInternalFields(
this
); - Let resources be GetInternalField(
this
,"resources"
); - Throw if resources is null
- Throw if data are absent or not formatted according to GetInternalField(
this
,”format”
) - Throw if params are absent but required, or present but not in the valid range
- Throw if resources are not writable
- Write from data into resources
- CheckInternalFields(
this
); - Throw if value is not in the valid range of
"format"
- SetInternalField(
this
,"format"
, value)
- CheckInternalFields(
this
); - Return GetInternalField(
this
,"format"
)
- Hardware resources can require one or several internal fields which should be all cleared and checked. The
"resources"
internal field is only a convention in this document. - For every available
format
, the ranges ofread
andwrite
data are defined by a separate table for every class conforming to the IO Class Pattern. - The order, requirements and ranges of
read
andwrite
params are defined by a separate table for every class conforming to the IO Class Pattern.
Property | Required | Range | Default |
---|---|---|---|
pin |
yes | Host dependent pin specifier | |
mode |
yes | Digital.Input , Digital.InputPullUp , Digital.InputPullDown , Digital.InputPullUpDown , Digital.Output , or Digital.OutputOpenDrain . |
|
edge |
no* | Digital.Rising , Digital.Falling , and `Digital.Rising |
Digital.Falling` |
onReadable |
no | null or Function |
null |
format |
no | "number" |
"number" |
- If the
onReadable
option is notnull
,edge
is required to have a non-zero value.
Format | Read | Write |
---|---|---|
"number" |
0 or 1 |
0 or 1 |
Param | Required | Range | Default |
---|
Param | Required | Range | Default |
---|
- Execute steps 1 to 7 of the Base Class Pattern constructor
- Try
- For each supported IO connection
- Let name be the name of the supported IO connection.
- Let ioOptions be GetProperty(params, name)
- Let ioConstructor be GetProperty(ioOptions,
"io"
) - Let ioConnection be Construct(ioConstructor, ioOptions)
- SetInternalField(
this
, name, ioConnection);
- Configure the peripheral with params
- Throw if the communication with the peripheral is not operational
- Activate the peripheral
- SetInternalField(
this
,"status"
,"ready"
);
- For each supported IO connection
- Catch exception
- Call(
this
, GetProperty(this
, "close"`)); - Throw exception
- Call(
- Execute step 8 of the Base Class Pattern constructor
- Execute step 1 of the Base Class Pattern
close
method - Let status be GetInternalField(
this
,"status"
); - Return if status is null
- Execute steps 2 and 3 of the Base Class Pattern
close
method - Deactivate the peripheral
- For each supported IO connection
- Let name be the name of the supported IO connection.
- Let ioConnection be GetInternalField(
this
, name); - If ioConnection is not
null
- Call(ioConnection,
"close"
);
- Call(ioConnection,
- Execute step 4 of the Base Class Pattern
close
method
- CheckInternalFields(
this
); - Let status be GetInternalField(
this
,"status"
); - Throw if status is null
- Throw if options is undefined or null
- For each supported option
- Let name be the name of the supported option
- If HasProperty(options, name)
- Let value be GetProperty(options, name)
- Throw if value is not in the valid range of the supported option
- Configure the peripheral with options
- Supported IO connections are supported options. Their value must be an object with an
io
property, which is the class of the IO connection.
- Execute all steps of the Peripheral Class Pattern constructor
- Execute all steps of the Peripheral Class Pattern
close
method
- Execute all steps of the Peripheral Class Pattern
configure
method
- CheckInternalFields(
this
); - Let status be GetInternalField(
this
,"status"
); - Throw if status is null
- Throw if params are absent but required, or present but not in the valid range
- If the peripheral is readable
- Let result be an empty object
- For each sample property
- Let name be the name of the sample property
- Let value be undefined
- Read from the peripheral into value
- DefineProperty(result, name, value);
- Else
- Let result be undefined
- Return result.
- The order, requirements and ranges of
sample
params are defined by a separate table for every class conforming to the Sensor Class Pattern. - The requirements and ranges of properties in
sample
result are defined by a separate table for every class conforming to the Sensor Class Pattern.
| Param | Required | Range | Default | | :--- | :---: | :--- | :--- |x
Property | Required | Range | Description |
---|---|---|---|
x | Yes | Number | acceleration along the x axis in meters per second squared |
y | Yes | Number | acceleration along the y axis in meters per second squared |
z | Yes | Number | acceleration along the z axis in meters per second squared |
- Execute steps 1 to 7 of the Base Class Pattern constructor
- Let onReadable be a function with the following steps:
- Let data be Call(
this
, GetProperty(this
, "read"`)); - Let provider be GetProperty(
this
,"target"
); - Dispatch data among IO objects of provider
- Let data be Call(
- Let count be the number of supported IO connection
- Let onWritable be a function with the following steps:
- Let count be count - 1
- If count is 0
- Let provider be GetProperty(
this
,"target"
); - Configure provider with params
- Add supported IO constructors to provider
- SetInternalField(provider,
"status"
,"ready"
); - Let callback be GetInternalField(provider,
"onReady"
); - If callback is not null
- Call(provider, callback);
- Let provider be GetProperty(
- Let onError be a function with the following steps:
- Let provider be GetProperty(
this
,"target"
); - Dispatch the error to open IO objects of provider
- Call(provider , GetProperty(provider, "close"`));
- Let callback be GetInternalField(provider ,
"onError"
); - If callback is not null
- Call(provider, callback);
- Let provider be GetProperty(
- Try
- For each supported IO connection
- Let name be the name of the supported IO connection.
- Let ioOptions be GetProperty(params, name)
- Let ioParams be a copy of ioOptions
- Let ioConstructor be GetProperty(ioParams,
"io"
) - DefineProperty(ioParams,
"onReadable"
, onReadable); - DefineProperty(ioParams,
"onWritable"
, onWritable); - DefineProperty(ioParams,
"onError"
, onError); - DefineProperty(ioParams,
"target"
,this
); - Let ioConnection be Construct(ioConstructor, ioParams)
- SetInternalField(
this
, name, ioConnection);
- For each supported IO connection
- Catch exception
- Call(
this
, GetProperty(this
, "close"`)); - Throw exception
- Call(
- Execute step 8 of the Base Class Pattern constructor
- Execute all steps of the Peripheral Class Pattern
close
method