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