tree: fab5c4f7ddd6c3e8b9c9f0428c9aa458bddafe51 [path history] [tgz]
  1. README.md
  2. ce_reactions_scope.cc
  3. ce_reactions_scope.h
  4. custom_element.cc
  5. custom_element.h
  6. custom_element_definition.cc
  7. custom_element_definition.h
  8. custom_element_definition_builder.h
  9. custom_element_definition_test.cc
  10. custom_element_descriptor.h
  11. custom_element_descriptor_hash.h
  12. custom_element_descriptor_test.cc
  13. custom_element_reaction.cc
  14. custom_element_reaction.h
  15. custom_element_reaction_factory.cc
  16. custom_element_reaction_factory.h
  17. custom_element_reaction_queue.cc
  18. custom_element_reaction_queue.h
  19. custom_element_reaction_queue_test.cc
  20. custom_element_reaction_stack.cc
  21. custom_element_reaction_stack.h
  22. custom_element_reaction_stack_test.cc
  23. custom_element_reaction_test_helpers.h
  24. custom_element_registry.cc
  25. custom_element_registry.h
  26. custom_element_registry.idl
  27. custom_element_registry_test.cc
  28. custom_element_test.cc
  29. custom_element_test_helpers.cc
  30. custom_element_test_helpers.h
  31. custom_element_upgrade_sorter.cc
  32. custom_element_upgrade_sorter.h
  33. custom_element_upgrade_sorter_test.cc
  34. element_internals.cc
  35. element_internals.h
  36. element_internals.idl
  37. v0_custom_element.cc
  38. v0_custom_element.h
  39. v0_custom_element_async_import_microtask_queue.cc
  40. v0_custom_element_async_import_microtask_queue.h
  41. v0_custom_element_callback_invocation.cc
  42. v0_custom_element_callback_invocation.h
  43. v0_custom_element_callback_queue.cc
  44. v0_custom_element_callback_queue.h
  45. v0_custom_element_definition.cc
  46. v0_custom_element_definition.h
  47. v0_custom_element_descriptor.h
  48. v0_custom_element_descriptor_hash.h
  49. v0_custom_element_exception.cc
  50. v0_custom_element_exception.h
  51. v0_custom_element_lifecycle_callbacks.h
  52. v0_custom_element_microtask_dispatcher.cc
  53. v0_custom_element_microtask_dispatcher.h
  54. v0_custom_element_microtask_import_step.cc
  55. v0_custom_element_microtask_import_step.h
  56. v0_custom_element_microtask_queue_base.cc
  57. v0_custom_element_microtask_queue_base.h
  58. v0_custom_element_microtask_resolution_step.cc
  59. v0_custom_element_microtask_resolution_step.h
  60. v0_custom_element_microtask_run_queue.cc
  61. v0_custom_element_microtask_run_queue.h
  62. v0_custom_element_microtask_step.h
  63. v0_custom_element_observer.cc
  64. v0_custom_element_observer.h
  65. v0_custom_element_processing_stack.cc
  66. v0_custom_element_processing_stack.h
  67. v0_custom_element_processing_step.h
  68. v0_custom_element_registration_context.cc
  69. v0_custom_element_registration_context.h
  70. v0_custom_element_registry.cc
  71. v0_custom_element_registry.h
  72. v0_custom_element_scheduler.cc
  73. v0_custom_element_scheduler.h
  74. v0_custom_element_sync_microtask_queue.cc
  75. v0_custom_element_sync_microtask_queue.h
  76. v0_custom_element_upgrade_candidate_map.cc
  77. v0_custom_element_upgrade_candidate_map.h
  78. validity_state_flags.idl
third_party/blink/renderer/core/html/custom/README.md

Custom Elements

Custom elements let authors create their own elements, with their own methods, behavior, and attribute handling. Custom elements shipped in M33. We colloquially refer to that version as “v0.”

Contact Dominic Cooney (dominicc@chromium.org) with questions.

Code Location

The custom elements implementation is split between core/dom and bindings/core/v8.

Design

Some Important Classes

CustomElementDefinition

The definition of one ‘class’ of element. This type is abstract to permit different kinds of definitions, although at the moment there is only one: ScriptCustomElementDefinition.

ScriptCustomElementDefinition is linked to its constructor by an ID number. The ID number is stored in a map, keyed by constructor, in a hidden value of the CustomElementRegistry wrapper. The ID is an index into a list of definitions stored in V8PerContextData.

CustomElementDescriptor

A tuple of local name, and custom element name. For autonomous custom elements, these strings are the same; for customized built-in elements these strings will be different. In that case, the local name is the element's tag name and the custom element name is related to the value of the “is” attribute.

CustomElementRegistry

Implements the window.customElements property. This maintains the set of registered names. The wrapper of this object is used by ScriptCustomElementDefinition to cache state in V8.

V8HTMLElement Constructor

The HTMLElement interface constructor. When a custom element is created from JavaScript all we have to go on is the constructor (in new.target); this uses ScriptCustomElementDefinition's state to find the definition to use.

Memory Management

Once defined, custom element constructors and prototypes have to be kept around indefinitely because they could be created in future by the parser. On the other hand, we must not leak when a window can no longer run script.

We use a V8HiddenValue on the CustomElementRegistry wrapper which points to a map that keeps constructors and prototypes alive. See ScriptCustomElementDefinition.

Style Guide

In comments and prose, write custom elements, not Custom Elements, to match the HTML standard.

Prefix type names with CustomElement (singular).

Testing

Custom elements have small C++ unit tests and medium “layout” tests.

C++ Unit Tests

These are in third_party/blink/renderer/core/dom/*_test.cc and are built as part of the webkit_unit_tests target. The test names start with CustomElement so you can run them with:

$ out/Debug/webkit_unit_tests --gtest_filter=CustomElement*
Web Tests

The custom element web tests are generally in third_party/blink/web_tests/custom-elements.

All custom elements web tests use the web-platform-tests harness and follow its style. The WPT style is not very prescriptive, so be consistent with other custom elements tests.

When naming tests, use short names describing what the test is doing. Avoid articles. For example, “HTMLElement constructor, invoke”. When writing assertion messages, start with a lowercase letter (unless the word is a proper noun), use normal grammar and articles, and include the word “should” to leave no doubt whate the expected behavior is.

Spec Tests

These will be upstreamed to WPT, replacing the tests for registerElement we contributed earlier. To facilitate that, follow these guidelines:

  • Keep the tests together in the spec directory.
  • Only test things required in a spec. The test should permit other possible reasonable implementations.
  • Avoid using Blink-specific test mechanisms. Don't use window.internals for example.
Implementation Tests

These are for testing Blink-specific details like object lifetimes, crash regressions, interaction with registerElement and HTML Imports, and so on.

These tests can use Blink-specific testing hooks like window.internals and testRunner.

Web Exposed Tests

Finally there are /TODO(dominicc): should be/ tests in webexposed/custom-elements which assert that we HAVE NOT shipped window.customElements.define yet. These tests need to be updated when we ship window.customElements.define or remove registerElement.

“V0” Deprecation

The plan is to:

  1. Implement the ‘new’ kind of custom elements separately from the existing implementation. We have renamed all of old implementation so that the type names start with V0; it should be easy to tell whether you are looking at the old or new implementation.
  2. When we ship window.customElements.define, add a deprecation warning to document.registerElement directing authors to use the new API.
  3. Change the ‘web’ API to use the new kind of custom elements. That API is used by extensions to implement the webview tag and things like that.
  4. When the use counter for registerElement drops below 0.03% of page loads, remove the old implementation. We may remove it even sooner, if we have evidence that sites are using feature detection correctly.

References

These have links to the parts of the DOM and HTML specs which define custom elements: