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