1use crate::runtime::host::{abi_arg, abi_result};
7use wasmtime::{FuncType, HeapType, Linker, RefType, StructType, Val, ValType};
8
9use crate::runtime::StoreData;
10use crate::runtime::fuel;
11use crate::runtime::host::{
12 intrinsic_array_type, intrinsic_string_type, intrinsic_uint8_array_type, register_host_fn,
13 register_host_fn_async, write_submilli_string_struct, write_submilli_string_struct_units,
14};
15use crate::runtime::intrinsic_types::{IntrinsicTypes, build_intrinsic_types, intrinsic_types};
16use crate::runtime::prelude::vtable::read_string_units;
17use crate::runtime::prelude::{MODULE_NAME, closure, declare_method};
18use crate::{MangledName, PackageDeclaration, Param, Type};
19
20const BYTES_PER_ELEMENT: f64 = 1.0;
23
24pub(crate) fn install_constants(
27 linker: &mut Linker<StoreData>,
28 store: &mut wasmtime::Store<StoreData>,
29) -> wasmtime::Result<()> {
30 let gty = wasmtime::GlobalType::new(ValType::F64, wasmtime::Mutability::Var);
31 let global = wasmtime::Global::new(&mut *store, gty, Val::F64(BYTES_PER_ELEMENT.to_bits()))?;
32 let mangled = ctor_key("BYTES_PER_ELEMENT");
33 linker.define(&mut *store, MODULE_NAME, mangled.as_str(), global)?;
34 Ok(())
35}
36
37fn method_key(method: &str) -> MangledName {
38 crate::mangle::extend(&crate::mangle::prelude("Uint8Array"), method)
39}
40
41fn ctor_key(method: &str) -> MangledName {
43 crate::mangle::extend(&crate::mangle::prelude("Uint8ArrayConstructor"), method)
44}
45
46fn ref_to(struct_ty: StructType) -> ValType {
47 ValType::Ref(RefType::new(false, HeapType::ConcreteStruct(struct_ty)))
48}
49
50fn object_ref(intr: &IntrinsicTypes) -> ValType {
53 ValType::Ref(RefType::new(
54 true,
55 HeapType::ConcreteStruct(intr.object.clone()),
56 ))
57}
58
59fn f64v(v: &Val) -> f64 {
60 match v {
61 Val::F64(bits) => f64::from_bits(*bits),
62 _ => f64::NAN,
63 }
64}
65
66fn string_val(caller: &mut wasmtime::Caller<'_, StoreData>, s: &str) -> wasmtime::Result<Val> {
67 let st = write_submilli_string_struct(caller, s)?;
68 Ok(Val::AnyRef(Some(st.to_anyref())))
69}
70
71#[allow(clippy::too_many_lines)]
72pub fn install(linker: &mut Linker<StoreData>) -> wasmtime::Result<()> {
73 let engine = linker.engine().clone();
74 let intr = build_intrinsic_types(&engine)?;
75 let uint8 = ref_to(intrinsic_uint8_array_type(&engine)?);
76 let string = ref_to(intrinsic_string_type(&engine)?);
77 let array = ref_to(intrinsic_array_type(&engine)?);
78 let obj = object_ref(&intr);
79 let num = ValType::F64;
80 let boolean = ValType::I32;
81 let callback = obj.clone();
83
84 let ft = |params: Vec<ValType>, results: Vec<ValType>| FuncType::new(&engine, params, results);
85
86 register_host_fn(
88 linker,
89 MODULE_NAME,
90 method_key("length"),
91 ft(vec![uint8.clone()], vec![num.clone()]),
92 |caller, params, results| {
93 *abi_result(results, 0)? = Val::F64(
94 super::length(caller, abi_arg(params, 0)?, "Uint8Array#length")?.to_bits(),
95 );
96 Ok(())
97 },
98 )?;
99 register_host_fn(
100 linker,
101 MODULE_NAME,
102 method_key("BYTES_PER_ELEMENT"),
103 ft(vec![uint8.clone()], vec![num.clone()]),
104 |_caller, _params, results| {
105 *abi_result(results, 0)? = Val::F64(BYTES_PER_ELEMENT.to_bits());
106 Ok(())
107 },
108 )?;
109 register_host_fn(
110 linker,
111 MODULE_NAME,
112 method_key("byteLength"),
113 ft(vec![uint8.clone()], vec![num.clone()]),
114 |caller, params, results| {
115 *abi_result(results, 0)? = Val::F64(
116 super::length(caller, abi_arg(params, 0)?, "Uint8Array#byteLength")?.to_bits(),
117 );
118 Ok(())
119 },
120 )?;
121 register_host_fn(
122 linker,
123 MODULE_NAME,
124 method_key("at"),
125 ft(vec![uint8.clone(), num.clone()], vec![obj.clone()]),
126 |caller, params, results| {
127 *abi_result(results, 0)? = super::at(
128 caller,
129 abi_arg(params, 0)?,
130 f64v(abi_arg(params, 1)?),
131 "Uint8Array#at",
132 )?;
133 Ok(())
134 },
135 )?;
136 for (name, kind) in [
137 ("keys", super::IterKind::Keys),
138 ("values", super::IterKind::Values),
139 ("iterator", super::IterKind::Values),
140 ("entries", super::IterKind::Entries),
141 ] {
142 register_host_fn(
143 linker,
144 MODULE_NAME,
145 method_key(name),
146 ft(vec![uint8.clone()], vec![obj.clone()]),
147 move |caller, params, results| {
148 *abi_result(results, 0)? = super::iterate(caller, abi_arg(params, 0)?, kind)?;
149 Ok(())
150 },
151 )?;
152 }
153 for name in ["slice", "subarray"] {
154 register_host_fn(
155 linker,
156 MODULE_NAME,
157 method_key(name),
158 ft(
159 vec![uint8.clone(), num.clone(), num.clone()],
160 vec![uint8.clone()],
161 ),
162 |caller, params, results| {
163 let out = super::slice(
164 caller,
165 abi_arg(params, 0)?,
166 f64v(abi_arg(params, 1)?),
167 f64v(abi_arg(params, 2)?),
168 "Uint8Array#slice",
169 )?;
170 *abi_result(results, 0)? = super::build(caller, &out)?;
171 Ok(())
172 },
173 )?;
174 }
175 register_host_fn(
176 linker,
177 MODULE_NAME,
178 method_key("with"),
179 ft(
180 vec![uint8.clone(), num.clone(), num.clone()],
181 vec![uint8.clone()],
182 ),
183 |caller, params, results| {
184 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#with")?;
185 let Some(out) =
186 super::with(&bytes, f64v(abi_arg(params, 1)?), f64v(abi_arg(params, 2)?))
187 else {
188 crate::runtime::fuel::charge(&mut *caller, crate::runtime::fuel::PARSE, 1)?;
189 return Err(crate::runtime::host::range_error(format!(
190 "index {} is out of range (length {})",
191 crate::runtime::number::format_number_js(f64v(abi_arg(params, 1)?)),
192 bytes.len()
193 )));
194 };
195 *abi_result(results, 0)? = super::build(caller, &out)?;
196 Ok(())
197 },
198 )?;
199 for name in ["indexOf", "lastIndexOf"] {
200 let last = name == "lastIndexOf";
201 register_host_fn(
202 linker,
203 MODULE_NAME,
204 method_key(name),
205 ft(
206 vec![uint8.clone(), num.clone(), num.clone()],
207 vec![num.clone()],
208 ),
209 move |caller, params, results| {
210 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#indexOf")?;
211 let r = if last {
212 super::last_index_of(
213 &bytes,
214 f64v(abi_arg(params, 1)?),
215 f64v(abi_arg(params, 2)?),
216 )
217 } else {
218 super::index_of(&bytes, f64v(abi_arg(params, 1)?), f64v(abi_arg(params, 2)?))
219 };
220 *abi_result(results, 0)? = Val::F64(r.to_bits());
221 Ok(())
222 },
223 )?;
224 }
225 register_host_fn(
226 linker,
227 MODULE_NAME,
228 method_key("includes"),
229 ft(
230 vec![uint8.clone(), num.clone(), num.clone()],
231 vec![boolean.clone()],
232 ),
233 |caller, params, results| {
234 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#includes")?;
235 let r = super::includes(&bytes, f64v(abi_arg(params, 1)?), f64v(abi_arg(params, 2)?));
236 *abi_result(results, 0)? = Val::I32(i32::from(r));
237 Ok(())
238 },
239 )?;
240 register_host_fn(
241 linker,
242 MODULE_NAME,
243 method_key("join"),
244 ft(vec![uint8.clone(), string.clone()], vec![string.clone()]),
245 |caller, params, results| {
246 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#join")?;
247 let sep = read_string_units(caller, abi_arg(params, 1)?, "Uint8Array#join separator")?;
248 let out = super::join(&bytes, &sep);
249 *abi_result(results, 0)? = {
250 let st = write_submilli_string_struct_units(caller, &out)?;
251 Val::AnyRef(Some(st.to_anyref()))
252 };
253 Ok(())
254 },
255 )?;
256 register_host_fn(
257 linker,
258 MODULE_NAME,
259 method_key("toString"),
260 ft(vec![uint8.clone()], vec![string.clone()]),
261 |caller, params, results| {
262 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#toString")?;
263 let out = super::join(&bytes, &[u16::from(b',')]);
264 *abi_result(results, 0)? = {
265 let st = write_submilli_string_struct_units(caller, &out)?;
266 Val::AnyRef(Some(st.to_anyref()))
267 };
268 Ok(())
269 },
270 )?;
271 register_host_fn(
272 linker,
273 MODULE_NAME,
274 method_key("toJson"),
275 ft(vec![uint8.clone()], vec![string.clone()]),
276 |caller, params, results| {
277 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#toJson")?;
278 let json = format!("\"{}\"", super::to_base64_standard(&bytes));
279 *abi_result(results, 0)? = string_val(caller, &json)?;
280 Ok(())
281 },
282 )?;
283 register_host_fn(
284 linker,
285 MODULE_NAME,
286 method_key("toHex"),
287 ft(vec![uint8.clone()], vec![string.clone()]),
288 |caller, params, results| {
289 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#toHex")?;
290 *abi_result(results, 0)? = string_val(caller, &super::to_hex(&bytes))?;
291 Ok(())
292 },
293 )?;
294 register_host_fn(
295 linker,
296 MODULE_NAME,
297 method_key("toBase64"),
298 ft(vec![uint8.clone(), obj.clone()], vec![string.clone()]),
299 |caller, params, results| {
300 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#toBase64")?;
301 let (url_safe, omit) = super::read_base64_options(caller, abi_arg(params, 1)?)?;
302 fuel::charge(&mut *caller, fuel::SCAN, bytes.len() as u64)?;
303 *abi_result(results, 0)? =
304 string_val(caller, &super::encode_base64(&bytes, url_safe, omit))?;
305 Ok(())
306 },
307 )?;
308 register_host_fn(
309 linker,
310 MODULE_NAME,
311 method_key("equals"),
312 ft(vec![uint8.clone(), uint8.clone()], vec![boolean.clone()]),
313 |caller, params, results| {
314 let a = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#equals")?;
315 let b = super::read_bytes(caller, abi_arg(params, 1)?, "Uint8Array#equals")?;
316 *abi_result(results, 0)? = Val::I32(i32::from(super::equals(&a, &b)));
317 Ok(())
318 },
319 )?;
320
321 register_host_fn(
323 linker,
324 MODULE_NAME,
325 method_key("reverse"),
326 ft(vec![uint8.clone()], vec![uint8.clone()]),
327 |caller, params, results| {
328 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#reverse")?;
329 *abi_result(results, 0)? = super::reverse(caller, abi_arg(params, 0)?, bytes)?;
330 Ok(())
331 },
332 )?;
333 register_host_fn(
334 linker,
335 MODULE_NAME,
336 method_key("fill"),
337 ft(
338 vec![uint8.clone(), num.clone(), num.clone(), num.clone()],
339 vec![uint8.clone()],
340 ),
341 |caller, params, results| {
342 *abi_result(results, 0)? = super::fill(
343 caller,
344 abi_arg(params, 0)?,
345 f64v(abi_arg(params, 1)?),
346 f64v(abi_arg(params, 2)?),
347 f64v(abi_arg(params, 3)?),
348 )?;
349 Ok(())
350 },
351 )?;
352 register_host_fn(
353 linker,
354 MODULE_NAME,
355 method_key("copyWithin"),
356 ft(
357 vec![uint8.clone(), num.clone(), num.clone(), num.clone()],
358 vec![uint8.clone()],
359 ),
360 |caller, params, results| {
361 *abi_result(results, 0)? = super::copy_within(
362 caller,
363 abi_arg(params, 0)?,
364 f64v(abi_arg(params, 1)?),
365 f64v(abi_arg(params, 2)?),
366 f64v(abi_arg(params, 3)?),
367 )?;
368 Ok(())
369 },
370 )?;
371 register_host_fn(
372 linker,
373 MODULE_NAME,
374 method_key("set"),
375 ft(vec![uint8.clone(), uint8.clone(), num.clone()], vec![]),
376 |caller, params, _results| {
377 super::set(
378 caller,
379 abi_arg(params, 0)?,
380 abi_arg(params, 1)?,
381 f64v(abi_arg(params, 2)?),
382 )
383 },
384 )?;
385 register_host_fn_async(
386 linker,
387 MODULE_NAME,
388 method_key("sort"),
389 ft(vec![uint8.clone(), obj.clone()], vec![uint8.clone()]),
390 |caller, params, results| {
391 Box::pin(async move {
392 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#sort")?;
393 let cmp =
394 read_comparator(caller, abi_arg(params, 1)?, "Uint8Array#sort comparator")?;
395 *abi_result(results, 0)? =
396 super::sort(caller, abi_arg(params, 0)?, bytes, cmp).await?;
397 Ok(())
398 })
399 },
400 )?;
401
402 register_host_fn(
404 linker,
405 MODULE_NAME,
406 method_key("toReversed"),
407 ft(vec![uint8.clone()], vec![uint8.clone()]),
408 |caller, params, results| {
409 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#toReversed")?;
410 let out = super::to_reversed(bytes);
411 *abi_result(results, 0)? = super::build(caller, &out)?;
412 Ok(())
413 },
414 )?;
415 register_host_fn_async(
416 linker,
417 MODULE_NAME,
418 method_key("toSorted"),
419 ft(vec![uint8.clone(), obj.clone()], vec![uint8.clone()]),
420 |caller, params, results| {
421 Box::pin(async move {
422 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#toSorted")?;
423 let cmp = read_comparator(
424 caller,
425 abi_arg(params, 1)?,
426 "Uint8Array#toSorted comparator",
427 )?;
428 let out = super::to_sorted(caller, bytes, cmp).await?;
429 *abi_result(results, 0)? = super::build(caller, &out)?;
430 Ok(())
431 })
432 },
433 )?;
434
435 register_host_fn_async(
437 linker,
438 MODULE_NAME,
439 method_key("forEach"),
440 ft(vec![uint8.clone(), callback.clone()], vec![]),
441 |caller, params, _results| {
442 Box::pin(async move {
443 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#forEach")?;
444 let f = closure::read_callback(
445 caller,
446 abi_arg(params, 1)?,
447 "Uint8Array#forEach callback",
448 )?;
449 super::for_each(caller, *abi_arg(params, 0)?, bytes, &f).await
450 })
451 },
452 )?;
453 register_host_fn_async(
454 linker,
455 MODULE_NAME,
456 method_key("map"),
457 ft(vec![uint8.clone(), callback.clone()], vec![uint8.clone()]),
458 |caller, params, results| {
459 Box::pin(async move {
460 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#map")?;
461 let f =
462 closure::read_callback(caller, abi_arg(params, 1)?, "Uint8Array#map callback")?;
463 let out = super::map(caller, *abi_arg(params, 0)?, bytes, &f).await?;
464 *abi_result(results, 0)? = super::build(caller, &out)?;
465 Ok(())
466 })
467 },
468 )?;
469 register_host_fn_async(
470 linker,
471 MODULE_NAME,
472 method_key("filter"),
473 ft(vec![uint8.clone(), callback.clone()], vec![uint8.clone()]),
474 |caller, params, results| {
475 Box::pin(async move {
476 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#filter")?;
477 let pred = closure::read_callback(
478 caller,
479 abi_arg(params, 1)?,
480 "Uint8Array#filter predicate",
481 )?;
482 let out = super::filter(caller, *abi_arg(params, 0)?, bytes, &pred).await?;
483 *abi_result(results, 0)? = super::build(caller, &out)?;
484 Ok(())
485 })
486 },
487 )?;
488 for (name, reverse) in [("reduce", false), ("reduceRight", true)] {
489 register_host_fn_async(
490 linker,
491 MODULE_NAME,
492 method_key(name),
493 ft(
494 vec![uint8.clone(), callback.clone(), obj.clone()],
495 vec![obj.clone()],
496 ),
497 move |caller, params, results| {
498 Box::pin(async move {
499 let bytes =
500 super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#reduce")?;
501 let f = closure::read_callback(
502 caller,
503 abi_arg(params, 1)?,
504 "Uint8Array#reduce callback",
505 )?;
506 *abi_result(results, 0)? = super::reduce(
507 caller,
508 *abi_arg(params, 0)?,
509 bytes,
510 &f,
511 *abi_arg(params, 2)?,
512 reverse,
513 )
514 .await?;
515 Ok(())
516 })
517 },
518 )?;
519 }
520 for (name, reverse) in [("find", false), ("findLast", true)] {
521 register_host_fn_async(
522 linker,
523 MODULE_NAME,
524 method_key(name),
525 ft(vec![uint8.clone(), callback.clone()], vec![obj.clone()]),
526 move |caller, params, results| {
527 Box::pin(async move {
528 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#find")?;
529 let pred = closure::read_callback(
530 caller,
531 abi_arg(params, 1)?,
532 "Uint8Array#find predicate",
533 )?;
534 *abi_result(results, 0)? = match super::find_match(
535 caller,
536 *abi_arg(params, 0)?,
537 &bytes,
538 &pred,
539 reverse,
540 )
541 .await?
542 {
543 Some(i) => {
544 let byte = *bytes.get(i).ok_or_else(|| {
545 crate::runtime::host::fatal_host_error(
546 "Uint8Array#find: invalid result index",
547 )
548 })?;
549 super::box_byte(caller, byte)?
550 }
551 None => crate::runtime::prelude::undefined::value(caller)?,
552 };
553 Ok(())
554 })
555 },
556 )?;
557 }
558 for (name, reverse) in [("findIndex", false), ("findLastIndex", true)] {
559 register_host_fn_async(
560 linker,
561 MODULE_NAME,
562 method_key(name),
563 ft(vec![uint8.clone(), callback.clone()], vec![num.clone()]),
564 move |caller, params, results| {
565 Box::pin(async move {
566 let bytes =
567 super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#findIndex")?;
568 let pred = closure::read_callback(
569 caller,
570 abi_arg(params, 1)?,
571 "Uint8Array#findIndex predicate",
572 )?;
573 let idx =
574 super::find_match(caller, *abi_arg(params, 0)?, &bytes, &pred, reverse)
575 .await?;
576 let r = idx.map_or(-1.0, |i| i as f64);
577 *abi_result(results, 0)? = Val::F64(r.to_bits());
578 Ok(())
579 })
580 },
581 )?;
582 }
583 register_host_fn_async(
584 linker,
585 MODULE_NAME,
586 method_key("some"),
587 ft(vec![uint8.clone(), callback.clone()], vec![boolean.clone()]),
588 |caller, params, results| {
589 Box::pin(async move {
590 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#some")?;
591 let pred = closure::read_callback(
592 caller,
593 abi_arg(params, 1)?,
594 "Uint8Array#some predicate",
595 )?;
596 let r = super::some(caller, *abi_arg(params, 0)?, bytes, &pred).await?;
597 *abi_result(results, 0)? = Val::I32(i32::from(r));
598 Ok(())
599 })
600 },
601 )?;
602 register_host_fn_async(
603 linker,
604 MODULE_NAME,
605 method_key("every"),
606 ft(vec![uint8.clone(), callback.clone()], vec![boolean.clone()]),
607 |caller, params, results| {
608 Box::pin(async move {
609 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array#every")?;
610 let pred = closure::read_callback(
611 caller,
612 abi_arg(params, 1)?,
613 "Uint8Array#every predicate",
614 )?;
615 let r = super::every(caller, *abi_arg(params, 0)?, bytes, &pred).await?;
616 *abi_result(results, 0)? = Val::I32(i32::from(r));
617 Ok(())
618 })
619 },
620 )?;
621
622 for (name, label) in [
624 ("fromArray", "Uint8Array.fromArray"),
625 ("of", "Uint8Array.of"),
626 ] {
627 register_host_fn(
628 linker,
629 MODULE_NAME,
630 ctor_key(name),
631 ft(vec![array.clone()], vec![uint8.clone()]),
632 move |caller, params, results| {
633 let bytes = super::read_number_array(caller, abi_arg(params, 0)?, label)?;
634 *abi_result(results, 0)? = super::build(caller, &bytes)?;
635 Ok(())
636 },
637 )?;
638 }
639 let object_nonnull = ValType::Ref(RefType::new(
644 false,
645 HeapType::ConcreteStruct(intr.object.clone()),
646 ));
647 register_host_fn(
648 linker,
649 MODULE_NAME,
650 ctor_key("new"),
651 ft(vec![object_nonnull], vec![uint8.clone()]),
652 |caller, params, results| {
653 let intr = intrinsic_types(&mut *caller)?;
654 let bytes = if crate::runtime::prelude::collection::is_a(
655 caller,
656 abi_arg(params, 0)?,
657 &intr.array,
658 )? {
659 super::read_number_array(caller, abi_arg(params, 0)?, "Uint8Array.new")?
660 } else {
661 let n = crate::runtime::host::read_boxed_number(
662 caller,
663 abi_arg(params, 0)?,
664 "Uint8Array.new",
665 )?;
666 *abi_result(results, 0)? = super::allocate(caller, super::alloc_len(n)?)?;
667 return Ok(());
668 };
669 *abi_result(results, 0)? = super::build(caller, &bytes)?;
670 Ok(())
671 },
672 )?;
673 register_host_fn(
674 linker,
675 MODULE_NAME,
676 ctor_key("alloc"),
677 ft(vec![num.clone()], vec![uint8.clone()]),
678 |caller, params, results| {
679 let n = super::alloc_len(f64v(abi_arg(params, 0)?))?;
680 *abi_result(results, 0)? = super::allocate(caller, n)?;
681 Ok(())
682 },
683 )?;
684 register_host_fn(
685 linker,
686 MODULE_NAME,
687 ctor_key("fromBytes"),
688 ft(vec![uint8.clone()], vec![uint8.clone()]),
689 |caller, params, results| {
690 let bytes = super::read_bytes(caller, abi_arg(params, 0)?, "Uint8Array.fromBytes")?;
691 *abi_result(results, 0)? = super::build(caller, &bytes)?;
692 Ok(())
693 },
694 )?;
695 register_host_fn(
696 linker,
697 MODULE_NAME,
698 ctor_key("fromBase64"),
699 ft(vec![string.clone(), obj.clone()], vec![uint8.clone()]),
700 |caller, params, results| {
701 let units = read_string_units(caller, abi_arg(params, 0)?, "Uint8Array.fromBase64")?;
702 let s = String::from_utf16_lossy(&units);
703 let (url_safe, _) = super::read_base64_options(caller, abi_arg(params, 1)?)?;
704 fuel::charge(&mut *caller, fuel::SCAN, s.len() as u64)?;
705 let bytes = super::decode_base64(&s, url_safe)?;
706 *abi_result(results, 0)? = super::build(caller, &bytes)?;
707 Ok(())
708 },
709 )?;
710 register_host_fn(
711 linker,
712 MODULE_NAME,
713 ctor_key("fromHex"),
714 ft(vec![string.clone()], vec![uint8.clone()]),
715 |caller, params, results| {
716 let units = read_string_units(caller, abi_arg(params, 0)?, "Uint8Array.fromHex")?;
717 let bytes = super::from_hex(&units)?;
718 *abi_result(results, 0)? = super::build(caller, &bytes)?;
719 Ok(())
720 },
721 )?;
722 Ok(())
723}
724
725fn read_comparator(
727 caller: &mut wasmtime::Caller<'_, StoreData>,
728 val: &Val,
729 name: &str,
730) -> wasmtime::Result<Option<closure::Closure>> {
731 if crate::runtime::prelude::undefined::is_undefined(caller, val)? {
732 Ok(None)
733 } else {
734 Ok(Some(closure::read_callback(caller, val, name)?))
735 }
736}
737
738fn byte_callback_params(leading: Vec<Type>) -> Vec<Type> {
742 leading
743 .into_iter()
744 .chain([Type::Number, Type::Number, Type::Uint8Array])
745 .collect()
746}
747
748pub fn declare(defs: &mut PackageDeclaration) {
749 let u8a = || Param::new("a", Type::Uint8Array);
750 let bytes_per_element = ctor_key("BYTES_PER_ELEMENT");
752 defs.values.insert(
753 bytes_per_element.as_str().to_string(),
754 crate::ValueSymbol {
755 name: "BYTES_PER_ELEMENT".to_string(),
756 mangled_name: bytes_per_element,
757 declaration_span: crate::Span::at(crate::FileId::PRELUDE),
758 kind: crate::ValueKind::Const {
759 ty: Type::Number,
760 doc: None,
761 },
762 },
763 );
764 let callback = || Param::new("f", Type::Unknown);
767 let n = |name: &str| Param::new(name, Type::Number);
768 let u8_ret = Type::Uint8Array;
769 let comparator = || {
770 Type::Union(vec![
771 Type::Function {
772 optional: 0,
773 params: vec![Type::Number, Type::Number],
774 ret: Box::new(Type::Number),
775 predicate: None,
776 has_rest: false,
777 },
778 Type::Undefined,
779 ])
780 };
781 let base64_options = || {
782 Type::Union(vec![
783 Type::prelude_interface("Base64Options".to_string(), Vec::new()),
784 Type::Undefined,
785 ])
786 };
787
788 let m = |defs: &mut PackageDeclaration, name: &str, params: Vec<Param>, ret: Type| {
789 declare_method(defs, name, method_key(name), params, ret);
790 };
791
792 m(defs, "length", vec![u8a()], Type::Number);
793 m(defs, "byteLength", vec![u8a()], Type::Number);
794 m(defs, "BYTES_PER_ELEMENT", vec![u8a()], Type::Number);
795 m(
796 defs,
797 "at",
798 vec![u8a(), n("index")],
799 Type::Union(vec![Type::Number, Type::Undefined]),
800 );
801 let iter = |ty: Type| Type::prelude_interface("Iterator".to_string(), vec![ty]);
802 m(defs, "keys", vec![u8a()], iter(Type::Number));
803 m(defs, "values", vec![u8a()], iter(Type::Number));
804 m(defs, "iterator", vec![u8a()], iter(Type::Number));
805 m(
806 defs,
807 "entries",
808 vec![u8a()],
809 iter(Type::Tuple(vec![Type::Number, Type::Number].into())),
810 );
811 for name in ["slice", "subarray"] {
812 m(
813 defs,
814 name,
815 vec![u8a(), n("start"), n("end")],
816 u8_ret.clone(),
817 );
818 }
819 m(
820 defs,
821 "with",
822 vec![u8a(), n("index"), n("value")],
823 u8_ret.clone(),
824 );
825 for name in ["indexOf", "lastIndexOf"] {
826 m(
827 defs,
828 name,
829 vec![u8a(), n("value"), n("fromIndex")],
830 Type::Number,
831 );
832 }
833 m(
834 defs,
835 "includes",
836 vec![u8a(), n("value"), n("fromIndex")],
837 Type::Boolean,
838 );
839 m(
840 defs,
841 "join",
842 vec![u8a(), Param::new("sep", Type::String)],
843 Type::String,
844 );
845 m(defs, "toString", vec![u8a()], Type::String);
846 m(defs, "toJson", vec![u8a()], Type::String);
847 m(defs, "toHex", vec![u8a()], Type::String);
848 m(
849 defs,
850 "toBase64",
851 vec![u8a(), Param::new("options", base64_options())],
852 Type::String,
853 );
854 m(
855 defs,
856 "equals",
857 vec![u8a(), Param::new("other", Type::Uint8Array)],
858 Type::Boolean,
859 );
860
861 m(defs, "reverse", vec![u8a()], u8_ret.clone());
862 m(
863 defs,
864 "fill",
865 vec![u8a(), n("value"), n("start"), n("end")],
866 u8_ret.clone(),
867 );
868 m(
869 defs,
870 "copyWithin",
871 vec![u8a(), n("target"), n("start"), n("end")],
872 u8_ret.clone(),
873 );
874 m(
875 defs,
876 "set",
877 vec![u8a(), Param::new("source", Type::Uint8Array), n("offset")],
878 Type::Void,
879 );
880 m(
881 defs,
882 "sort",
883 vec![u8a(), Param::new("compareFn", comparator())],
884 u8_ret.clone(),
885 );
886 m(defs, "toReversed", vec![u8a()], u8_ret.clone());
887 m(
888 defs,
889 "toSorted",
890 vec![u8a(), Param::new("compareFn", comparator())],
891 u8_ret.clone(),
892 );
893
894 m(defs, "forEach", vec![u8a(), callback()], Type::Void);
895 for name in ["map", "filter"] {
896 m(defs, name, vec![u8a(), callback()], u8_ret.clone());
897 }
898 let u = || Type::TypeVar("U".to_string());
899 for name in ["reduce", "reduceRight"] {
900 m(
901 defs,
902 name,
903 vec![u8a(), callback(), Param::new("initial", u())],
904 u(),
905 );
906 }
907 for name in ["find", "findLast"] {
908 m(
909 defs,
910 name,
911 vec![u8a(), callback()],
912 Type::Union(vec![Type::Number, Type::Undefined]),
913 );
914 }
915 for name in ["findIndex", "findLastIndex"] {
916 m(defs, name, vec![u8a(), callback()], Type::Number);
917 }
918 for name in ["some", "every"] {
919 m(defs, name, vec![u8a(), callback()], Type::Boolean);
920 }
921
922 let items = || Param::new("items", Type::Array(Box::new(Type::Number)));
923 for name in ["fromArray", "of"] {
924 declare_method(defs, name, ctor_key(name), vec![items()], u8_ret.clone());
925 }
926 declare_method(
929 defs,
930 "new",
931 ctor_key("new"),
932 vec![Param::with_default(
933 "values",
934 Type::Union(vec![Type::Array(Box::new(Type::Number)), Type::Number]),
935 crate::DefaultValue::Number(0.0),
936 )],
937 u8_ret.clone(),
938 );
939 declare_method(
940 defs,
941 "alloc",
942 ctor_key("alloc"),
943 vec![Param::new("length", Type::Number)],
944 u8_ret.clone(),
945 );
946 declare_method(
947 defs,
948 "fromBytes",
949 ctor_key("fromBytes"),
950 vec![Param::new("bytes", Type::Uint8Array)],
951 u8_ret.clone(),
952 );
953 declare_method(
954 defs,
955 "fromBase64",
956 ctor_key("fromBase64"),
957 vec![
958 Param::new("encoded", Type::String),
959 Param::new("options", base64_options()),
960 ],
961 u8_ret.clone(),
962 );
963 declare_method(
964 defs,
965 "fromHex",
966 ctor_key("fromHex"),
967 vec![Param::new("encoded", Type::String)],
968 u8_ret,
969 );
970}
971
972#[allow(clippy::too_many_lines)]
975pub(crate) fn declare_types(defs: &mut crate::PackageDeclaration) {
976 use crate::runtime::prelude::declaration::doc;
977 use crate::{
978 Dispatch, MethodSig, Param, PropertySig, Span, Type, TypeKind, TypeSymbol, ValueKind,
979 ValueSymbol,
980 };
981 use std::collections::BTreeMap;
982 defs.types.insert(
983 "Uint8Array".to_string(),
984 TypeSymbol {
985 name: "Uint8Array".to_string(),
986 mangled_name: crate::mangle::prelude("Uint8Array"),
987 declaration_span: Span::at(crate::FileId::PRELUDE),
988 kind: TypeKind::Interface { index: None,
989 generics: Default::default(),
990 methods: BTreeMap::from([
991 (
992 "toString".to_string(),
993 MethodSig {
994 optional: false,
995 generics: Default::default(),
996 params: Vec::new(),
997 ret: Type::String,
998 predicate: None,
999 doc: doc(
1000 "/** Returns this array's bytes joined as a comma-separated decimal string — e.g. `Uint8Array.new([1, 2, 3]).toString() === \"1,2,3\"`. Matches the JS `Uint8Array.prototype.toString` shape. */",
1001 ),
1002 },
1003 ),
1004 (
1005 "toJson".to_string(),
1006 MethodSig {
1007 optional: false,
1008 generics: Default::default(),
1009 params: Vec::new(),
1010 ret: Type::String,
1011 predicate: None,
1012 doc: doc(
1013 "/** Returns this array's bytes as a standard (padded) base64 string wrapped in `\"…\"` (the JSON string form). */",
1014 ),
1015 },
1016 ),
1017 (
1018 "equals".to_string(),
1019 MethodSig {
1020 optional: false,
1021 generics: Default::default(),
1022 params: vec![Param::new("other", Type::Uint8Array)],
1023 ret: Type::Boolean,
1024 predicate: None,
1025 doc: doc(
1026 "/**\n * Byte-by-byte equality with `other`. Returns `false` when lengths differ.\n * @param other Bytes to compare against.\n */",
1027 ),
1028 },
1029 ),
1030 (
1031 "join".to_string(),
1032 MethodSig {
1033 optional: false,
1034 generics: Default::default(),
1035 params: vec![Param::with_default(
1036 "separator",
1037 Type::String,
1038 crate::DefaultValue::String(",".to_string()),
1039 )],
1040 ret: Type::String,
1041 predicate: None,
1042 doc: doc(
1043 "/**\n * Returns this array's bytes formatted in decimal and concatenated with `separator` between adjacent pairs.\n * @param separator String placed between elements. Defaults to `\",\"`.\n */",
1044 ),
1045 },
1046 ),
1047 (
1048 "reverse".to_string(),
1049 MethodSig {
1050 optional: false,
1051 generics: Default::default(),
1052 params: Vec::new(),
1053 ret: Type::Uint8Array,
1054 predicate: None,
1055 doc: doc(
1056 "/** Reverses this array's bytes in place and returns `this`. */",
1057 ),
1058 },
1059 ),
1060 (
1061 "fill".to_string(),
1062 MethodSig {
1063 optional: false,
1064 generics: Default::default(),
1065 params: vec![
1066 Param::new("value", Type::Number),
1067 Param::with_default("start", Type::Number, crate::DefaultValue::Number(0.0)),
1068 Param::with_default("end", Type::Number, crate::DefaultValue::Number(f64::INFINITY)),
1069 ],
1070 ret: Type::Uint8Array,
1071 predicate: None,
1072 doc: doc("/** Converts `value` to a byte and writes it to every position in `[start, end)`. Returns `this`. */"),
1073 },
1074 ),
1075 (
1076 "copyWithin".to_string(),
1077 MethodSig {
1078 optional: false,
1079 generics: Default::default(),
1080 params: vec![
1081 Param::new("target", Type::Number),
1082 Param::with_default("start", Type::Number, crate::DefaultValue::Number(0.0)),
1083 Param::with_default("end", Type::Number, crate::DefaultValue::Number(f64::INFINITY)),
1084 ],
1085 ret: Type::Uint8Array,
1086 predicate: None,
1087 doc: doc("/** Copies `bytes[start..end)` to `bytes[target..]` in place. Returns `this`. */"),
1088 },
1089 ),
1090 (
1091 "slice".to_string(),
1092 MethodSig {
1093 optional: false,
1094 generics: Default::default(),
1095 params: vec![
1096 Param::with_default("start", Type::Number, crate::DefaultValue::Number(0.0)),
1097 Param::with_default("end", Type::Number, crate::DefaultValue::Number(f64::INFINITY)),
1098 ],
1099 ret: Type::Uint8Array,
1100 predicate: None,
1101 doc: doc("/** Returns a fresh copy of the bytes in `[start, end)`. */"),
1102 },
1103 ),
1104 (
1105 "subarray".to_string(),
1106 MethodSig {
1107 optional: false,
1108 generics: Default::default(),
1109 params: vec![
1110 Param::with_default("start", Type::Number, crate::DefaultValue::Number(0.0)),
1111 Param::with_default("end", Type::Number, crate::DefaultValue::Number(f64::INFINITY)),
1112 ],
1113 ret: Type::Uint8Array,
1114 predicate: None,
1115 doc: doc("/** Deep-copy alias for `slice` under v1 (no `ArrayBuffer` view sharing). */"),
1116 },
1117 ),
1118 (
1119 "with".to_string(),
1120 MethodSig {
1121 optional: false,
1122 generics: Default::default(),
1123 params: vec![
1124 Param::new("index", Type::Number),
1125 Param::new("value", Type::Number),
1126 ],
1127 ret: Type::Uint8Array,
1128 predicate: None,
1129 doc: doc("/** Returns a clone of this array with `value` converted to a byte and written at `index`. */"),
1130 },
1131 ),
1132 (
1133 "set".to_string(),
1134 MethodSig {
1135 optional: false,
1136 generics: Default::default(),
1137 params: vec![
1138 Param::new("values", Type::Uint8Array),
1139 Param::with_default("offset", Type::Number, crate::DefaultValue::Number(0.0)),
1140 ],
1141 ret: Type::Void,
1142 predicate: None,
1143 doc: doc("/** Copies `values` into this array starting at `offset`. Throws on out-of-bounds. */"),
1144 },
1145 ),
1146 (
1147 "forEach".to_string(),
1148 MethodSig {
1149 optional: false,
1150 generics: Default::default(),
1151 params: vec![Param::new("callback", Type::Function {
1152 optional: 0,
1153 params: byte_callback_params(Vec::new()),
1154 ret: Box::new(Type::Void),
1155 predicate: None,
1156 has_rest: false,
1157 })],
1158 ret: Type::Void,
1159 predicate: None,
1160 doc: doc("/** Invokes `callback(byte, index, array)` for every byte in order. */"),
1161 },
1162 ),
1163 (
1164 "map".to_string(),
1165 MethodSig {
1166 optional: false,
1167 generics: Default::default(),
1168 params: vec![Param::new("callback", Type::Function {
1169 optional: 0,
1170 params: byte_callback_params(Vec::new()),
1171 ret: Box::new(Type::Number),
1172 predicate: None,
1173 has_rest: false,
1174 })],
1175 ret: Type::Uint8Array,
1176 predicate: None,
1177 doc: doc("/** Returns a new `Uint8Array` with each `callback(this[i], i, this)` result converted to a byte. */"),
1178 },
1179 ),
1180 (
1181 "filter".to_string(),
1182 MethodSig {
1183 optional: false,
1184 generics: Default::default(),
1185 params: vec![Param::new("predicate", Type::Function {
1186 optional: 0,
1187 params: byte_callback_params(Vec::new()),
1188 ret: Box::new(Type::Unknown),
1189 predicate: None,
1190 has_rest: false,
1191 })],
1192 ret: Type::Uint8Array,
1193 predicate: None,
1194 doc: doc("/** Returns a new `Uint8Array` containing every byte for which `predicate(byte, index, array)` returns a truthy value. */"),
1195 },
1196 ),
1197 (
1198 "some".to_string(),
1199 MethodSig {
1200 optional: false,
1201 generics: Default::default(),
1202 params: vec![Param::new("predicate", Type::Function {
1203 optional: 0,
1204 params: byte_callback_params(Vec::new()),
1205 ret: Box::new(Type::Unknown),
1206 predicate: None,
1207 has_rest: false,
1208 })],
1209 ret: Type::Boolean,
1210 predicate: None,
1211 doc: doc("/** Returns `true` if `predicate` returns a truthy value for any byte. */"),
1212 },
1213 ),
1214 (
1215 "every".to_string(),
1216 MethodSig {
1217 optional: false,
1218 generics: Default::default(),
1219 params: vec![Param::new("predicate", Type::Function {
1220 optional: 0,
1221 params: byte_callback_params(Vec::new()),
1222 ret: Box::new(Type::Unknown),
1223 predicate: None,
1224 has_rest: false,
1225 })],
1226 ret: Type::Boolean,
1227 predicate: None,
1228 doc: doc("/** Returns `true` iff `predicate(byte, index, array)` returns a truthy value for every byte. */"),
1229 },
1230 ),
1231 (
1232 "reduce".to_string(),
1233 MethodSig {
1234 optional: false,
1235 generics: crate::GenericParameters::unconstrained(vec!["U".to_string()]),
1236 params: vec![
1237 Param::new("callback", Type::Function {
1238 optional: 0,
1239 params: byte_callback_params(vec![Type::TypeVar("U".to_string())]),
1240 ret: Box::new(Type::TypeVar("U".to_string())),
1241 predicate: None,
1242 has_rest: false,
1243 }),
1244 Param::new("initial", Type::TypeVar("U".to_string())),
1245 ],
1246 ret: Type::TypeVar("U".to_string()),
1247 predicate: None,
1248 doc: doc("/** Folds bytes left-to-right with `callback(acc, byte, index, array)`. */"),
1249 },
1250 ),
1251 (
1252 "reduceRight".to_string(),
1253 MethodSig {
1254 optional: false,
1255 generics: crate::GenericParameters::unconstrained(vec!["U".to_string()]),
1256 params: vec![
1257 Param::new("callback", Type::Function {
1258 optional: 0,
1259 params: byte_callback_params(vec![Type::TypeVar("U".to_string())]),
1260 ret: Box::new(Type::TypeVar("U".to_string())),
1261 predicate: None,
1262 has_rest: false,
1263 }),
1264 Param::new("initial", Type::TypeVar("U".to_string())),
1265 ],
1266 ret: Type::TypeVar("U".to_string()),
1267 predicate: None,
1268 doc: doc("/** Folds bytes right-to-left with `callback(acc, byte, index, array)`. */"),
1269 },
1270 ),
1271 (
1272 "keys".to_string(),
1273 MethodSig {
1274 optional: false,
1275 generics: Default::default(),
1276 params: Vec::new(),
1277 ret: Type::prelude_interface("Iterator".to_string(), vec![Type::Number]),
1278 predicate: None,
1279 doc: doc("/** Returns a live `Iterator<number>` of the indices. */"),
1280 },
1281 ),
1282 (
1283 "values".to_string(),
1284 MethodSig {
1285 optional: false,
1286 generics: Default::default(),
1287 params: Vec::new(),
1288 ret: Type::prelude_interface("Iterator".to_string(), vec![Type::Number]),
1289 predicate: None,
1290 doc: doc("/** Returns a live `Iterator<number>` of the bytes; writes during iteration are seen. */"),
1291 },
1292 ),
1293 (
1294 "iterator".to_string(),
1295 MethodSig {
1296 optional: false,
1297 generics: Default::default(),
1298 params: Vec::new(),
1299 ret: Type::prelude_interface("Iterator".to_string(), vec![Type::Number]),
1300 predicate: None,
1301 doc: doc("/** Returns a live `Iterator<number>` of the bytes, which `for-of` and spread use. */"),
1302 },
1303 ),
1304 (
1305 "entries".to_string(),
1306 MethodSig {
1307 optional: false,
1308 generics: Default::default(),
1309 params: Vec::new(),
1310 ret: Type::prelude_interface("Iterator".to_string(), vec![Type::Tuple(vec![Type::Number, Type::Number].into())]),
1311 predicate: None,
1312 doc: doc("/** Returns a live `Iterator<[number, number]>` of index/byte pairs. */"),
1313 },
1314 ),
1315 (
1316 "at".to_string(),
1317 MethodSig {
1318 optional: false,
1319 generics: Default::default(),
1320 params: vec![Param::new("index", Type::Number)],
1321 ret: Type::Union(vec![Type::Number, Type::Undefined]),
1322 predicate: None,
1323 doc: doc("/** Returns the byte at `index`, or `undefined` if out of range. Negative indices count from the end. */"),
1324 },
1325 ),
1326 (
1327 "indexOf".to_string(),
1328 MethodSig {
1329 optional: false,
1330 generics: Default::default(),
1331 params: vec![
1332 Param::new("target", Type::Number),
1333 Param::with_default("fromIndex", Type::Number, crate::DefaultValue::Number(0.0)),
1334 ],
1335 ret: Type::Number,
1336 predicate: None,
1337 doc: doc("/** Returns the first index of `target`, or `-1`. */"),
1338 },
1339 ),
1340 (
1341 "lastIndexOf".to_string(),
1342 MethodSig {
1343 optional: false,
1344 generics: Default::default(),
1345 params: vec![
1346 Param::new("target", Type::Number),
1347 Param::with_default("fromIndex", Type::Number, crate::DefaultValue::OmittedNumber { omitted: f64::INFINITY, undefined: 0.0 }),
1348 ],
1349 ret: Type::Number,
1350 predicate: None,
1351 doc: doc("/** Returns the last index of `target`, or `-1`. */"),
1352 },
1353 ),
1354 (
1355 "includes".to_string(),
1356 MethodSig {
1357 optional: false,
1358 generics: Default::default(),
1359 params: vec![
1360 Param::new("target", Type::Number),
1361 Param::with_default("fromIndex", Type::Number, crate::DefaultValue::Number(0.0)),
1362 ],
1363 ret: Type::Boolean,
1364 predicate: None,
1365 doc: doc("/** Returns `true` if `target` appears at or after `fromIndex`. */"),
1366 },
1367 ),
1368 (
1369 "find".to_string(),
1370 MethodSig {
1371 optional: false,
1372 generics: Default::default(),
1373 params: vec![Param::new("predicate", Type::Function {
1374 optional: 0,
1375 params: byte_callback_params(Vec::new()),
1376 ret: Box::new(Type::Boolean),
1377 predicate: None,
1378 has_rest: false,
1379 })],
1380 ret: Type::Union(vec![Type::Number, Type::Undefined]),
1381 predicate: None,
1382 doc: doc("/** Returns the first byte for which `predicate(byte, index, array)` returns `true`, or `undefined`. */"),
1383 },
1384 ),
1385 (
1386 "findLast".to_string(),
1387 MethodSig {
1388 optional: false,
1389 generics: Default::default(),
1390 params: vec![Param::new("predicate", Type::Function {
1391 optional: 0,
1392 params: byte_callback_params(Vec::new()),
1393 ret: Box::new(Type::Unknown),
1394 predicate: None,
1395 has_rest: false,
1396 })],
1397 ret: Type::Union(vec![Type::Number, Type::Undefined]),
1398 predicate: None,
1399 doc: doc("/** Returns the last byte for which `predicate(byte, index, array)` returns a truthy value, or `undefined`. */"),
1400 },
1401 ),
1402 (
1403 "findIndex".to_string(),
1404 MethodSig {
1405 optional: false,
1406 generics: Default::default(),
1407 params: vec![Param::new("predicate", Type::Function {
1408 optional: 0,
1409 params: byte_callback_params(Vec::new()),
1410 ret: Box::new(Type::Boolean),
1411 predicate: None,
1412 has_rest: false,
1413 })],
1414 ret: Type::Number,
1415 predicate: None,
1416 doc: doc("/** Returns the index of the first matching byte, or `-1`. */"),
1417 },
1418 ),
1419 (
1420 "findLastIndex".to_string(),
1421 MethodSig {
1422 optional: false,
1423 generics: Default::default(),
1424 params: vec![Param::new("predicate", Type::Function {
1425 optional: 0,
1426 params: byte_callback_params(Vec::new()),
1427 ret: Box::new(Type::Unknown),
1428 predicate: None,
1429 has_rest: false,
1430 })],
1431 ret: Type::Number,
1432 predicate: None,
1433 doc: doc("/** Returns the index of the last matching byte, or `-1`. */"),
1434 },
1435 ),
1436 (
1437 "sort".to_string(),
1438 MethodSig {
1439 optional: false,
1440 generics: Default::default(),
1441 params: vec![Param::with_default(
1442 "compareFn",
1443 Type::Union(vec![
1444 Type::Function {
1445 optional: 0,
1446 params: vec![Type::Number, Type::Number],
1447 ret: Box::new(Type::Number),
1448 predicate: None,
1449 has_rest: false,
1450 },
1451 Type::Undefined,
1452 ]),
1453 crate::DefaultValue::Undefined,
1454 )],
1455 ret: Type::Uint8Array,
1456 predicate: None,
1457 doc: doc("/** Sorts bytes in place via `compareFn(a, b)`. With no `compareFn`, sorts numerically ascending. Returns `this`. */"),
1458 },
1459 ),
1460 (
1461 "toReversed".to_string(),
1462 MethodSig {
1463 optional: false,
1464 generics: Default::default(),
1465 params: Vec::new(),
1466 ret: Type::Uint8Array,
1467 predicate: None,
1468 doc: doc("/** Returns a fresh copy with bytes reversed. */"),
1469 },
1470 ),
1471 (
1472 "toSorted".to_string(),
1473 MethodSig {
1474 optional: false,
1475 generics: Default::default(),
1476 params: vec![Param::with_default(
1477 "compareFn",
1478 Type::Union(vec![
1479 Type::Function {
1480 optional: 0,
1481 params: vec![Type::Number, Type::Number],
1482 ret: Box::new(Type::Number),
1483 predicate: None,
1484 has_rest: false,
1485 },
1486 Type::Undefined,
1487 ]),
1488 crate::DefaultValue::Undefined,
1489 )],
1490 ret: Type::Uint8Array,
1491 predicate: None,
1492 doc: doc("/** Returns a fresh copy sorted via `compareFn`. With no `compareFn`, sorts numerically ascending. */"),
1493 },
1494 ),
1495 (
1496 "toBase64".to_string(),
1497 MethodSig {
1498 optional: false,
1499 generics: Default::default(),
1500 params: vec![Param::with_default(
1501 "options",
1502 Type::Union(vec![
1503 Type::prelude_interface("Base64Options".to_string(), Vec::new()),
1504 Type::Undefined,
1505 ]),
1506 crate::DefaultValue::Undefined,
1507 )],
1508 ret: Type::String,
1509 predicate: None,
1510 doc: doc("/** Returns the bytes as a base64 string. `options` selects alphabet and padding. */"),
1511 },
1512 ),
1513 (
1514 "toHex".to_string(),
1515 MethodSig {
1516 optional: false,
1517 generics: Default::default(),
1518 params: Vec::new(),
1519 ret: Type::String,
1520 predicate: None,
1521 doc: doc("/** Returns the bytes as a lowercase hex string. */"),
1522 },
1523 ),
1524 ]),
1525 properties: BTreeMap::from([
1526 (
1527 "length".to_string(),
1528 PropertySig {
1529 ty: Type::Number,
1530 readonly: true,
1531 intrinsic: false,
1532 optional: false,
1533 doc: doc("/** The number of bytes in this array. */"),
1534 },
1535 ),
1536 (
1537 "BYTES_PER_ELEMENT".to_string(),
1538 PropertySig {
1539 ty: Type::Number,
1540 readonly: true,
1541 intrinsic: false,
1542 optional: false,
1543 doc: doc("/** The size in bytes of each element: always `1`. */"),
1544 },
1545 ),
1546 (
1547 "byteLength".to_string(),
1548 PropertySig {
1549 ty: Type::Number,
1550 readonly: true,
1551 intrinsic: false,
1552 optional: false,
1553 doc: doc("/** Equivalent to `length`. Provided for JS `TypedArray` API compatibility. */"),
1554 },
1555 ),
1556 ]),
1557 dispatch: Dispatch::Direct,
1558 doc: doc(
1559 "/** Packed byte array. Constructed via `new Uint8Array([...])` / `Uint8Array.alloc(n)` / `Uint8Array.fromArray(...)` / etc. */",
1560 ),
1561 },
1562 },
1563 );
1564
1565 defs.types.insert(
1566 "Uint8ArrayConstructor".to_string(),
1567 TypeSymbol {
1568 name: "Uint8ArrayConstructor".to_string(),
1569 mangled_name: crate::mangle::prelude("Uint8ArrayConstructor"),
1570 declaration_span: Span::at(crate::FileId::PRELUDE),
1571 kind: TypeKind::Interface { index: None,
1572 generics: Default::default(),
1573 methods: BTreeMap::from([
1574 (
1575 "new".to_string(),
1576 MethodSig {
1577 optional: false,
1578 generics: Default::default(),
1579 params: vec![Param::with_default(
1580 "values",
1581 Type::Union(vec![
1582 Type::Array(Box::new(Type::Number)),
1583 Type::Number,
1584 ]),
1585 crate::DefaultValue::Number(0.0),
1586 )],
1587 ret: Type::Uint8Array,
1588 predicate: None,
1589 doc: doc(
1590 "/**\n * Build a new `Uint8Array`. Given an array, truncates each element and reduces it modulo 256, as JavaScript does, so `-1` is 255. Given a number, allocates that many zero bytes (the same as `Uint8Array.alloc`, including its `RangeError` on a negative or too-large length). With no argument, the array is empty.\n * @param values Numeric values to copy into the new array, or the length to allocate. Defaults to `0`.\n */",
1591 ),
1592 },
1593 ),
1594 (
1595 "alloc".to_string(),
1596 MethodSig {
1597 optional: false,
1598 generics: Default::default(),
1599 params: vec![Param::new("n", Type::Number)],
1600 ret: Type::Uint8Array,
1601 predicate: None,
1602 doc: doc(
1603 "/**\n * Allocate a zero-filled `Uint8Array` of length `n`. Fractional values truncate toward zero and `NaN` gives an empty array; a negative or too-large `n` raises a `RangeError`.\n * @param n Length in bytes.\n */",
1604 ),
1605 },
1606 ),
1607 (
1608 "fromArray".to_string(),
1609 MethodSig {
1610 optional: false,
1611 generics: Default::default(),
1612 params: vec![Param::new(
1613 "values",
1614 Type::Array(Box::new(Type::Number)),
1615 )],
1616 ret: Type::Uint8Array,
1617 predicate: None,
1618 doc: doc(
1619 "/** Build a new `Uint8Array` from `values` — canonical name for `Uint8Array.new(values)`. */",
1620 ),
1621 },
1622 ),
1623 (
1624 "fromBytes".to_string(),
1625 MethodSig {
1626 optional: false,
1627 generics: Default::default(),
1628 params: vec![Param::new("other", Type::Uint8Array)],
1629 ret: Type::Uint8Array,
1630 predicate: None,
1631 doc: doc(
1632 "/** Returns a deep copy of `other`. Mutations on the result don't touch `other`. */",
1633 ),
1634 },
1635 ),
1636 (
1637 "of".to_string(),
1638 MethodSig {
1639 optional: false,
1640 generics: Default::default(),
1641 params: vec![Param::rest(
1642 "values",
1643 Type::Array(Box::new(Type::Number)),
1644 )],
1645 ret: Type::Uint8Array,
1646 predicate: None,
1647 doc: doc(
1648 "/** Build a `Uint8Array` from the supplied byte values — `Uint8Array.of(1, 2, 3)`. */",
1649 ),
1650 },
1651 ),
1652 (
1653 "fromBase64".to_string(),
1654 MethodSig {
1655 optional: false,
1656 generics: Default::default(),
1657 params: vec![
1658 Param::new("s", Type::String),
1659 Param::with_default(
1660 "options",
1661 Type::Union(vec![
1662 Type::prelude_interface("Base64Options".to_string(), Vec::new()),
1663 Type::Undefined,
1664 ]),
1665 crate::DefaultValue::Undefined,
1666 ),
1667 ],
1668 ret: Type::Uint8Array,
1669 predicate: None,
1670 doc: doc(
1671 "/** Decode `s` as base64; `options.alphabet` picks standard vs URL-safe. Malformed input throws a `SyntaxError`. */",
1672 ),
1673 },
1674 ),
1675 (
1676 "fromHex".to_string(),
1677 MethodSig {
1678 optional: false,
1679 generics: Default::default(),
1680 params: vec![Param::new("s", Type::String)],
1681 ret: Type::Uint8Array,
1682 predicate: None,
1683 doc: doc(
1684 "/** Decode `s` as a hex string. Mixed case accepted; whitespace or an odd length throws a `SyntaxError`. */",
1685 ),
1686 },
1687 ),
1688 ]),
1689 properties: BTreeMap::from([(
1690 "BYTES_PER_ELEMENT".to_string(),
1691 PropertySig {
1692 ty: Type::Number,
1693 readonly: true,
1694 intrinsic: false,
1695 optional: false,
1696 doc: doc("/** The size in bytes of each element: always `1`. */"),
1697 },
1698 )]),
1699 dispatch: Dispatch::Static,
1700 doc: doc(
1701 "/** Constructor object for `Uint8Array`. Accessed via the global `Uint8Array` binding. */",
1702 ),
1703 },
1704 },
1705 );
1706
1707 defs.types.insert(
1708 "Base64Options".to_string(),
1709 TypeSymbol {
1710 name: "Base64Options".to_string(),
1711 mangled_name: crate::mangle::prelude("Base64Options"),
1712 declaration_span: Span::at(crate::FileId::PRELUDE),
1713 kind: TypeKind::Interface { index: None,
1714 generics: Default::default(),
1715 methods: BTreeMap::new(),
1716 properties: BTreeMap::from([
1717 (
1718 "alphabet".to_string(),
1719 PropertySig {
1720 ty: Type::Union(vec![
1721 Type::StringLiteral("base64".to_string()),
1722 Type::StringLiteral("base64url".to_string()),
1723 ]),
1724 readonly: false,
1725 intrinsic: false,
1726 optional: true,
1727 doc: doc(
1728 "/** Alphabet selector. `\"base64\"` (default) or `\"base64url\"`. */",
1729 ),
1730 },
1731 ),
1732 (
1733 "omitPadding".to_string(),
1734 PropertySig {
1735 ty: Type::Boolean,
1736 readonly: false,
1737 intrinsic: false,
1738 optional: true,
1739 doc: doc(
1740 "/** When `true`, omit the trailing `=` padding. Encode-only. */",
1741 ),
1742 },
1743 ),
1744 ]),
1745 dispatch: Dispatch::VTable,
1746 doc: doc(
1747 "/** Options bag for `Uint8Array#toBase64` / `Uint8Array.fromBase64`. All fields optional. */",
1748 ),
1749 },
1750 },
1751 );
1752
1753 defs.values.insert(
1754 "Uint8Array".to_string(),
1755 ValueSymbol {
1756 name: "Uint8Array".to_string(),
1757 mangled_name: crate::mangle::prelude("Uint8Array"),
1758 declaration_span: Span::at(crate::FileId::PRELUDE),
1759 kind: ValueKind::Const {
1760 ty: Type::prelude_interface("Uint8ArrayConstructor".to_string(), Vec::new()),
1761 doc: doc(
1762 "/** The `Uint8Array` constructor — call `Uint8Array.new([...])` or `Uint8Array.alloc(n)` to make instances. */",
1763 ),
1764 },
1765 },
1766 );
1767}