Превышен максимальный размер стека вызовов при замене прототипа на ES6 Proxy - PullRequest
0 голосов
/ 24 января 2020

У меня есть декоратор класса машинописного текста

export function Profile(config: ProfilerConfig): ClassDecorator {
  return function <TFunction extends Function> (target: TFunction) {
    logToConsole = config.logToConsole || false;
    Object.setPrototypeOf(
      target.prototype,
      new Proxy(target.prototype , handler)
    );
  };
}

И я пытаюсь заменить прототип прокси целевого прототипа, и я получаю

ERROR RangeError: Maximum call stack size exceeded

Но я не видя любую видимую рекурсию. Когда я использую

target.prototype = new Proxy(target.prototype , handler)

, этого не происходит. Есть идеи?

Ответы [ 3 ]

1 голос
/ 24 января 2020

Максимальный стек вызовов здесь превышает:

Object.setPrototypeOf( target.prototype, new Proxy(target.prototype , handler) );

Давайте посмотрим, что здесь произошло: вы хотите добавить прокси к target.prototype. Я не уверен, если все в порядке, потому что то, что MDN говорит о цели прокси:

Целевой объект, который нужно обернуть прокси. Это может быть объект любого типа, включая собственный массив, функцию или даже другой прокси.

Но прототипом объекта является any sort of object, поэтому предположим, что вы можете это сделать.

Затем вы пытаетесь добавить прокси-прототип в качестве прототипа для прототипа цели (извините за это)). Обведенные кружком ссылки - это хороший способ получить превышение стека. Так и здесь.

Я думаю, что некоторые JS обходные пути с простым геттером вам очень помогут:

Object.defineProperty(proto, 'foo', get: function() { ...} );
1 голос
/ 24 января 2020

Это не указано c до target.prototype, это может произойти с любым объектом:

const o = {};
Object.setPrototypeOf(o, new Proxy(o, {}));
o.property;

Откуда вы ожидаете, что property придет. Это может быть либо собственное свойство o, либо его можно унаследовать от своего прототипа: прокси-сервер говорит, что это не собственное свойство, но его можно унаследовать от его прототипа ... Что приводит нас в рекурсивную кроличью нору get доступов. Вы можете попытаться предоставить ловушку для этого в вашем обработчике прокси и использовать его для регистрации или отладки рекурсии.

Обратите внимание, что Object.setPrototypeOf(o, o) выдает исключение, запрещающее циклические c цепочки наследования, но прокси обходит это.

1 голос
/ 24 января 2020
target.prototype = new Proxy(target.prototype , handler)

Устанавливает prototype из target для самого прокси.

Object.setPrototypeOf(
  target.prototype,
  new Proxy(target.prototype , handler)
);

Устанавливает prototype из target.prototype в качестве прокси target.prototype. Тогда у вас есть циклическая c зависимость: Object.getPrototypeOf(target.prototype) == proxy(target.prototype), поэтому, когда JavaScript пытается пройти цепочку прототипов, он застрянет в бесконечном l oop повторного вызова обработчика Proxy.


Я думаю, Object.setPrototypeOf() здесь не имеет никакого смысла в любом случае. Эта функция предназначена для установки прототипа instance . Похоже, вы пытаетесь установить прототип конструктора, то есть объект constructor.prototype, который будет наследоваться при создании экземпляра с помощью new constructor. Вам нужно назначить prototype конструктора напрямую, как в вашем первом фрагменте.

...