计算的 属性 查找似乎改变了 class/subtype
Computed property lookup seems to mutate a class/subtype
给出以下代码(从较大的程序中分离出来):
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
的原型,因此 dispatcher
中的 Object.prototype.toString
调用会产生不同的标签。
计算的 属性 查找 x[VALUE]
似乎是导致突变的决定性部分。我不知道这里发生了什么。也许...
- 问题很明显,但是看了一个小时的代码就没机会看了
- 突变是由
Sum
class
- 这是一个 chromium/chrome 相关的错误
据我了解,Sum
声明了一个 class,随后的块作用域创建了一个引用副本,并将 class 名称与最终调用 [=47] 的函数重新绑定=] 与 new
,以便在调用端可以省略 new
。但是,我看不出这与突变有什么关系。
是的,这绝对是一个错误。我能写的最小复制案例是
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.
给出以下代码(从较大的程序中分离出来):
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
的原型,因此 dispatcher
中的 Object.prototype.toString
调用会产生不同的标签。
计算的 属性 查找 x[VALUE]
似乎是导致突变的决定性部分。我不知道这里发生了什么。也许...
- 问题很明显,但是看了一个小时的代码就没机会看了
- 突变是由
Sum
class - 这是一个 chromium/chrome 相关的错误
据我了解,Sum
声明了一个 class,随后的块作用域创建了一个引用副本,并将 class 名称与最终调用 [=47] 的函数重新绑定=] 与 new
,以便在调用端可以省略 new
。但是,我看不出这与突变有什么关系。
是的,这绝对是一个错误。我能写的最小复制案例是
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.