| OLD | NEW |
| 1 Sky DOM APIs | 1 Sky DOM APIs |
| 2 ============ | 2 ============ |
| 3 | 3 |
| 4 ```dart | 4 ```dart |
| 5 SKY MODULE | 5 SKY MODULE |
| 6 <!-- part of sky:core --> | 6 <!-- part of sky:core --> |
| 7 | 7 |
| 8 <script> | 8 <script> |
| 9 // ELEMENT TREE API | 9 // ELEMENT TREE API |
| 10 | 10 |
| 11 abstract class ChildNode { | 11 abstract class Node extends EventTarget { |
| 12 @nonnull external TreeScope get ownerScope; // O(1) | 12 @override |
| 13 external List<EventTarget> getEventDispatchChain(); // O(N) in number of ances
tors across shadow trees |
| 14 // implements EventTarget.getEventDispatchChain() |
| 15 // returns the event dispatch chain (including handling shadow trees) |
| 16 |
| 17 external Root get owner; // O(1) |
| 13 | 18 |
| 14 external ParentNode get parentNode; // O(1) | 19 external ParentNode get parentNode; // O(1) |
| 15 external Element get parentElement; // O(1) // if parentNode isn't an element,
returns null | 20 external Element get parentElement; // O(1) // if parentNode isn't an element,
returns null |
| 16 external ChildNode get previousSibling; // O(1) | 21 external Node get previousSibling; // O(1) |
| 17 external ChildNode get nextSibling; // O(1) | 22 external Node get nextSibling; // O(1) |
| 18 | 23 |
| 19 // the following all throw if parentNode is null | 24 // the following all throw if parentNode is null |
| 20 external void insertBefore(@nonnull List</*@nonnull*/ ChildNode> nodes); // O(
N) in number of arguments plus all their descendants | 25 external void insertBefore(List nodes); // O(N) in number of arguments plus al
l their descendants |
| 21 external void insertAfter(@nonnull List</*@nonnull*/ ChildNode> nodes); // O(N
) in number of arguments plus all their descendants | 26 external void insertAfter(List nodes); // O(N) in number of arguments plus all
their descendants |
| 22 external void replaceWith(@nonnull List</*@nonnull*/ ChildNode> nodes); // O(N
) in number of descendants plus arguments plus all their descendants | 27 external void replaceWith(List nodes); // O(N) in number of descendants plus a
rguments plus all their descendants |
| 28 // nodes must be String, Text, or Element |
| 29 |
| 23 external void remove(); // O(N) in number of descendants | 30 external void remove(); // O(N) in number of descendants |
| 24 | 31 |
| 25 // called when parentNode changes | 32 // called when parentNode changes |
| 26 external void parentChangeCallback(ParentNode oldParent, ParentNode newParent,
ChildNode previousSibling, ChildNode nextSibling); // O(N) in descendants | 33 // this is why insertBefore(), append(), et al, are O(N) -- the whole affected
subtree is walked |
| 34 // mutating the element tree from within this is strongly discouraged, since i
t will result in the |
| 35 // callbacks being invoked while the element tree is in a different state than
implied by the callbacks |
| 36 external void parentChangeCallback(ParentNode oldParent, ParentNode newParent,
Node previousSibling, Node nextSibling); // O(N) in descendants |
| 27 // default implementation calls attached/detached | 37 // default implementation calls attached/detached |
| 28 void attachedCallback() { } | 38 void attachedCallback() { } |
| 29 void detachedCallback() { } | 39 void detachedCallback() { } |
| 30 | 40 |
| 31 external List<ContentElement> getDestinationInsertionPoints(); // O(N) in numb
er of insertion points the node is in | 41 external List<ContentElement> getDestinationInsertionPoints(); // O(N) in numb
er of insertion points the node is in |
| 32 // returns the <content> elements to which this element was distributed | 42 // returns the <content> elements to which this element was distributed |
| 33 } | |
| 34 | |
| 35 abstract class Node extends EventTarget { | |
| 36 @override | |
| 37 external List</*@nonnull*/ EventTarget> getEventDispatchChain(); // O(N) in nu
mber of ancestors across shadow trees | |
| 38 // implements EventTarget.getEventDispatchChain() | |
| 39 // returns the event dispatch chain (including handling shadow trees) | |
| 40 | 43 |
| 41 external Node cloneNode({bool deep: false}); // O(1) if deep=false, O(N) in th
e number of descendants if deep=true | 44 external Node cloneNode({bool deep: false}); // O(1) if deep=false, O(N) in th
e number of descendants if deep=true |
| 42 | 45 |
| 43 external ElementStyleDeclarationList get style; // O(1) | 46 external ElementStyleDeclarationList get style; // O(1) |
| 44 // for nodes that aren't reachable from the Application Document, returns null | 47 // for nodes that aren't in the ApplicationRoot's composed tree, |
| 45 // (so in particular orphaned subtrees and nodes in module documents don't hav
e one) | 48 // returns null (so in particular orphaned subtrees and nodes in |
| 46 // -- should be updated when the node's parent chain changes (same time as, e
.g., | 49 // module Roots don't have one, nor do shadow tree Roots) |
| 47 // the id hashtable is updated) | 50 // also always returns null for ContentElement elements |
| 48 // also always returns null for ContentElement elements and ShadowRoot nodes | 51 // -- should be (lazily) updated when the node's parent chain |
| 52 // changes (same time as, e.g., the id hashtable is marked |
| 53 // dirty) |
| 49 | 54 |
| 50 external RenderNode get renderNode; // O(1) | 55 external RenderNode get renderNode; // O(1) |
| 51 // this will be null until the first time it is rendered | 56 // this will be null until the first time it is rendered |
| 52 // it becomes null again when it is taken out of the rendering (see style.md) | 57 // it becomes null again when it is taken out of the rendering (see style.md) |
| 53 | 58 |
| 54 Type getLayoutManager() => null; // O(1) | 59 Type getLayoutManager() => null; // O(1) |
| 55 | 60 |
| 56 void resetLayoutManager() { // O(1) | 61 void resetLayoutManager() { // O(1) |
| 57 if (renderNode != null) { | 62 if (renderNode != null) { |
| 58 renderNode._layoutManager = null; | 63 renderNode._layoutManager = null; |
| 59 renderNode._needsManager = true; | 64 renderNode._needsManager = true; |
| 60 } | 65 } |
| 61 } | 66 } |
| 62 } | 67 } |
| 63 | 68 |
| 64 abstract class ParentNode extends Node { | 69 abstract class ParentNode extends Node { |
| 65 external ChildNode get firstChild; // O(1) | 70 external Node get firstChild; // O(1) |
| 66 external ChildNode get lastChild; // O(1) | 71 external Node get lastChild; // O(1) |
| 67 | 72 |
| 68 // Returns a new List every time. | 73 // Returns a new List every time. |
| 69 external List</*nonnull*/ ChildNode> getChildNodes(); // O(N) in number of chi
ld nodes | 74 external List<Node> getChildren(); // O(N) in number of child nodes |
| 70 external List<Element> getChildElements(); // O(N) in number of child nodes | 75 external List<Element> getChildElements(); // O(N) in number of child nodes |
| 71 // TODO(ianh): might not be necessary if we have the parser drop unnecessary w
hitespace text nodes | 76 // TODO(ianh): might not be necessary if we have the parser drop unnecessary w
hitespace text nodes |
| 72 | 77 |
| 73 external void append(@nonnull List</*nonnull*/ ChildNode> nodes); // O(N) in n
umber of arguments plus all their descendants | 78 external void append(List nodes); // O(N) in number of arguments plus all thei
r descendants |
| 74 external void prepend(@nonnull List</*nonnull*/ ChildNode> nodes); // O(N) in
number of arguments plus all their descendants | 79 external void appendSingle(Node nodes); // O(N) in number of descandants |
| 75 external void replaceChildrenWith(@nonnull List</*nonnull*/ ChildNode> nodes);
// O(N) in number of descendants plus arguments plus all their descendants | 80 external void prepend(List nodes); // O(N) in number of arguments plus all the
ir descendants |
| 81 external void replaceChildrenWith(List nodes); // O(N) in number of descendant
s plus arguments plus all their descendants |
| 82 // nodes must be String, Text, or Element |
| 76 } | 83 } |
| 77 | 84 |
| 78 class Attr { | 85 class Attr { |
| 79 const Attr (this.name, [this.value = '']); // O(1) | 86 const Attr (this.name, [this.value = '']); // O(1) |
| 80 final String name; // O(1) | 87 final String name; // O(1) |
| 81 final String value; // O(1) | 88 final String value; // O(1) |
| 82 } | 89 } |
| 83 | 90 |
| 84 // @tagname annotation for registering elements | 91 // @tagname annotation for registering elements |
| 85 // only useful when placed on classes that inherit from Element | 92 // only useful when placed on classes that inherit from Element |
| 86 class tagname extends AutomaticMetadata { | 93 class tagname extends AutomaticMetadata { |
| 87 const tagname(this.name); | 94 const tagname(this.name); |
| 88 @nonnull final String name; | 95 final String name; |
| 89 void init(DeclarationMirror target, Module module) { | 96 void init(DeclarationMirror target, Module module) { |
| 90 assert(target is ClassMirror); | 97 assert(target is ClassMirror); |
| 91 if (!target.isSubclassOf(reflectClass(Element))) | 98 if (!target.isSubclassOf(reflectClass(Element))) |
| 92 throw Error('@tagname can only be used on descendants of Element'); | 99 throw Error('@tagname can only be used on descendants of Element'); |
| 93 module.registerElement(name, (target as ClassMirror).reflectedType); | 100 module.registerElement(name, (target as ClassMirror).reflectedType); |
| 94 } | 101 } |
| 95 } | 102 } |
| 96 | 103 |
| 97 abstract class FindRoot { } | 104 abstract class Element extends ParentNode with Node { |
| 98 | 105 external Element({Map<String, String> attributes: null, |
| 99 abstract class Element extends ParentNode with ChildNode implements FindRoot { | 106 List children: null, |
| 100 external Element({Map</*@nonnull*/ String, /*@nonnull*/ String> attributes: nu
ll, | 107 Module hostModule: null}); // O(M+N), M = number of attribute
s, N = number of children nodes plus all their descendants |
| 101 List</*nonnull*/ ChildNode> nodes: null, | |
| 102 Module hostModule: null}); // O(M+N), M = number of attribute
s, N = number of nodes plus all their descendants | |
| 103 // initialises the internal attributes table | 108 // initialises the internal attributes table |
| 104 // appends the given child nodes | 109 // appends the given children nodes |
| 110 // children must be String, Text, or Element |
| 105 // if this.needsShadow, creates a shadow tree | 111 // if this.needsShadow, creates a shadow tree |
| 106 | 112 |
| 107 @nonnull String get tagName { // O(N) in number of annotations on the class | 113 String get tagName { // O(N) in number of annotations on the class |
| 108 // throws a StateError if the class doesn't have an @tagname annotation | 114 // throws a StateError if the class doesn't have an @tagname annotation |
| 109 var tagnameClass = reflectClass(tagname); | 115 var tagnameClass = reflectClass(tagname); |
| 110 return (reflectClass(this.runtimeType).metadata.singleWhere((mirror) => mirr
or.type == tagnameClass).reflectee as tagname).value; | 116 return (reflectClass(this.runtimeType).metadata.singleWhere((mirror) => mirr
or.type == tagnameClass).reflectee as tagname).value; |
| 111 } | 117 } |
| 112 | 118 |
| 113 @nonnull external bool hasAttribute(@nonnull String name); // O(N) in number o
f attributes | 119 external bool hasAttribute(String name); // O(N) in number of attributes |
| 114 @nonnull external String getAttribute(@nonnull String name); // O(N) in number
of attributes | 120 external String getAttribute(String name); // O(N) in number of attributes |
| 115 external void setAttribute(@nonnull String name, [@nonnull String value = ''])
; // O(N) in number of attributes | 121 external void setAttribute(String name, [String value = '']); // O(N) in numbe
r of attributes |
| 116 external void removeAttribute(@nonnull String name); // O(N) in number of attr
ibutes | 122 external void removeAttribute(String name); // O(N) in number of attributes |
| 123 // calling setAttribute() with a null value removes the attribute |
| 124 // (calling it without a value sets it to the empty string) |
| 117 | 125 |
| 118 // Returns a new Array and new Attr instances every time. | 126 // Returns a new Array and new Attr instances every time. |
| 119 @nonnull external List<Attr> getAttributes(); // O(N) in number of attributes | 127 external List<Attr> getAttributes(); // O(N) in number of attributes |
| 120 | 128 |
| 121 get bool needsShadow => false; // O(1) | 129 get bool needsShadow => false; // O(1) |
| 122 external ShadowRoot get shadowRoot; // O(1) | 130 external Root get shadowRoot; // O(1) |
| 123 // returns the shadow root | 131 // returns the shadow root |
| 124 // TODO(ianh): Should this be mutable? It would help explain how it gets set..
. | 132 // TODO(ianh): Should this be mutable? It would help explain how it gets set..
. |
| 125 | 133 |
| 126 void endTagParsedCallback() { } | 134 void endTagParsedCallback() { } |
| 127 void attributeChangeCallback(String name, String oldValue, String newValue) {
} | 135 void attributeChangeCallback(String name, String oldValue, String newValue) {
} |
| 128 // name will never be null when this is called by sky | 136 // name will never be null when this is called by sky |
| 129 | 137 |
| 130 // TODO(ianh): does a node ever need to know when it's been redistributed? | 138 // TODO(ianh): does a node ever need to know when it's been redistributed? |
| 131 | 139 |
| 132 @override | 140 @override |
| 133 Type getLayoutManager() { // O(1) | 141 Type getLayoutManager() { // O(1) |
| 134 if (renderNode) | 142 if (renderNode) |
| 135 return renderNode.getProperty(phDisplay); | 143 return renderNode.getProperty(phDisplay); |
| 136 return super.getLayoutManager(); | 144 return super.getLayoutManager(); |
| 137 } | 145 } |
| 138 } | 146 } |
| 139 | 147 |
| 140 class Text extends Node with ChildNode { | 148 class Text extends Node with Node { |
| 141 external Text([@nonnull String value = '']); // O(1) | 149 external Text([String value = '']); // O(1) |
| 142 | 150 |
| 143 @nonnull external String get value; // O(1) | 151 external String get value; // O(1) |
| 144 external void set (@nonnull String value); // O(1) | 152 external void set (String value); // O(1) |
| 145 | 153 |
| 146 void valueChangeCallback(@nonnull String oldValue, @nonnull String newValue) {
} | 154 void valueChangeCallback(String oldValue, String newValue) { } |
| 147 | 155 |
| 148 @override | 156 @override |
| 149 Type getLayoutManager() => TextLayoutManager; // O(1) | 157 Type getLayoutManager() => TextLayoutManager; // O(1) |
| 150 } | 158 } |
| 151 | 159 |
| 152 class DocumentFragment extends ParentNode implements FindRoot { | 160 class Fragment extends ParentNode { |
| 153 DocumentFragment([List</*nonnull*/ ChildNode> nodes = null]); // O(N) in numbe
r of arguments plus all their descendants | 161 Fragment({List children}); // O(N) in number of arguments plus all their desce
ndants |
| 162 // children must be String, Text, or Element |
| 154 } | 163 } |
| 155 | 164 |
| 156 abstract class TreeScope extends ParentNode { | 165 class Root extends ParentNode { |
| 157 external Document get ownerDocument; // O(1) | 166 external Root ({List children, Element host}); // O(N) in number of children n
odes arguments plus all their descendants |
| 158 external TreeScope get parentScope; // O(1) | 167 // children must be String, Text, or Element |
| 168 |
| 169 final Element host; |
| 159 | 170 |
| 160 external Element findId(String id); // O(1) | 171 external Element findId(String id); // O(1) |
| 161 // throws if id is null | 172 // throws if id is null |
| 162 } | 173 } |
| 163 | 174 |
| 164 class ShadowRoot extends TreeScope implements FindRoot { | 175 class ApplicationRoot extends Root { |
| 165 ShadowRoot([this._host]); // O(1) | 176 external ApplicationRoot ({List children}) : Root(children: children); // O(N)
in number of children nodes arguments plus all their descendants |
| 166 // note that there is no way in the API to use a newly created ShadowRoot curr
ently | 177 // children must be String, Text, or Element |
| 167 | |
| 168 Element _host; | |
| 169 Element get host => _host; // O(1) | |
| 170 } | |
| 171 | |
| 172 class Document extends TreeScope implements FindRoot { | |
| 173 external Document ([List</*@nonnull*/ ChildNode> nodes = null]); // O(N) in nu
mber of arguments plus all their descendants | |
| 174 } | |
| 175 | |
| 176 class ApplicationDocument extends Document { | |
| 177 external ApplicationDocument ([List</*@nonnull*/ ChildNode> nodes = null]); //
O(N) in number of /nodes/ arguments plus all their descendants | |
| 178 | 178 |
| 179 @override | 179 @override |
| 180 Type getLayoutManager() => rootLayoutManager; // O(1) | 180 Type getLayoutManager() => rootLayoutManager; // O(1) |
| 181 } | 181 } |
| 182 | 182 |
| 183 Type rootLayoutManager = BlockLayoutManager; // O(1) | 183 Type rootLayoutManager = BlockLayoutManager; // O(1) |
| 184 | 184 |
| 185 | 185 |
| 186 // BUILT-IN ELEMENTS | 186 // BUILT-IN ELEMENTS |
| 187 | 187 |
| 188 @tagname('import') | 188 @tagname('import') |
| 189 class ImportElement extends Element { | 189 class ImportElement extends Element { |
| 190 ImportElement = Element; | 190 ImportElement = Element; |
| 191 | 191 |
| 192 @override | 192 @override |
| 193 Type getLayoutManager() => null; // O(1) | 193 Type getLayoutManager() => null; // O(1) |
| 194 } | 194 } |
| 195 | 195 |
| 196 @tagname('template') | 196 @tagname('template') |
| 197 class TemplateElement extends Element { | 197 class TemplateElement extends Element { |
| 198 TemplateElement = Element; | 198 TemplateElement = Element; |
| 199 | 199 |
| 200 // TODO(ianh): convert <template> to using a token stream instead of a Documen
tFragment | 200 // TODO(ianh): convert <template> to using a token stream instead of a Fragmen
t |
| 201 | 201 |
| 202 @nonnull external DocumentFragment get content; // O(1) | 202 external Fragment get content; // O(1) |
| 203 | 203 |
| 204 @override | 204 @override |
| 205 Type getLayoutManager() => null; // O(1) | 205 Type getLayoutManager() => null; // O(1) |
| 206 } | 206 } |
| 207 | 207 |
| 208 @tagname('script') | 208 @tagname('script') |
| 209 class ScriptElement extends Element { | 209 class ScriptElement extends Element { |
| 210 ScriptElement = Element; | 210 ScriptElement = Element; |
| 211 | 211 |
| 212 @override | 212 @override |
| 213 Type getLayoutManager() => null; // O(1) | 213 Type getLayoutManager() => null; // O(1) |
| 214 } | 214 } |
| 215 | 215 |
| 216 @tagname('style') | 216 @tagname('style') |
| 217 class StyleElement extends Element { | 217 class StyleElement extends Element { |
| 218 StyleElement = Element; | 218 StyleElement = Element; |
| 219 | 219 |
| 220 @nonnull external List</*@nonnull*/ Rule> getRules(); // O(N) in rules | 220 external List<Rule> getRules(); // O(N) in rules |
| 221 | 221 |
| 222 @override | 222 @override |
| 223 Type getLayoutManager() => null; // O(1) | 223 Type getLayoutManager() => null; // O(1) |
| 224 } | 224 } |
| 225 | 225 |
| 226 @tagname('content') | 226 @tagname('content') |
| 227 class ContentElement extends Element { | 227 class ContentElement extends Element { |
| 228 ContentElement = Element; | 228 ContentElement = Element; |
| 229 | 229 |
| 230 @nonnull external List</*@nonnull*/ Node> getDistributedNodes(); // O(N) in di
stributed nodes | 230 external List<Node> getDistributedNodes(); // O(N) in distributed nodes |
| 231 | 231 |
| 232 @override | 232 @override |
| 233 Type getLayoutManager() => null; // O(1) | 233 Type getLayoutManager() => null; // O(1) |
| 234 } | 234 } |
| 235 | 235 |
| 236 @tagname('img') | 236 @tagname('img') |
| 237 class ImgElement extends Element { | 237 class ImgElement extends Element { |
| 238 ImgElement = Element; | 238 ImgElement = Element; |
| 239 | 239 |
| 240 @override | 240 @override |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 } | 278 } |
| 279 | 279 |
| 280 class _ErrorElement extends Element { | 280 class _ErrorElement extends Element { |
| 281 _ErrorElement._create(); | 281 _ErrorElement._create(); |
| 282 | 282 |
| 283 @override | 283 @override |
| 284 Type getLayoutManager() => _ErrorElementLayoutManager; // O(1) | 284 Type getLayoutManager() => _ErrorElementLayoutManager; // O(1) |
| 285 } | 285 } |
| 286 | 286 |
| 287 class SelectorQuery { | 287 class SelectorQuery { |
| 288 external SelectorQuery(@nonnull String selector); // O(F()) where F() is the c
omplexity of the selector | 288 external SelectorQuery(String selector); // O(F()) where F() is the complexity
of the selector |
| 289 | 289 |
| 290 @nonnull external bool matches(@nonnull Element element); // O(F()) | 290 external bool matches(Element element); // O(F()) |
| 291 external Element find(@nonnull FindRoot root); // O(N*F())+O(M) where N is the
number of descendants and M the average depth of the tree | 291 external Element find(node root); // O(N*F())+O(M) where N is the number of de
scendants and M the average depth of the tree |
| 292 @nonnull external List</*@nonnull*/ Element> findAll(FindRoot root); // O(N*F(
))+O(N*M) where N is the number of descendants and M the average depth of the tr
ee | 292 external List<Element> findAll(Node root); // O(N*F())+O(N*M) where N is the n
umber of descendants and M the average depth of the tree |
| 293 // find() and findAll() throw if the root is not one of the following: |
| 294 // - Element |
| 295 // - Fragment |
| 296 // - Root |
| 293 } | 297 } |
| 294 </script> | 298 </script> |
| 295 ``` | 299 ``` |
| OLD | NEW |