Похоже, что поиск по вычисляемому свойству изменяет класс / подтип - PullRequest
0 голосов
/ 28 апреля 2018

Дан следующий код (отсоединен от большой программы):

class Sum extends Number {} {
  const Sum_ = Sum;

  Sum = function(n) {
    return new Sum_(n);
  };

  Sum.prototype = Sum_.prototype;
}

Sum.prototype[Symbol.toStringTag] = "Sum";

const dispatcher = (...args) => args.map(arg => {
  const tag = Object.prototype.toString.call(arg);
  return tag.slice(tag.lastIndexOf(" ") + 1, -1);
}).join("/");

const VALUE = Symbol("VALUE");

const foo = x => y => {
  if (x && x[VALUE] && (VALUE in x))
    x = x(y);

  else if (y && y[VALUE] && (VALUE in y))
    y = y(x);

  return dispatcher(x, y);
};

const bar = x => y => {
  if (typeof x === "function" && (VALUE in x)) // deviates
    x = x(y);

  else if (typeof y === "function" && (VALUE in y)) // deviates
    y = y(x);

  return dispatcher(x, y);
};

console.log("bar:", bar(Sum(2)) (Sum(3))); // "Sum/Sum"
console.log("bar:", bar(Sum(2)) (Sum(3))); // "Sum/Sum"
console.log("foo:", foo(Sum(2)) (Sum(3))); // "Sum/Sum"
console.log("foo:", foo(Sum(2)) (Sum(3))); // "Number/Number"
console.log("bar:", bar(Sum(2)) (Sum(3))); // "Number/Number"

Как видите, foo / bar почти идентичны. Тем не менее, первый вызов foo как бы изменяет прототип Sum, так что вызов Object.prototype.toString в dispatcher приводит к другому тегу.

Поиск вычисленных свойств x[VALUE] представляется решающей частью, вызывающей мутацию. Я понятия не имею, что здесь происходит. Может быть ...

  • проблема очевидна, но после того, как я часами смотрю на код, у меня больше нет шансов его увидеть
  • мутация вызвана Sum классом
  • это ошибка, связанная с хромом / хромом

Насколько я понимаю, Sum объявляет класс, а следующая область видимости блока создает эталонную копию и повторно связывает имя класса с функцией, которая в конечном итоге вызывает класс с new, так что new можно опустить на вызывающая сторона. Однако я не вижу, как это связано с мутацией.

1 Ответ

0 голосов
/ 28 апреля 2018

Да, это определенно ошибка. Минимальный случай воспроизведения, который я мог бы написать, -

class Sum extends Number {}
Sum.prototype[Symbol.toStringTag] = "Sum";

const VALUE = Symbol("VALUE");

function foo(x) {
  console.log("x.value", x[VALUE]);
  return Object.prototype.toString.call(x);
}

console.log("foo:", foo(new Sum(2))); // "[object Sum]"
console.log("foo:", foo(new Sum(2))); // "[object Number]"

Понятия не имею, что здесь происходит, но я могу только рекомендовать не расширять нативные примитивные оболочки: -)
Я сделал файл https://bugs.chromium.org/p/v8/issues/detail?id=7706.

...