I started testing the following proxy pattern, and got the titled error when using the .splice()
method.
class A extends Array {
constructor(...x) {
super(...x)
return new Proxy(this, {
set(o,p,v) {
console.log("set: ",o,p,v)
return o[p] = v
},
get(o,p) {
console.log("get: ",o,p)
return o[p]
},
})
}
}
const a = new A(1,2,3)
a.splice(1,0,"a")
Producing the following console output:
get: Array(3) [ 1, 2, 3 ] splice
get: Array(3) [ 1, 2, 3 ] length
get: Array(3) [ 1, 2, 3 ] constructor
set: Array [] length 0
Uncaught TypeError: proxy set handler returned false for property '"length"'
InnerModuleEvaluation self-hosted:2411
InnerModuleEvaluation self-hosted:2411
evaluation self-hosted:2358
Does anyone know what internal specifics I am missing that requires set
to return true
in the case of using .splice()
?
CodePudding user response:
It's not just the splice
method, this happens in all strict mode code when attempting to set a non-writable property. The falsy return value of the trap handler indicates that setting the property failed.
"use strict";
const a = new Proxy([1,2,3], {
set(o,p,v) {
console.log("set: ",o,p,v)
return o[p] = v
},
});
a.length = 0; // TypeError: 'set' on proxy: trap returned falsish for property 'length'
In your case, the problem is that you return the new property value, while a set
trap ought to return a boolean. So it "works" when you set the a.length = 5
, but not for a.length = 0
. Fix this by using the default implementation provided by the Reflect
object for the trap, if all you want is to log and not actually intercept the assignment, and do not forget the receiver parameter:
const handler = {
set(o,p,v,r) {
console.log("set: ",o,p,v)
return Reflect.set(o,p,v,r);
},
get(o,p,r) {
console.log("get: ",o,p)
return Reflect.get(o,p,r);
},
}
class A extends Array {
constructor(...x) {
super(...x)
return new Proxy(this, handler)
}
}