APIs ==== The Sky core API ---------------- ```javascript module 'sky:core' { // EVENTS interface Event { constructor (String type, Boolean bubbles, any data); // 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) void preventDefault(); // O(1) attribute any result; // O(1) // defaults to undefined // TODO(ianh): do events get blocked at scope boundaries, e.g. focus events when both sides are in the scope? // TODO(ianh): do events ger retargetted, e.g. focus when leaving a custom element? } callback EventListener any (Event event); // return value is assigned to Event.result interface EventTarget { any dispatchEvent(Event event); // O(N) in total number of listeners for this type in the chain // returns Event.result void addEventListener(String type, EventListener listener); // O(1) void removeEventListener(String type, EventListener listener); // O(N) in event listeners with that type private Array getRegisteredEventListenerTypes(); // O(N) private Array getRegisteredEventListenersForType(String type); // O(N) } interface CustomEventTarget : EventTarget { constructor (); // O(1) attribute EventTarget parentNode; // getter O(1), setter O(N) in height of tree, throws if this would make a loop // you can inherit from this to make your object into an event target } // DOM typedef ChildNode (Element or Text); typedef ChildArgument (Element or Text or String); abstract interface Node : EventTarget { 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) // 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); // 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 interface ParentNode : Node { readonly attribute ChildNode? firstChild; // O(1) readonly attribute ChildNode? lastChild; // O(1) // Returns a new Array every time. Array getChildNodes(); // O(N) in number of child nodes Array 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 } interface Attr { constructor (String name, String value); // O(1) readonly attribute String name; // O(1) readonly attribute String value; // O(1) } interface Element : ParentNode { readonly attribute String tagName; // O(1) Boolean hasAttribute(String name); // O(N) in arguments String getAttribute(String name); // O(N) in arguments void setAttribute(String name, String value); // O(N) in arguments void removeAttribute(String name); // O(N) in arguments // Returns a new Array and new Attr instances every time. Array getAttributes(); // O(N) in arguments readonly attribute ShadowRoot? shadowRoot; // O(1) // returns the shadow root Array getDestinationInsertionPoints(); // O(N) in number of insertion points the node is in virtual void attributeChangeCallback(String name, String? oldValue, String? newValue); // noop // TODO(ianh): does a node ever need to know when it's been redistributed? } Element createElement(String tagName, Dictionary attributes, ChildArguments... nodes); // O(M+N), M = number of attributes, N = number of nodes plus all their descendants Element createElement(String tagName, Dictionary attributes); // shorthand Element createElement(String tagName, ChildArguments... nodes); // shorthand Element createElement(String tagName); // shorthand dictionary ElementRegistration { String tagName; Boolean shadow; Object prototype; } Object registerElement(ElementRegistration options); // O(N) in number of outstanding elements with that tag name to be upgraded interface 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 } interface DocumentFragment : ParentNode { constructor (ChildArguments... nodes); // O(N) in number of arguments plus all their descendants } abstract interface TreeScope : ParentNode { readonly attribute Document? ownerDocument; // O(1) readonly attribute TreeScope? parentScope; // O(1) Element? findId(String id); // O(1) } interface 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) } interface Document : TreeScope { constructor (ChildArguments... nodes); // O(N) in number of arguments plus all their descendants } interface SelectorQuery { constructor (String selector); // O(F()) where F() is the complexity of the selector Boolean matches(Element element); // O(F()) Element? find(ParentNode root); // O(N*F()) where N is the number of descendants Array findAll(ParentNode root); // O(N*F()) where N is the number of descendants } // Built-in Elements interface ImportElement : Element { } interface TemplateElement : Element { readonly attribute DocumentFragment content; // O(1) } interface ScriptElement : Element { } interface StyleElement : Element { } interface ContentElement : Element { Array getDistributedNodes(); // O(N) in distributed nodes } interface ImgElement : Element { } interface IframeElement : Element { } interface TElement : Element { } interface AElement : Element { } interface TitleElement : Element { } // MODULES abstract interface AbstractModule : EventTarget { Promise import(String url); // O(Yikes) // returns the module's exports ScriptElement? currentScript; // O(1) // returns the ``` ### Types ### The following types are available: * ``Integer`` - WebIDL ``long long`` * ``Float`` - WebIDL ``double`` * ``String`` - WebIDL ``USVString`` * ``Boolean`` - WebIDL ``boolean`` # ``Object`` - WebIDL ``object`` * ``InterfaceName`` - an instance of the interface InterfaceName * ``DictionaryName`` - an instance of the dictionary DictionaryName * ``Promise`` - WebIDL ``Promise`` * ``Array`` - WebIDL ``sequence`` * ``Dictionary`` - unordered set of name-value String-String 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): Figure out what should happen with omitted and extraneous parameters 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.