Skip to content

Instantly share code, notes, and snippets.

@barneycarroll
Created February 25, 2021 15:08
Show Gist options
  • Save barneycarroll/08ad22c85f76c85bb3cb879d418472fe to your computer and use it in GitHub Desktop.
Save barneycarroll/08ad22c85f76c85bb3cb879d418472fe to your computer and use it in GitHub Desktop.
const noop = () => {}
const elementHandler = {
get: (element, key) => {
if(key === 'setAttribute')
return noop
if(key === 'style')
return {
setProperty : noop,
}
if(typeof element[key] === 'function')
return element[key].bind(element)
return Reflect.get(element, key)
},
}
const documentMethods = [
'createElement',
'createElementNS',
'createDocumentFragment',
'createTextNode',
]
.map(key => [key, document[key]])
const nodeMethods = [
'appendChild',
'insertBefore',
]
.map(key => [key, Node.prototype[key]])
export function mount(host, Component){
host.vnodes = []
return m.mount(host, {
view: () => m(Hydrator, {host}, m(Component))
})
}
export function render(host, children, callback){
if(!host.vnodes)
host.vnodes = []
return m.render(
host,
m(Hydrator, {host}, children),
callback,
)
}
function Hydrator(){
return {
view : v =>
v.children,
oninit : v => {
hijack(v.attrs.host)
},
oncreate: () => {
reinstate()
},
}
}
function hijack(host){
nodeMethods.forEach(([key, method]) => {
Node.prototype[key] = noop
})
const walker = document.createTreeWalker(host)
document.createDocumentFragment = () =>
walker.currentNode
document.createTextNode = input => {
let node = walker.nextNode()
if(node.nodeType !== node.TEXT_NODE)
node = walker.nextNode()
if(!input.length)
node.before(input)
else if(node.nodeValue.length > input.length)
node.splitText(input.length)
return node
}
document.createElement = document.createElementNS = () =>
new Proxy(walker.nextNode(), elementHandler)
elementHandler.set = (element, key, value) => {
if(key === 'textContent'){
debugger
walker.nextNode()
}
return value
}
}
function reinstate(){
Object.assign(document,
Object.fromEntries(documentMethods)
)
Object.assign(Node.prototype,
Object.fromEntries(nodeMethods)
)
delete elementHandler.set
elementHandler.get = (element, key) =>
typeof element[key] === 'function'
?
element[key].bind(element)
:
Reflect.get(element, key)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment