Hixie 318dcf3b04 Specs: handle (in the parser) the case of an element constructor being
turned into something that doesn't inherit from Element, since JS lets
you do that kind of thing after registration

Review URL: https://codereview.chromium.org/829113003
2015-01-07 11:31:52 -08:00

14 KiB

Sky DOM APIs


// 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

  readonly attribute ElementStyleDeclarationList? style; // O(1)
    // for nodes that aren't reachable from the Application Document, returns null
    // (so in particular orphaned subtrees and nodes in module documents don't have one)
    //  -- should be updated when the node's parent chain changes (same time as, e.g.,
    //     the id hashtable is updated)
    // also always returns null for ContentElement elements and ShadowRoot nodes
  readonly attribute RenderNode? renderNode; // O(1)
    // this will be null until the first time it is rendered
    // it becomes null again when it is taken out of the rendering (see style.md)
  abstract virtual LayoutManagerConstructor getLayoutManager(); // O(1)
  void resetLayoutManager(); // O(1)
    // if renderNode is non-null:
    //   sets renderNode.layoutManager to null
    //   sets renderNode.needsManager to true
}

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 // TODO(ianh): Should this be mutable? It would help explain how it gets set...
  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?

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // default implementation looks up the 'display' property and returns the value:
    //   if (renderNode)
    //     return renderNode.getProperty(phDisplay);
    //   return null;
}

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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // default implementation returns TextLayoutManager's constructor
}

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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns sky.rootLayoutManager;
}

attribute LayoutManagerConstructor rootLayoutManager; // O(1)
  // initially configured to return BlockLayoutManager


// 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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns null
}
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)
  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns null
}
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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns null
}
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
  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns null
}
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
  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns null
}
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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns ImgElementLayoutManager
}
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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns IframeElementLayoutManager
}
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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns null
}
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

  virtual LayoutManagerConstructor getLayoutManager(); // O(1)
    // returns ErrorElementLayoutManager
}

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;
}

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
}