function IsIntlService(c) { returntypeof c === "function" &&
c.hasOwnProperty("prototype") &&
c.prototype.hasOwnProperty("resolvedOptions");
}
function IsObject(o) { return Object(o) === o;
}
function IsPrimitive(o) { return Object(o) !== o;
}
function intlObjects(ctor) {
let args = []; if (ctor === Intl.DisplayNames) { // Intl.DisplayNames can't be constructed without any arguments.
args = [undefined, {type: "language"}];
}
return [ // Instance of an Intl constructor. new ctor(...args),
// Instance of a subclassed Intl constructor. newclassextends ctor {}(...args),
// Intl object not inheriting from its default prototype.
Object.setPrototypeOf(new ctor(...args), Object.prototype),
];
}
function thisValues(C) { const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
// Test Intl.NumberFormat.prototype methods. for (let {function: numberFormatFunction, unwrap} of numberFormatFunctions) { // Test a TypeError is thrown when the this-value isn't an initialized // Intl.NumberFormat instance. for (let thisValue of thisValues(Intl.NumberFormat)) {
assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError);
}
// And test no error is thrown for initialized Intl.NumberFormat instances. for (let thisValue of intlObjects(Intl.NumberFormat)) {
numberFormatFunction.call(thisValue);
}
// Manually add [[FallbackSymbol]] to objects and then repeat the tests from above. for (let thisValue of thisValues(Intl.NumberFormat)) {
assertThrowsInstanceOf(() => numberFormatFunction.call({
__proto__: Intl.NumberFormat.prototype,
[intlFallbackSymbol]: thisValue,
}), TypeError);
}
for (let thisValue of intlObjects(Intl.NumberFormat)) {
let obj = {
__proto__: Intl.NumberFormat.prototype,
[intlFallbackSymbol]: thisValue,
}; if (unwrap) {
numberFormatFunction.call(obj);
} else {
assertThrowsInstanceOf(() => numberFormatFunction.call(obj), TypeError);
}
}
// Ensure [[FallbackSymbol]] isn't retrieved for Intl.NumberFormat instances. for (let thisValue of intlObjects(Intl.NumberFormat)) {
Object.defineProperty(thisValue, intlFallbackSymbol, {
get() { assertEq(false, true); }
});
numberFormatFunction.call(thisValue);
}
// Ensure [[FallbackSymbol]] is only retrieved for objects inheriting from Intl.NumberFormat.prototype. for (let thisValue of thisValues(Intl.NumberFormat).filter(IsObject)) { if (Intl.NumberFormat.prototype.isPrototypeOf(thisValue)) continue;
Object.defineProperty(thisValue, intlFallbackSymbol, {
get() { assertEq(false, true); }
});
assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError);
}
// Repeat the test from above, but also change Intl.NumberFormat[@@hasInstance] // so it always returns |true|. for (let thisValue of thisValues(Intl.NumberFormat).filter(IsObject)) {
let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue);
let hasInstanceCalled = false, symbolGetterCalled = false;
Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
value() {
assertEq(hasInstanceCalled, false);
hasInstanceCalled = true; returntrue;
}, configurable: true
});
Object.defineProperty(thisValue, intlFallbackSymbol, {
get() {
assertEq(symbolGetterCalled, false);
symbolGetterCalled = true; returnnull;
}, configurable: true
});
delete Intl.NumberFormat[Symbol.hasInstance]; if (!isUndefinedOrNull) delete symbolHolder[intlFallbackSymbol];
}
}
// Test format() returns the correct result for objects initialized as Intl.NumberFormat instances.
{ // An actual Intl.NumberFormat instance.
let numberFormat = new Intl.NumberFormat();
// An object initialized as a NumberFormat instance.
let thisValue = Object.create(Intl.NumberFormat.prototype);
Intl.NumberFormat.call(thisValue);
// Object with [[FallbackSymbol]] set to NumberFormat instance.
let fakeObj = {
__proto__: Intl.NumberFormat.prototype,
[intlFallbackSymbol]: numberFormat,
};
for (let number of [0, 1, 1.5, Infinity, NaN]) {
let expected = numberFormat.format(number);
assertEq(thisValue.format(number), expected);
assertEq(thisValue[intlFallbackSymbol].format(number), expected);
assertEq(fakeObj.format(number), expected);
}
}
// Ensure formatToParts() doesn't use the fallback semantics.
{
let formatToParts = Intl.NumberFormat.prototype.formatToParts;
// An object initialized as a NumberFormat instance.
let thisValue = Object.create(Intl.NumberFormat.prototype);
Intl.NumberFormat.call(thisValue);
assertThrowsInstanceOf(() => formatToParts.call(thisValue), TypeError);
// Object with [[FallbackSymbol]] set to NumberFormat instance.
let fakeObj = {
__proto__: Intl.NumberFormat.prototype,
[intlFallbackSymbol]: new Intl.NumberFormat(),
};
assertThrowsInstanceOf(() => formatToParts.call(fakeObj), TypeError);
}
// Test resolvedOptions() returns the same results.
{ // An actual Intl.NumberFormat instance.
let numberFormat = new Intl.NumberFormat();
// An object initialized as a NumberFormat instance.
let thisValue = Object.create(Intl.NumberFormat.prototype);
Intl.NumberFormat.call(thisValue);
// Object with [[FallbackSymbol]] set to NumberFormat instance.
let fakeObj = {
__proto__: Intl.NumberFormat.prototype,
[intlFallbackSymbol]: numberFormat,
};
function assertEqOptions(actual, expected) {
actual = Object.entries(actual);
expected = Object.entries(expected);
assertEq(actual.length, expected.length, "options count mismatch"); for (var i = 0; i < expected.length; i++) {
assertEq(actual[i][0], expected[i][0], "key mismatch at " + i);
assertEq(actual[i][1], expected[i][1], "value mismatch at " + i);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.