Extensible 3D (X3D) language bindings
Part 1: ECMAScript
4 Concepts
This clause describes key concepts in this part of ISO/IEC 19777. This includes conformance criteria and abstract concepts of the binding to ECMAScript defined in this part to the abstract definitions of the X3D scene authoring interface (SAI) specified in part 2 of ISO/IEC 19775. The ECMAScript programming language is specified in ISO/IEC 16262.
See Table 4.1 for the table of contents for this clause.
Table 4.1 — Topics in this clause
|
Since ECMAScript is an untyped language it has no language constructs to describe the types of parameters passed to, or values returned from, functions. Therefore this Part uses a notational convention to describe these types. Parameters passed are preceded by their type, and the type of any return value precedes the function name. Normally these types correspond to X3D field types, so those names are used. In the case of no return value, the identifier void is used. In the case of a ECMAScript numeric value or numeric array return, the identifier numeric or numeric[ ] is used. In the case of a string return, the identifier String is used.
This part of ISO/IEC 19777 defines the binding of services as defined in part 2 of ISO/IEC 19775 to ECMAScript. Details of providing ECMAScript support for ISO/IEC 14772 may be found in Annex A — Relationship to ISO/IEC 14772.
A browser supporting an ECMAScript language interface for the SAI shall conform to 7 Conformance of part 2 of ISO/IEC 19775 and shall conform to the provisions of this part of ISO/IEC 19777.
ECMAScript bindings within scripting node types shall be supported by a conforming browser. A browser may optionally support ECMAScript when used for external interactions as defined in part 2 of ISO/IEC 19775.
An implementation shall not modify the objects and functions defined in this specification with their own specific methods or additional methods. There shall be one exception to this requirement in order to allow browser-specific extension functions within the Browser services.
The Browser object may be extended with new function calls that indicate the extended functionality. Part 2 of ISO/IEC 19775 defines the requirements for naming conventions. For the purposes of this specification, browser-specific function calls that are added to the Browser object shall conform to the naming conventions including prefix/suffix additions.
EXAMPLE Browser XYZ has an extension function as:
Browser.XYZ_customFunction();To satisfy this requirement, a browser implementation may provide additional new objects, but shall not extend or modify the objects defined in this part of ISO/IEC 19777.
Implementation dependent for the scope of this part of ISO/IEC 19777 is defined to be the browser writer implementation of the ECMAScript host objects and how those objects interact with the environment and the X3D browser.
This specification provides a set of implementation independent objects that a piece of ECMAScript code may assume are Host Objects as defined by ISO/IEC 16262. These objects represent the possible interactions with the X3D scene through the SAI. Browser specific implementation dependencies shall remain hidden to the general user.
Apart from the Browser object (see 7.2.1 Native objects), an implementation shall not modify these objects and functions with their own specific methods or additional methods. The term application is used to describe the ECMAScript code that wishes to access the X3D browser, regardless of how the initial reference to the browser was obtained.
All objects defined in this part of ISO/IEC 19777 shall be treated as Native Objects in the ECMAScript environment. The process of implementing and registering these objects with the ECMAScript engine shall be implementation dependent as each engine is different. The specification only defines the functions and properties of the objects, and not how they are to be implemented.
An object is described by the functions and properties it contains. Properties may only be defined as a single primitive type or another object. Many concepts in X3D are described using array semantics, and ECMAScript does not allow the definition of properties that are arrays of values. To overcome this limitation, this specification defines a collection of auxiliary objects to function as array placeholders that are required by the various service requests.
These auxiliary objects are not meant to be directly instantiated by user code. They are implied properties of the parent object and therefore no public constructor shall be provided. Individual elements of each auxiliary object can be accessed using access by zero-based indices.
EXAMPLE To read the 3rd available component, the following syntax is used:
comp = Browser.supportedComponents[2];
This component request is the result of a [[get]] request on the Browser host object, which returns a ComponentInfoArray host object, on which a [[get]] request is made with the index value of 2.
A browser shall only be required to support the standard built-in objects defined by ISO/IEC 16262.
A browser implementation may optionally provide other host objects for the user code to use.
EXAMPLE A browser in a web page may provide host objects for accessing the containing external document structure.
A Script node defines content through its URL field. ECMAscript code may be supported through either direct in-line declaration of the code or by using an external file.
Browsers supporting the ECMAScript scripting language shall support the use of in-lined script nodes through the use of the customized protocol definition ecmascript. This support is required in addition to the other required protocols as defined in 7, Conformance and minimum support requirements of part 2 of ISO/IEC 19775.
EXAMPLE 1 An example of the in-lined script definition is:
Script { url "ecmascript: function foo() { ... }" }
EXAMPLE 2 The url field may contain multiple URL's referencing either a remote file or in-line code as shown in the following example:
Script { url [ "http://foo.com/myScript.js", "ecmascript: function foo( ) { ... }" ] }
A browser implementation shall support no other protocol type for in-lined script code that conforms to this part of ISO/IEC 19777.
The file extension for ECMASCript source code is ‘.js’, unless a protocol returning MIME types is used (such as HTTP). In that case, any suffix is allowed as long as the proper MIME type is returned (see 4.3.1.4.4 MIME type).
The MIME type for ECMAScript source code is defined as follows:
application/ecmascript
For backwards compatibility with old web servers, it is recommended browsers also support the following MIME type:
application/x-ecmascript
A session for ECMAScript-based communications is dependent on the type of handle established: embedded object or standalone application.
The difference between the two forms of the browser is limited to how to initially obtain the browser reference. Once this has been obtained, the services provided shall not differ. The term application is used to describe the ECMAScript code that wishes to access the X3D browser regardless of how the initial reference to the browser was obtained.
Since ECMAScript does not define a user interface creation set of libraries, the usefulness of creating standalone browsers that may be embedded in custom applications is limited. Therefore, the createBrowser service (see 6.2.3 createBrowser of part 2 of ISO/IEC 19775) is not defined for this binding. Browser implementations may optionally provide a browser-specific mechanism for creating a new browser instance.
When the X3D browser exists as an element embedded in a HTML page to which an ECMScript script has access, it shall use the underlying web browser APIs to access the document and plug-in. The session is defined to last as long as that particular plug-in instance is associated with a currently active page.
The browser shall also provide notification to the listening applications when the world is no longer displayed on the page. When the browser is removed from visibility, it shall generate a shutdown event to all registered listeners. If the browser becomes visible again an initialized event shall be generated. If a new page is loaded with a X3D browser as part of it, it will contain a different Browser reference and hence scripts (e.g., onMouseOver, not X3D scripts) in the page will not receive any such notification of its presence.
Due to the nature of ECMAScript code interaction, it is possible that
two instances of an ECMAScript object may refer to the same node or field inside
the X3D scene (that is, using the ==
comparison
may be false
). For this reason, an identifier of a node or field
cannot be implied to mean the same instance reference of the object representation
between separate function calls to the user code. Within a single function call,
the identifier shall be identical. This ensures that the following semantics
seem logical to the end user:
O1 = new SFVec3f(0, 0, 0); O2 = new SFVec3f(2, 4, 0); O1.x = 6; // O1 is (6, 0, 0) O2.y = O1.x; // O2 is (2, 6, 0) transform.translation = O2; //call translation.setValue(2, 6, 0);
The representation of an identifier in ECMAScript is implementation dependent
and hidden from the ordinary user. However, objects instances may be checked for
equivalence by calling the equals()
function of the appropriate object
instances. Implementations of the objects shall provide the equals()
function so that comparing two nodes, fields or other objects that require an
identifier will return the correct result.
In the object definitions, it is possible to associate user definable data references with each field of a node and with the node itself. This data is separate from the metadata capability required by the X3DNode and X3DMetadataObject definitions. If one reference to a node has data associated with it, this information shall be available to all references to that node at all times. For example, if a field has data associated with it, is then disposed and a later application references that node, the data shall still remain (if that other application is ECMAScript). There is no requirement to store this information if the node/field is no longer referenced by external applications or the internal scene graph. An optional capability that a browser may provide is for the object to be available across languages such that an object set in an ECMAScript script many be fetched and examined using an external application in another language.
Several services allow user code to register for notifications of state changes. When the browser code needs to inform the user code of the item of interest, this shall be performed through a callback. Because ECMAScript is an interpreted language, the means of defining the callback shall be to provide a string, which is the name of the function to be called when required. In addition to the name of the function, a second optional parameter may be supplied which is any arbitrary object value (for example a string). This second parameter shall have no implied semantics other than as a piece of user code to identify which object this callback was registered with. The parameters to be provided to the callback function shall be defined by the individual service request mapping. They shall include the user provided data as one of the parameters of the callback function. User code is allowed to use a single callback function for registering interest with multiple sources.
The ECMAscript null
reference to an object shall
be treated as the equivalent of the X3D NULL
value. Where an
SFNode field has its value set to null
, this shall clear the
field of the node reference causing the default behaviour defined by the
parent node to be used for that field. When reading a value of an SFNode
field where it is empty, the return value shall be null
.
Single valued field types may be represented in one of two ways. For simple objects, that can correspond to one of the ECMAScript primitive types of numeric, String and boolean. Where such a simple mapping is not possible, the data type is represented by a host object bearing the same name as the type. If the type represents a compound type such as SFVec3f, each part of the type may be directly accessible as either a property or using array-indexed access. The definitions and name of each property are specified in 6 Type definitions.
Where field types represent primitive data types such as integers and strings, there shall be no standard object type supplied.
Each multi-valued field type is represented by a host object bearing the same name as the type. The properties of the object is an array of the equivalent single-valued object types. Access is through numerical array access and there are no separately defined properties.
EXAMPLE mfColorObjectName[index], where index is an integer-valued expression with 0 ≤ index < length and length is the number of elements in the array.
set1Value/get1Value service requests are equivalent to the array access mechanism provided by the object representing the field. Setting or getting a single array index shall use the same semantics for the setValue and getValue services.
Assigning to an element with index ≥ length results in the array being dynamically expanded to contain length elements. All elements not explicitly initialized are set to the default value for that field type
The executable content of a script shall be made available to the browser as either an external file or through the use of one of the custom protocol types defined in 4.3.1.4 SupportedScriptURLs. The content may define zero or more functions. For the X3D Browser to communicate information to the script, a number of functions are defined by this specification. If the script content defines one of these functions, it shall be called at the appropriate time as defined by the following specification. If the script does not define the function, the browser silently ignores the action to be taken.
EXAMPLE If the script content does not define
an eventsProcessed()
function, the browser does not attempt to call it.
All fields of a Script node are accessible from its ECMAScript functions. As in all other nodes, the initializeOnly fields are accessible only within the Script. The inputOnly fields are not accessible. The node’s input-capable fields can be routed to and its output-capable fields can be routed from. Another node with a reference to this node can access its input fields and output fields just like any other node.
A field defined in the containing node is available to the user code by using its name. Its value can be read or written. This value is persistent across function calls. Output-capable fields defined in the script node can also be read. The value is the last value assigned.
When using the script node as the parameter to methods that require an SFNode object instance, the this keyword may be used. For the purposes of this specification, the script context and the containing X3D X3DScriptNode are equivalent.
The script can access any field type except initializeOnly fields of any node to which it has access:
EXAMPLE
DEF SomeNode Transform { } Script { field SFNode node USE SomeNode eventIn SFVec3f pos directOutput TRUE url "ecmascript: function pos(value) { node.set_translation = value; } " }
This example sends a set_translation event to the Transform node.
A writable field on a passed node can appear only on the left side of the assignment. A readable field in the passed node can appear only on the right side, which reads the last value sent out. Fields in the passed node cannot be accessed. However, inputOutput fields can either send an event to the "set_..." inputOnly field or read the current value of the "..._changed" outputOnly field. This follows the routing model as defined in part 1 of ISO/IEC 19775.
Events generated by setting an input-capable field on a node are sent at the completion of the initial function call made to the user code by the browser. The inputOnly field shall be assigned a value of the same data type; no partial assignments are allowed.
EXAMPLE It is not possible to assign the red component value of an SFColor inputOnly field.
Since inputOnly fields are strictly write-only, the remainder of the partial assignment would have invalid field values. Assigning to the inputOnly field multiple times during one execution of the function still only sends one event and that event shall be the last value assigned.
An event on a field is queued if that field is writable and is assigned, or an element of a writable field (i.e., an index of an MF field type or a property of an SF field type) is assigned. Events are sent at the end of script execution. An output-capable field may be assigned a value multiple times within the script during a single call to the script. If during a single call to a script, multiple attempts are made to write a value to an output-capable field, only the last such attempt shall be used. If the value of individual components of a field is changed, the last value given to each component shall be sent. Elements of the field that are not changed in the user code send their initial value determined at the beginning of the script execution.
EXAMPLE The following code segment produces an value of (4, 3, 1) for the outputOnly field SFVec3f foo_changed with an initial value of (6, 6, 6):
a = foo_changed; // copy by reference a(6,6,6) a.x = 5; // foo_changed(5,6,6) a.z = 1; // foo_changed(5,6,1) b = foo_changed; // copy by reference b(5,6,1) b.x = 4; // foo_changed(4,6,1) c = a; // copy by reference c(4,6,1) c.y = 3; // foo_changed(4,3,1))
If a script is called multiple times within a single timestamp, in accordance
with the loop-breaking rule, only the first event generated from any output
capable fields is queued.
Events sent to the containing node are passed to the corresponding ECMAScript function in the script. The function's name is the same as the field and is passed two arguments. If the function represents an inputOutput field, the name of the function shall be the same name as the field declaration, without the set_ or _changed modifiers. The value of the event is passed as the first argument and the timestamp of the event is passed as the second argument. The type of the value is the same as the type of the event and the type of the timestamp is SFTime. 4.3.4.3 X3D field to ECMAScript variable conversion provides a description of how X3D types appear in ECMAScript. The values of the parameters have no visibility outside the function.
If there is no corresponding ECMAScript function in the script, the browser's behaviour is to silently ignore the event.
EXAMPLE The following Script node has one writable field whose name is start:
Script { eventIn SFBool start url "ecmascript: function start(value, timestamp) { ... }" }
When the start event is received, the start() function is executed.
If beginUpdate()
has been called and multiple individual
[[put]] actions have been performed on a single field, the result when
endUpdate()
is called shall be a single event with all of the
individual values set. If two calls are made to set a particular array index,
the last value written shall be used.
If beginUpdate()
has not been called, the result shall be an
event that contains the entire field value with the individual value changed.
Multiple [[put]] calls on the field object shall result in the equivalent
number of events being generated inside the X3D browser.
Although not required by the ECMAScript
environment because all objects are automatically disposed, the SAI defines
a service request for explicit disposal. Each host object defined by this
specification and any extension objects provided by a browser shall have
a dispose()
function available. This shall dispose of the local
handle to the underlying node. Any further access to that object shall generate
an error.