| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- export function scope(node) {
- return mergeProxies(closestDataStack(node))
- }
- export function addScopeToNode(node, data, referenceNode) {
- node._x_dataStack = [data, ...closestDataStack(referenceNode || node)]
- return () => {
- node._x_dataStack = node._x_dataStack.filter(i => i !== data)
- }
- }
- export function hasScope(node) {
- return !! node._x_dataStack
- }
- export function closestDataStack(node) {
- if (node._x_dataStack) return node._x_dataStack
- if (typeof ShadowRoot === 'function' && node instanceof ShadowRoot) {
- return closestDataStack(node.host)
- }
- if (! node.parentNode) {
- return []
- }
- return closestDataStack(node.parentNode)
- }
- export function closestDataProxy(el) {
- return mergeProxies(closestDataStack(el))
- }
- export function mergeProxies(objects) {
- let thisProxy = new Proxy({}, {
- ownKeys: () => {
- return Array.from(new Set(objects.flatMap(i => Object.keys(i))))
- },
- has: (target, name) => {
- return objects.some(obj => obj.hasOwnProperty(name))
- },
- get: (target, name) => {
- return (objects.find(obj => {
- if (obj.hasOwnProperty(name)) {
- let descriptor = Object.getOwnPropertyDescriptor(obj, name)
- // If we already bound this getter, don't rebind.
- if ((descriptor.get && descriptor.get._x_alreadyBound) || (descriptor.set && descriptor.set._x_alreadyBound)) {
- return true
- }
- // Properly bind getters and setters to this wrapper Proxy.
- if ((descriptor.get || descriptor.set) && descriptor.enumerable) {
- // Only bind user-defined getters, not our magic properties.
- let getter = descriptor.get
- let setter = descriptor.set
- let property = descriptor
- getter = getter && getter.bind(thisProxy)
- setter = setter && setter.bind(thisProxy)
- if (getter) getter._x_alreadyBound = true
- if (setter) setter._x_alreadyBound = true
- Object.defineProperty(obj, name, {
- ...property,
- get: getter,
- set: setter,
- })
- }
- return true
- }
- return false
- }) || {})[name]
- },
- set: (target, name, value) => {
- let closestObjectWithKey = objects.find(obj => obj.hasOwnProperty(name))
- if (closestObjectWithKey) {
- closestObjectWithKey[name] = value
- } else {
- objects[objects.length - 1][name] = value
- }
- return true
- },
- })
- return thisProxy
- }
|