181 lines
6.4 KiB
TypeScript
181 lines
6.4 KiB
TypeScript
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
|
import { CodeModeDate } from "../values.js"
|
|
import { coerceToNumber, coerceToString } from "./value.js"
|
|
|
|
const dateSetterArguments = new Map<string, number>([
|
|
["setTime", 1],
|
|
["setMilliseconds", 1],
|
|
["setUTCMilliseconds", 1],
|
|
["setSeconds", 2],
|
|
["setUTCSeconds", 2],
|
|
["setMinutes", 3],
|
|
["setUTCMinutes", 3],
|
|
["setHours", 4],
|
|
["setUTCHours", 4],
|
|
["setDate", 1],
|
|
["setUTCDate", 1],
|
|
["setMonth", 2],
|
|
["setUTCMonth", 2],
|
|
["setFullYear", 3],
|
|
["setUTCFullYear", 3],
|
|
])
|
|
|
|
export const dateMethods = new Set([
|
|
"getTime",
|
|
"valueOf",
|
|
"toISOString",
|
|
"toJSON",
|
|
"toString",
|
|
"toUTCString",
|
|
"toGMTString",
|
|
"getFullYear",
|
|
"getMonth",
|
|
"getDate",
|
|
"getDay",
|
|
"getHours",
|
|
"getMinutes",
|
|
"getSeconds",
|
|
"getMilliseconds",
|
|
"getUTCFullYear",
|
|
"getUTCMonth",
|
|
"getUTCDate",
|
|
"getUTCDay",
|
|
"getUTCHours",
|
|
"getUTCMinutes",
|
|
"getUTCSeconds",
|
|
"getUTCMilliseconds",
|
|
"getTimezoneOffset",
|
|
...dateSetterArguments.keys(),
|
|
])
|
|
|
|
export const dateStatics = new Set(["now", "parse", "UTC"])
|
|
|
|
export const invokeDateStatic = (name: string, args: Array<unknown>, node: AstNode): number => {
|
|
switch (name) {
|
|
case "now":
|
|
return Date.now()
|
|
case "parse":
|
|
return Date.parse(coerceToString(args[0]))
|
|
case "UTC":
|
|
return Date.UTC(...(args.map((arg) => coerceToNumber(arg)) as Parameters<typeof Date.UTC>))
|
|
default:
|
|
throw new InterpreterRuntimeError(`Date.${name} is not available.`, node)
|
|
}
|
|
}
|
|
|
|
export const dateSetterArgumentCount = (name: string): number | undefined => dateSetterArguments.get(name)
|
|
|
|
export const invokeDateMethod = (
|
|
value: CodeModeDate,
|
|
name: string,
|
|
args: Array<number>,
|
|
node: AstNode,
|
|
initialTime = value.time,
|
|
): unknown => {
|
|
const hosted = new Date(initialTime)
|
|
switch (name) {
|
|
case "getTime":
|
|
case "valueOf":
|
|
return value.time
|
|
case "toISOString":
|
|
if (!Number.isFinite(value.time)) throw new InterpreterRuntimeError("Invalid time value.", node).as("RangeError")
|
|
return hosted.toISOString()
|
|
case "toJSON":
|
|
return Number.isFinite(value.time) ? hosted.toISOString() : null
|
|
case "toString":
|
|
return coerceToString(value)
|
|
case "toUTCString":
|
|
case "toGMTString":
|
|
return hosted.toUTCString()
|
|
case "getFullYear":
|
|
return hosted.getFullYear()
|
|
case "getMonth":
|
|
return hosted.getMonth()
|
|
case "getDate":
|
|
return hosted.getDate()
|
|
case "getDay":
|
|
return hosted.getDay()
|
|
case "getHours":
|
|
return hosted.getHours()
|
|
case "getMinutes":
|
|
return hosted.getMinutes()
|
|
case "getSeconds":
|
|
return hosted.getSeconds()
|
|
case "getMilliseconds":
|
|
return hosted.getMilliseconds()
|
|
case "getUTCFullYear":
|
|
return hosted.getUTCFullYear()
|
|
case "getUTCMonth":
|
|
return hosted.getUTCMonth()
|
|
case "getUTCDate":
|
|
return hosted.getUTCDate()
|
|
case "getUTCDay":
|
|
return hosted.getUTCDay()
|
|
case "getUTCHours":
|
|
return hosted.getUTCHours()
|
|
case "getUTCMinutes":
|
|
return hosted.getUTCMinutes()
|
|
case "getUTCSeconds":
|
|
return hosted.getUTCSeconds()
|
|
case "getUTCMilliseconds":
|
|
return hosted.getUTCMilliseconds()
|
|
case "getTimezoneOffset":
|
|
return hosted.getTimezoneOffset()
|
|
case "setTime":
|
|
return updateDate(value, hosted.setTime(args[0]))
|
|
case "setMilliseconds":
|
|
return updateDate(value, hosted.setMilliseconds(args[0]))
|
|
case "setUTCMilliseconds":
|
|
return updateDate(value, hosted.setUTCMilliseconds(args[0]))
|
|
case "setSeconds":
|
|
if (args.length < 2) return updateDate(value, hosted.setSeconds(args[0]))
|
|
return updateDate(value, hosted.setSeconds(args[0], args[1]))
|
|
case "setUTCSeconds":
|
|
if (args.length < 2) return updateDate(value, hosted.setUTCSeconds(args[0]))
|
|
return updateDate(value, hosted.setUTCSeconds(args[0], args[1]))
|
|
case "setMinutes":
|
|
if (args.length < 2) return updateDate(value, hosted.setMinutes(args[0]))
|
|
if (args.length < 3) return updateDate(value, hosted.setMinutes(args[0], args[1]))
|
|
return updateDate(value, hosted.setMinutes(args[0], args[1], args[2]))
|
|
case "setUTCMinutes":
|
|
if (args.length < 2) return updateDate(value, hosted.setUTCMinutes(args[0]))
|
|
if (args.length < 3) return updateDate(value, hosted.setUTCMinutes(args[0], args[1]))
|
|
return updateDate(value, hosted.setUTCMinutes(args[0], args[1], args[2]))
|
|
case "setHours":
|
|
if (args.length < 2) return updateDate(value, hosted.setHours(args[0]))
|
|
if (args.length < 3) return updateDate(value, hosted.setHours(args[0], args[1]))
|
|
if (args.length < 4) return updateDate(value, hosted.setHours(args[0], args[1], args[2]))
|
|
return updateDate(value, hosted.setHours(args[0], args[1], args[2], args[3]))
|
|
case "setUTCHours":
|
|
if (args.length < 2) return updateDate(value, hosted.setUTCHours(args[0]))
|
|
if (args.length < 3) return updateDate(value, hosted.setUTCHours(args[0], args[1]))
|
|
if (args.length < 4) return updateDate(value, hosted.setUTCHours(args[0], args[1], args[2]))
|
|
return updateDate(value, hosted.setUTCHours(args[0], args[1], args[2], args[3]))
|
|
case "setDate":
|
|
return updateDate(value, hosted.setDate(args[0]))
|
|
case "setUTCDate":
|
|
return updateDate(value, hosted.setUTCDate(args[0]))
|
|
case "setMonth":
|
|
if (args.length < 2) return updateDate(value, hosted.setMonth(args[0]))
|
|
return updateDate(value, hosted.setMonth(args[0], args[1]))
|
|
case "setUTCMonth":
|
|
if (args.length < 2) return updateDate(value, hosted.setUTCMonth(args[0]))
|
|
return updateDate(value, hosted.setUTCMonth(args[0], args[1]))
|
|
case "setFullYear":
|
|
if (args.length < 2) return updateDate(value, hosted.setFullYear(args[0]))
|
|
if (args.length < 3) return updateDate(value, hosted.setFullYear(args[0], args[1]))
|
|
return updateDate(value, hosted.setFullYear(args[0], args[1], args[2]))
|
|
case "setUTCFullYear":
|
|
if (args.length < 2) return updateDate(value, hosted.setUTCFullYear(args[0]))
|
|
if (args.length < 3) return updateDate(value, hosted.setUTCFullYear(args[0], args[1]))
|
|
return updateDate(value, hosted.setUTCFullYear(args[0], args[1], args[2]))
|
|
default:
|
|
throw new InterpreterRuntimeError(`Date method '${name}' is not available.`, node)
|
|
}
|
|
}
|
|
|
|
const updateDate = (value: CodeModeDate, time: number): number => {
|
|
value.time = time
|
|
return time
|
|
}
|