mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
Add Float16Array (#1249)
This commit is contained in:
@@ -1 +1 @@
|
||||
- **ArrayBuffers and typed arrays:** Fixed-length ArrayBuffers support shared typed-array and DataView storage. Resizing, transferring, Float16 arrays, and BigInt arrays are unsupported. Numeric typed arrays and Buffers preserve their kind and shared storage through `unknown`, including when nested in records and arrays. Numeric typed-array constructors can be stored and used with `new`, including constructors read from an array's `constructor` property. JavaScript numeric-array parameters and returns preserve typed-array storage. `Buffer.from`, `Buffer.allocUnsafe`, and `Buffer.concat` return views into a per-thread pool of `Buffer.poolSize` bytes (64 KiB by default) when the size is below `Buffer.poolSize >>> 1`, as in Node; a pool slab stays in memory while any of its Buffers does. Node's own startup code allocates from the first slab, so the `byteOffset` of Buffers in that slab differs from Node's. Buffers returned by other Node APIs, such as `fs.readFileSync` and `zlib`, own their `ArrayBuffer`, where Node allocates small ones from the pool.
|
||||
- **ArrayBuffers and typed arrays:** Fixed-length ArrayBuffers support shared typed-array and DataView storage. Resizing, transferring, and BigInt arrays are unsupported. `Float16Array` stores IEEE 754 half-precision values, rounding each stored number to nearest-even as Node does; `Math.f16round`, `DataView.prototype.getFloat16` and `setFloat16`, and `util.types.isFloat16Array` compile. Numeric typed arrays and Buffers preserve their kind and shared storage through `unknown`, including when nested in records and arrays. Numeric typed-array constructors can be stored and used with `new`, including constructors read from an array's `constructor` property. JavaScript numeric-array parameters and returns preserve typed-array storage. `Buffer.from`, `Buffer.allocUnsafe`, and `Buffer.concat` return views into a per-thread pool of `Buffer.poolSize` bytes (64 KiB by default) when the size is below `Buffer.poolSize >>> 1`, as in Node; a pool slab stays in memory while any of its Buffers does. Node's own startup code allocates from the first slab, so the `byteOffset` of Buffers in that slab differs from Node's. Buffers returned by other Node APIs, such as `fs.readFileSync` and `zlib`, own their `ArrayBuffer`, where Node allocates small ones from the pool.
|
||||
|
||||
+1
-1
@@ -3252,6 +3252,7 @@ declare module "util/types" {
|
||||
export function isInt8Array(value: unknown): value is Int8Array;
|
||||
export function isInt16Array(value: unknown): value is Int16Array;
|
||||
export function isInt32Array(value: unknown): value is Int32Array;
|
||||
export function isFloat16Array(value: unknown): value is Float16Array;
|
||||
export function isFloat32Array(value: unknown): value is Float32Array;
|
||||
export function isFloat64Array(value: unknown): value is Float64Array;
|
||||
export function isMap(value: unknown): value is Map<unknown, unknown>;
|
||||
@@ -3279,7 +3280,6 @@ declare module "util/types" {
|
||||
export function isBoxedPrimitive(value: unknown): boolean;
|
||||
export function isBigInt64Array(value: unknown): value is BigInt64Array;
|
||||
export function isBigUint64Array(value: unknown): value is BigUint64Array;
|
||||
export function isFloat16Array(value: unknown): boolean;
|
||||
export function isCryptoKey(value: unknown): boolean;
|
||||
export function isExternal(value: unknown): boolean;
|
||||
}
|
||||
|
||||
@@ -182,7 +182,11 @@ export function emitByteNumber(
|
||||
const integerType = bits <= 32 ? "i32" : "i64";
|
||||
if (spec.write) {
|
||||
let raw: string;
|
||||
if (spec.floating) {
|
||||
if (spec.floating && bits === 16) {
|
||||
host.declare(`declare zeroext i16 @scr_f16_from_f64(double)`);
|
||||
raw = B.tmp();
|
||||
B.line(`${raw} = call zeroext i16 @scr_f16_from_f64(double ${value!.name})`);
|
||||
} else if (spec.floating) {
|
||||
let stored = value!.name;
|
||||
if (bits === 32) {
|
||||
stored = B.tmp();
|
||||
@@ -228,7 +232,10 @@ export function emitByteNumber(
|
||||
const raw = endianBits(host, loaded, spec.width, little);
|
||||
fastResult = B.tmp();
|
||||
if (spec.floating) {
|
||||
if (bits === 32) {
|
||||
if (bits === 16) {
|
||||
host.declare(`declare double @scr_f16_to_f64(i16 zeroext)`);
|
||||
B.line(`${fastResult} = call double @scr_f16_to_f64(i16 zeroext ${raw})`);
|
||||
} else if (bits === 32) {
|
||||
const float = B.tmp();
|
||||
B.line(`${float} = bitcast i32 ${raw} to float`);
|
||||
B.line(`${fastResult} = fpext float ${float} to double`);
|
||||
|
||||
@@ -159,6 +159,7 @@ export const BYTES_ELEM_NUM: Record<IrBytesElem, number> = {
|
||||
u16: 6,
|
||||
i16: 7,
|
||||
u8c: 8,
|
||||
f16: 9,
|
||||
};
|
||||
|
||||
/** The payload marker of an ABSENT record field slot (IR fieldAbsent): the
|
||||
|
||||
@@ -44,6 +44,7 @@ const DV_GET_KIND: Record<string, number> = {
|
||||
dvGetFloat64: 7,
|
||||
dvGetBigUint64Number: 8,
|
||||
dvGetBigInt64Number: 9,
|
||||
dvGetFloat16: 10,
|
||||
};
|
||||
|
||||
const DV_SET_KIND: Record<string, number> = {
|
||||
@@ -55,6 +56,7 @@ const DV_SET_KIND: Record<string, number> = {
|
||||
dvSetInt32: 5,
|
||||
dvSetFloat32: 6,
|
||||
dvSetFloat64: 7,
|
||||
dvSetFloat16: 10,
|
||||
};
|
||||
|
||||
export function emitIntegerLoopIndex(host: LlvmEmitterContext, expr: IrExpr): string | null {
|
||||
@@ -273,7 +275,7 @@ function emitSharedOrLocalLoad(
|
||||
idx: string,
|
||||
): LlValue {
|
||||
const B = host.B;
|
||||
const floating = elem === "f32" || elem === "f64";
|
||||
const floating = elem === "f16" || elem === "f32" || elem === "f64";
|
||||
const fn = floating ? "scr_bytes_shared_get_f64" : "scr_bytes_shared_get_int";
|
||||
const ret = floating ? "double" : "i32";
|
||||
host.declare(`declare ${ret} @${fn}(ptr, ${host.sizeType})`);
|
||||
@@ -314,6 +316,16 @@ function emitBytesLoadAt(
|
||||
const B = host.B;
|
||||
const data = host.emitBytesData(receiver);
|
||||
const p = B.tmp();
|
||||
if (elem === "f16") {
|
||||
// Half-precision bits widen exactly; the runtime converts them.
|
||||
host.declare(`declare double @scr_f16_to_f64(i16 zeroext)`);
|
||||
const raw = B.tmp();
|
||||
const out = B.tmp();
|
||||
B.line(`${p} = getelementptr inbounds i16, ptr ${data}, ${host.sizeType} ${idx}`);
|
||||
B.line(`${raw} = load i16, ptr ${p}, align 1`);
|
||||
B.line(`${out} = call double @scr_f16_to_f64(i16 zeroext ${raw})`);
|
||||
return { name: out, type: F64 };
|
||||
}
|
||||
if (BYTES_ELEMENT_SIZE[elem] < 4) {
|
||||
const bits = BYTES_ELEMENT_SIZE[elem] * 8;
|
||||
const signed = elem === "i8" || elem === "i16";
|
||||
@@ -472,10 +484,19 @@ export function emitBytesSet(
|
||||
B.line(`${stored} = fptoui double ${clamped} to i32`);
|
||||
} else
|
||||
stored =
|
||||
elem === "f32" || elem === "f64" ? null : host.emitToUint32(value.name, expr, value.uint32);
|
||||
elem === "f16" || elem === "f32" || elem === "f64"
|
||||
? null
|
||||
: host.emitToUint32(value.name, expr, value.uint32);
|
||||
const data = host.emitBytesData(receiver);
|
||||
const p = B.tmp();
|
||||
if (BYTES_ELEMENT_SIZE[elem] < 4) {
|
||||
if (elem === "f16") {
|
||||
// One round-to-nearest-even step from the double, in the runtime.
|
||||
host.declare(`declare zeroext i16 @scr_f16_from_f64(double)`);
|
||||
const narrowed = B.tmp();
|
||||
B.line(`${narrowed} = call zeroext i16 @scr_f16_from_f64(double ${value.name})`);
|
||||
B.line(`${p} = getelementptr inbounds i16, ptr ${data}, ${host.sizeType} ${idx}`);
|
||||
B.line(`store i16 ${narrowed}, ptr ${p}, align 1`);
|
||||
} else if (BYTES_ELEMENT_SIZE[elem] < 4) {
|
||||
const bits = BYTES_ELEMENT_SIZE[elem] * 8;
|
||||
const byte = B.tmp();
|
||||
B.line(`${byte} = trunc i32 ${stored!} to i${bits}`);
|
||||
@@ -882,6 +903,7 @@ export function emitBytesIntrinsic(
|
||||
case "dvGetInt16":
|
||||
case "dvGetUint32":
|
||||
case "dvGetInt32":
|
||||
case "dvGetFloat16":
|
||||
case "dvGetFloat32":
|
||||
case "dvGetFloat64":
|
||||
case "dvGetBigUint64Number":
|
||||
@@ -912,6 +934,7 @@ export function emitBytesIntrinsic(
|
||||
case "dvSetInt16":
|
||||
case "dvSetUint32":
|
||||
case "dvSetInt32":
|
||||
case "dvSetFloat16":
|
||||
case "dvSetFloat32":
|
||||
case "dvSetFloat64": {
|
||||
// DataView setters: [offset, value, littleEndian?] — void; throw
|
||||
|
||||
@@ -1039,6 +1039,16 @@ export function emitPrimitiveLibCall(host: LlvmEmitterContext, e: LibCallExpr):
|
||||
B.line(`${t} = sitofp i32 ${product} to double`);
|
||||
return { name: t, type: e.type, uint32: product };
|
||||
}
|
||||
if (e.fn === "math.f16round") {
|
||||
const v = host.emitExpr(e.args[0]!);
|
||||
host.declare(`declare zeroext i16 @scr_f16_from_f64(double)`);
|
||||
host.declare(`declare double @scr_f16_to_f64(i16 zeroext)`);
|
||||
const narrowed = B.tmp();
|
||||
const t = B.tmp();
|
||||
B.line(`${narrowed} = call zeroext i16 @scr_f16_from_f64(double ${v.name})`);
|
||||
B.line(`${t} = call double @scr_f16_to_f64(i16 zeroext ${narrowed})`);
|
||||
return { name: t, type: e.type };
|
||||
}
|
||||
if (e.fn === "math.fround") {
|
||||
const v = host.emitExpr(e.args[0]!);
|
||||
const narrowed = B.tmp();
|
||||
|
||||
@@ -65,6 +65,7 @@ export const LIB_FN_SYMS: Record<string, string> = {
|
||||
"arrayBuffer.viewU8": "scr_array_buffer_view_u8",
|
||||
"arrayBuffer.viewU32": "scr_array_buffer_view_u32",
|
||||
"arrayBuffer.viewI32": "scr_array_buffer_view_i32",
|
||||
"arrayBuffer.viewF16": "scr_array_buffer_view_f16",
|
||||
"arrayBuffer.viewF32": "scr_array_buffer_view_f32",
|
||||
"arrayBuffer.viewF64": "scr_array_buffer_view_f64",
|
||||
"arrayBuffer.viewDV": "scr_array_buffer_view_dv",
|
||||
|
||||
@@ -108,6 +108,7 @@ const PURE_MATH = new Set<string>([
|
||||
"math.exp",
|
||||
"math.expm1",
|
||||
"math.floor",
|
||||
"math.f16round",
|
||||
"math.fround",
|
||||
"math.imul",
|
||||
"math.log",
|
||||
|
||||
@@ -151,7 +151,7 @@ function lowerBytesSortCall(
|
||||
/* ── typed arrays / Buffer ─────────────────────────────────────────────── */
|
||||
|
||||
/** The typed-array constructors with a runtime representation, by lib
|
||||
* interface name. Other flavors (Float16Array, BigInt64Array, ...) fall through
|
||||
* interface name. Other flavors (BigInt64Array, BigUint64Array) fall through
|
||||
* to the generic stdlib-constructor fence. DataView is handled separately. */
|
||||
const BYTES_CTORS: Record<string, IrBytesElem | undefined> = {
|
||||
Uint8Array: "u8",
|
||||
@@ -161,6 +161,7 @@ const BYTES_CTORS: Record<string, IrBytesElem | undefined> = {
|
||||
Int16Array: "i16",
|
||||
Uint32Array: "u32",
|
||||
Int32Array: "i32",
|
||||
Float16Array: "f16",
|
||||
Float32Array: "f32",
|
||||
Float64Array: "f64",
|
||||
};
|
||||
@@ -397,6 +398,7 @@ function lowerArrayBufferView(
|
||||
u8: "arrayBuffer.viewU8",
|
||||
u32: "arrayBuffer.viewU32",
|
||||
i32: "arrayBuffer.viewI32",
|
||||
f16: "arrayBuffer.viewF16",
|
||||
f32: "arrayBuffer.viewF32",
|
||||
f64: "arrayBuffer.viewF64",
|
||||
dv: "arrayBuffer.viewDV",
|
||||
@@ -1220,6 +1222,7 @@ const DV_GETTERS: Record<string, { method: IrBytesIntrinsicMethod; le: boolean }
|
||||
getInt16: { method: "dvGetInt16", le: true },
|
||||
getUint32: { method: "dvGetUint32", le: true },
|
||||
getInt32: { method: "dvGetInt32", le: true },
|
||||
getFloat16: { method: "dvGetFloat16", le: true },
|
||||
getFloat32: { method: "dvGetFloat32", le: true },
|
||||
getFloat64: { method: "dvGetFloat64", le: true },
|
||||
};
|
||||
@@ -1231,6 +1234,7 @@ const DV_SETTERS: Record<string, { method: IrBytesIntrinsicMethod; le: boolean }
|
||||
setInt16: { method: "dvSetInt16", le: true },
|
||||
setUint32: { method: "dvSetUint32", le: true },
|
||||
setInt32: { method: "dvSetInt32", le: true },
|
||||
setFloat16: { method: "dvSetFloat16", le: true },
|
||||
setFloat32: { method: "dvSetFloat32", le: true },
|
||||
setFloat64: { method: "dvSetFloat64", le: true },
|
||||
};
|
||||
|
||||
@@ -2364,6 +2364,7 @@ const BYTES_BRANDS: ReadonlySet<string> = new Set([
|
||||
"Int8Array",
|
||||
"Int16Array",
|
||||
"Int32Array",
|
||||
"Float16Array",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"BigInt64Array",
|
||||
|
||||
@@ -191,6 +191,7 @@ const TYPED_ARRAYS = new Set([
|
||||
"Uint16Array",
|
||||
"Int32Array",
|
||||
"Uint32Array",
|
||||
"Float16Array",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
]);
|
||||
|
||||
@@ -834,6 +834,7 @@ const INERT_CONSTRUCTORS = new Set([
|
||||
"Int16Array",
|
||||
"Uint32Array",
|
||||
"Int32Array",
|
||||
"Float16Array",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"BigInt64Array",
|
||||
|
||||
@@ -664,6 +664,7 @@ export const STDLIB_SURFACE = {
|
||||
cosh: ISL_N1,
|
||||
exp: ISL_N1,
|
||||
expm1: ISL_N1,
|
||||
f16round: ISL_N1,
|
||||
fround: ISL_N1,
|
||||
hypot: ISL_N2,
|
||||
imul: ISL_N2,
|
||||
@@ -751,6 +752,7 @@ export const STATIC_MATH_FNS: Record<string, { fn: IrLibFn; arity: number } | un
|
||||
sign: { fn: "math.sign", arity: 1 },
|
||||
exp: { fn: "math.exp", arity: 1 },
|
||||
expm1: { fn: "math.expm1", arity: 1 },
|
||||
f16round: { fn: "math.f16round", arity: 1 },
|
||||
fround: { fn: "math.fround", arity: 1 },
|
||||
sqrt: { fn: "math.sqrt", arity: 1 },
|
||||
log: { fn: "math.log", arity: 1 },
|
||||
|
||||
@@ -2521,6 +2521,7 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null {
|
||||
// ToInt32-wrap) — the Atomics.wait sleep idiom constructs one over a
|
||||
// SharedArrayBuffer, and the i32 semantics hold for every other use.
|
||||
if (isStdlibInterface("Int32Array")) return bytesOf("i32");
|
||||
if (isStdlibInterface("Float16Array")) return bytesOf("f16");
|
||||
if (isStdlibInterface("Float32Array")) return bytesOf("f32");
|
||||
if (isStdlibInterface("Float64Array")) return bytesOf("f64");
|
||||
// DataView: the ONE view kind — a u8 bytes value whose runtime
|
||||
|
||||
@@ -219,6 +219,7 @@ const BORROW_SAFE_MATH = new Set<IrLibFn>([
|
||||
"math.sign",
|
||||
"math.exp",
|
||||
"math.expm1",
|
||||
"math.f16round",
|
||||
"math.fround",
|
||||
"math.log",
|
||||
"math.log1p",
|
||||
|
||||
@@ -75,6 +75,7 @@ export const MAY_THROW_LIB_FNS: ReadonlySet<IrLibFn> = new Set([
|
||||
"arrayBuffer.viewU8",
|
||||
"arrayBuffer.viewU32",
|
||||
"arrayBuffer.viewI32",
|
||||
"arrayBuffer.viewF16",
|
||||
"arrayBuffer.viewF32",
|
||||
"arrayBuffer.viewF64",
|
||||
"arrayBuffer.viewDV",
|
||||
|
||||
@@ -648,6 +648,7 @@ export const LIB_FN_SIGS = defineLibFnSignatures({
|
||||
"math.sign": { argTypes: [F64], result: F64 },
|
||||
"math.exp": { argTypes: [F64], result: F64 },
|
||||
"math.expm1": { argTypes: [F64], result: F64 },
|
||||
"math.f16round": { argTypes: [F64], result: F64 },
|
||||
"math.fround": { argTypes: [F64], result: F64 },
|
||||
"math.sqrt": { argTypes: [F64], result: F64 },
|
||||
"math.log": { argTypes: [F64], result: F64 },
|
||||
@@ -3163,6 +3164,7 @@ export const LIB_FN_SIGS = defineLibFnSignatures({
|
||||
"arrayBuffer.viewU8": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
|
||||
"arrayBuffer.viewU32": { argTypes: [DYN, DYN, DYN], result: bytesOf("u32") },
|
||||
"arrayBuffer.viewI32": { argTypes: [DYN, DYN, DYN], result: bytesOf("i32") },
|
||||
"arrayBuffer.viewF16": { argTypes: [DYN, DYN, DYN], result: bytesOf("f16") },
|
||||
"arrayBuffer.viewF32": { argTypes: [DYN, DYN, DYN], result: bytesOf("f32") },
|
||||
"arrayBuffer.viewF64": { argTypes: [DYN, DYN, DYN], result: bytesOf("f64") },
|
||||
"arrayBuffer.viewDV": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
|
||||
|
||||
@@ -25,6 +25,7 @@ const FORMATS: Readonly<Record<string, ByteNumberFormat | undefined>> = {
|
||||
i16: { width: 2, signed: true, floating: false },
|
||||
u32: { width: 4, signed: false, floating: false },
|
||||
i32: { width: 4, signed: true, floating: false },
|
||||
f16: { width: 2, signed: false, floating: true },
|
||||
f32: { width: 4, signed: false, floating: true },
|
||||
f64: { width: 8, signed: false, floating: true },
|
||||
u64: { width: 8, signed: false, floating: false },
|
||||
@@ -38,6 +39,7 @@ const VIEW_FORMATS: Readonly<Record<string, string | undefined>> = {
|
||||
dvGetInt16: "i16",
|
||||
dvGetUint32: "u32",
|
||||
dvGetInt32: "i32",
|
||||
dvGetFloat16: "f16",
|
||||
dvGetFloat32: "f32",
|
||||
dvGetFloat64: "f64",
|
||||
dvGetBigUint64Number: "u64",
|
||||
@@ -48,6 +50,7 @@ const VIEW_FORMATS: Readonly<Record<string, string | undefined>> = {
|
||||
dvSetInt16: "i16",
|
||||
dvSetUint32: "u32",
|
||||
dvSetInt32: "i32",
|
||||
dvSetFloat16: "f16",
|
||||
dvSetFloat32: "f32",
|
||||
dvSetFloat64: "f64",
|
||||
};
|
||||
|
||||
@@ -336,6 +336,7 @@ const BOUNDARY_KINDS = new Set<IrExpr["kind"]>([
|
||||
* property, except literal-keyed `dyn.keySet`/`dyn.keyDelete`. */
|
||||
const DYN_READ_ONLY = new Set<string>([
|
||||
"arrayBuffer.new",
|
||||
"arrayBuffer.viewF16",
|
||||
"arrayBuffer.viewF32",
|
||||
"arrayBuffer.viewF64",
|
||||
"arrayBuffer.viewI16",
|
||||
|
||||
@@ -26,9 +26,19 @@ export interface SrcLoc {
|
||||
|
||||
/* ── types ─────────────────────────────────────────────────────────────── */
|
||||
|
||||
/** Numeric typed-array element kinds with a native representation. Float16
|
||||
* and BigInt typed arrays remain frontend-fenced. */
|
||||
export type IrBytesElem = "u8" | "u8c" | "i8" | "u16" | "i16" | "u32" | "i32" | "f32" | "f64";
|
||||
/** Numeric typed-array element kinds with a native representation. BigInt
|
||||
* typed arrays remain frontend-fenced. */
|
||||
export type IrBytesElem =
|
||||
| "u8"
|
||||
| "u8c"
|
||||
| "i8"
|
||||
| "u16"
|
||||
| "i16"
|
||||
| "u32"
|
||||
| "i32"
|
||||
| "f16"
|
||||
| "f32"
|
||||
| "f64";
|
||||
|
||||
export const BYTES_ELEMENT_SIZE: Record<IrBytesElem, number> = {
|
||||
u8: 1,
|
||||
@@ -38,13 +48,14 @@ export const BYTES_ELEMENT_SIZE: Record<IrBytesElem, number> = {
|
||||
i16: 2,
|
||||
u32: 4,
|
||||
i32: 4,
|
||||
f16: 2,
|
||||
f32: 4,
|
||||
f64: 8,
|
||||
};
|
||||
|
||||
/** Integer element kinds: a valid element read is never NaN. */
|
||||
export function isIntegerBytesElem(elem: IrBytesElem): boolean {
|
||||
return elem !== "f32" && elem !== "f64";
|
||||
return elem !== "f16" && elem !== "f32" && elem !== "f64";
|
||||
}
|
||||
|
||||
export const BYTES_ELEMENT_NAME: Record<IrBytesElem, string> = {
|
||||
@@ -55,6 +66,7 @@ export const BYTES_ELEMENT_NAME: Record<IrBytesElem, string> = {
|
||||
i16: "Int16Array",
|
||||
u32: "Uint32Array",
|
||||
i32: "Int32Array",
|
||||
f16: "Float16Array",
|
||||
f32: "Float32Array",
|
||||
f64: "Float64Array",
|
||||
};
|
||||
@@ -2242,6 +2254,7 @@ export type IrBytesIntrinsicMethod =
|
||||
| "dvGetInt16"
|
||||
| "dvGetUint32"
|
||||
| "dvGetInt32"
|
||||
| "dvGetFloat16"
|
||||
| "dvGetFloat32"
|
||||
| "dvGetFloat64"
|
||||
| "dvGetBigUint64Number"
|
||||
@@ -2252,6 +2265,7 @@ export type IrBytesIntrinsicMethod =
|
||||
| "dvSetInt16"
|
||||
| "dvSetUint32"
|
||||
| "dvSetInt32"
|
||||
| "dvSetFloat16"
|
||||
| "dvSetFloat32"
|
||||
| "dvSetFloat64";
|
||||
|
||||
@@ -2283,6 +2297,7 @@ export const MAY_THROW_BYTES_METHODS: ReadonlySet<IrBytesIntrinsicMethod> = new
|
||||
"dvGetInt16",
|
||||
"dvGetUint32",
|
||||
"dvGetInt32",
|
||||
"dvGetFloat16",
|
||||
"dvGetFloat32",
|
||||
"dvGetFloat64",
|
||||
"dvGetBigUint64Number",
|
||||
@@ -2293,6 +2308,7 @@ export const MAY_THROW_BYTES_METHODS: ReadonlySet<IrBytesIntrinsicMethod> = new
|
||||
"dvSetInt16",
|
||||
"dvSetUint32",
|
||||
"dvSetInt32",
|
||||
"dvSetFloat16",
|
||||
"dvSetFloat32",
|
||||
"dvSetFloat64",
|
||||
]);
|
||||
|
||||
@@ -4602,6 +4602,13 @@
|
||||
"status": "static",
|
||||
"note": "compiles statically at arity 1; other declared call shapes are refused with SC2012"
|
||||
},
|
||||
{
|
||||
"id": "stdlib.math.f16round",
|
||||
"kind": "stdlib",
|
||||
"name": "Math.f16round",
|
||||
"status": "static",
|
||||
"note": "compiles statically at arity 1; other declared call shapes are refused with SC2012"
|
||||
},
|
||||
{
|
||||
"id": "stdlib.math.floor",
|
||||
"kind": "stdlib",
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/5900-float16-array.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/5901-float16-array-js.js"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -3111,6 +3111,11 @@ static double scr_bytes_sort_load(const ScrBytes *b, size_t i) {
|
||||
memcpy(&v, at, sizeof v);
|
||||
return v;
|
||||
}
|
||||
case SCR_BYTES_F16: {
|
||||
uint16_t v;
|
||||
memcpy(&v, at, sizeof v);
|
||||
return scr_f16_to_f64(v);
|
||||
}
|
||||
case SCR_BYTES_F32: {
|
||||
float v;
|
||||
memcpy(&v, at, sizeof v);
|
||||
@@ -3151,6 +3156,11 @@ static void scr_bytes_sort_store(ScrBytes *b, size_t i, double value) {
|
||||
memcpy(at, &v, sizeof v);
|
||||
break;
|
||||
}
|
||||
case SCR_BYTES_F16: {
|
||||
uint16_t v = scr_f16_from_f64(value);
|
||||
memcpy(at, &v, sizeof v);
|
||||
break;
|
||||
}
|
||||
case SCR_BYTES_F32: {
|
||||
float v = (float)value;
|
||||
memcpy(at, &v, sizeof v);
|
||||
@@ -3263,6 +3273,18 @@ static int scr_bytes_f32_key(const uint8_t *at, int32_t order, uint32_t *key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Float16 keys use the low 16 bits of a 32-bit key; a descending order
|
||||
* complements all 32, which keeps the order of keys. */
|
||||
static int scr_bytes_f16_key(const uint8_t *at, int32_t order, uint32_t *key) {
|
||||
uint16_t bits;
|
||||
memcpy(&bits, at, sizeof bits);
|
||||
if ((bits & 0x7fff) > 0x7c00) return order ? 2 : 1;
|
||||
if (order && bits == 0x8000) return 2;
|
||||
uint32_t k = (bits & 0x8000) ? (uint16_t)~bits : (uint32_t)bits | 0x8000;
|
||||
*key = k ^ (order < 0 ? ~UINT32_C(0) : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scr_bytes_f64_key(const uint8_t *at, int32_t order, uint64_t *key) {
|
||||
double v;
|
||||
uint64_t bits;
|
||||
@@ -3323,6 +3345,9 @@ static bool scr_bytes_sort_refused(const ScrBytes *b, int32_t order) {
|
||||
if (b->elem == SCR_BYTES_F32) {
|
||||
uint32_t key;
|
||||
if (scr_bytes_f32_key(data + i * 4, order, &key)) return true;
|
||||
} else if (b->elem == SCR_BYTES_F16) {
|
||||
uint32_t key;
|
||||
if (scr_bytes_f16_key(data + i * 2, order, &key)) return true;
|
||||
} else if (b->elem == SCR_BYTES_F64) {
|
||||
uint64_t key;
|
||||
if (scr_bytes_f64_key(data + i * 8, order, &key)) return true;
|
||||
@@ -3353,7 +3378,7 @@ bool scr_bytes_sort_numeric(ScrBytes *b, int32_t order) {
|
||||
size_t width = scr_bytes_elem_size(b->elem);
|
||||
uint8_t *data = b->data;
|
||||
/* Integer elements have no NaN or -0: every order is a value order. */
|
||||
if (width == 1 || (width == 2 && n >= SCR_BYTES_COUNT_SORT)) {
|
||||
if (width == 1 || (width == 2 && b->elem != SCR_BYTES_F16 && n >= SCR_BYTES_COUNT_SORT)) {
|
||||
scr_bytes_count_sort(b, order < 0);
|
||||
return true;
|
||||
}
|
||||
@@ -3392,13 +3417,23 @@ bool scr_bytes_sort_numeric(ScrBytes *b, int32_t order) {
|
||||
uint32_t bits_ = (k_ & SCR_SORT_SIGN32) ? k_ & ~SCR_SORT_SIGN32 : ~k_; \
|
||||
memcpy(data + (i) * 4, &bits_, 4); \
|
||||
} while (0)
|
||||
#define SCR_BYTES_READ32_F16(i, key) scr_bytes_f16_key(data + (i) * 2, order, (key))
|
||||
#define SCR_BYTES_WRITE32_F16(i, key) \
|
||||
do { \
|
||||
uint16_t k_ = (uint16_t)((key) ^ flip32); \
|
||||
uint16_t bits_ = (k_ & 0x8000) ? (uint16_t)(k_ & 0x7fff) : (uint16_t)~k_; \
|
||||
memcpy(data + (i) * 2, &bits_, 2); \
|
||||
} while (0)
|
||||
if (b->elem == SCR_BYTES_F32) SCR_BYTES_KEYS32(F32);
|
||||
else if (b->elem == SCR_BYTES_F16) SCR_BYTES_KEYS32(F16);
|
||||
else SCR_BYTES_KEYS32(INT);
|
||||
#undef SCR_BYTES_KEYS32
|
||||
#undef SCR_BYTES_READ32_INT
|
||||
#undef SCR_BYTES_WRITE32_INT
|
||||
#undef SCR_BYTES_READ32_F32
|
||||
#undef SCR_BYTES_WRITE32_F32
|
||||
#undef SCR_BYTES_READ32_F16
|
||||
#undef SCR_BYTES_WRITE32_F16
|
||||
free(keys);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -791,7 +791,7 @@ static bool scr_assert_loose_error(const ScrDyn *a, const ScrDyn *b) {
|
||||
}
|
||||
|
||||
static bool scr_assert_loose_float_elem(ScrBytesElem elem) {
|
||||
return elem == SCR_BYTES_F32 || elem == SCR_BYTES_F64;
|
||||
return elem == SCR_BYTES_F16 || elem == SCR_BYTES_F32 || elem == SCR_BYTES_F64;
|
||||
}
|
||||
|
||||
/* Typed arrays and Buffers: the same tag (a Buffer is a Uint8Array here),
|
||||
@@ -1305,6 +1305,7 @@ static const char *scr_assert_cf_bytes_class(ScrBytesElem elem) {
|
||||
switch (elem) {
|
||||
case SCR_BYTES_U8: return "Uint8Array";
|
||||
case SCR_BYTES_U32: return "Uint32Array";
|
||||
case SCR_BYTES_F16: return "Float16Array";
|
||||
case SCR_BYTES_F32: return "Float32Array";
|
||||
case SCR_BYTES_I32: return "Int32Array";
|
||||
case SCR_BYTES_F64: return "Float64Array";
|
||||
|
||||
@@ -87,10 +87,60 @@ static void scr_bytes_oom(void) {
|
||||
scr_trap("scriptc: out of memory\n");
|
||||
}
|
||||
|
||||
uint16_t scr_f16_from_f64(double value) {
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &value, sizeof bits);
|
||||
uint16_t sign = (uint16_t)((bits >> 48) & 0x8000);
|
||||
uint64_t magnitude = bits & UINT64_C(0x7fffffffffffffff);
|
||||
if (magnitude >= UINT64_C(0x7ff0000000000000)) {
|
||||
if (magnitude == UINT64_C(0x7ff0000000000000)) return sign | 0x7c00;
|
||||
return sign | 0x7e00 | (uint16_t)((magnitude >> 42) & 0x3ff);
|
||||
}
|
||||
int exponent = (int)(magnitude >> 52) - 1023;
|
||||
if (exponent > 15) return sign | 0x7c00;
|
||||
uint64_t fraction = magnitude & ((UINT64_C(1) << 52) - 1);
|
||||
uint64_t significand = exponent == -1023 ? fraction : fraction | (UINT64_C(1) << 52);
|
||||
if (exponent == -1023) exponent = -1022;
|
||||
int biased = exponent + 15;
|
||||
/* Normal results keep 10 of the 52 fraction bits; subnormal results
|
||||
* shift further, by how far the exponent is below the normal range. */
|
||||
int shift = biased >= 1 ? 42 : 42 + (1 - biased);
|
||||
if (shift >= 54) return sign;
|
||||
uint64_t q = significand >> shift;
|
||||
uint64_t rest = significand & ((UINT64_C(1) << shift) - 1);
|
||||
uint64_t half = UINT64_C(1) << (shift - 1);
|
||||
if (rest > half || (rest == half && (q & 1))) q++;
|
||||
if (biased < 1) return sign | (uint16_t)q; /* a carry into 0x400 is the smallest normal */
|
||||
if (q == 2048) {
|
||||
q = 1024;
|
||||
biased++;
|
||||
}
|
||||
if (biased >= 31) return sign | 0x7c00;
|
||||
return sign | (uint16_t)(biased << 10) | (uint16_t)(q & 0x3ff);
|
||||
}
|
||||
|
||||
double scr_f16_to_f64(uint16_t h) {
|
||||
uint64_t sign = (uint64_t)(h >> 15) << 63;
|
||||
unsigned exponent = (h >> 10) & 0x1f, fraction = h & 0x3ff;
|
||||
uint64_t bits;
|
||||
if (exponent == 0) {
|
||||
double v = (double)fraction * 5.9604644775390625e-8; /* fraction * 2^-24, exact */
|
||||
memcpy(&bits, &v, sizeof bits);
|
||||
bits |= sign;
|
||||
} else if (exponent == 31) {
|
||||
bits = sign | UINT64_C(0x7ff0000000000000) | ((uint64_t)fraction << 42);
|
||||
} else {
|
||||
bits = sign | ((uint64_t)(exponent - 15 + 1023) << 52) | ((uint64_t)fraction << 42);
|
||||
}
|
||||
double out;
|
||||
memcpy(&out, &bits, sizeof out);
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t scr_bytes_elem_size(ScrBytesElem elem) {
|
||||
switch (elem) {
|
||||
case SCR_BYTES_U8: case SCR_BYTES_U8C: case SCR_BYTES_I8: return 1;
|
||||
case SCR_BYTES_U16: case SCR_BYTES_I16: return 2;
|
||||
case SCR_BYTES_U16: case SCR_BYTES_I16: case SCR_BYTES_F16: return 2;
|
||||
case SCR_BYTES_U32: case SCR_BYTES_I32: case SCR_BYTES_F32: return 4;
|
||||
case SCR_BYTES_F64: return 8;
|
||||
}
|
||||
@@ -106,6 +156,7 @@ const char *scr_bytes_elem_name(ScrBytesElem elem) {
|
||||
case SCR_BYTES_I16: return "Int16Array";
|
||||
case SCR_BYTES_U32: return "Uint32Array";
|
||||
case SCR_BYTES_I32: return "Int32Array";
|
||||
case SCR_BYTES_F16: return "Float16Array";
|
||||
case SCR_BYTES_F32: return "Float32Array";
|
||||
case SCR_BYTES_F64: return "Float64Array";
|
||||
}
|
||||
@@ -329,6 +380,11 @@ static double scr_bytes_decode(ScrBytesElem elem, const uint8_t *p) {
|
||||
memcpy(&v, p, 4);
|
||||
return (double)v;
|
||||
}
|
||||
case SCR_BYTES_F16: {
|
||||
uint16_t v;
|
||||
memcpy(&v, p, 2);
|
||||
return scr_f16_to_f64(v);
|
||||
}
|
||||
case SCR_BYTES_F32: {
|
||||
float v;
|
||||
memcpy(&v, p, 4);
|
||||
@@ -368,6 +424,11 @@ static void scr_bytes_encode(ScrBytesElem elem, uint8_t *p, double v) {
|
||||
memcpy(p, &u, 4);
|
||||
break;
|
||||
}
|
||||
case SCR_BYTES_F16: {
|
||||
uint16_t h = scr_f16_from_f64(v);
|
||||
memcpy(p, &h, 2);
|
||||
break;
|
||||
}
|
||||
case SCR_BYTES_F32: {
|
||||
float f = (float)v; /* round-to-nearest-even, exactly Float32Array */
|
||||
memcpy(p, &f, 4);
|
||||
@@ -511,6 +572,13 @@ static void scr_bytes_read_numbers(double *out, const uint8_t *src, ScrBytesElem
|
||||
SCR_READ_NUMBERS(SCR_BYTES_I32, int32_t);
|
||||
SCR_READ_NUMBERS(SCR_BYTES_F32, float);
|
||||
SCR_READ_NUMBERS(SCR_BYTES_F64, double);
|
||||
case SCR_BYTES_F16:
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
uint16_t value;
|
||||
memcpy(&value, src + i * sizeof value, sizeof value);
|
||||
out[i] = scr_f16_to_f64(value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#undef SCR_READ_NUMBERS
|
||||
}
|
||||
@@ -535,6 +603,9 @@ static void scr_bytes_write_numbers(uint8_t *dst, ScrBytesElem elem, const doubl
|
||||
case SCR_BYTES_U32: case SCR_BYTES_I32: {
|
||||
SCR_WRITE_NUMBERS(uint32_t, scr_numeric_to_u32(src[i]));
|
||||
}
|
||||
case SCR_BYTES_F16: {
|
||||
SCR_WRITE_NUMBERS(uint16_t, scr_f16_from_f64(src[i]));
|
||||
}
|
||||
case SCR_BYTES_F32: {
|
||||
SCR_WRITE_NUMBERS(float, (float)src[i]);
|
||||
}
|
||||
@@ -936,6 +1007,7 @@ static size_t scr_dataview_get_size(ScrDataViewGet kind) {
|
||||
return 1;
|
||||
case SCR_DV_U16:
|
||||
case SCR_DV_I16:
|
||||
case SCR_DV_F16:
|
||||
return 2;
|
||||
case SCR_DV_U32:
|
||||
case SCR_DV_I32:
|
||||
@@ -974,6 +1046,8 @@ double scr_dataview_get(const ScrBytes *b, double byte_off, ScrDataViewGet kind,
|
||||
return (double)(int16_t)u;
|
||||
case SCR_DV_I32:
|
||||
return (double)(int32_t)u;
|
||||
case SCR_DV_F16:
|
||||
return scr_f16_to_f64((uint16_t)u);
|
||||
case SCR_DV_F32: {
|
||||
uint32_t bits = (uint32_t)u;
|
||||
float f;
|
||||
@@ -1018,6 +1092,9 @@ void scr_dataview_set(ScrBytes *b, double byte_off, double value, ScrDataViewGet
|
||||
case SCR_DV_I32:
|
||||
u = (uint64_t)scr_bytes_to_u32(value);
|
||||
break;
|
||||
case SCR_DV_F16:
|
||||
u = scr_f16_from_f64(value);
|
||||
break;
|
||||
case SCR_DV_F32: {
|
||||
float f = (float)value;
|
||||
uint32_t bits;
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
* Elements are scalars only and the backing edge is acyclic by
|
||||
* construction (owners point at nothing): never part of a cycle, no
|
||||
* trace. Element reads widen to double; writes coerce JS-exactly (ToUint8
|
||||
* / ToUint32 modular truncation, double→float rounding for f32).
|
||||
* / ToUint32 modular truncation, double→float rounding for f32, one
|
||||
* double→binary16 rounding for f16).
|
||||
* Out-of-bounds typed ELEMENT reads trap like arrays; invalid writes are
|
||||
* ignored as in JavaScript. The Node-shaped operations
|
||||
* (construction lengths, set(), the read/write numeric families, the
|
||||
@@ -37,7 +38,16 @@ typedef enum ScrBytesElem {
|
||||
SCR_BYTES_U16, /* Uint16Array */
|
||||
SCR_BYTES_I16, /* Int16Array */
|
||||
SCR_BYTES_U8C, /* Uint8ClampedArray */
|
||||
SCR_BYTES_F16, /* Float16Array (IEEE 754 binary16 storage) */
|
||||
} ScrBytesElem;
|
||||
#define SCR_BYTES_ELEM_COUNT 10
|
||||
|
||||
/* Float16Array's element conversions: one round-to-nearest-even step from
|
||||
* the double (Float16Array stores, Math.f16round and DataView.setFloat16
|
||||
* all round this way), and the exact widening back. NaN keeps its sign and
|
||||
* top payload bits with the quiet bit set. */
|
||||
uint16_t scr_f16_from_f64(double value);
|
||||
double scr_f16_to_f64(uint16_t bits);
|
||||
|
||||
typedef struct ScrSharedBytes ScrSharedBytes;
|
||||
|
||||
@@ -149,6 +159,7 @@ ScrBytes *scr_array_buffer_view_i16(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_u8(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_u32(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_i32(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_f16(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_f32(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_f64(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
ScrBytes *scr_array_buffer_view_dv(ScrDyn *, ScrDyn *, ScrDyn *);
|
||||
@@ -206,7 +217,7 @@ ScrBytes *scr_dataview_new(ScrBytes *src, double byte_off, bool has_len, double
|
||||
* with the exception pending). */
|
||||
typedef enum ScrDataViewGet {
|
||||
SCR_DV_U8, SCR_DV_I8, SCR_DV_U16, SCR_DV_I16, SCR_DV_U32, SCR_DV_I32,
|
||||
SCR_DV_F32, SCR_DV_F64, SCR_DV_BIGU64, SCR_DV_BIGI64,
|
||||
SCR_DV_F32, SCR_DV_F64, SCR_DV_BIGU64, SCR_DV_BIGI64, SCR_DV_F16,
|
||||
} ScrDataViewGet;
|
||||
double scr_dataview_get(const ScrBytes *b, double byte_off, ScrDataViewGet kind, bool le);
|
||||
|
||||
|
||||
@@ -1520,7 +1520,7 @@ static ScrDyn *scr_dyn_invoke_impl(
|
||||
if (recv->kind == SCR_DYN_BYTES) {
|
||||
ScrBytes *bytes = recv->v.bytes;
|
||||
if (bytes->is_data_view) {
|
||||
static const char *const kinds[] = { "Uint8", "Int8", "Uint16", "Int16", "Uint32", "Int32", "Float32", "Float64", "BigUint64", "BigInt64" };
|
||||
static const char *const kinds[] = { "Uint8", "Int8", "Uint16", "Int16", "Uint32", "Int32", "Float32", "Float64", "BigUint64", "BigInt64", "Float16" };
|
||||
const bool get = !strncmp(method, "get", 3);
|
||||
const bool set = !strncmp(method, "set", 3);
|
||||
for (size_t kind = 0; (get || set) && kind < sizeof kinds / sizeof kinds[0]; kind++) {
|
||||
@@ -1537,7 +1537,7 @@ static ScrDyn *scr_dyn_invoke_impl(
|
||||
}
|
||||
const bool le = argc > (get ? 1 : 2) && scr_dyn_truthy(args[get ? 1 : 2]);
|
||||
if (get) {
|
||||
if (kind >= SCR_DV_BIGU64) {
|
||||
if (kind == SCR_DV_BIGU64 || kind == SCR_DV_BIGI64) {
|
||||
ScrBigInt *value = scr_bigint_dataview_get(bytes, offset, kind == SCR_DV_BIGI64, le);
|
||||
if (scr_exc_pending()) return NULL;
|
||||
ScrDyn *result = scr_dyn_new_bigint(value);
|
||||
@@ -1547,7 +1547,7 @@ static ScrDyn *scr_dyn_invoke_impl(
|
||||
double value = scr_dataview_get(bytes, offset, (ScrDataViewGet)kind, le);
|
||||
return scr_exc_pending() ? NULL : scr_dyn_new_num(value);
|
||||
}
|
||||
if (kind >= SCR_DV_BIGU64) {
|
||||
if (kind == SCR_DV_BIGU64 || kind == SCR_DV_BIGI64) {
|
||||
ScrBigInt *value = scr_dyn_bigint_coerce(argc > 1 ? args[1] : scr_dyn_undefined());
|
||||
if (scr_exc_pending()) return NULL;
|
||||
scr_bigint_dataview_set(bytes, offset, value, le);
|
||||
|
||||
@@ -3146,6 +3146,7 @@ bool scr_dyn_util_type_is(const ScrDyn *value, const ScrStr *probe) {
|
||||
if (PROBE("isInt8Array")) return scr_dyn_typed_array_is(value, SCR_BYTES_I8);
|
||||
if (PROBE("isInt16Array")) return scr_dyn_typed_array_is(value, SCR_BYTES_I16);
|
||||
if (PROBE("isInt32Array")) return scr_dyn_typed_array_is(value, SCR_BYTES_I32);
|
||||
if (PROBE("isFloat16Array")) return scr_dyn_typed_array_is(value, SCR_BYTES_F16);
|
||||
if (PROBE("isFloat32Array")) return scr_dyn_typed_array_is(value, SCR_BYTES_F32);
|
||||
if (PROBE("isFloat64Array")) return scr_dyn_typed_array_is(value, SCR_BYTES_F64);
|
||||
if (PROBE("isMap")) return value->kind == SCR_DYN_HANDLE && value->v.handle.tag == SCR_DYNH_MAP;
|
||||
@@ -3162,13 +3163,11 @@ bool scr_dyn_util_type_is(const ScrDyn *value, const ScrStr *probe) {
|
||||
if (PROBE("isMapIterator")) return scr_native_iterator_over(value, 2);
|
||||
if (PROBE("isSetIterator")) return scr_native_iterator_over(value, 3);
|
||||
if (PROBE("isKeyObject")) return value->kind == SCR_DYN_HANDLE && value->v.handle.tag == SCR_DYNH_KEY_OBJECT;
|
||||
/* Boxed primitives, BigInt64Array, BigUint64Array, Float16Array, CryptoKey
|
||||
* and external values cannot be created here, so no value has these
|
||||
* brands. */
|
||||
/* Boxed primitives, BigInt64Array, BigUint64Array, CryptoKey and external
|
||||
* values cannot be created here, so no value has these brands. */
|
||||
if (PROBE("isNumberObject") || PROBE("isStringObject") || PROBE("isBooleanObject") ||
|
||||
PROBE("isBigIntObject") || PROBE("isSymbolObject") || PROBE("isBoxedPrimitive") ||
|
||||
PROBE("isBigInt64Array") || PROBE("isBigUint64Array") || PROBE("isFloat16Array") ||
|
||||
PROBE("isCryptoKey") || PROBE("isExternal"))
|
||||
PROBE("isBigInt64Array") || PROBE("isBigUint64Array") || PROBE("isCryptoKey") || PROBE("isExternal"))
|
||||
return false;
|
||||
if (PROBE("isNativeError")) {
|
||||
ScrError *error = scr_errdyn_err_of(value);
|
||||
@@ -3184,7 +3183,7 @@ bool scr_dyn_util_type_is(const ScrDyn *value, const ScrStr *probe) {
|
||||
* anonymous with length zero. Keep their native closure identity intact. */
|
||||
ScrDyn *scr_dyn_util_type_value(const ScrDyn *value, const ScrStr *probe) {
|
||||
static const char *const named[] = { "isDataView", "isTypedArray", "isUint8Array", "isUint8ClampedArray", "isUint16Array", "isUint32Array",
|
||||
"isInt8Array", "isInt16Array", "isInt32Array", "isFloat32Array", "isFloat64Array" };
|
||||
"isInt8Array", "isInt16Array", "isInt32Array", "isFloat16Array", "isFloat32Array", "isFloat64Array" };
|
||||
const char *name = "";
|
||||
if (probe->len == 17 && memcmp(probe->data, "isArrayBufferView", 17) == 0) name = "isView";
|
||||
for (size_t i = 0; i < sizeof named / sizeof named[0]; i++)
|
||||
@@ -3203,16 +3202,16 @@ ScrBytes *scr_dyn_bytes_unbox(const ScrDyn *d) {
|
||||
/* Numeric typed-array constructor values share native function identity.
|
||||
* The cache owns one reference until runtime cleanup; arbitrary strings or
|
||||
* functions cannot impersonate one of these constructors. */
|
||||
static SCR_TL ScrDyn *scr_bytes_ctors[9];
|
||||
static SCR_TL ScrDyn *scr_bytes_ctors[SCR_BYTES_ELEM_COUNT];
|
||||
static void scr_bytes_ctors_cleanup(void) {
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
for (size_t i = 0; i < SCR_BYTES_ELEM_COUNT; i++) {
|
||||
scr_dyn_release(scr_bytes_ctors[i]);
|
||||
scr_bytes_ctors[i] = NULL;
|
||||
}
|
||||
}
|
||||
static ScrDyn *scr_bytes_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
|
||||
(void)args; (void)argc;
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
for (size_t i = 0; i < SCR_BYTES_ELEM_COUNT; i++) {
|
||||
if (!scr_bytes_ctors[i] || scr_bytes_ctors[i]->v.fn.clo != closure) continue;
|
||||
ScrJsonBuf message;
|
||||
scr_jb_init(&message);
|
||||
@@ -3228,7 +3227,7 @@ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function);
|
||||
static ScrDyn *scr_bytes_constructor_for(ScrBytesElem elem) {
|
||||
if (!scr_bytes_ctors[elem]) {
|
||||
bool initialized = false;
|
||||
for (size_t i = 0; i < 9; i++) if (scr_bytes_ctors[i]) initialized = true;
|
||||
for (size_t i = 0; i < SCR_BYTES_ELEM_COUNT; i++) if (scr_bytes_ctors[i]) initialized = true;
|
||||
if (!initialized) scr_atexit(scr_bytes_ctors_cleanup);
|
||||
scr_bytes_ctors[elem] = scr_dyn_new_func(scr_closure_new(NULL, 0),
|
||||
scr_bytes_ctor_call, 3, "typed-array-constructor", scr_bytes_elem_name(elem));
|
||||
@@ -3241,7 +3240,7 @@ static ScrDyn *scr_bytes_constructor_for(ScrBytesElem elem) {
|
||||
return scr_dyn_retain(scr_bytes_ctors[elem]);
|
||||
}
|
||||
ScrDyn *scr_bytes_constructor(const ScrStr *name) {
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
for (size_t i = 0; i < SCR_BYTES_ELEM_COUNT; i++) {
|
||||
const char *candidate = scr_bytes_elem_name((ScrBytesElem)i);
|
||||
if (strlen(candidate) == name->len && memcmp(candidate, name->data, name->len) == 0)
|
||||
return scr_bytes_constructor_for((ScrBytesElem)i);
|
||||
@@ -3308,7 +3307,7 @@ bool scr_bytes_instanceof(const ScrDyn *value, const ScrDyn *callee) {
|
||||
}
|
||||
if (scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo) return scr_array_buffer_is(value);
|
||||
if (scr_array_ctor && callee->v.fn.clo == scr_array_ctor->v.fn.clo) return value->kind == SCR_DYN_ARR || scr_dyn_ref_is_array(value);
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
for (size_t i = 0; i < SCR_BYTES_ELEM_COUNT; i++) {
|
||||
if (scr_bytes_ctors[i] && callee->v.fn.clo == scr_bytes_ctors[i]->v.fn.clo)
|
||||
return scr_dyn_typed_array_is(value, (int)i);
|
||||
}
|
||||
@@ -3321,7 +3320,7 @@ ScrDyn *scr_bytes_construct(const ScrDyn *callee, const ScrDyn *args, const ScrS
|
||||
return scr_array_ctor_call(callee->v.fn.clo, args->v.arr.items, args->v.arr.len);
|
||||
if (callee->kind == SCR_DYN_FUNC && scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo)
|
||||
return scr_array_buffer_new(args->v.arr.len ? args->v.arr.items[0] : scr_dyn_undefined());
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
for (size_t i = 0; i < SCR_BYTES_ELEM_COUNT; i++) {
|
||||
if (callee->kind != SCR_DYN_FUNC || !scr_bytes_ctors[i] || callee->v.fn.clo != scr_bytes_ctors[i]->v.fn.clo) continue;
|
||||
const ScrDyn *input = args->v.arr.len > 0 ? args->v.arr.items[0] : scr_dyn_undefined();
|
||||
const ScrDyn *offset = args->v.arr.len > 1 ? args->v.arr.items[1] : scr_dyn_undefined();
|
||||
@@ -12377,6 +12376,7 @@ SCR_ARRAY_BUFFER_VIEW(i16, SCR_BYTES_I16)
|
||||
SCR_ARRAY_BUFFER_VIEW(u8, SCR_BYTES_U8)
|
||||
SCR_ARRAY_BUFFER_VIEW(u32, SCR_BYTES_U32)
|
||||
SCR_ARRAY_BUFFER_VIEW(i32, SCR_BYTES_I32)
|
||||
SCR_ARRAY_BUFFER_VIEW(f16, SCR_BYTES_F16)
|
||||
SCR_ARRAY_BUFFER_VIEW(f32, SCR_BYTES_F32)
|
||||
SCR_ARRAY_BUFFER_VIEW(f64, SCR_BYTES_F64)
|
||||
#undef SCR_ARRAY_BUFFER_VIEW
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// util.types brand checks over typed values: isDate, isSharedArrayBuffer,
|
||||
// isMapIterator, isSetIterator and isKeyObject answer from the value's
|
||||
// internal brand, and isBoxedPrimitive (with the per-kind boxed checks),
|
||||
// isBigInt64Array, isBigUint64Array, isFloat16Array, isCryptoKey and
|
||||
// isExternal answer false for every value a program here can create. A
|
||||
// Date-typed argument answers from its static type.
|
||||
// isBigInt64Array, isBigUint64Array, isCryptoKey and isExternal answer
|
||||
// false for every value a program here can create. A Date-typed argument
|
||||
// answers from its static type.
|
||||
import { types } from "node:util";
|
||||
import * as direct from "node:util/types";
|
||||
import { createSecretKey } from "node:crypto";
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// Float16Array: construction from lengths, arrays, typed arrays and ArrayBuffer
|
||||
// views; round-to-nearest-even stores with overflow, NaN, -0 and subnormals;
|
||||
// fill, set, subarray, slice and both sort orders; DataView getFloat16 and
|
||||
// setFloat16 in both byte orders; Math.f16round; util.types and instanceof;
|
||||
// structuredClone, assert and Buffer views. Node.js prints the same.
|
||||
import { types } from "node:util";
|
||||
import assert from "node:assert";
|
||||
const show = (label: string, a: Float16Array): void => console.log(label, a.length, Array.from(a).join(","));
|
||||
const a = new Float16Array(6);
|
||||
a[0] = 1.5;
|
||||
a[1] = 65519;
|
||||
a[2] = 65520;
|
||||
a[3] = 0.1;
|
||||
a[4] = -0;
|
||||
a[5] = 5.960464477539063e-8 / 2;
|
||||
show("rounding", a);
|
||||
const b = new Float16Array([NaN, Infinity, -Infinity, 1e-8, 2049, 2051, 4097, -1e6]);
|
||||
show("specials", b);
|
||||
console.log(Object.is(a[4], -0), a[6], a.length, a.byteLength, Number.isNaN(b[0]));
|
||||
const c = Float16Array.from([3.14159, 2.71828, 1.41421]);
|
||||
show("from", c);
|
||||
const e = new Float16Array(c);
|
||||
e[0] = 100;
|
||||
show("copy", e);
|
||||
show("source untouched", c);
|
||||
const f32 = new Float32Array([1 / 3, 2 / 3]);
|
||||
show("from f32", new Float16Array(f32));
|
||||
const buf = new ArrayBuffer(8);
|
||||
const view = new Float16Array(buf, 2, 2);
|
||||
view[0] = 1;
|
||||
view[1] = -2;
|
||||
console.log("view bytes", Array.from(new Uint8Array(buf)).join(","), new Uint16Array(buf)[1]);
|
||||
const g = new Float16Array(5);
|
||||
g.fill(0.3);
|
||||
show("fill", g);
|
||||
g.set([1.1, 2.2], 3);
|
||||
show("set", g);
|
||||
show("subarray", g.subarray(1, 4));
|
||||
show("slice", g.slice(-2));
|
||||
const h = new Float16Array([3, -0, 0, NaN, -1, 2.5, -Infinity, 0.1]);
|
||||
show("sort", h.slice().sort());
|
||||
show("sort desc", h.slice().sort((x, y) => y - x));
|
||||
show("toSorted", h.toSorted());
|
||||
let sum = 0;
|
||||
for (const v of c) sum += v;
|
||||
console.log("for-of", sum, h.join("|"), String(c), Object.prototype.toString.call(c));
|
||||
const dv = new DataView(new ArrayBuffer(8));
|
||||
dv.setFloat16(0, 3.14159);
|
||||
dv.setFloat16(2, 3.14159, true);
|
||||
dv.setFloat16(4, -65504);
|
||||
dv.setFloat16(6, NaN, true);
|
||||
console.log("dataview", dv.getFloat16(0), dv.getFloat16(2, true), dv.getFloat16(4), dv.getFloat16(6, true), dv.getUint16(0), dv.getUint16(2));
|
||||
try {
|
||||
dv.getFloat16(7);
|
||||
} catch (err) {
|
||||
console.log((err as Error).name, (err as Error).message);
|
||||
}
|
||||
console.log("f16round", Math.f16round(1.337), Math.f16round(65520), Math.f16round(-0), Math.f16round(5e-8), Math.f16round(2 ** -25), Math.f16round(1.0009765625 + 2 ** -12));
|
||||
console.log("types", types.isFloat16Array(a), types.isFloat32Array(a), types.isTypedArray(a), a instanceof Float16Array);
|
||||
const u: unknown = a;
|
||||
console.log("unknown", u instanceof Float16Array, u instanceof Float32Array);
|
||||
const big = new Float16Array(1000);
|
||||
for (let i = 0; i < big.length; i++) big[i] = Math.sin(i) * 1000;
|
||||
let acc = 0;
|
||||
for (let i = 0; i < big.length; i++) acc += big[i]!;
|
||||
console.log("loop", acc, big[999]);
|
||||
const f = new Float16Array([1.5, NaN, -0, 65504]);
|
||||
const clone = structuredClone(f);
|
||||
clone[0] = 2;
|
||||
console.log(clone[0], f[0], clone.length);
|
||||
assert.deepStrictEqual(new Float16Array([NaN, 1]), new Float16Array([NaN, 1]));
|
||||
try {
|
||||
assert.deepStrictEqual(new Float16Array([0]), new Float16Array([-0]));
|
||||
} catch (e) {
|
||||
console.log("deepStrictEqual -0", (e as Error).name);
|
||||
}
|
||||
assert.deepEqual(new Float16Array([0]), new Float16Array([-0]));
|
||||
const raw = Buffer.from(f.buffer);
|
||||
console.log(raw.length, raw.readUInt16LE(0), raw.readUInt16LE(6));
|
||||
const fromBuf = new Float16Array(f.buffer, 2, 1);
|
||||
console.log(Number.isNaN(fromBuf[0]));
|
||||
const list: Float16Array[] = [f, new Float16Array(2)];
|
||||
const m = new Map<string, Float16Array>([["a", f]]);
|
||||
console.log(list.length, m.get("a")![3], list[1]!.length);
|
||||
const Ctor = Float16Array;
|
||||
const x = new Ctor(3);
|
||||
x[1] = 0.2;
|
||||
console.log(x.length, x[1]);
|
||||
const y = new Float16Array([1, 2]);
|
||||
const D = y.constructor as Float16ArrayConstructor;
|
||||
const z = new D(2);
|
||||
console.log(z.length, z instanceof Float16Array);
|
||||
const unknownView: unknown = new Float16Array([7]);
|
||||
console.log(unknownView instanceof Float16Array);
|
||||
@@ -0,0 +1,95 @@
|
||||
// Float16Array from JavaScript: construction from lengths, arrays, typed
|
||||
// arrays and ArrayBuffer views; round-to-nearest-even stores with overflow,
|
||||
// NaN, -0 and subnormals; fill, set, subarray, slice and both sort orders;
|
||||
// DataView getFloat16 and setFloat16 in both byte orders; Math.f16round;
|
||||
// util.types and instanceof; structuredClone, assert and Buffer views.
|
||||
// Node.js prints the same.
|
||||
import { types } from "node:util";
|
||||
import assert from "node:assert";
|
||||
const show = (label , a ) => console.log(label, a.length, Array.from(a).join(","));
|
||||
const a = new Float16Array(6);
|
||||
a[0] = 1.5;
|
||||
a[1] = 65519;
|
||||
a[2] = 65520;
|
||||
a[3] = 0.1;
|
||||
a[4] = -0;
|
||||
a[5] = 5.960464477539063e-8 / 2;
|
||||
show("rounding", a);
|
||||
const b = new Float16Array([NaN, Infinity, -Infinity, 1e-8, 2049, 2051, 4097, -1e6]);
|
||||
show("specials", b);
|
||||
console.log(Object.is(a[4], -0), a[6], a.length, a.byteLength, Number.isNaN(b[0]));
|
||||
const c = Float16Array.from([3.14159, 2.71828, 1.41421]);
|
||||
show("from", c);
|
||||
const e = new Float16Array(c);
|
||||
e[0] = 100;
|
||||
show("copy", e);
|
||||
show("source untouched", c);
|
||||
const f32 = new Float32Array([1 / 3, 2 / 3]);
|
||||
show("from f32", new Float16Array(f32));
|
||||
const buf = new ArrayBuffer(8);
|
||||
const view = new Float16Array(buf, 2, 2);
|
||||
view[0] = 1;
|
||||
view[1] = -2;
|
||||
console.log("view bytes", Array.from(new Uint8Array(buf)).join(","), new Uint16Array(buf)[1]);
|
||||
const g = new Float16Array(5);
|
||||
g.fill(0.3);
|
||||
show("fill", g);
|
||||
g.set([1.1, 2.2], 3);
|
||||
show("set", g);
|
||||
show("subarray", g.subarray(1, 4));
|
||||
show("slice", g.slice(-2));
|
||||
const h = new Float16Array([3, -0, 0, NaN, -1, 2.5, -Infinity, 0.1]);
|
||||
show("sort", h.slice().sort());
|
||||
show("sort desc", h.slice().sort((x, y) => y - x));
|
||||
show("toSorted", h.toSorted());
|
||||
let sum = 0;
|
||||
for (const v of c) sum += v;
|
||||
console.log("for-of", sum, h.join("|"), String(c), Object.prototype.toString.call(c));
|
||||
const dv = new DataView(new ArrayBuffer(8));
|
||||
dv.setFloat16(0, 3.14159);
|
||||
dv.setFloat16(2, 3.14159, true);
|
||||
dv.setFloat16(4, -65504);
|
||||
dv.setFloat16(6, NaN, true);
|
||||
console.log("dataview", dv.getFloat16(0), dv.getFloat16(2, true), dv.getFloat16(4), dv.getFloat16(6, true), dv.getUint16(0), dv.getUint16(2));
|
||||
try {
|
||||
dv.getFloat16(7);
|
||||
} catch (err) {
|
||||
console.log((err ).name, (err ).message);
|
||||
}
|
||||
console.log("f16round", Math.f16round(1.337), Math.f16round(65520), Math.f16round(-0), Math.f16round(5e-8), Math.f16round(2 ** -25), Math.f16round(1.0009765625 + 2 ** -12));
|
||||
console.log("types", types.isFloat16Array(a), types.isFloat32Array(a), types.isTypedArray(a), a instanceof Float16Array);
|
||||
const u = a;
|
||||
console.log("unknown", u instanceof Float16Array, u instanceof Float32Array);
|
||||
const big = new Float16Array(1000);
|
||||
for (let i = 0; i < big.length; i++) big[i] = Math.sin(i) * 1000;
|
||||
let acc = 0;
|
||||
for (let i = 0; i < big.length; i++) acc += big[i] ;
|
||||
console.log("loop", acc, big[999]);
|
||||
const f = new Float16Array([1.5, NaN, -0, 65504]);
|
||||
const clone = structuredClone(f);
|
||||
clone[0] = 2;
|
||||
console.log(clone[0], f[0], clone.length);
|
||||
assert.deepStrictEqual(new Float16Array([NaN, 1]), new Float16Array([NaN, 1]));
|
||||
try {
|
||||
assert.deepStrictEqual(new Float16Array([0]), new Float16Array([-0]));
|
||||
} catch (e) {
|
||||
console.log("deepStrictEqual -0", (e ).name);
|
||||
}
|
||||
assert.deepEqual(new Float16Array([0]), new Float16Array([-0]));
|
||||
const raw = Buffer.from(f.buffer);
|
||||
console.log(raw.length, raw.readUInt16LE(0), raw.readUInt16LE(6));
|
||||
const fromBuf = new Float16Array(f.buffer, 2, 1);
|
||||
console.log(Number.isNaN(fromBuf[0]));
|
||||
const list = [f, new Float16Array(2)];
|
||||
const m = new Map ([["a", f]]);
|
||||
console.log(list.length, m.get("a") [3], list[1] .length);
|
||||
const Ctor = Float16Array;
|
||||
const x = new Ctor(3);
|
||||
x[1] = 0.2;
|
||||
console.log(x.length, x[1]);
|
||||
const y = new Float16Array([1, 2]);
|
||||
const D = y.constructor ;
|
||||
const z = new D(2);
|
||||
console.log(z.length, z instanceof Float16Array);
|
||||
const unknownView = new Float16Array([7]);
|
||||
console.log(unknownView instanceof Float16Array);
|
||||
@@ -1,6 +1,8 @@
|
||||
// Stored ArrayBuffers and DataViews lower; Float16 accessors remain unsupported.
|
||||
// Stored ArrayBuffers and DataViews lower, Float16 accessors included;
|
||||
// detached accessor methods remain unsupported.
|
||||
const buffer = new ArrayBuffer(16);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat16(0, 1.5);
|
||||
console.log(view.getFloat16(0));
|
||||
const getter = view.getFloat16;
|
||||
// End of the diagnostic fixture.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// The es2025-lib surface WITHOUT a lowering fences by name: resizable
|
||||
// ArrayBuffers and transfer, SharedArrayBuffer.grow, Atomics.waitAsync,
|
||||
// Float16Array and its Math/DataView companions, first-class iterator
|
||||
// objects, and the unlowered forms of the implemented statics
|
||||
// (Promise.try with fewer arguments than parameters, groupBy's
|
||||
// literal-union keys, a set-like non-Set argument).
|
||||
// first-class iterator objects, and the unlowered forms of the
|
||||
// implemented statics (Promise.try with fewer arguments than parameters,
|
||||
// groupBy's literal-union keys, a set-like non-Set argument).
|
||||
|
||||
// Resizable ArrayBuffer + transfer (ES2024).
|
||||
const ab = new ArrayBuffer(8, { maxByteLength: 16 });
|
||||
@@ -22,12 +21,6 @@ sab.grow(16);
|
||||
const ia = new Int32Array(4);
|
||||
const waited = Atomics.waitAsync(ia, 0, 0, 1);
|
||||
|
||||
// Float16 (ES2025): the typed array, Math.f16round, DataView accessors.
|
||||
const f16 = new Float16Array(4);
|
||||
console.log(Math.f16round(1.337));
|
||||
const dv = new DataView(new Uint8Array(8).buffer);
|
||||
dv.setFloat16(0, 1.5);
|
||||
|
||||
// First-class iterator objects.
|
||||
const it = Iterator.from([1, 2, 3].values());
|
||||
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
dataview.ts:4:1 - error SC2020: 'DataView<ArrayBuffer>.setFloat16' is part of the standard library types but has no scriptc lowering yet
|
||||
dataview.ts:7:16 - error SC2020: 'DataView<ArrayBuffer>.getFloat16' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
3 | const view = new DataView(buffer);
|
||||
4 | view.setFloat16(0, 1.5);
|
||||
| ^~~~~~~~~~~~~~~
|
||||
5 | console.log(view.getFloat16(0));
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
dataview.ts:5:13 - error SC2020: 'DataView<ArrayBuffer>.getFloat16' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
4 | view.setFloat16(0, 1.5);
|
||||
5 | console.log(view.getFloat16(0));
|
||||
| ^~~~~~~~~~~~~~~
|
||||
6 | // End of the diagnostic fixture.
|
||||
6 | console.log(view.getFloat16(0));
|
||||
7 | const getter = view.getFloat16;
|
||||
| ^~~~~~~~~~~~~~~
|
||||
8 | // End of the diagnostic fixture.
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
@@ -1,125 +1,89 @@
|
||||
es2025-fences.ts:9:12 - error SC2020: 'resizable ArrayBuffer construction' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:8:12 - error SC2020: 'resizable ArrayBuffer construction' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
8 | // Resizable ArrayBuffer + transfer (ES2024).
|
||||
9 | const ab = new ArrayBuffer(8, { maxByteLength: 16 });
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
10 | ab.resize(16);
|
||||
7 | // Resizable ArrayBuffer + transfer (ES2024).
|
||||
8 | const ab = new ArrayBuffer(8, { maxByteLength: 16 });
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
9 | ab.resize(16);
|
||||
|
||||
hint: fixed-length ArrayBuffers accept a byte length; resizable storage is not supported yet
|
||||
|
||||
es2025-fences.ts:15:27 - error SC2020: 'resizable ArrayBuffer construction' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:14:27 - error SC2020: 'resizable ArrayBuffer construction' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
14 | // fixed-length new Uint8Array(new ArrayBuffer(8)) lowers).
|
||||
15 | const rz = new Uint8Array(new ArrayBuffer(8, { maxByteLength: 16 }));
|
||||
13 | // fixed-length new Uint8Array(new ArrayBuffer(8)) lowers).
|
||||
14 | const rz = new Uint8Array(new ArrayBuffer(8, { maxByteLength: 16 }));
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
16 |
|
||||
15 |
|
||||
|
||||
hint: fixed-length ArrayBuffers accept a byte length; resizable storage is not supported yet
|
||||
|
||||
es2025-fences.ts:18:13 - error SC2020: 'resizable ArrayBuffer construction' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:17:13 - error SC2020: 'resizable ArrayBuffer construction' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
17 | // SharedArrayBuffer growth.
|
||||
18 | const sab = new SharedArrayBuffer(8, { maxByteLength: 16 });
|
||||
16 | // SharedArrayBuffer growth.
|
||||
17 | const sab = new SharedArrayBuffer(8, { maxByteLength: 16 });
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
19 | sab.grow(16);
|
||||
18 | sab.grow(16);
|
||||
|
||||
hint: fixed-length ArrayBuffers accept a byte length; resizable storage is not supported yet
|
||||
|
||||
es2025-fences.ts:23:7 - error SC2009: values of type '{ async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; }' cannot be compiled: the union shape is supported, but its arm '{ async: false; value: "not-equal" | "timed-out"; }' does not compile
|
||||
es2025-fences.ts:22:7 - error SC2009: values of type '{ async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; }' cannot be compiled: the union shape is supported, but its arm '{ async: false; value: "not-equal" | "timed-out"; }' does not compile
|
||||
|
||||
22 | const ia = new Int32Array(4);
|
||||
23 | const waited = Atomics.waitAsync(ia, 0, 0, 1);
|
||||
21 | const ia = new Int32Array(4);
|
||||
22 | const waited = Atomics.waitAsync(ia, 0, 0, 1);
|
||||
| ^~~~~~
|
||||
24 |
|
||||
23 |
|
||||
|
||||
hint: the outer shape is supported — the named component is the blocker; restate it inside the compilable set (number, string, boolean, arrays, Maps, Sets, RegExp, functions, classes, records, unions of those, and 'unknown')
|
||||
|
||||
es2025-fences.ts:23:16 - error SC2020: 'Atomics.waitAsync' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:22:16 - error SC2020: 'Atomics.waitAsync' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
22 | const ia = new Int32Array(4);
|
||||
23 | const waited = Atomics.waitAsync(ia, 0, 0, 1);
|
||||
21 | const ia = new Int32Array(4);
|
||||
22 | const waited = Atomics.waitAsync(ia, 0, 0, 1);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
24 |
|
||||
23 |
|
||||
|
||||
hint: use integer load, store, exchange, compareExchange, add, sub, and, or, xor, wait or notify
|
||||
|
||||
es2025-fences.ts:26:7 - error SC2020: 'Float16Array<ArrayBuffer>' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:25:7 - error SC2020: 'IteratorObject<number, undefined, unknown>' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
25 | // Float16 (ES2025): the typed array, Math.f16round, DataView accessors.
|
||||
26 | const f16 = new Float16Array(4);
|
||||
| ^~~
|
||||
27 | console.log(Math.f16round(1.337));
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
es2025-fences.ts:26:13 - error SC2020: 'new Float16Array' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
25 | // Float16 (ES2025): the typed array, Math.f16round, DataView accessors.
|
||||
26 | const f16 = new Float16Array(4);
|
||||
| ^~~~~~~~~~~~~~~~~~~
|
||||
27 | console.log(Math.f16round(1.337));
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
es2025-fences.ts:27:13 - error SC2020: 'Math.f16round' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
26 | const f16 = new Float16Array(4);
|
||||
27 | console.log(Math.f16round(1.337));
|
||||
| ^~~~~~~~~~~~~
|
||||
28 | const dv = new DataView(new Uint8Array(8).buffer);
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
es2025-fences.ts:29:1 - error SC2020: 'DataView<ArrayBuffer>.setFloat16' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
28 | const dv = new DataView(new Uint8Array(8).buffer);
|
||||
29 | dv.setFloat16(0, 1.5);
|
||||
| ^~~~~~~~~~~~~
|
||||
30 |
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
es2025-fences.ts:32:7 - error SC2020: 'IteratorObject<number, undefined, unknown>' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
31 | // First-class iterator objects.
|
||||
32 | const it = Iterator.from([1, 2, 3].values());
|
||||
24 | // First-class iterator objects.
|
||||
25 | const it = Iterator.from([1, 2, 3].values());
|
||||
| ^~
|
||||
33 |
|
||||
26 |
|
||||
|
||||
hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations)
|
||||
|
||||
es2025-fences.ts:32:12 - error SC2020: 'Iterator.from' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:25:12 - error SC2020: 'Iterator.from' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
31 | // First-class iterator objects.
|
||||
32 | const it = Iterator.from([1, 2, 3].values());
|
||||
24 | // First-class iterator objects.
|
||||
25 | const it = Iterator.from([1, 2, 3].values());
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
33 |
|
||||
26 |
|
||||
|
||||
hint: first-class iterator objects have no lowering — iterator helpers compile as one chain on an array iterator, consumed in place: arr.values().map(f).take(n).toArray()
|
||||
|
||||
es2025-fences.ts:35:27 - error SC2020: 'Promise.try over a callback of type '(a: number, b?: number | undefined) => number' with 1 argument' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:28:27 - error SC2020: 'Promise.try over a callback of type '(a: number, b?: number | undefined) => number' with 1 argument' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
34 | // Promise.try with fewer arguments than the callback's parameters.
|
||||
35 | const tried = Promise.try((a: number, b?: number) => a + (b ?? 0), 1);
|
||||
27 | // Promise.try with fewer arguments than the callback's parameters.
|
||||
28 | const tried = Promise.try((a: number, b?: number) => a + (b ?? 0), 1);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
36 |
|
||||
29 |
|
||||
|
||||
hint: pass one argument per callback parameter: Promise.try((a, b) => a + b, 1, 2)
|
||||
|
||||
es2025-fences.ts:38:17 - error SC2020: 'Object.groupBy at this result type' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:31:17 - error SC2020: 'Object.groupBy at this result type' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
37 | // Object.groupBy at a literal-union key type (a fixed-field record).
|
||||
38 | const grouped = Object.groupBy([1, 2, 3], (n) => (n % 2 === 0 ? "even" : "odd"));
|
||||
30 | // Object.groupBy at a literal-union key type (a fixed-field record).
|
||||
31 | const grouped = Object.groupBy([1, 2, 3], (n) => (n % 2 === 0 ? "even" : "odd"));
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
39 |
|
||||
32 |
|
||||
|
||||
hint: a string-keyed result (Partial<Record<string, T[]>>) is the supported form — a literal-union key type makes a fixed-field record: widen the callback's key type to string (numbers stringify like JS property keys)
|
||||
|
||||
es2025-fences.ts:43:19 - error SC2020: 'Set.prototype.union over a set-like argument of type '{ size: number; has: (x: number) => x is 1; keys: () => ArrayIterator<number>; }'' is part of the standard library types but has no scriptc lowering yet
|
||||
es2025-fences.ts:36:19 - error SC2020: 'Set.prototype.union over a set-like argument of type '{ size: number; has: (x: number) => x is 1; keys: () => ArrayIterator<number>; }'' is part of the standard library types but has no scriptc lowering yet
|
||||
|
||||
42 | const like = { size: 1, has: (x: number) => x === 1, keys: () => [1].values() };
|
||||
43 | const u = s.union(like);
|
||||
35 | const like = { size: 1, has: (x: number) => x === 1, keys: () => [1].values() };
|
||||
36 | const u = s.union(like);
|
||||
| ^~~~
|
||||
44 |
|
||||
37 |
|
||||
|
||||
hint: only a real Set or Map lowers (the argument's has/size/keys must be the builtins) — build one first: new Set(...)
|
||||
@@ -1860,6 +1860,8 @@
|
||||
"5886-inspect-dates.ts": 2559,
|
||||
"5887-inspect-typed-arrays.ts": 3448,
|
||||
"5888-inspect-sorted.ts": 2998,
|
||||
"5900-float16-array.ts": 3000,
|
||||
"5901-float16-array-js.js": 2900,
|
||||
"5904-async-generator-completion.ts": 2950,
|
||||
"5905-array-from-async-generator.ts": 2750,
|
||||
"5906-array-from-async-generator-js.js": 2950,
|
||||
@@ -4523,6 +4525,8 @@
|
||||
"5886-inspect-dates.ts": 2736,
|
||||
"5887-inspect-typed-arrays.ts": 2997,
|
||||
"5888-inspect-sorted.ts": 2861,
|
||||
"5900-float16-array.ts": 3750,
|
||||
"5901-float16-array-js.js": 3700,
|
||||
"5904-async-generator-completion.ts": 3800,
|
||||
"5905-array-from-async-generator.ts": 3500,
|
||||
"5906-array-from-async-generator-js.js": 3750,
|
||||
|
||||
Reference in New Issue
Block a user