I wanted to check what does a library do with video element I pass to it so I naively did this:
cosnt videoElement = new Proxy(document.querySelector('video'), {
get(target, key) {
const name = typeof key === 'symbol'? key.toString() : key;
console.info(`Accessing video.${ name }`)
return target[key];
}
});
But I got an error:
TypeError: Failed to execute 'contains' on 'Node': parameter 1 is not of type 'Node'.
Is there a way to make this work?
EDIT: I have gained some knowledge, with it I updated my proxy as fallow:
cosnt videoElement = document.querySelector('video');
cosnt proxyElement = new Proxy(videoElement , {
get(target, key) {
if (key == '___element___') {
return video;
}
const name = typeof key === 'symbol'? key.toString() : key;
console.info(`Accessing video.${ name }`);
const value = video[key];
if (value instanceof Function) {
return video[key].bind(video);
} else {
return video[key];
}
},
set(target, key, value) {
const name = typeof key === 'symbol'? key.toString() : key;
console.info(`Writing video.${ name } = ${ value }`);
video[key] = value;
return true;
}
});
It is meant for debugging, so I edited the compiled code and replaced all DOM manipulation references with element.___element___
.
Next I found out that there seem to be problems with calling functions trough proxy, so I added the .bind(video)
part.
And finally setting values was throwing. So I had to replace target with direct video reference (as matter of fact, I replaced all target references with video, just to be sure), that made it work... I am not sure why or how, but it did.
Questions are:
document.body.contains(myProxyElement)
part)Bonus: playground
const video = document.querySelector('video');
const proxy = new Proxy(video, {
get(target, key) {
console.log(`Getting video.${typeof key === 'symbol'? key.toString() : key}`);
const value = video[key];
if (value instanceof Function) {
return value.bind(video);
} else {
return value;
}
},
set(target, key, value) {
console.log(`Setting video.${typeof key === 'symbol'? key.toString() : key} =`, value);
video[key] = value;
return true;
}
});
proxy.muted = true;
proxy.play();
proxy.controls = true;
try {
console.log(document.body.contains(proxy));
} catch (e) {
console.error('DOM operation failed', e);
}
video { max-width: 100%; }
<video src="//vjs.zencdn.net/v/oceans.mp4">
As already mentioned in the comments, the Proxy
object will not get automatically casted into Node
when calling document.body.contains(proxy)
.
Therefore, you can i.e. set a specific key that will return the proxy's target:
const video = document.querySelector('video');
const proxy = new Proxy(video, {
get(target, key) {
const value = video[key];
if (value instanceof Function) {
return value.bind(video);
} else if (key == 'target') {
return target;
} else {
return value;
}
},
set(target, key, value) {
target[key] = value;
return true;
}
});
And then you can do:
console.log(document.body.contains(proxy.target));
Edit:
Is this really how it is supposed to be? (the document.body.contains(myProxyElement) part):
Yes, I do not see any other way how to do this.
Setting values to video element throwing when setting inside proxy seemed weird, is it a bug? (3rd point, kinda second too, I suppose it is connected):
Since I am not able to reproduce this issue, it is hard to say. Maybe try to replace new Proxy(video, ...
with new Proxy({}, ...
and then set the video as proxy.video = video
(you will have to also update the logic in the get
and set
) and see how that behaves?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With