diff --git a/harness/temporalHelpers.js b/harness/temporalHelpers.js index 54214c424e..3875b71938 100644 --- a/harness/temporalHelpers.js +++ b/harness/temporalHelpers.js @@ -1635,6 +1635,44 @@ var TemporalHelpers = { return new SpringForwardFallBackTimeZone(); }, + /* + * timeZoneObserver: + * A custom calendar that behaves exactly like the UTC time zone but tracks + * calls to any of its methods, and Get/Has operations on its properties, by + * appending messages to an array. This is for the purpose of testing order of + * operations that are observable from user code. objectName is used in the + * log. methodOverrides is an optional object containing properties with the + * same name as Temporal.TimeZone methods. If the property value is a function + * it will be called with the proper arguments instead of the UTC method. + * Otherwise, the property value will be returned directly. + */ + timeZoneObserver(calls, objectName, methodOverrides = {}) { + const utc = new Temporal.TimeZone("UTC"); + const trackingMethods = {}; + // Automatically generate the methods + ["getOffsetNanosecondsFor", "getPossibleInstantsFor", "toString"].forEach((methodName) => { + trackingMethods[methodName] = function (...args) { + actual.push(`call ${formatPropertyName(methodName, objectName)}`); + if (methodName in methodOverrides) { + const value = methodOverrides[methodName]; + return typeof value === "function" ? value(...args) : value; + } + return utc[methodName](...args); + }; + }); + return new Proxy(trackingMethods, { + get(target, key, receiver) { + const result = Reflect.get(target, key, receiver); + actual.push(`get ${formatPropertyName(key, objectName)}`); + return result; + }, + has(target, key) { + actual.push(`has ${formatPropertyName(key, objectName)}`); + return Reflect.has(target, key); + }, + }); + }, + /* * Returns an object that will append logs of any Gets or Calls of its valueOf * or toString properties to the array calls. Both valueOf and toString will diff --git a/test/built-ins/Temporal/Instant/prototype/toString/timezone.js b/test/built-ins/Temporal/Instant/prototype/toString/timezone.js index d8dc6cf13a..acf2219485 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/timezone.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/timezone.js @@ -18,28 +18,12 @@ const expected = [ ]; const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456Z"); -const timeZone = new Proxy({ - name: "Custom/TimeZone", - - toString() { - actual.push("call timeZone.toString"); - return TemporalHelpers.toPrimitiveObserver(actual, "Custom/TimeZone", "name"); - }, - +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { + toString: TemporalHelpers.toPrimitiveObserver(actual, "Custom/TimeZone", "name"), getOffsetNanosecondsFor(instantArg) { - actual.push("call timeZone.getOffsetNanosecondsFor"); assert.sameValue(instantArg.epochNanoseconds, instant.epochNanoseconds); return -8735135801679; }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, }); Object.defineProperty(Temporal.TimeZone, "from", { diff --git a/test/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js b/test/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js index 0c2d574e16..be9aee8992 100644 --- a/test/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js +++ b/test/built-ins/Temporal/Instant/prototype/toZonedDateTime/plain-custom-timezone.js @@ -4,7 +4,7 @@ /*--- esid: sec-temporal.instant.prototype.tozoneddatetime description: TimeZone.getPlainDateTimeFor is not called -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -14,22 +14,9 @@ const expected = [ ]; const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z"); -const dateTime = Temporal.PlainDateTime.from("1963-07-02T12:00:00.987654321"); const calendar = Temporal.Calendar.from("iso8601"); -const timeZone = new Proxy({ - getPlainDateTimeFor() { - actual.push("call timeZone.getPlainDateTimeFor"); - return dateTime; - } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { + getPlainDateTimeFor: Temporal.PlainDateTime.from("1963-07-02T12:00:00.987654321"), }); const result = instant.toZonedDateTime({ timeZone, calendar }); diff --git a/test/built-ins/Temporal/Now/plainDate/toPlainDate-override.js b/test/built-ins/Temporal/Now/plainDate/toPlainDate-override.js index d63fd75556..3e76b5534b 100644 --- a/test/built-ins/Temporal/Now/plainDate/toPlainDate-override.js +++ b/test/built-ins/Temporal/Now/plainDate/toPlainDate-override.js @@ -4,7 +4,7 @@ /*--- esid: sec-temporal.now.plaindate description: PlainDateTime.toPlainDate is not observably called -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -24,21 +24,11 @@ Object.defineProperty(Temporal.PlainDateTime.prototype, "toPlainDate", { }, }); -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push("call timeZone.getOffsetNanosecondsFor"); assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); return 86399_999_999_999; }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, }); const result = Temporal.Now.plainDate("iso8601", timeZone); diff --git a/test/built-ins/Temporal/Now/plainDateTime/calendar-function.js b/test/built-ins/Temporal/Now/plainDateTime/calendar-function.js index 4a0045c25e..7147a27575 100644 --- a/test/built-ins/Temporal/Now/plainDateTime/calendar-function.js +++ b/test/built-ins/Temporal/Now/plainDateTime/calendar-function.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.now.plaindatetime description: Behavior when provided calendar value is a function -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [BigInt, Proxy, Temporal] ---*/ const actual = []; @@ -16,21 +16,10 @@ const expected = [ const calendar = function() {}; -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call timeZone.getOffsetNanosecondsFor'); return -Number(instant.epochNanoseconds % 86400000000000n); - } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; }, - - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - } }); Object.defineProperty(Temporal.Calendar, 'from', { diff --git a/test/built-ins/Temporal/Now/plainDateTime/timezone-object.js b/test/built-ins/Temporal/Now/plainDateTime/timezone-object.js index 33682891b8..384f361087 100644 --- a/test/built-ins/Temporal/Now/plainDateTime/timezone-object.js +++ b/test/built-ins/Temporal/Now/plainDateTime/timezone-object.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.now.plaindatetime description: Observable interactions with the provided timezone-like object -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [BigInt, Proxy, Temporal] ---*/ const actual = []; @@ -16,10 +16,8 @@ const expected = [ 'call nestedTimeZone.getOffsetNanosecondsFor' ]; -const nestedTimeZone = new Proxy({ +const nestedTimeZone = TemporalHelpers.timeZoneObserver(actual, "nestedTimeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -28,24 +26,10 @@ const nestedTimeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has nestedTimeZone.${String(property)}`); - return property in target; - }, - - get(target, property) { - actual.push(`get nestedTimeZone.${String(property)}`); - return target[property]; - } }); -const timeZone = new Proxy({ - timeZone: nestedTimeZone, - +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call timeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -54,17 +38,8 @@ const timeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - } }); +timeZone.timeZone = nestedTimeZone; Object.defineProperty(Temporal.TimeZone, 'from', { get() { diff --git a/test/built-ins/Temporal/Now/plainDateTime/timezone.js b/test/built-ins/Temporal/Now/plainDateTime/timezone.js index c290189922..c0fab52049 100644 --- a/test/built-ins/Temporal/Now/plainDateTime/timezone.js +++ b/test/built-ins/Temporal/Now/plainDateTime/timezone.js @@ -4,7 +4,7 @@ /*--- esid: sec-temporal.now.plaindatetime description: The value returned by TimeZone.getOffsetNanosecondsFor affects the result -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -15,21 +15,11 @@ const expected = [ "call timeZone.getOffsetNanosecondsFor", ]; -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push("call timeZone.getOffsetNanosecondsFor"); assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); return -Number(instant.epochNanoseconds % 86400_000_000_000n); }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, }); const calendar = Temporal.Calendar.from("iso8601"); diff --git a/test/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js b/test/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js index f81bd4ad15..5ef5745ba5 100644 --- a/test/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js +++ b/test/built-ins/Temporal/Now/plainDateTimeISO/timezone-object.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.now.plaindatetimeiso description: Observable interactions with the provided timezone-like object -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [BigInt, Proxy, Temporal] ---*/ const actual = []; @@ -16,10 +16,8 @@ const expected = [ 'call nestedTimeZone.getOffsetNanosecondsFor' ]; -const nestedTimeZone = new Proxy({ +const nestedTimeZone = TemporalHelpers.timeZoneObserver(actual, "nestedTimeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -28,24 +26,10 @@ const nestedTimeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has nestedTimeZone.${String(property)}`); - return property in target; - }, - - get(target, property) { - actual.push(`get nestedTimeZone.${String(property)}`); - return target[property]; - } }); -const timeZone = new Proxy({ - timeZone: nestedTimeZone, - +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call timeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -54,17 +38,8 @@ const timeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - } }); +timeZone.timeZone = nestedTimeZone; Object.defineProperty(Temporal.TimeZone, 'from', { get() { diff --git a/test/built-ins/Temporal/Now/plainTimeISO/timezone.js b/test/built-ins/Temporal/Now/plainTimeISO/timezone.js index 81894b2a6b..246bf54d8f 100644 --- a/test/built-ins/Temporal/Now/plainTimeISO/timezone.js +++ b/test/built-ins/Temporal/Now/plainTimeISO/timezone.js @@ -4,7 +4,7 @@ /*--- esid: sec-temporal.now.plaintimeiso description: The value returned by TimeZone.getOffsetNanosecondsFor affects the result -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -15,21 +15,11 @@ const expected = [ "call timeZone.getOffsetNanosecondsFor", ]; -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push("call timeZone.getOffsetNanosecondsFor"); assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); return -Number(instant.epochNanoseconds % 86400_000_000_000n); }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, }); const result = Temporal.Now.plainTimeISO(timeZone); diff --git a/test/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js b/test/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js index 03a856ae9a..b276ab7264 100644 --- a/test/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js +++ b/test/built-ins/Temporal/Now/plainTimeISO/toPlainTime-override.js @@ -4,7 +4,7 @@ /*--- esid: sec-temporal.now.plaintimeiso description: PlainDateTime.toPlainTime is not observably called -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -24,21 +24,11 @@ Object.defineProperty(Temporal.PlainDateTime.prototype, "toPlainTime", { }, }); -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push("call timeZone.getOffsetNanosecondsFor"); assert.sameValue(instant instanceof Temporal.Instant, true, "Instant"); return -Number(instant.epochNanoseconds % 86400_000_000_000n); }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, }); const result = Temporal.Now.plainTimeISO(timeZone); diff --git a/test/built-ins/Temporal/Now/zonedDateTime/calendar-function.js b/test/built-ins/Temporal/Now/zonedDateTime/calendar-function.js index e2092c9d94..8c3fa3ab56 100644 --- a/test/built-ins/Temporal/Now/zonedDateTime/calendar-function.js +++ b/test/built-ins/Temporal/Now/zonedDateTime/calendar-function.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.now.zoneddatetime description: Behavior when provided calendar value is a function -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [BigInt, Proxy, Temporal] ---*/ const actual = []; @@ -14,21 +14,10 @@ const expected = [ const calendar = function() {}; -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call timeZone.getOffsetNanosecondsFor'); return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - } }); Object.defineProperty(Temporal.Calendar, 'from', { diff --git a/test/built-ins/Temporal/Now/zonedDateTime/timezone-object.js b/test/built-ins/Temporal/Now/zonedDateTime/timezone-object.js index 15260a3852..579d015629 100644 --- a/test/built-ins/Temporal/Now/zonedDateTime/timezone-object.js +++ b/test/built-ins/Temporal/Now/zonedDateTime/timezone-object.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.now.zoneddatetime description: Observable interactions with the provided timezone-like object -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [BigInt, Proxy, Temporal] ---*/ const actual = []; @@ -14,10 +14,8 @@ const expected = [ 'has nestedTimeZone.timeZone' ]; -const nestedTimeZone = new Proxy({ +const nestedTimeZone = TemporalHelpers.timeZoneObserver(actual, "nestedTimeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -26,24 +24,10 @@ const nestedTimeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has nestedTimeZone.${String(property)}`); - return property in target; - }, - - get(target, property) { - actual.push(`get nestedTimeZone.${String(property)}`); - return target[property]; - } }); -const timeZone = new Proxy({ - timeZone: nestedTimeZone, - +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call timeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -52,17 +36,8 @@ const timeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - } }); +timeZone.timeZone = nestedTimeZone; Object.defineProperty(Temporal.TimeZone, 'from', { get() { diff --git a/test/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js b/test/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js index 2a10e4ab00..ae3489504e 100644 --- a/test/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js +++ b/test/built-ins/Temporal/Now/zonedDateTimeISO/timezone-object.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.now.zoneddatetime description: Observable interactions with the provided timezone-like object -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [BigInt, Proxy, Temporal] ---*/ const actual = []; @@ -14,10 +14,8 @@ const expected = [ 'has nestedTimeZone.timeZone' ]; -const nestedTimeZone = new Proxy({ +const nestedTimeZone = TemporalHelpers.timeZoneObserver(actual, "nestedTimeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call nestedTimeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -26,24 +24,10 @@ const nestedTimeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has nestedTimeZone.${String(property)}`); - return property in target; - }, - - get(target, property) { - actual.push(`get nestedTimeZone.${String(property)}`); - return target[property]; - } }); -const timeZone = new Proxy({ - timeZone: nestedTimeZone, - +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getOffsetNanosecondsFor(instant) { - actual.push('call timeZone.getOffsetNanosecondsFor'); - assert.sameValue( instant instanceof Temporal.Instant, true, @@ -52,17 +36,8 @@ const timeZone = new Proxy({ return -Number(instant.epochNanoseconds % 86400000000000n); } -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - } }); +timeZone.timeZone = nestedTimeZone; Object.defineProperty(Temporal.TimeZone, 'from', { get() { diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js b/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js index 652da56c6e..9549832a30 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/plain-custom-timezone.js @@ -30,21 +30,11 @@ const instant = Temporal.Instant.fromEpochNanoseconds(-205156799012345679n); const options = TemporalHelpers.propertyBagObserver(actual, { disambiguation: "reject" }, "options"); -const timeZone = new Proxy({ +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { getPossibleInstantsFor(dateTimeArg) { - actual.push("call timeZone.getPossibleInstantsFor"); assert.sameValue(dateTimeArg, dateTime); return [instant]; }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, }); const result = dateTime.toZonedDateTime(timeZone, options); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js index 51806b01b4..55d04475f3 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainDateTime/plain-custom-timezone.js @@ -4,7 +4,7 @@ /*--- esid: sec-temporal.zoneddatetime.prototype.toplaindatetime description: timeZone.getOffsetNanosecondsFor() called -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -15,20 +15,8 @@ const expected = [ "call timeZone.getOffsetNanosecondsFor", ]; -const timeZone = new Proxy({ - getOffsetNanosecondsFor() { - actual.push("call timeZone.getOffsetNanosecondsFor"); - return -8735135802468; - }, -}, { - has(target, property) { - actual.push(`has timeZone.${property}`); - return property in target; - }, - get(target, property) { - actual.push(`get timeZone.${property}`); - return target[property]; - }, +const timeZone = TemporalHelpers.timeZoneObserver(actual, "timeZone", { + getOffsetNanosecondsFor: -8735135802468, }); const zdt = new Temporal.ZonedDateTime(160583136123456789n, timeZone);