The Qworum script, specification version 1
Summary
Qworum is a variant of the World Wide Web that is especially suitable for applications.
This specification is intended for the developers of Qworum applications and services.
1. Introduction
The World Wide Web ♦︎ was initially conceived as a decentralised information system consisting of interlinked documents, yet its potential as a platform for applications soon became apparent. The ongoing effort that has been undertaken by the ICT community since the Web's early days in order to better support Web applications has sofar produced various client-side and server-side upgrades to the initial Web, such as JavaScript and application servers.
Yet there is room for improvement, particularly regarding the decentralisation of the front-ends of Web applications. In today's Web, an application is contained within a single Web origin (example: https://example.com) ♦︎, and frequently even within a single Web page. This limits the amount of functionality that can be shared amongst application developer teams, and results in considerable duplication of effort. (One notable exception to this picture is OAuth-based services which can be called remotely by applications.)
Qworum enables new gains in productivity for the software community by making it possible to build Web applications that are composed of interactive services ("Qworum services") that are hosted anywhere on the Web and that are callable remotely.
It is worth noting that Qworum services are of practical use even if the caller of a service has the same Web origin as the called service. This is because Qworum services can be inserted in any user flow without disrupting it, similarly to functions in conventional programming. For example, with Qworum an application no longer needs to pass a return path to the login dialog when it requires the end-user to sign in before accessing a restricted page. Again, this is similar to conventional programming where a function does not know how the execution proceeds when its own execution finishes.
As a foretaste, here is how an e-commerce site might call a remote shopping cart service:
2. Terminology
2.1. Phase
An HTTP(S) ♦︎ request-response pair.
2.2. Single-Phase Service Call
A call to a Web API that consists of a single phase. Calls to Web APIs that conform to conventional specifications such as REST ♦︎ or XML-RPC ♦︎ are always single-phase calls.
2.3. Multi-Phase Service Call
A call to a Web API that consists of one or more phases. Calls to Web APIs that conform to the Qworum specification are multi-phase calls.
During a multi-phase call, the first request that is sent by the user agent to the server contains 0, 1 or more call arguments. The service then returns a response that:
- contains a call result (in which case the call is a single-phase call), or
- allows the user agent to initiate a second phase for the current call.
In this manner, each phase of a multi-phase call can choose to return a result or continue the current call with another phase.
Qworum mandates that each phase of a particular multi-phase call have the same Web origin, otherwise an * origin
fault will be raised during run-time.
2.4. The Qworum Script
Qworum scripts contain instructions that are to be executed by user agents such as Web browsers. The root element of Qworum scripts must be an instruction. Qworum scripts can also contain data values.
2.4.1 XML scripts
Users agents can receive Qworum scripts from Web servers in XML documents ♦︎ that have the content type application/xml
or text/xml
.
2.4.2 Generating Qworum scripts on the client
Web pages can also use JavaScript for generating and executing Qworum scripts. To this end, Qworum makes the qworum-for-web-pages.mjs ♦︎ JavaScript library available to Web developers.
Generating and executing Qworum scripts on the client in this way is equivalent to the user agent receiving an XML Qworum script from the URL of the HTML page.
2.5. Service Composition
The mechanism by which multi-phase calls perform other nested multi-phase calls during their execution. Nested calls are performed between two consecutive phases of the call that initiated the nested call.
When a call is to perform a nested call, one of its phases returns a script that contains a call instruction. These nested calls are then performed by the user agent between two consecutive phases of the call that initiated the nested call.
2.6. Interactive Service
A multi-phase service that can interact with the end-user through HTML ♦︎ pages during its execution.
For example, a shopping cart service may provide a method that shows shopping cart contents to the end-user by offering this type of interactivity.
2.7. Execution State
In Qworum, each Web browser tab has its own execution state, which consists of:
- A call stack that contains one or more call frames. The topmost call frame pertains to the call currently being executed; the remaining call frames contain the states of calls whose executions are currently suspended. Call frames are used for storing call states in the form of datas (which point to data) and objects.
- A main object that is attached to the browser tab. The main object is the owner of the first call frame in the call stack.
A regular browsing session on the World Wide Web can be thought of as a multi-phase service call that doesn't use the Qworum-related functionality that the user agent provides (except that browsing different Web origins within the same browser tab does not raise an * origin
fault). In particular:
- regular Web browsing happens within the bounds of the first call frame in the call stack, and
- the main object remains unused during a regular Web browsing session.
2.8. Qworum Object
In conventional object-oriented programming, objects are used for storing state that is shared between multiple calls to one or more functions, which are the object's methods. Qworum is porting this concept into the Web environment in the form of Qworum objects.
A Qworum object, then, is a container for run-time state that is shared between different calls. Qworum objects are used for storing datas (which point to data) and other Qworum objects.
Qworum objects are needed for storing the states of services such as shopping carts that must remember their contents across different calls incoming from an e-commerce site for example. In the absence of Qworum objects, Qworum would only be able to support services where each incoming call is independent from one another, which is the case for user authentication services and payment processing services among others.
Here is how Qworum objects are used in practice:
- Each multi-phase call has a Qworum object that is the owner of the call. When initiating a call, the call's owner object is created by the user agent if it does not already exist in the browser tab's execution state.
- Each Qworum object has a Web origin which is determined when the object is first used as the owner of a call. All phases of all calls which are owned by a Qworum object must have the object's origin, otherwise an
* origin
fault will be raised during run-time. - Qworum objects can be stored in call frames, or as the main object of an execution state.
2.9. Qworum Class
Qworum does not mandate that all Qworum objects stored in an execution state have different origins. It follows that calls to the same URL can be made using different owner objects, even within the same browser tab. This is how the concept of Qworum classes emerges; not as a browser feature, but rather as an aid for designing Qworum-based applications and services.
Formally, we can define Qworum objects to be instances of Qworum classes, and also that each Web origin can host any number of Qworum classes.
Going back to our shopping cart example, we can imagine an e-commerce site that allows its users to create several shopping carts on the same shopping cart service, for example one "Home" cart, one "Work" cart and one "New year's eve party" cart.
3. Instructions
This section lists the instructions that are available to Qworum scripts. When evaluated by the user agent, all instructions will yield a value (which is data
), except for the goto
and fault
instructions.
Qworum instructions that conform to this specification must have the XML namespace ♦︎ https://qworum.net/ns/v1/instruction/
.
Unless otherwise stated, in the XML code examples below all elements whose tags don't have a prefix have the namespace The The location of the data container that is being accessed is determined by Within this array, some strings are treated differently by the user agent: Here is an example of reading data from a data container: Another example: And another: When trying to read from a data container that is located inside a Qworum object, if the Qworum object does not exist then a If a data container does not contain a data value (that is, the container has not yet been initialised), then trying to read from it will raise a When writing to a data container, the And another: When trying to write to a data container that is located in a Qworum object, if the Qworum object does not exist then a The Some of the Service calls generate an HTTP(S) GET request when evaluated by the browser. Service calls can have data arguments and/or object arguments. Service calls can have named data arguments, each argument containing one instruction or data. If a data argument contains an instruction, then the instruction will be evaluated before executing the call. Data arguments will be will be made available to the new call on the client side as local data with the same names as the data arguments. Service calls can receive Qworum objects as arguments. These object arguments will be made available to the new call on the client side as local objects that have the same names as the object arguments. The If the current call is the main call of the current browser tab, then this instruction will terminate the tab's execution. The The The The sequence will not yield a result in the following cases: In computer programming, exceptions are used for disrupting the normal course of execution, because an exceptional event has occurred which prevents the program to proceed as intended. Exceptions are called "faults" in Qworum parlance. The The Faults are split into two categories: Here is a visual overview of the predefined faults: Note there must be whitespace after When an instruction in a Qworum script raises a The The https://qworum.net/ns/v1/instruction/
, and all elements whose tags have the prefix data
have the namespace https://qworum.net/ns/v1/data/
.3.1.
data
data
instruction allows writing to, and reading from, a data container that is stored in an execution state. The current call has read/write access to data in the following locations:data
's mandatory path
attribute. This attribute's value is a JSON-encoded array of strings. In these strings, the leading and trailing whitespace characters are ignored.@
denotes the current call's owner object, and$
or #
are reserved and should not be used at this time.3.1.1. Reading from a data container
* reference
fault will be raised at run-time.* reference
fault.3.1.2. Writing to a data container
data
instruction must contain one instruction or data value. Here is an example:* reference
fault will be raised at run-time.3.2.
call
call
instruction initiates a multi-phase service call. It has two optional attributes:object
attribute specifies the path of the object that owns the call within the execution state. The value of the object
attribute is a JSON-encoded array of strings (some string values are reserved). If this attribute is omitted, then the new call's owner will be the owner of the current call.href
attribute specifies the URL of the call's first phase. If this attribute is omitted, then this URL will be the browser tab's current URL.fault
s that service calls can raise are * origin
and * reference
.3.2.1. Calls with data arguments
3.2.2. Calls with object arguments
3.3.
return
return
instruction returns the current multi-phase service call. This instruction must contain one instruction or data element.3.4.
goto
goto
instruction starts a new phase for the current multi-phase service call. It has one optional attribute:href
attribute specifies the URL of the new phase. If this attribute is omitted, then this URL will be the browser tab's current URL.goto
instruction will raise an * origin
fault
if the object that the current call belongs to has a different origin ♦︎ than this goto
phase's origin. This is because all phases of all service calls belonging to an object must have the same origin URL.3.5.
sequence
sequence
instruction contains one or more instructions or data elements, each of which is evaluated in turn. This instruction will yield the evaluation result of the last instruction/data in the sequence.3.6.
fault
fault
instruction has one optional attribute:type
attribute specifies the type of the raised fault. If this attribute is omitted, then the fault type will be * service-specific
. If specified, the type
value must not start with *
.type
attribute's value has the following equivalent forms:payment cancelled
and Payment Cancelled
are equivalent.payment cancelled
and payment cancelled
are equivalent.payment cancelled
and payment cancelled
are equivalent.type
value starts with *
. These can only be raised by the Qworum runtime itself. This means that a Qworum script must not contain a fault
instruction whose type is explicitly specified as being a platform fault.login aborted
). Qworum scripts are allowed to contain and explicitly raise such faults. The type
value of such faults must not start with *
.3.6.1. Fault types
argument
is the only predefined service-specific fault. A service call can raise this fault if a call argument is non-conformant or absent.* entitlement
— Raised when a Qworum service tries to use a Qworum feature that it isn't entitled to. These faults are typically raised when evaluating a call
instruction.* origin
— Raised when a phase of a Qworum object does not have the same origin ♦︎ as the Qworum object itself.* platform fault in script
— Raised when an XML Qworum script contains a platform fault. Note that this fault isn't raised for Qworum scripts that are generated in web pages using the official Qworum JavaScript library, in which case a TypeError is thrown instead.* platform entitlement
— Raised when a service that is being called isn't part of Qworum's Service Web. This may be because the service is not subscribed to a Qworum platform plan, or the current subscription isn't sufficient and needs to be upgraded.* reference
— Raised when the path of a data container or Qworum object can't be resolved.* runtime
— Raised when an unexpected error occurs in Qworum's browser runtime.* script
— Raised when a Qworum script is non-conformant.* service
— Parent type of all "user space"♦︎ faults that are caused by a Qworum service in a Qworum session.* service entitlement
— The service that is being called is a paid service, and the caller isn't subscribed to the called service.* service-specific
— The parent type of all service-specific faults.* syntax
— Raised when a Qworum script has syntax errors.* user agent
— Parent type of all "kernel space"♦︎ faults that occur in the user agent.*
.3.7.
try
fault
, then the current call will terminate unless the fault is caught by a try
instruction.try
instruction contains one or more catch clauses, each of which contains one or more instructions or data elements. Catch clauses have one optional attribute:faults
attribute is a JSON-encoded array of strings that indicate the fault types that are caught by the clause. If this attribute is omitted or if the faults
array is empty, then the clause will catch all faults.try
instruction will yield the result of the last instruction or data value it evaluates.
4. Data values
An XML element represents a data value if:
- its namespace is
https://qworum.net/ns/v1/data/
, and the XML element conforms to this specification.
4.1. json
Represents JSON-encoded data ♦︎.
4.2. semantic
Represents semantic RDF♦︎ data. This data can be specified in one of the following formats:
5. Workarounds for browser limitations
The developers of Qworum applications and services must observe some simple rules for their Qworum-based software to work properly on browsers. These rules are necessary because Qworum is implemented as a browser extension, and web browsers impose certain constraints on what extensions can do. One notable restriction is that extensions are not allowed to prevent the end-user from going back in the tab history.
The following programming constraints will prevent the application UI from going out of sync with the application's session state.
5.1. Hyperlinks
In HTML pages, use window.location.replace()
for hyperlinks.
5.2. Forms
In HTML pages, use AJAX rather than web forms for sending data to servers.
6. References
- ETL Extract, transform, load (Wikipedia)
- HTML HTML: HyperText Markup Language
- HTTP HTTP/3
- Jamstack Jamstack.org website
- JSON JSON.org website
- RDF RDF 1.1 Primer, W3C Working Group Note 24 June 2014
- TriG RDF 1.1 TriG, RDF Dataset Language, W3C Recommendation, 25 February 2014
- TriG RDF 1.1 Turtle, Terse RDF Triple Language, W3C Recommendation, 25 February 2014
- N-Triples RDF 1.1 N-Triples, A line-based syntax for an RDF graph, W3C Recommendation 25 February 2014
- N-Quads RDF 1.1 N-Quads, A line-based syntax for RDF datasets, W3C Recommendation, 25 February 2014
- Origin Mozilla Developer Network Documentation
- qworum-for-web-pages.mjs Qworum for web pages on GitHub
- User space and kernel space Wikipedia article
- REST Representational state transfer
- Semantic Web Semantic Web (W3C)
- WWW World Wide Web (Wikipedia)
- XML Extensible Markup Language (XML) 1.1 (Second Edition)
- XMLNS Namespaces in XML 1.0 (Third Edition)
- XML-RPC XML-RPC
∎