UNPKG

@js-temporal/polyfill

Version:

Polyfill for Tc39 Stage 3 proposal Temporal (https://github.com/tc39/proposal-temporal)

144 lines (134 loc) 5.6 kB
import type JSBI from 'jsbi'; import type { Temporal } from '..'; import { DEBUG } from './debug'; type OmitConstructor<T> = { [P in keyof T as T[P] extends new (...args: any[]) => any ? P : never]: T[P] }; type TemporalIntrinsics = Omit<typeof Temporal, 'Now' | 'Instant' | 'ZonedDateTime'> & { Instant: OmitConstructor<Temporal.Instant> & (new (epochNanoseconds: JSBI) => Temporal.Instant) & { prototype: typeof Temporal.Instant.prototype }; ZonedDateTime: OmitConstructor<Temporal.ZonedDateTime> & (new ( epochNanoseconds: JSBI, timeZone: Temporal.TimeZoneProtocol | string, calendar?: Temporal.CalendarProtocol | string ) => Temporal.ZonedDateTime) & { prototype: typeof Temporal.ZonedDateTime.prototype; from: typeof Temporal.ZonedDateTime.from; compare: typeof Temporal.ZonedDateTime.compare; }; }; type TemporalIntrinsicRegistrations = { [key in keyof TemporalIntrinsics as `Temporal.${key}`]: TemporalIntrinsics[key]; }; type TemporalIntrinsicPrototypeRegistrations = { [key in keyof TemporalIntrinsics as `Temporal.${key}.prototype`]: TemporalIntrinsics[key]['prototype']; }; type TemporalIntrinsicRegisteredKeys = { [key in keyof TemporalIntrinsicRegistrations as `%${key}%`]: TemporalIntrinsicRegistrations[key]; }; type TemporalIntrinsicPrototypeRegisteredKeys = { [key in keyof TemporalIntrinsicPrototypeRegistrations as `%${key}%`]: TemporalIntrinsicPrototypeRegistrations[key]; }; interface StandaloneIntrinsics { 'Temporal.Calendar.from': typeof Temporal.Calendar.from; } type RegisteredStandaloneIntrinsics = { [key in keyof StandaloneIntrinsics as `%${key}%`]: StandaloneIntrinsics[key] }; const INTRINSICS = {} as TemporalIntrinsicRegisteredKeys & TemporalIntrinsicPrototypeRegisteredKeys & RegisteredStandaloneIntrinsics; type customFormatFunction<T> = ( this: T, depth: number, options: { stylize: (value: unknown, type: 'number' | 'special') => string } ) => string; const customUtilInspectFormatters: Partial<{ [key in keyof TemporalIntrinsicRegistrations]: customFormatFunction< InstanceType<TemporalIntrinsicRegistrations[key]> >; }> = { ['Temporal.Duration'](depth, options) { const descr = options.stylize(`${this[Symbol.toStringTag]} <${this}>`, 'special'); if (depth < 1) return descr; const entries = []; for (const prop of [ 'years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds' ] as const) { if (this[prop] !== 0) entries.push(` ${prop}: ${options.stylize(this[prop], 'number')}`); } return descr + ' {\n' + entries.join(',\n') + '\n}'; } }; type InspectFormatterOptions = { stylize: (str: string, styleType: string) => string }; function defaultUtilInspectFormatter(this: any, depth: number, options: InspectFormatterOptions) { return options.stylize(`${this[Symbol.toStringTag]} <${this}>`, 'special'); } export function MakeIntrinsicClass( Class: TemporalIntrinsicRegistrations[typeof name], name: keyof TemporalIntrinsicRegistrations ) { Object.defineProperty(Class.prototype, Symbol.toStringTag, { value: name, writable: false, enumerable: false, configurable: true }); if (DEBUG) { Object.defineProperty(Class.prototype, Symbol.for('nodejs.util.inspect.custom'), { value: customUtilInspectFormatters[name] || defaultUtilInspectFormatter, writable: false, enumerable: false, configurable: true }); } for (const prop of Object.getOwnPropertyNames(Class)) { // we know that `prop` is present, so the descriptor is never undefined // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const desc = Object.getOwnPropertyDescriptor(Class, prop)!; if (!desc.configurable || !desc.enumerable) continue; desc.enumerable = false; Object.defineProperty(Class, prop, desc); } for (const prop of Object.getOwnPropertyNames(Class.prototype)) { // we know that `prop` is present, so the descriptor is never undefined // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const desc = Object.getOwnPropertyDescriptor(Class.prototype, prop)!; if (!desc.configurable || !desc.enumerable) continue; desc.enumerable = false; Object.defineProperty(Class.prototype, prop, desc); } DefineIntrinsic(name, Class); DefineIntrinsic(`${name}.prototype`, Class.prototype); } type IntrinsicDefinitionKeys = | keyof TemporalIntrinsicRegistrations | keyof TemporalIntrinsicPrototypeRegistrations | keyof StandaloneIntrinsics; export function DefineIntrinsic<KeyT extends keyof TemporalIntrinsicRegistrations>( name: KeyT, value: TemporalIntrinsicRegistrations[KeyT] ): void; export function DefineIntrinsic<KeyT extends keyof TemporalIntrinsicPrototypeRegistrations>( name: KeyT, value: TemporalIntrinsicPrototypeRegistrations[KeyT] ): void; export function DefineIntrinsic<KeyT extends keyof StandaloneIntrinsics>( name: KeyT, value: StandaloneIntrinsics[KeyT] ): void; export function DefineIntrinsic<KeyT>(name: KeyT, value: never): void; export function DefineIntrinsic<KeyT extends IntrinsicDefinitionKeys>(name: KeyT, value: unknown): void { const key: `%${IntrinsicDefinitionKeys}%` = `%${name}%`; if (INTRINSICS[key] !== undefined) throw new Error(`intrinsic ${name} already exists`); INTRINSICS[key] = value; } export function GetIntrinsic<KeyT extends keyof typeof INTRINSICS>(intrinsic: KeyT): typeof INTRINSICS[KeyT] { return INTRINSICS[intrinsic]; }