1# Custom Elements
2
3Custom elements let authors create their own elements, with their own
4methods, behavior, and attribute handling. Custom elements shipped in
5M33. We colloquially refer to that version as "v0."
6
7Contact Dominic Cooney
8([dominicc@chromium.org](mailto:dominicc@chromium.org)) with
9questions.
10
11### Code Location
12
13The custom elements implementation is split between core/dom and
14bindings/core/v8.
15
16## Design
17
18### Some Important Classes
19
20###### CustomElementDefinition
21
22The definition of one ‘class’ of element. This type is
23abstract to permit different kinds of definitions, although at the
24moment there is only one: ScriptCustomElementDefinition.
25
26ScriptCustomElementDefinition is linked to its constructor by an ID
27number. The ID number is stored in a map, keyed by constructor, in a
28hidden value of the CustomElementRegistry wrapper. The ID is an index
29into a list of definitions stored in V8PerContextData.
30
31###### CustomElementDescriptor
32
33A tuple of local name, and custom element name. For autonomous custom
34elements, these strings are the same; for customized built-in elements
35these strings will be different. In that case, the local name is the
36element's tag name and the custom element name is related to the value
37of the “is” attribute.
38
39###### CustomElementRegistry
40
41Implements the `window.customElements` property. This maintains the
42set of registered names. The wrapper of this object is used by
43ScriptCustomElementDefinition to cache state in V8.
44
45###### V8HTMLElement Constructor
46
47The `HTMLElement` interface constructor. When a custom element is
48created from JavaScript all we have to go on is the constructor (in
49`new.target`); this uses ScriptCustomElementDefinition's state to find
50the definition to use.
51
52### Memory Management
53
54Once defined, custom element constructors and prototypes have to be
55kept around indefinitely because they could be created in future by
56the parser. On the other hand, we must not leak when a window can no
57longer run script.
58
59We use a V8HiddenValue on the CustomElementRegistry wrapper which
60points to a map that keeps constructors and prototypes alive. See
61ScriptCustomElementDefinition.
62
63## Style Guide
64
65In comments and prose, write custom elements, not Custom Elements, to
66match the HTML standard.
67
68Prefix type names with CustomElement (singular).
69
70## Testing
71
72Custom elements have small C++ unit tests and medium
73“layout” tests.
74
75###### C++ Unit Tests
76
77These are in third_party/blink/renderer/core/dom/*_test.cc and are
78built as part of the blink_unittests target. The test names start
79with CustomElement so you can run them with:
80
81    $ out/Debug/blink_unittests --gtest_filter=CustomElement*
82
83###### Web Tests
84
85The custom element web tests are generally in
86third_party/blink/web_tests/custom-elements.
87
88All custom elements web tests use the [web-platform-tests
89harness](https://web-platform-tests.org/) and follow its style. The
90WPT style is not very prescriptive, so be consistent with other custom
91elements tests.
92
93When naming tests, use short names describing what the test is doing.
94Avoid articles. For example, "HTMLElement constructor, invoke". When
95writing assertion messages, start with a lowercase letter (unless the
96word is a proper noun), use normal grammar and articles, and include
97the word “should” to leave no doubt whate the expected
98behavior is.
99
100###### Spec Tests
101
102These will be upstreamed to WPT, replacing [the tests for
103registerElement](https://github.com/web-platform-tests/wpt/tree/master/custom-elements)
104we contributed earlier. To facilitate that, follow these guidelines:
105
106* Keep the tests together in the `spec` directory.
107* Only test things required in a spec. The test should permit other
108  possible reasonable implementations.
109* Avoid using Blink-specific test mechanisms. Don't use
110  `window.internals` for example.
111
112###### Implementation Tests
113
114These are for testing Blink-specific details like object lifetimes,
115crash regressions, interaction with registerElement and HTML Imports,
116and so on.
117
118These tests can use Blink-specific testing hooks like
119`window.internals` and `testRunner`.
120
121###### Web Exposed Tests
122
123Finally there are /TODO(dominicc): should be/ tests in
124webexposed/custom-elements which assert that we HAVE NOT shipped
125`window.customElements.define` yet. These tests need to be updated
126when we ship `window.customElements.define` or remove
127`registerElement`.
128
129## “V0” Deprecation
130
131The plan is to:
132
1331. Implement the ‘new’ kind of custom elements separately
134   from the existing implementation. We have renamed all of old
135   implementation so that the type names start with V0; it should be
136   easy to tell whether you are looking at the old or new
137   implementation.
1381. When we ship `window.customElements.define`, add a deprecation
139   warning to `document.registerElement` directing authors to use the
140   new API.
1411. Change the ‘web’ API to use the new kind of custom
142   elements. That API is used by extensions to implement the webview
143   tag and things like that.
1441. When [the use counter for
145   registerElement](https://www.chromestatus.com/metrics/feature/timeline/popularity/457)
146   drops below 0.03% of page loads, remove the old implementation. We
147   may remove it even sooner, if we have evidence that sites are using
148   feature detection correctly.
149
150## References
151
152These have links to the parts of the DOM and HTML specs which define
153custom elements:
154
155* [WHATWG DOM Wiki: Custom Elements](https://github.com/whatwg/dom/wiki#custom-elements)
156* [WHATWG HTML Wiki: Custom Elements](https://github.com/whatwg/html/wiki#custom-elements)
157