Home > Back-end >  Uncaught TypeError: proxy set handler returned false for property '"length"'
Uncaught TypeError: proxy set handler returned false for property '"length"'

Time:05-24

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)
  }
}
  • Related