mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Specs: Split apis.md into dom.md, events.md, idl.md, and move the remainder into README.md and modules.md
Specs: Add runloop.md stub. Specs: Add animation.md stub. Review URL: https://codereview.chromium.org/824773002
This commit is contained in:
parent
a2b4ed2f1a
commit
baec01edaf
@ -24,3 +24,16 @@ For module files, one of the following:
|
||||
* ``53 4b 59 20 4d 4f 44 55 4c 45 0a`` ("``SKY MODULE\n``")
|
||||
* ``53 4b 59 20 4d 4f 44 55 4c 45 0d`` ("``SKY MODULE\r``")
|
||||
* ``53 4b 59 20 4d 4f 44 55 4c 45 20`` ("``SKY MODULE ``")
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
```
|
||||
magical imports:
|
||||
the core mojo fabric JS API sky:mojo:fabric:core
|
||||
the asyncWait/cancelWait mojo fabric JS API (interface to IPC thread) sky:mojo:fabric:ipc
|
||||
the mojom for the shell, proxying through C++ so that the shell pipe isn't exposed sky:mojo:shell
|
||||
the sky API sky:core
|
||||
the sky debug symbols for private APIs sky:debug
|
||||
```
|
||||
|
||||
21
specs/animation.md
Normal file
21
specs/animation.md
Normal file
@ -0,0 +1,21 @@
|
||||
Animation API
|
||||
=============
|
||||
|
||||
```javascript
|
||||
|
||||
dictionary EasingFunctionSettings {
|
||||
Float duration; // required
|
||||
Callback? completionCallback = null;
|
||||
}
|
||||
|
||||
abstract class EasingFunction {
|
||||
abstract constructor (EasingFunctionSettings settings);
|
||||
abstract Float getFactor(Float time);
|
||||
// calls completionCallback if time >= duration
|
||||
// then returns a number ostensibly in the range 0.0 to 1.0
|
||||
// (but it could in practice go outside this range, e.g. for
|
||||
// animation styles that overreach then come back)
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
553
specs/apis.md
553
specs/apis.md
@ -1,553 +0,0 @@
|
||||
APIs
|
||||
====
|
||||
|
||||
The Sky core API
|
||||
----------------
|
||||
|
||||
```javascript
|
||||
module 'sky:core' {
|
||||
|
||||
// EVENTS
|
||||
|
||||
class Event {
|
||||
constructor (String type, Boolean bubbles = true, any data = null); // O(1)
|
||||
readonly attribute String type; // O(1)
|
||||
readonly attribute Boolean bubbles; // O(1)
|
||||
attribute any data; // O(1)
|
||||
|
||||
readonly attribute EventTarget target; // O(1)
|
||||
attribute Boolean handled; // O(1)
|
||||
attribute any result; // O(1)
|
||||
|
||||
// TODO(ianh): do events get blocked at scope boundaries, e.g. focus events when both sides are in the scope?
|
||||
// TODO(ianh): do events get retargetted, e.g. focus when leaving a custom element?
|
||||
}
|
||||
|
||||
callback EventListener any (Event event);
|
||||
// if the return value is not undefined:
|
||||
// assign it to event.result
|
||||
// set event.handled to true
|
||||
|
||||
abstract class EventTarget {
|
||||
any dispatchEvent(Event event); // O(N) in total number of listeners for this type in the chain
|
||||
// sets event.handled to false and event.result to undefined
|
||||
// makes a record of the event target chain by calling getEventDispatchChain()
|
||||
// invokes all the handlers on the chain in turn
|
||||
// returns event.result
|
||||
virtual Array<EventTarget> getEventDispatchChain(); // O(1) // returns []
|
||||
void addEventListener(String type, EventListener listener); // O(1)
|
||||
void removeEventListener(String type, EventListener listener); // O(N) in event listeners with that type
|
||||
private Array<String> getRegisteredEventListenerTypes(); // O(N)
|
||||
private Array<EventListener> getRegisteredEventListenersForType(String type); // O(N)
|
||||
}
|
||||
|
||||
class CustomEventTarget : EventTarget { // implemented in JS
|
||||
constructor (); // O(1)
|
||||
attribute EventTarget parentNode; // getter O(1), setter O(N) in height of tree, throws if this would make a loop
|
||||
|
||||
virtual Array<EventTarget> getEventDispatchChain(); // O(N) in height of tree // implements EventTarget.getEventDispatchChain()
|
||||
// let result = [];
|
||||
// let node = this;
|
||||
// while (node) {
|
||||
// result.push(node);
|
||||
// node = node.parentNode;
|
||||
// }
|
||||
// return result;
|
||||
|
||||
// you can inherit from this to make your object into an event target
|
||||
// or you can inherit from EventTarget and implement your own getEventDispatchChain()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// DOM
|
||||
|
||||
typedef ChildNode (Element or Text);
|
||||
typedef ChildArgument (Element or Text or String);
|
||||
|
||||
abstract class Node : EventTarget { // implemented in C++
|
||||
readonly attribute TreeScope? ownerScope; // O(1)
|
||||
|
||||
readonly attribute ParentNode? parentNode; // O(1)
|
||||
readonly attribute Element? parentElement; // O(1) // if parentNode isn't an element, returns null
|
||||
readonly attribute ChildNode? previousSibling; // O(1)
|
||||
readonly attribute ChildNode? nextSibling; // O(1)
|
||||
|
||||
virtual Array<EventTarget> getEventDispatchChain(); // O(N) in number of ancestors across shadow trees // implements EventTarget.getEventDispatchChain()
|
||||
// returns the event dispatch chain (including handling shadow trees)
|
||||
|
||||
// the following all throw if parentNode is null
|
||||
void insertBefore(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void insertAfter(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void replaceWith(ChildArgument... nodes); // O(N) in number of descendants plus arguments plus all their descendants
|
||||
void remove(); // O(N) in number of descendants
|
||||
Node cloneNode(Boolean deep = false); // O(1) if deep=false, O(N) in the number of descendants if deep=true
|
||||
|
||||
// called when parentNode changes
|
||||
virtual void parentChangeCallback(ParentNode? oldParent, ParentNode? newParent, ChildNode? previousSibling, ChildNode? nextSibling); // O(N) in descendants (calls attached/detached)
|
||||
virtual void attachedCallback(); // noop
|
||||
virtual void detachedCallback(); // noop
|
||||
}
|
||||
|
||||
abstract class ParentNode : Node {
|
||||
readonly attribute ChildNode? firstChild; // O(1)
|
||||
readonly attribute ChildNode? lastChild; // O(1)
|
||||
|
||||
// Returns a new Array every time.
|
||||
Array<ChildNode> getChildNodes(); // O(N) in number of child nodes
|
||||
Array<Element> getChildElements(); // O(N) in number of child nodes // TODO(ianh): might not be necessary if we have the parser drop unnecessary whitespace text nodes
|
||||
|
||||
void append(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void prepend(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void replaceChildrenWith(ChildArgument... nodes); // O(N) in number of descendants plus arguments plus all their descendants
|
||||
}
|
||||
|
||||
class Attr {
|
||||
constructor (String name, String value = ''); // O(1)
|
||||
readonly attribute String name; // O(1)
|
||||
readonly attribute String value; // O(1)
|
||||
}
|
||||
|
||||
abstract class Element : ParentNode {
|
||||
readonly attribute String tagName; // O(1)
|
||||
|
||||
Boolean hasAttribute(String name); // O(N) in number of attributes
|
||||
String getAttribute(String name); // O(N) in number of attributes
|
||||
void setAttribute(String name, String value = ''); // O(N) in number of attributes
|
||||
void removeAttribute(String name); // O(N) in number of attributes
|
||||
|
||||
// Returns a new Array and new Attr instances every time.
|
||||
Array<Attr> getAttributes(); // O(N) in number of attributes
|
||||
|
||||
readonly attribute ShadowRoot? shadowRoot; // O(1) // returns the shadow root
|
||||
Array<ContentElement> getDestinationInsertionPoints(); // O(N) in number of insertion points the node is in
|
||||
|
||||
virtual void endTagParsedCallback(); // noop
|
||||
virtual void attributeChangeCallback(String name, String? oldValue, String? newValue); // noop
|
||||
// TODO(ianh): does a node ever need to know when it's been redistributed?
|
||||
|
||||
readonly attribute ElementStyleDeclarationList style; // O(1)
|
||||
virtual LayoutManagerConstructor getLayoutManager(RenderNode renderNode); // O(1)
|
||||
// default implementation looks up the 'display' property and returns the value:
|
||||
// if (renderNode)
|
||||
// return renderNode.getProperty(phDisplay);
|
||||
// return null;
|
||||
readonly attribute RenderNode? renderNode; // O(1)
|
||||
// this will be null until the first time it is rendered
|
||||
void resetLayoutManager(); // O(1)
|
||||
// if renderNode is non-null:
|
||||
// sets renderNode.layoutManager to null
|
||||
// sets renderNode.needsManager to true
|
||||
}
|
||||
|
||||
class Text : Node {
|
||||
constructor (String value = ''); // O(1)
|
||||
attribute String value; // O(1)
|
||||
|
||||
void replaceWith(String node); // O(1) // special case override of Node.replaceWith()
|
||||
|
||||
virtual void valueChangeCallback(String? oldValue, String? newValue); // noop
|
||||
}
|
||||
|
||||
class DocumentFragment : ParentNode {
|
||||
constructor (ChildArguments... nodes); // O(N) in number of arguments plus all their descendants
|
||||
}
|
||||
|
||||
abstract class TreeScope : ParentNode {
|
||||
readonly attribute Document? ownerDocument; // O(1)
|
||||
readonly attribute TreeScope? parentScope; // O(1)
|
||||
|
||||
Element? findId(String id); // O(1)
|
||||
}
|
||||
|
||||
class ShadowRoot : TreeScope {
|
||||
constructor (Element host); // O(1) // note that there is no way in the API to use a newly created ShadowRoot
|
||||
readonly attribute Element host; // O(1)
|
||||
}
|
||||
|
||||
class Document : TreeScope {
|
||||
constructor (ChildArguments... nodes); // O(N) in number of arguments plus all their descendants
|
||||
}
|
||||
|
||||
class SelectorQuery {
|
||||
constructor (String selector); // O(F()) where F() is the complexity of the selector
|
||||
|
||||
Boolean matches(Element element); // O(F())
|
||||
Element? find(Element root); // O(N*F())+O(M) where N is the number of descendants and M the average depth of the tree
|
||||
Element? find(DocumentFragment root); // O(N*F())+O(M) where N is the number of descendants and M the average depth of the tree
|
||||
Element? find(TreeScope root); // O(N*F()) where N is the number of descendants
|
||||
Array<Element> findAll(Element root); // O(N*F())+O(N*M) where N is the number of descendants and M the average depth of the tree
|
||||
Array<Element> findAll(DocumentFragment root); // O(N*F())+O(N*M) where N is the number of descendants and M the average depth of the tree
|
||||
Array<Element> findAll(TreeScope root); // O(N*F()) where N is the number of descendants
|
||||
}
|
||||
|
||||
|
||||
// BUILT-IN ELEMENTS
|
||||
|
||||
class ImportElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "import"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class TemplateElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "template"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
|
||||
readonly attribute DocumentFragment content; // O(1)
|
||||
}
|
||||
class ScriptElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "script"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class StyleElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "style"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
|
||||
Array<Rule> getRules(); // O(N) in rules
|
||||
}
|
||||
class ContentElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "content"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
|
||||
Array<Node> getDistributedNodes(); // O(N) in distributed nodes
|
||||
}
|
||||
class ImgElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "img"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class DivElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "div"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class SpanElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "span"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class IframeElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "iframe"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class TElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "t"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class AElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "a"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class TitleElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "title"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class ErrorElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "error"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MODULES
|
||||
|
||||
callback InternalElementConstructor void (Module module);
|
||||
dictionary ElementRegistration {
|
||||
String tagName;
|
||||
Boolean shadow = false;
|
||||
InternalElementConstructor? constructor = null;
|
||||
}
|
||||
|
||||
interface ElementConstructor {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
|
||||
constructor attribute String tagName;
|
||||
constructor attribute Boolean shadow;
|
||||
}
|
||||
|
||||
abstract class AbstractModule : EventTarget {
|
||||
readonly attribute Document document; // O(1) // the Documentof the module or application
|
||||
Promise<any> import(String url); // O(Yikes) // returns the module's exports
|
||||
private Array<Module> getImports(); O(N) // returns the Module objects of all the imported modules
|
||||
|
||||
readonly attribute String url;
|
||||
|
||||
ElementConstructor registerElement(ElementRegistration options); // O(1)
|
||||
// if you call registerElement() with an object that was created by
|
||||
// registerElement(), it just returns the object after registering it,
|
||||
// rather than creating a new constructor
|
||||
// otherwise, it proceeds as follows:
|
||||
// 1. let constructor be the constructor passed in, if any
|
||||
// 2. let prototype be the constructor's prototype; if there is no
|
||||
// constructor, let prototype be Element
|
||||
// 3. create a new Function that:
|
||||
// 1. throws if not called as a constructor
|
||||
// 2. creates an actual Element object
|
||||
// 3. initialises the shadow tree if shadow on the options is true
|
||||
// 4. calls constructor, if it's not null, with the module as the argument
|
||||
// 4. let that new Function's prototype be the aforementioned prototype
|
||||
// 5. let that new Function have tagName and shadow properties set to
|
||||
// the values passed in on options
|
||||
// 6. register the new element
|
||||
|
||||
readonly attribute ScriptElement? currentScript; // O(1) // returns the <script> element currently being executed if any, and if it's in this module; else null
|
||||
}
|
||||
|
||||
class Module : AbstractModule {
|
||||
constructor (Application application, Document document, String url); // O(1)
|
||||
readonly attribute Application application; // O(1)
|
||||
|
||||
attribute any exports; // O(1) // defaults to {}
|
||||
}
|
||||
|
||||
class Application : AbstractModule {
|
||||
constructor (Document document, String url); // O(1)
|
||||
attribute String title; // O(1)
|
||||
}
|
||||
|
||||
// see script.md for a description of the global object, though note that
|
||||
// the sky core module doesn't use it or affect it in any way.
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
TODO(ianh): event loop
|
||||
|
||||
TODO(ianh): define the DOM APIs listed above, including firing the
|
||||
change callbacks
|
||||
|
||||
TODO(ianh): schedule microtask, schedule task, requestAnimationFrame,
|
||||
custom element callbacks...
|
||||
|
||||
|
||||
|
||||
Appendices
|
||||
==========
|
||||
|
||||
Sky IDL
|
||||
-------
|
||||
|
||||
The Sky IDL language is used to describe JS APIs found in Sky, in
|
||||
particular, the JS APIs exposed by the four magical imports defined in
|
||||
this document.
|
||||
|
||||
Sky IDL definitions are typically compiled to C++ that exposes the C++
|
||||
implementations of the APIs to JavaScript.
|
||||
|
||||
Sky IDL works more or less the same as Web IDL but the syntax is a bit
|
||||
different.
|
||||
|
||||
```javascript
|
||||
module 'sky:modulename' {
|
||||
|
||||
// this is a comment
|
||||
|
||||
typedef NewType OldType; // useful when OldType is a commonly-used union
|
||||
|
||||
callback CallbackName ReturnType (ArgumentType argumentName);
|
||||
|
||||
class ClassName {
|
||||
// a class corresponds to a JavaScript prototype
|
||||
// corresponds to a WebIDL 'interface'
|
||||
}
|
||||
|
||||
abstract class Superclass {
|
||||
// an abstract class can't have a non-abstract constructor
|
||||
// an abstract class may have abstract constructors and methods
|
||||
// an abstract class may have everything else a class can have
|
||||
|
||||
abstract constructor ();
|
||||
// this indicates that non-abstract subclasses must have a constructor with the given arguments
|
||||
|
||||
abstract ReturnType methodCallback();
|
||||
// this method does nothing, but is included to describe the interface that subclasses will implement
|
||||
// a non-abstract class must have an explicit implementation of all inherited abstract methods
|
||||
|
||||
}
|
||||
|
||||
class Subclass : Superclass {
|
||||
// properties
|
||||
readonly attribute ReturnType attributeName; // getter
|
||||
attribute ReturnType attributeName; // getter and setter
|
||||
|
||||
// methods and constructors
|
||||
constructor ();
|
||||
ReturnType method();
|
||||
// When the platform calls this method, it always invokes the "real" method, even if it's been
|
||||
// deleted from the prototypes (as if it took a reference to the method at startup, and stored
|
||||
// state using Symbols)
|
||||
// Calling a method with fewer arguments than defined will throw.
|
||||
// Calling a method with more arguments ignores the extra arguments.
|
||||
virtual ReturnType methodCallback();
|
||||
// when the platform calls this, it actually calls it the way JS would, so author overrides do
|
||||
// affect what gets called. Make sure if you override it that you call the superclass implementation!
|
||||
// The default implementations of 'virtual' methods all end by calling the identically named method
|
||||
// on the superclass, if there is such a method.
|
||||
|
||||
// non-abstract classes cannot have abstract constructors or methods, and in particular, must
|
||||
// have explicit non-abstract versions of any inherited abstract constructors or methods
|
||||
|
||||
// properties on the constructor
|
||||
constructor readonly attribute ReturnType staticName;
|
||||
|
||||
// private APIs - see below
|
||||
private void method();
|
||||
|
||||
// arguments and overloading are done as follows
|
||||
// note that the argument names are only for documentation purposes
|
||||
ReturnType method(ArgumentType argumentName1, ArgumentType argumentName2);
|
||||
// the last argument's type can have "..." appended to it to indicate a varargs-like situation
|
||||
ReturnType method(ArgumentType argumentName1, ArgumentType... allSubsequentArguments);
|
||||
// trailing arguments can have a default value, which must be a literal of the given type
|
||||
ReturnType method(ArgumentType argumentName1, ArgumentType argumentName2 = defaultValue);
|
||||
}
|
||||
|
||||
dictionary Options {
|
||||
String foo; // if there's no default, the property must be specified or it's a TypeError
|
||||
Integer bar = 4; // properties can have default values
|
||||
}
|
||||
|
||||
// the module can have properties and methods also
|
||||
attribute String Foo;
|
||||
void method();
|
||||
|
||||
interface InterfaceName {
|
||||
// describes a template of a prototype, in the same syntax as a class
|
||||
// not actually exposed in the runtime
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Private APIs ###
|
||||
|
||||
Private APIs are only accessible via Symbol objects, which are then
|
||||
exposed on the sky:debug module's exports object as the name of the
|
||||
member given in the IDL.
|
||||
|
||||
For example, consider:
|
||||
|
||||
```javascript
|
||||
class Foo {
|
||||
private void Bar();
|
||||
}
|
||||
```
|
||||
|
||||
In a script with a ``foo`` object of type ``Foo``, ``foo.Bar`` is
|
||||
undefined. However, it can be obtained as follows:
|
||||
|
||||
```html
|
||||
<import src="sky:debug" as="debug"/>
|
||||
<!-- ... import whatever defines 'foo' ... -->
|
||||
<script>
|
||||
foo[debug.Bar]
|
||||
</script>
|
||||
```
|
||||
|
||||
### Types ###
|
||||
|
||||
The following types are available:
|
||||
|
||||
* ``Integer`` - WebIDL ``long long``
|
||||
* ``Float`` - WebIDL ``double``
|
||||
* ``Infinity`` - singleton type with value ``Infinity``
|
||||
* ``String`` - WebIDL ``USVString``
|
||||
* ``Boolean`` - WebIDL ``boolean``
|
||||
# ``Object`` - WebIDL ``object`` (``ClassName`` can be used as a literal for this type)
|
||||
* ``ClassName`` - an instance of the class ClassName
|
||||
* ``Class<ClassName>`` - a class ClassName or one of its subclasses (not an instance)
|
||||
* ``DictionaryName`` - an instance of the dictionary DictionaryName
|
||||
* ``Promise<Type>`` - WebIDL ``Promise<T>``
|
||||
* ``Generator<Type>`` - An ECMAScript generator function that returns data of the given type
|
||||
* ``Array<Type>`` - WebIDL ``sequence<T>``
|
||||
* ``Dictionary<Type>`` - unordered set of name-value String-Type pairs with no duplicate names
|
||||
* ``Type?`` - union of Type and the singleton type with value ``null`` (WebIDL nullable)
|
||||
* ``(Type1 or Type2)`` - union of Type1 and Type2 (WebIDL union)
|
||||
* ``any`` - union of all types (WebIDL ``any``)
|
||||
|
||||
Methods that return nothing (undefined, in JS) use the keyword "void"
|
||||
instead of a type.
|
||||
|
||||
|
||||
TODO(ianh): Define in detail how this actually works
|
||||
|
||||
|
||||
Mojom IDL
|
||||
---------
|
||||
|
||||
The Mojom IDL language is used to describe the APIs exposed over Mojo
|
||||
pipes.
|
||||
|
||||
Mojom IDL definitions are typically compiled to wrappers in each
|
||||
language, which are then used as imports.
|
||||
|
||||
TODO(ianh): Define in detail how this actually works
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
```javascript
|
||||
global object = {} // with Math, RegExp, etc
|
||||
|
||||
magical imports:
|
||||
the core mojo fabric JS API sky:mojo:fabric:core
|
||||
the asyncWait/cancelWait mojo fabric JS API (interface to IPC thread) sky:mojo:fabric:ipc
|
||||
the mojom for the shell, proxying through C++ so that the shell pipe isn't exposed sky:mojo:shell
|
||||
the sky API sky:core
|
||||
the sky debug symbols for private APIs sky:debug
|
||||
```
|
||||
|
||||
TODO(ianh): determine if we want to separate the "this" from the
|
||||
Document, especially for Modules, so that exposing a module's element
|
||||
doesn't expose the module's exports attribute.
|
||||
257
specs/dom.md
Normal file
257
specs/dom.md
Normal file
@ -0,0 +1,257 @@
|
||||
Sky DOM APIs
|
||||
============
|
||||
|
||||
```javascript
|
||||
|
||||
// DOM
|
||||
|
||||
typedef ChildNode (Element or Text);
|
||||
typedef ChildArgument (Element or Text or String);
|
||||
|
||||
abstract class Node : EventTarget { // implemented in C++
|
||||
readonly attribute TreeScope? ownerScope; // O(1)
|
||||
|
||||
readonly attribute ParentNode? parentNode; // O(1)
|
||||
readonly attribute Element? parentElement; // O(1) // if parentNode isn't an element, returns null
|
||||
readonly attribute ChildNode? previousSibling; // O(1)
|
||||
readonly attribute ChildNode? nextSibling; // O(1)
|
||||
|
||||
virtual Array<EventTarget> getEventDispatchChain(); // O(N) in number of ancestors across shadow trees // implements EventTarget.getEventDispatchChain()
|
||||
// returns the event dispatch chain (including handling shadow trees)
|
||||
|
||||
// the following all throw if parentNode is null
|
||||
void insertBefore(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void insertAfter(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void replaceWith(ChildArgument... nodes); // O(N) in number of descendants plus arguments plus all their descendants
|
||||
void remove(); // O(N) in number of descendants
|
||||
Node cloneNode(Boolean deep = false); // O(1) if deep=false, O(N) in the number of descendants if deep=true
|
||||
|
||||
// called when parentNode changes
|
||||
virtual void parentChangeCallback(ParentNode? oldParent, ParentNode? newParent, ChildNode? previousSibling, ChildNode? nextSibling); // O(N) in descendants (calls attached/detached)
|
||||
virtual void attachedCallback(); // noop
|
||||
virtual void detachedCallback(); // noop
|
||||
}
|
||||
|
||||
abstract class ParentNode : Node {
|
||||
readonly attribute ChildNode? firstChild; // O(1)
|
||||
readonly attribute ChildNode? lastChild; // O(1)
|
||||
|
||||
// Returns a new Array every time.
|
||||
Array<ChildNode> getChildNodes(); // O(N) in number of child nodes
|
||||
Array<Element> getChildElements(); // O(N) in number of child nodes // TODO(ianh): might not be necessary if we have the parser drop unnecessary whitespace text nodes
|
||||
|
||||
void append(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void prepend(ChildArgument... nodes); // O(N) in number of arguments plus all their descendants
|
||||
void replaceChildrenWith(ChildArgument... nodes); // O(N) in number of descendants plus arguments plus all their descendants
|
||||
}
|
||||
|
||||
class Attr {
|
||||
constructor (String name, String value = ''); // O(1)
|
||||
readonly attribute String name; // O(1)
|
||||
readonly attribute String value; // O(1)
|
||||
}
|
||||
|
||||
abstract class Element : ParentNode {
|
||||
readonly attribute String tagName; // O(1)
|
||||
|
||||
Boolean hasAttribute(String name); // O(N) in number of attributes
|
||||
String getAttribute(String name); // O(N) in number of attributes
|
||||
void setAttribute(String name, String value = ''); // O(N) in number of attributes
|
||||
void removeAttribute(String name); // O(N) in number of attributes
|
||||
|
||||
// Returns a new Array and new Attr instances every time.
|
||||
Array<Attr> getAttributes(); // O(N) in number of attributes
|
||||
|
||||
readonly attribute ShadowRoot? shadowRoot; // O(1) // returns the shadow root
|
||||
Array<ContentElement> getDestinationInsertionPoints(); // O(N) in number of insertion points the node is in
|
||||
|
||||
virtual void endTagParsedCallback(); // noop
|
||||
virtual void attributeChangeCallback(String name, String? oldValue, String? newValue); // noop
|
||||
// TODO(ianh): does a node ever need to know when it's been redistributed?
|
||||
|
||||
readonly attribute ElementStyleDeclarationList style; // O(1)
|
||||
readonly attribute RenderNode? renderNode; // O(1)
|
||||
// this will be null until the first time it is rendered
|
||||
virtual LayoutManagerConstructor getLayoutManager(); // O(1)
|
||||
// default implementation looks up the 'display' property and returns the value:
|
||||
// if (renderNode)
|
||||
// return renderNode.getProperty(phDisplay);
|
||||
// return null;
|
||||
void resetLayoutManager(); // O(1)
|
||||
// if renderNode is non-null:
|
||||
// sets renderNode.layoutManager to null
|
||||
// sets renderNode.needsManager to true
|
||||
}
|
||||
|
||||
class Text : Node {
|
||||
constructor (String value = ''); // O(1)
|
||||
attribute String value; // O(1)
|
||||
|
||||
void replaceWith(String node); // O(1) // special case override of Node.replaceWith()
|
||||
|
||||
virtual void valueChangeCallback(String? oldValue, String? newValue); // noop
|
||||
}
|
||||
|
||||
class DocumentFragment : ParentNode {
|
||||
constructor (ChildArguments... nodes); // O(N) in number of arguments plus all their descendants
|
||||
}
|
||||
|
||||
abstract class TreeScope : ParentNode {
|
||||
readonly attribute Document? ownerDocument; // O(1)
|
||||
readonly attribute TreeScope? parentScope; // O(1)
|
||||
|
||||
Element? findId(String id); // O(1)
|
||||
}
|
||||
|
||||
class ShadowRoot : TreeScope {
|
||||
constructor (Element host); // O(1) // note that there is no way in the API to use a newly created ShadowRoot
|
||||
readonly attribute Element host; // O(1)
|
||||
}
|
||||
|
||||
class Document : TreeScope {
|
||||
constructor (ChildArguments... nodes); // O(N) in number of arguments plus all their descendants
|
||||
}
|
||||
|
||||
class SelectorQuery {
|
||||
constructor (String selector); // O(F()) where F() is the complexity of the selector
|
||||
|
||||
Boolean matches(Element element); // O(F())
|
||||
Element? find(Element root); // O(N*F())+O(M) where N is the number of descendants and M the average depth of the tree
|
||||
Element? find(DocumentFragment root); // O(N*F())+O(M) where N is the number of descendants and M the average depth of the tree
|
||||
Element? find(TreeScope root); // O(N*F()) where N is the number of descendants
|
||||
Array<Element> findAll(Element root); // O(N*F())+O(N*M) where N is the number of descendants and M the average depth of the tree
|
||||
Array<Element> findAll(DocumentFragment root); // O(N*F())+O(N*M) where N is the number of descendants and M the average depth of the tree
|
||||
Array<Element> findAll(TreeScope root); // O(N*F()) where N is the number of descendants
|
||||
}
|
||||
|
||||
|
||||
// BUILT-IN ELEMENTS
|
||||
|
||||
class ImportElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "import"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class TemplateElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "template"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
|
||||
readonly attribute DocumentFragment content; // O(1)
|
||||
}
|
||||
class ScriptElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "script"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class StyleElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "style"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
|
||||
Array<Rule> getRules(); // O(N) in rules
|
||||
}
|
||||
class ContentElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "content"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
|
||||
Array<Node> getDistributedNodes(); // O(N) in distributed nodes
|
||||
}
|
||||
class ImgElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "img"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class DivElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "div"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class SpanElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "span"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class IframeElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "iframe"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class TElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "t"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class AElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "a"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class TitleElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "title"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
class ErrorElement : Element {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
constructor attribute String tagName; // O(1) // "error"
|
||||
constructor attribute Boolean shadow; // O(1) // false
|
||||
}
|
||||
|
||||
callback InternalElementConstructor void (Module module);
|
||||
dictionary ElementRegistration {
|
||||
String tagName;
|
||||
Boolean shadow = false;
|
||||
InternalElementConstructor? constructor = null;
|
||||
}
|
||||
|
||||
interface ElementConstructor {
|
||||
constructor (Dictionary<String> attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants
|
||||
constructor (ChildArguments... nodes); // shorthand
|
||||
constructor (Dictionary<String> attributes); // shorthand
|
||||
constructor (); // shorthand
|
||||
|
||||
constructor attribute String tagName;
|
||||
constructor attribute Boolean shadow;
|
||||
}
|
||||
```
|
||||
55
specs/events.md
Normal file
55
specs/events.md
Normal file
@ -0,0 +1,55 @@
|
||||
Sky Event Model
|
||||
===============
|
||||
|
||||
```javascript
|
||||
// EVENTS
|
||||
|
||||
class Event {
|
||||
constructor (String type, Boolean bubbles = true, any data = null); // O(1)
|
||||
readonly attribute String type; // O(1)
|
||||
readonly attribute Boolean bubbles; // O(1)
|
||||
attribute any data; // O(1)
|
||||
|
||||
readonly attribute EventTarget target; // O(1)
|
||||
attribute Boolean handled; // O(1)
|
||||
attribute any result; // O(1)
|
||||
|
||||
// TODO(ianh): do events get blocked at scope boundaries, e.g. focus events when both sides are in the scope?
|
||||
// TODO(ianh): do events get retargetted, e.g. focus when leaving a custom element?
|
||||
}
|
||||
|
||||
callback EventListener any (Event event);
|
||||
// if the return value is not undefined:
|
||||
// assign it to event.result
|
||||
// set event.handled to true
|
||||
|
||||
abstract class EventTarget {
|
||||
any dispatchEvent(Event event); // O(N) in total number of listeners for this type in the chain
|
||||
// sets event.handled to false and event.result to undefined
|
||||
// makes a record of the event target chain by calling getEventDispatchChain()
|
||||
// invokes all the handlers on the chain in turn
|
||||
// returns event.result
|
||||
virtual Array<EventTarget> getEventDispatchChain(); // O(1) // returns []
|
||||
void addEventListener(String type, EventListener listener); // O(1)
|
||||
void removeEventListener(String type, EventListener listener); // O(N) in event listeners with that type
|
||||
private Array<String> getRegisteredEventListenerTypes(); // O(N)
|
||||
private Array<EventListener> getRegisteredEventListenersForType(String type); // O(N)
|
||||
}
|
||||
|
||||
class CustomEventTarget : EventTarget { // implemented in JS
|
||||
constructor (); // O(1)
|
||||
attribute EventTarget parentNode; // getter O(1), setter O(N) in height of tree, throws if this would make a loop
|
||||
|
||||
virtual Array<EventTarget> getEventDispatchChain(); // O(N) in height of tree // implements EventTarget.getEventDispatchChain()
|
||||
// let result = [];
|
||||
// let node = this;
|
||||
// while (node) {
|
||||
// result.push(node);
|
||||
// node = node.parentNode;
|
||||
// }
|
||||
// return result;
|
||||
|
||||
// you can inherit from this to make your object into an event target
|
||||
// or you can inherit from EventTarget and implement your own getEventDispatchChain()
|
||||
}
|
||||
```
|
||||
158
specs/idl.md
Normal file
158
specs/idl.md
Normal file
@ -0,0 +1,158 @@
|
||||
Sky IDL
|
||||
=======
|
||||
|
||||
The Sky IDL language is used to describe JS APIs found in Sky, in
|
||||
particular, the JS APIs exposed by the four magical imports defined in
|
||||
this document.
|
||||
|
||||
Sky IDL definitions are typically compiled to C++ that exposes the C++
|
||||
implementations of the APIs to JavaScript.
|
||||
|
||||
Sky IDL works more or less the same as Web IDL but the syntax is a bit
|
||||
different.
|
||||
|
||||
```javascript
|
||||
module 'sky:modulename' {
|
||||
|
||||
// this is a comment
|
||||
|
||||
typedef NewType OldType; // useful when OldType is a commonly-used union
|
||||
|
||||
callback CallbackName ReturnType (ArgumentType argumentName);
|
||||
|
||||
class ClassName {
|
||||
// a class corresponds to a JavaScript prototype
|
||||
// corresponds to a WebIDL 'interface'
|
||||
}
|
||||
|
||||
abstract class Superclass {
|
||||
// an abstract class can't have a non-abstract constructor
|
||||
// an abstract class may have abstract constructors and methods
|
||||
// an abstract class may have everything else a class can have
|
||||
|
||||
abstract constructor ();
|
||||
// this indicates that non-abstract subclasses must have a constructor with the given arguments
|
||||
|
||||
abstract ReturnType methodCallback();
|
||||
// this method does nothing, but is included to describe the interface that subclasses will implement
|
||||
// a non-abstract class must have an explicit implementation of all inherited abstract methods
|
||||
|
||||
}
|
||||
|
||||
class Subclass : Superclass {
|
||||
// properties
|
||||
readonly attribute ReturnType attributeName; // getter
|
||||
attribute ReturnType attributeName; // getter and setter
|
||||
|
||||
// methods and constructors
|
||||
constructor ();
|
||||
ReturnType method();
|
||||
// When the platform calls this method, it always invokes the "real" method, even if it's been
|
||||
// deleted from the prototypes (as if it took a reference to the method at startup, and stored
|
||||
// state using Symbols)
|
||||
// Calling a method with fewer arguments than defined will throw.
|
||||
// Calling a method with more arguments ignores the extra arguments.
|
||||
virtual ReturnType methodCallback();
|
||||
// when the platform calls this, it actually calls it the way JS would, so author overrides do
|
||||
// affect what gets called. Make sure if you override it that you call the superclass implementation!
|
||||
// The default implementations of 'virtual' methods all end by calling the identically named method
|
||||
// on the superclass, if there is such a method.
|
||||
|
||||
// non-abstract classes cannot have abstract constructors or methods, and in particular, must
|
||||
// have explicit non-abstract versions of any inherited abstract constructors or methods
|
||||
|
||||
// properties on the constructor
|
||||
constructor readonly attribute ReturnType staticName;
|
||||
|
||||
// private APIs - see below
|
||||
private void method();
|
||||
|
||||
// arguments and overloading are done as follows
|
||||
// note that the argument names are only for documentation purposes
|
||||
ReturnType method(ArgumentType argumentName1, ArgumentType argumentName2);
|
||||
// the last argument's type can have "..." appended to it to indicate a varargs-like situation
|
||||
ReturnType method(ArgumentType argumentName1, ArgumentType... allSubsequentArguments);
|
||||
// trailing arguments can have a default value, which must be a literal of the given type
|
||||
ReturnType method(ArgumentType argumentName1, ArgumentType argumentName2 = defaultValue);
|
||||
}
|
||||
|
||||
dictionary Options {
|
||||
String foo; // if there's no default, the property must be specified or it's a TypeError
|
||||
Integer bar = 4; // properties can have default values
|
||||
}
|
||||
|
||||
// the module can have properties and methods also
|
||||
attribute String Foo;
|
||||
void method();
|
||||
|
||||
interface InterfaceName {
|
||||
// describes a template of a prototype, in the same syntax as a class
|
||||
// not actually exposed in the runtime
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Private APIs ###
|
||||
|
||||
Private APIs are only accessible via Symbol objects, which are then
|
||||
exposed on the sky:debug module's exports object as the name of the
|
||||
member given in the IDL.
|
||||
|
||||
For example, consider:
|
||||
|
||||
```javascript
|
||||
class Foo {
|
||||
private void Bar();
|
||||
}
|
||||
```
|
||||
|
||||
In a script with a ``foo`` object of type ``Foo``, ``foo.Bar`` is
|
||||
undefined. However, it can be obtained as follows:
|
||||
|
||||
```html
|
||||
<import src="sky:debug" as="debug"/>
|
||||
<!-- ... import whatever defines 'foo' ... -->
|
||||
<script>
|
||||
foo[debug.Bar]
|
||||
</script>
|
||||
```
|
||||
|
||||
### Types ###
|
||||
|
||||
The following types are available:
|
||||
|
||||
* ``Integer`` - WebIDL ``long long``
|
||||
* ``Float`` - WebIDL ``double``
|
||||
* ``Infinity`` - singleton type with value ``Infinity``
|
||||
* ``String`` - WebIDL ``USVString``
|
||||
* ``Boolean`` - WebIDL ``boolean``
|
||||
# ``Object`` - WebIDL ``object`` (``ClassName`` can be used as a literal for this type)
|
||||
* ``ClassName`` - an instance of the class ClassName
|
||||
* ``Class<ClassName>`` - a class ClassName or one of its subclasses (not an instance)
|
||||
* ``DictionaryName`` - an instance of the dictionary DictionaryName
|
||||
* ``Promise<Type>`` - WebIDL ``Promise<T>``
|
||||
* ``Generator<Type>`` - An ECMAScript generator function that returns data of the given type
|
||||
* ``Array<Type>`` - WebIDL ``sequence<T>``
|
||||
* ``Dictionary<Type>`` - unordered set of name-value String-Type pairs with no duplicate names
|
||||
* ``Type?`` - union of Type and the singleton type with value ``null`` (WebIDL nullable)
|
||||
* ``(Type1 or Type2)`` - union of Type1 and Type2 (WebIDL union)
|
||||
* ``any`` - union of all types (WebIDL ``any``)
|
||||
|
||||
Methods that return nothing (undefined, in JS) use the keyword "void"
|
||||
instead of a type.
|
||||
|
||||
|
||||
TODO(ianh): Define in detail how this actually works
|
||||
|
||||
|
||||
Mojom IDL
|
||||
---------
|
||||
|
||||
The Mojom IDL language is used to describe the APIs exposed over Mojo
|
||||
pipes.
|
||||
|
||||
Mojom IDL definitions are typically compiled to wrappers in each
|
||||
language, which are then used as imports.
|
||||
|
||||
TODO(ianh): Define in detail how this actually works
|
||||
@ -47,6 +47,50 @@ the imported module's ``exports`` value, and for each property that is
|
||||
an element constructor (generated by ``registerElement()``), it adds
|
||||
an element to the importee's element registry.
|
||||
|
||||
### IDL ###
|
||||
|
||||
```javascript
|
||||
abstract class AbstractModule : EventTarget {
|
||||
readonly attribute Document document; // O(1) // the Documentof the module or application
|
||||
Promise<any> import(String url); // O(Yikes) // returns the module's exports
|
||||
private Array<Module> getImports(); O(N) // returns the Module objects of all the imported modules
|
||||
|
||||
readonly attribute String url;
|
||||
|
||||
ElementConstructor registerElement(ElementRegistration options); // O(1)
|
||||
// if you call registerElement() with an object that was created by
|
||||
// registerElement(), it just returns the object after registering it,
|
||||
// rather than creating a new constructor
|
||||
// otherwise, it proceeds as follows:
|
||||
// 1. let constructor be the constructor passed in, if any
|
||||
// 2. let prototype be the constructor's prototype; if there is no
|
||||
// constructor, let prototype be Element
|
||||
// 3. create a new Function that:
|
||||
// 1. throws if not called as a constructor
|
||||
// 2. creates an actual Element object
|
||||
// 3. initialises the shadow tree if shadow on the options is true
|
||||
// 4. calls constructor, if it's not null, with the module as the argument
|
||||
// 4. let that new Function's prototype be the aforementioned prototype
|
||||
// 5. let that new Function have tagName and shadow properties set to
|
||||
// the values passed in on options
|
||||
// 6. register the new element
|
||||
|
||||
readonly attribute ScriptElement? currentScript; // O(1) // returns the <script> element currently being executed if any, and if it's in this module; else null
|
||||
}
|
||||
|
||||
class Module : AbstractModule {
|
||||
constructor (Application application, Document document, String url); // O(1)
|
||||
readonly attribute Application application; // O(1)
|
||||
|
||||
attribute any exports; // O(1) // defaults to {}
|
||||
}
|
||||
|
||||
class Application : AbstractModule {
|
||||
constructor (Document document, String url); // O(1)
|
||||
attribute String title; // O(1)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Naming modules
|
||||
--------------
|
||||
|
||||
23
specs/runloop.md
Normal file
23
specs/runloop.md
Normal file
@ -0,0 +1,23 @@
|
||||
Sky's Run Loop
|
||||
==============
|
||||
|
||||
Sky's run loop consists of running the following, at 120Hz (each loop
|
||||
takes 8.333ms):
|
||||
|
||||
1. Send scroll and resize events if necessary, limiting each handler
|
||||
to 1ms, and limiting the total time spent on these handlers to 1ms.
|
||||
|
||||
2. Update as much of layout as possible; after 1ms, stop, leaving the
|
||||
remaining nodes unprepared.
|
||||
|
||||
3. Update as much of paint as possible; after 1ms, stop, leaving the
|
||||
remaining nodes unprepared.
|
||||
|
||||
4. Send frame to GPU.
|
||||
|
||||
5. Run pending tasks until the 8.333ms expires. Each task may only run
|
||||
for at most 1ms, after 1ms they get a (catchable) EDeadlineExceeded
|
||||
exception. While there are no pending tasks, sleep.
|
||||
|
||||
TODO(ianh): Update the timings above to have some relationship to
|
||||
reality.
|
||||
Loading…
x
Reference in New Issue
Block a user