Skip to content

Commit 12250ef

Browse files
committed
feat: add more granular root on platforms with custom element (v1 or v0) support
1 parent 54d859d commit 12250ef

File tree

4 files changed

+78
-12
lines changed

4 files changed

+78
-12
lines changed

src/index.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
import { observe } from './observer'
2-
observe(document)
3-
41
export { default as component } from './component'
52
export { register as load } from './loaders'

src/registerRoot.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import setupDom from './setupDom'
2+
import cleanupDom from './cleanupDom'
3+
import { observe, unobserve } from './observer'
4+
5+
let documentObserved = false
6+
7+
export default function registerRoot (name, config) {
8+
if ('customElements' in window) {
9+
registerRootV1(name, config)
10+
} else if ('registerElement' in document) {
11+
registerRootV0(name, config)
12+
} else if (!documentObserved) {
13+
observe(document)
14+
documentObserved = true
15+
}
16+
}
17+
18+
function registerRootV1 (name, config) {
19+
const parentProto = getParentProto(config)
20+
const parentConstructor = getParentConstructor(config)
21+
22+
function RootElement () {
23+
return Reflect.construct(parentConstructor, [], RootElement)
24+
}
25+
const proto = RootElement.prototype
26+
proto.connectedCallback = attachedCallback
27+
proto.disconnectedCallback = detachedCallback
28+
Object.setPrototypeOf(proto, parentProto)
29+
Object.setPrototypeOf(RootElement, parentConstructor)
30+
customElements.define(name, RootElement, { extends: config.element })
31+
}
32+
33+
function registerRootV0 (name, config) {
34+
const parentProto = getParentProto(config)
35+
const proto = Object.create(parentProto)
36+
proto.attachedCallback = attachedCallback
37+
proto.detachedCallback = detachedCallback
38+
document.registerElement(name, { prototype: proto, extends: config.element })
39+
}
40+
41+
function getParentProto (config) {
42+
if (config.element) {
43+
return Object.getPrototypeOf(document.createElement(config.element))
44+
}
45+
return HTMLElement.prototype
46+
}
47+
48+
function getParentConstructor (config) {
49+
if (config.element) {
50+
return document.createElement(config.element).constructor
51+
}
52+
return HTMLElement
53+
}
54+
55+
function attachedCallback () {
56+
setupDom(this)
57+
observe(this)
58+
}
59+
60+
function detachedCallback () {
61+
cleanupDom(this)
62+
unobserve(this)
63+
}

src/registry.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import registerRoot from './registerRoot'
12
import setupDom from './setupDom'
23
import { run as runLoader } from './loaders'
34

@@ -10,7 +11,11 @@ export function register (name, config) {
1011
throw new Error('double registration')
1112
}
1213
registry.set(name, config)
13-
processRegistered(name, config)
14+
if (config.root) {
15+
registerRoot(name, config)
16+
} else {
17+
processRegistered(name, config)
18+
}
1419
}
1520

1621
function processRegistered (name, config) {
@@ -63,10 +68,10 @@ function upgradeElement (elem, config) {
6368
}
6469

6570
const originalCreateElement = document.createElement
66-
document.createElement = function createElement (name, is) {
71+
document.createElement = function createElement (name, config) {
6772
const element = originalCreateElement.call(document, name)
68-
if (is) {
69-
element.setAttribute('is', is)
73+
if (config && config.is) {
74+
element.setAttribute('is', config.is)
7075
}
7176
return element
7277
}

src/setupDom.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ export default function setupDom (node) {
1414
}
1515

1616
function shouldSetupDom (node, parent) {
17-
return (
18-
!node.$lifecycleStage &&
19-
((parent && parent.$lifecycleStage === 'attached' && parent.$isolate !== true) ||
20-
node.$root === node)
21-
)
17+
const validParent = (parent && parent.$lifecycleStage === 'attached' && parent.$isolate !== true)
18+
const isRoot = (node.$root === node)
19+
if (validParent && isRoot) {
20+
throw new Error('Nested root component.')
21+
}
22+
return (!node.$lifecycleStage && (validParent || isRoot))
2223
}
2324

2425
function setupNode (node, parent) {

0 commit comments

Comments
 (0)