-
Notifications
You must be signed in to change notification settings - Fork 35
RFC: Fix null-check stuff #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,7 +117,7 @@ export class Calendar implements Temporal.Calendar { | |
return ES.ToString(this); | ||
} | ||
dateFromFields( | ||
fields: Params['dateFromFields'][0], | ||
fields?: Params['dateFromFields'][0], | ||
optionsParam: Params['dateFromFields'][1] = undefined | ||
): Return['dateFromFields'] { | ||
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver'); | ||
|
@@ -178,7 +178,7 @@ export class Calendar implements Temporal.Calendar { | |
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver'); | ||
const date = ES.ToTemporalDate(dateParam); | ||
const duration = ES.ToTemporalDuration(durationParam); | ||
const options = ES.GetOptionsObject(optionsParam); | ||
const options = ES.GetOptionsObject<Temporal.ArithmeticOptions>(optionsParam); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this explicit type parameter needed? Can't the type be inferred by TS from the type of |
||
const overflow = ES.ToTemporalOverflow(options); | ||
const { days } = ES.BalanceDuration( | ||
GetSlot(duration, DAYS), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1069,8 +1069,8 @@ export function ToPartialRecord<B extends AnyTemporalLikeType>( | |
} | ||
|
||
export function PrepareTemporalFields<B extends AnyTemporalLikeType>( | ||
bag: B, | ||
fields: ReadonlyArray<FieldRecord<B>> | ||
bag?: B, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably the wrong solution. See tc39/proposal-temporal#1963. |
||
fields: ReadonlyArray<FieldRecord<B>> = [] | ||
): Required<B> | undefined { | ||
if (!IsObject(bag)) return undefined; | ||
const result = {} as B; | ||
|
@@ -1109,8 +1109,8 @@ export function PrepareTemporalFields<B extends AnyTemporalLikeType>( | |
|
||
// field access in the following operations is intentionally alphabetical | ||
export function ToTemporalDateFields( | ||
bag: Temporal.PlainDateLike, | ||
fieldNames: readonly (keyof Temporal.PlainDateLike)[] | ||
bag?: Temporal.PlainDateLike, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above. |
||
fieldNames: readonly (keyof Temporal.PlainDateLike)[] = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing runtime behavior like this is probably a bad idea because it risks deviating from the spec and from the non-prod polyfill behavior in proposal-temporal. Probably better to look upstream to see if undefined is actually valid here or not. |
||
) { | ||
const entries: [keyof Temporal.PlainDateLike, 0 | undefined][] = [ | ||
['day', undefined], | ||
|
@@ -1899,8 +1899,8 @@ export function CalendarFields<F extends Iterable<string>>(calendar: Temporal.Ca | |
|
||
export function CalendarMergeFields( | ||
calendar: Temporal.CalendarProtocol, | ||
fields: Record<string, unknown>, | ||
additionalFields: Record<string, unknown> | ||
fields?: Record<string, unknown>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK both of these fields are not optional. (Although should check upstream about the second one-- not sure) |
||
additionalFields?: Record<string, unknown> | ||
) { | ||
const calMergeFields = calendar.mergeFields; | ||
if (!calMergeFields) { | ||
|
@@ -2102,7 +2102,7 @@ export function ConsolidateCalendars(one: Temporal.CalendarProtocol, two: Tempor | |
|
||
export function DateFromFields( | ||
calendar: Temporal.CalendarProtocol, | ||
fields: CalendarProtocolParams['dateFromFields'][0], | ||
fields?: CalendarProtocolParams['dateFromFields'][0], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK this is not optional. |
||
options?: Partial<CalendarProtocolParams['dateFromFields'][1]> | ||
) { | ||
const result = calendar.dateFromFields(fields, options); | ||
|
@@ -2112,7 +2112,7 @@ export function DateFromFields( | |
|
||
export function YearMonthFromFields( | ||
calendar: Temporal.CalendarProtocol, | ||
fields: CalendarProtocolParams['yearMonthFromFields'][0], | ||
fields?: CalendarProtocolParams['yearMonthFromFields'][0], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK this is not optional. |
||
options?: CalendarProtocolParams['yearMonthFromFields'][1] | ||
) { | ||
const result = calendar.yearMonthFromFields(fields, options); | ||
|
@@ -2122,7 +2122,7 @@ export function YearMonthFromFields( | |
|
||
export function MonthDayFromFields( | ||
calendar: Temporal.CalendarProtocol, | ||
fields: CalendarProtocolParams['monthDayFromFields'][0], | ||
fields?: CalendarProtocolParams['monthDayFromFields'][0], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK this is not optional. |
||
options?: CalendarProtocolParams['monthDayFromFields'][1] | ||
) { | ||
const result = calendar.monthDayFromFields(fields, options); | ||
|
@@ -4666,7 +4666,7 @@ export function RoundDuration( | |
nanosecondsParam: number, | ||
increment: number, | ||
unit: Temporal.DateTimeUnit, | ||
roundingMode: Temporal.RoundingMode, | ||
roundingMode: Temporal.RoundingMode = 'trunc', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usually, defaults are assigned upstream, not in default arguments like this. So I think this change is probably wrong. |
||
relativeToParam: ReturnType<typeof ToRelativeTemporalObject> = undefined | ||
) { | ||
let years = yearsParam; | ||
|
@@ -4996,7 +4996,7 @@ export function ComparisonResult(value: number) { | |
return value < 0 ? -1 : value > 0 ? 1 : (value as 0); | ||
} | ||
|
||
export function GetOptionsObject<T>(options: T) { | ||
export function GetOptionsObject<T>(options: T | undefined) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain why this change is needed? If |
||
if (options === undefined) return ObjectCreate(null) as T; | ||
if (IsObject(options) && options !== null) return options; | ||
throw new TypeError(`Options parameter must be an object, not ${options === null ? 'null' : `${typeof options}`}`); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import * as ES from './ecmascript'; | ||
import { GetIntrinsic, MakeIntrinsicClass } from './intrinsicclass'; | ||
import { MakeIntrinsicClass } from './intrinsicclass'; | ||
justingrant marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import { | ||
ISO_YEAR, | ||
ISO_MONTH, | ||
|
@@ -188,8 +188,8 @@ export class PlainDate implements Temporal.PlainDate { | |
this | ||
)); | ||
|
||
const Duration = GetIntrinsic('%Temporal.Duration%'); | ||
return new Duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0); | ||
// const Duration = GetIntrinsic('%Temporal.Duration%')!; | ||
return new Temporal.Duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This we can't do, because it would break if user code monkey-patched I think the best solution here (and elsewhere in the file) would be to type GetIntrinsic such that TypeScript knows that it returns Temporal.Duration for an argument of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this be avoided by just doing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we can import as it causes circular value dependencies between the different files? If that would work that could be one potential fix. If we need to stick with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Circular dependencies should be fine as there's already ecmascript -> calendar -> ecmascript :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does TypeScript usually handle circular module dependencies? |
||
} | ||
since(otherParam: Params['since'][0], optionsParam: Params['since'][1] = undefined): Return['since'] { | ||
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver'); | ||
|
@@ -212,9 +212,8 @@ export class PlainDate implements Temporal.PlainDate { | |
|
||
const untilOptions = { ...options, largestUnit }; | ||
let { years, months, weeks, days } = ES.CalendarDateUntil(calendar, this, other, untilOptions); | ||
const Duration = GetIntrinsic('%Temporal.Duration%'); | ||
if (smallestUnit === 'day' && roundingIncrement === 1) { | ||
return new Duration(-years, -months, -weeks, -days, 0, 0, 0, 0, 0, 0); | ||
return new Temporal.Duration(-years, -months, -weeks, -days, 0, 0, 0, 0, 0, 0); | ||
} | ||
({ years, months, weeks, days } = ES.RoundDuration( | ||
years, | ||
|
@@ -233,7 +232,7 @@ export class PlainDate implements Temporal.PlainDate { | |
this | ||
)); | ||
|
||
return new Duration(-years, -months, -weeks, -days, 0, 0, 0, 0, 0, 0); | ||
return new Temporal.Duration(-years, -months, -weeks, -days, 0, 0, 0, 0, 0, 0); | ||
} | ||
equals(otherParam: Params['equals'][0]): Return['equals'] { | ||
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,9 +275,10 @@ export function HasSlot(container: unknown, ...ids: (keyof Slots)[]): boolean { | |
return !!myslots && ids.reduce((all: boolean, id) => all && id in myslots, true); | ||
} | ||
export function GetSlot<KeyT extends keyof Slots>( | ||
container: Slots[typeof id]['usedBy'], | ||
container: Slots[typeof id]['usedBy'] | undefined, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it signifies a bug in the polyfill if we end up calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case it can be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can tighten the types in BuiltinTimeZoneGetInstantFor to ensure at compile time that no incorrect disambiguation can be given there? Or otherwise throw earlier if that happens? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like there may be a legit issue with throw new Error(`assertion failed: invalid disambiguation value ${disambiguation}`); |
||
id: KeyT | ||
): Slots[KeyT]['value'] { | ||
if (container === undefined) throw new TypeError('Missing container'); | ||
const value = GetSlots(container)[id]; | ||
if (value === undefined) throw new TypeError(`Missing internal slot ${id}`); | ||
return value; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fields
should never be undefined.Also, if
undefined
were acceptable, then for any public API (like this one) it's intentional to leave it asParams...
because that enforces alignment between the implementation and index.d.ts. So let's imagine that undefined were OK for this API, then the right fix would be to change index.d.ts, not here.