1use std::collections::{BTreeSet, HashSet};
4use std::fmt::Write;
5
6use crate::source::Source;
7use crate::{TranspileOpts, uwrite, uwriteln};
8
9pub(crate) mod conversion;
10use conversion::ConversionIntrinsic;
11
12pub(crate) mod js_helper;
13use js_helper::JsHelperIntrinsic;
14
15pub(crate) mod webidl;
16use webidl::WebIdlIntrinsic;
17
18pub(crate) mod string;
19use string::StringIntrinsic;
20
21pub(crate) mod resource;
22use resource::ResourceIntrinsic;
23
24pub(crate) mod lift;
25use lift::LiftIntrinsic;
26
27pub(crate) mod lower;
28use lower::LowerIntrinsic;
29
30pub(crate) mod component;
31use component::ComponentIntrinsic;
32
33pub(crate) mod p3;
34use p3::async_future::AsyncFutureIntrinsic;
35use p3::async_stream::AsyncStreamIntrinsic;
36use p3::async_task::AsyncTaskIntrinsic;
37use p3::error_context::ErrCtxIntrinsic;
38use p3::host::HostIntrinsic;
39use p3::waitable::WaitableIntrinsic;
40
41#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
47pub enum Intrinsic {
48 JsHelper(JsHelperIntrinsic),
49 WebIdl(WebIdlIntrinsic),
50 Conversion(ConversionIntrinsic),
51 String(StringIntrinsic),
52 Resource(ResourceIntrinsic),
53 ErrCtx(ErrCtxIntrinsic),
54 AsyncTask(AsyncTaskIntrinsic),
55 Waitable(WaitableIntrinsic),
56 Lift(LiftIntrinsic),
57 Lower(LowerIntrinsic),
58 AsyncStream(AsyncStreamIntrinsic),
59 AsyncFuture(AsyncFutureIntrinsic),
60 Component(ComponentIntrinsic),
61 Host(HostIntrinsic),
62
63 PromiseWithResolversPonyfill,
65
66 DebugLog,
68
69 GlobalAsyncDeterminism,
71
72 CoinFlip,
74
75 ConstantI32Max,
77 ConstantI32Min,
78 TypeCheckValidI32,
79 TypeCheckAsyncFn,
80 AsyncFunctionCtor,
81
82 Base64Compile,
83 ClampGuest,
84 FetchCompile,
85
86 SymbolCabiDispose,
88 SymbolCabiLower,
89 SymbolResourceHandle,
90 SymbolResourceRep,
91 SymbolDispose,
92 SymbolAsyncIterator,
93 SymbolIterator,
94 ScopeId,
95 HandleTables,
96
97 PlatformReadableStreamClass,
101
102 FinalizationRegistryCreate,
104
105 ComponentError,
107
108 GetErrorPayload,
110 GetErrorPayloadString,
111
112 ManagedBufferClass,
114
115 BufferManagerClass,
117
118 GlobalBufferManager,
120
121 RepTableClass,
125
126 AsyncEventCodeEnum,
128
129 IsLE,
131 ThrowInvalidBool,
132 ThrowUninitialized,
133 HasOwnProperty,
134 InstantiateCore,
135
136 GlobalComponentMemoryMap,
138
139 RegisterGlobalMemoryForComponent,
141
142 LookupMemoriesForComponent,
144
145 GlobalCurrentTaskMeta,
147
148 GetGlobalCurrentTaskMetaFn,
150
151 SetGlobalCurrentTaskMetaFn,
153
154 WithGlobalCurrentTaskMetaFn,
156
157 WithGlobalCurrentTaskMetaFnAsync,
159
160 ClearGlobalCurrentTaskMetaFn,
162}
163
164impl Intrinsic {
165 pub fn render(&self, output: &mut Source, args: &RenderIntrinsicsArgs) {
166 match self {
167 Intrinsic::JsHelper(i) => i.render(output, args),
168 Intrinsic::Conversion(i) => i.render(output, args),
169 Intrinsic::String(i) => i.render(output, args),
170 Intrinsic::ErrCtx(i) => i.render(output, args),
171 Intrinsic::Resource(i) => i.render(output, args),
172 Intrinsic::AsyncTask(i) => i.render(output, args),
173 Intrinsic::Waitable(i) => i.render(output, args),
174 Intrinsic::Lift(i) => i.render(output, args),
175 Intrinsic::Lower(i) => i.render(output, args),
176 Intrinsic::AsyncStream(i) => i.render(output, args),
177 Intrinsic::AsyncFuture(i) => i.render(output, args),
178 Intrinsic::Component(i) => i.render(output, args),
179 Intrinsic::Host(i) => i.render(output, args),
180
181 Intrinsic::GlobalAsyncDeterminism => {
182 uwriteln!(
183 output,
184 "const {var_name} = '{determinism}';",
185 var_name = self.name(),
186 determinism = args.determinism_profile,
187 );
188 }
189
190 Intrinsic::CoinFlip => {
191 uwriteln!(
192 output,
193 "const {var_name} = () => {{ return Math.random() > 0.5; }};",
194 var_name = self.name(),
195 );
196 }
197
198 Intrinsic::ConstantI32Min => output.push_str(&format!(
199 "const {const_name} = -2_147_483_648;\n",
200 const_name = self.name()
201 )),
202
203 Intrinsic::ConstantI32Max => {
204 uwriteln!(
205 output,
206 r#"
207 const {const_name} = 2_147_483_647;
208 "#,
209 const_name = self.name()
210 )
211 }
212
213 Intrinsic::TypeCheckValidI32 => {
214 let i32_const_min = Intrinsic::ConstantI32Min.name();
215 let i32_const_max = Intrinsic::ConstantI32Max.name();
216
217 uwriteln!(
218 output,
219 r#"
220 const {fn_name} = (n) => typeof n === 'number' && n >= {i32_const_min} && n <= {i32_const_max};
221 "#,
222 fn_name = self.name()
223 );
224 }
225
226 Intrinsic::AsyncFunctionCtor => {
227 let async_fn_type = Intrinsic::AsyncFunctionCtor.name();
228 uwriteln!(
229 output,
230 "const {async_fn_type} = (async () => {{}}).constructor;"
231 );
232 }
233
234 Intrinsic::TypeCheckAsyncFn => {
235 let async_fn_check = Intrinsic::TypeCheckAsyncFn.name();
236 let async_fn_ctor = Intrinsic::AsyncFunctionCtor.name();
237 uwriteln!(
238 output,
239 r#"
240 const {async_fn_check} = (f) => {{
241 return f instanceof {async_fn_ctor};
242 }};
243 "#,
244 );
245 }
246
247 Intrinsic::Base64Compile => {
248 if !args.transpile_opts.nodejs_compat_disabled {
249 uwriteln!(
250 output,
251 r#"
252 const base64Compile = str => WebAssembly.compile(
253 typeof Buffer !== 'undefined'
254 ? Buffer.from(str, 'base64')
255 : Uint8Array.from(atob(str), b => b.charCodeAt(0))
256 );
257 "#
258 );
259 } else {
260 uwriteln!(
261 output,
262 r#"
263 const base64Compile = str => WebAssembly.compile(Uint8Array.from(atob(str), b => b.charCodeAt(0)));
264 "#
265 );
266 }
267 }
268
269 Intrinsic::ClampGuest => {
270 uwriteln!(
271 output,
272 r#"
273 function clampGuest(i, min, max) {{
274 if (i < min || i > max) {{
275 throw new TypeError(`must be between ${{min}} and ${{max}}`);
276 }}
277 return i;
278 }}
279 "#
280 );
281 }
282
283 Intrinsic::ComponentError => output.push_str(
284 "
285 class ComponentError extends Error {
286 constructor (value) {
287 const enumerable = typeof value !== 'string';
288 super(enumerable ? `${String(value)} (see error.payload)` : value);
289 Object.defineProperty(this, 'payload', { value, enumerable });
290 }
291 }
292 ",
293 ),
294
295 Intrinsic::FinalizationRegistryCreate => output.push_str(
296 "
297 function finalizationRegistryCreate (unregister) {
298 if (typeof FinalizationRegistry === 'undefined') {
299 return { unregister () {} };
300 }
301 return new FinalizationRegistry(unregister);
302 }
303 ",
304 ),
305
306 Intrinsic::FetchCompile => {
307 if !args.transpile_opts.nodejs_compat_disabled {
308 output.push_str("
309 const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
310 let _fs;
311 async function fetchCompile (url) {
312 if (isNode) {
313 _fs = _fs || await import('node:fs/promises');
314 return WebAssembly.compile(await _fs.readFile(url));
315 }
316 return fetch(url).then(WebAssembly.compileStreaming);
317 }
318 ")
319 } else {
320 output.push_str(
321 "
322 const fetchCompile = url => fetch(url).then(WebAssembly.compileStreaming);
323 ",
324 )
325 }
326 }
327
328 Intrinsic::GetErrorPayload => {
329 let hop = Intrinsic::HasOwnProperty.name();
330 uwrite!(
331 output,
332 "
333 function getErrorPayload(e) {{
334 if (e && {hop}.call(e, 'payload')) return e.payload;
335 if (e instanceof Error) throw e;
336 return e;
337 }}
338 "
339 )
340 }
341
342 Intrinsic::GetErrorPayloadString => {
343 let hop = Intrinsic::HasOwnProperty.name();
344 uwrite!(
345 output,
346 "
347 function getErrorPayloadString(e) {{
348 if (e && {hop}.call(e, 'payload')) return e.payload;
349 if (e instanceof Error) return e.message;
350 return e;
351 }}
352 "
353 )
354 }
355
356 Intrinsic::WebIdl(w) => w.render(output),
357
358 Intrinsic::HandleTables => {
359 let var_name = self.name();
360 uwriteln!(
361 output,
362 r#"
363 const {var_name} = [];
364 "#,
365 );
366 }
367
368 Intrinsic::HasOwnProperty => output.push_str(
369 "
370 const hasOwnProperty = Object.prototype.hasOwnProperty;
371 ",
372 ),
373
374 Intrinsic::InstantiateCore => {
375 if !args.instantiation_occurred {
376 output.push_str(
377 "
378 const instantiateCore = WebAssembly.instantiate;
379 ",
380 )
381 }
382 }
383
384 Intrinsic::IsLE => output.push_str(
385 "
386 const isLE = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;
387 ",
388 ),
389
390 Intrinsic::SymbolCabiDispose => output.push_str(
391 "
392 const symbolCabiDispose = Symbol.for('cabiDispose');
393 ",
394 ),
395
396 Intrinsic::SymbolCabiLower => output.push_str(
397 "
398 const symbolCabiLower = Symbol.for('cabiLower');
399 ",
400 ),
401
402 Intrinsic::ScopeId => {
403 let name = self.name();
404 uwriteln!(output, "let {name} = 0;");
405 }
406
407 Intrinsic::SymbolResourceHandle => output.push_str(
408 "
409 const symbolRscHandle = Symbol('handle');
410 ",
411 ),
412
413 Intrinsic::SymbolResourceRep => output.push_str(
414 "
415 const symbolRscRep = Symbol.for('cabiRep');
416 ",
417 ),
418
419 Intrinsic::SymbolDispose => {
420 let var_name = self.name();
421 uwriteln!(
422 output,
423 "const {var_name} = Symbol.dispose || Symbol.for('dispose');"
424 );
425 }
426
427 Intrinsic::SymbolAsyncIterator => {
428 let var_name = self.name();
429 uwriteln!(output, "const {var_name} = Symbol.asyncIterator;");
430 }
431
432 Intrinsic::SymbolIterator => {
433 let var_name = self.name();
434 uwriteln!(output, "const {var_name} = Symbol.iterator;");
435 }
436
437 Intrinsic::ThrowInvalidBool => output.push_str(
438 "
439 function throwInvalidBool() {
440 throw new TypeError('invalid variant discriminant for bool');
441 }
442 ",
443 ),
444
445 Intrinsic::ThrowUninitialized => output.push_str(
446 "
447 function throwUninitialized() {
448 throw new TypeError('Wasm uninitialized use `await $init` first');
449 }
450 ",
451 ),
452
453 Intrinsic::DebugLog => {
454 let fn_name = Intrinsic::DebugLog.name();
455 output.push_str(&format!(
456 "
457 const {fn_name} = (...args) => {{
458 if (!globalThis?.process?.env?.JCO_DEBUG) {{ return; }}
459 console.debug(...args);
460 }};
461 "
462 ));
463 }
464
465 Intrinsic::PromiseWithResolversPonyfill => {
466 let fn_name = self.name();
467 output.push_str(&format!(
468 r#"
469 function {fn_name}() {{
470 if (Promise.withResolvers) {{
471 return Promise.withResolvers();
472 }} else {{
473 let resolve;
474 let reject;
475 const promise = new Promise((res, rej) => {{
476 resolve = res;
477 reject = rej;
478 }});
479 return {{ promise, resolve, reject }};
480 }}
481 }}
482 "#
483 ));
484 }
485
486 Intrinsic::AsyncEventCodeEnum => {
487 let name = Intrinsic::AsyncEventCodeEnum.name();
488 output.push_str(&format!(
489 "
490 const {name} = {{
491 NONE: 0,
492 SUBTASK: 1,
493 STREAM_READ: 2,
494 STREAM_WRITE: 3,
495 FUTURE_READ: 4,
496 FUTURE_WRITE: 5,
497 TASK_CANCELLED: 6,
498 }};
499 "
500 ));
501 }
502
503 Intrinsic::ManagedBufferClass => {
504 let debug_log_fn = Intrinsic::DebugLog.name();
505 let managed_buffer_class = Intrinsic::ManagedBufferClass.name();
506 output.push_str(&format!(
507 r#"
508 class {managed_buffer_class} {{
509 static MAX_LENGTH = 2**28 - 1;
510 #componentIdx;
511 #memory;
512
513 #elemMeta = null;
514
515 #start;
516 #ptr;
517 capacity;
518 processed = 0;
519
520 #hostOnlyData; // initial data (only filled out for host-owned)
521
522 target;
523
524 constructor(args) {{
525 if (args.capacity > {managed_buffer_class}.MAX_LENGTH) {{
526 throw new Error(`buffer size [${{args.capacity}}] greater than max length`);
527 }}
528 if (args.componentIdx === undefined) {{ throw new TypeError('missing/invalid component idx'); }}
529 if (args.capacity === undefined) {{ throw new TypeError('missing/invalid capacity'); }}
530 if (!args.elemMeta || typeof args.elemMeta.align32 !== 'number') {{
531 throw new TypeError('missing/invalid element metadata');
532 }}
533
534 if (!args.memory && args.start === undefined && args.data === undefined) {{
535 throw new TypeError('either memory and start ptr or data must be provided for managed buffers');
536 }}
537
538 if (args.memory && args.start == undefined) {{
539 throw new TypeError('missing/invalid start ptr, depsite memory being present');
540 }}
541
542 if (!args.elemMeta.isNone && args.capacity > 0) {{
543 if (args.start && args.start % args.elemMeta.align32 !== 0) {{
544 throw new Error(`invalid alignment: type with 32bit alignment [${{args.elemMeta.align32}}] at starting pointer [${{args.start}}]`);
545 }}
546 // TODO: memory lenght bounds check
547 }}
548
549 this.#componentIdx = args.componentIdx;
550 this.#memory = args.memory;
551 this.#start = args.start;
552 this.#ptr = this.#start;
553 this.capacity = args.capacity;
554 this.#elemMeta = args.elemMeta;
555
556 if (args.data !== undefined && !Array.isArray(args.data)) {{
557 throw new TypeError('host-only data must be an array');
558 }}
559 this.#hostOnlyData = args.data;
560
561 this.target = args.target;
562 }}
563
564 setTarget(tgt) {{ this.target = tgt; }}
565
566 remaining() {{
567 return this.capacity - this.processed;
568 }}
569
570 componentIdx() {{ return this.#componentIdx; }}
571
572 getElemMeta() {{ return this.#elemMeta; }}
573
574 isHostOwned() {{ return !this.#memory; }}
575
576 read(count) {{
577 {debug_log_fn}('[{managed_buffer_class}#read()] args', {{ count }});
578 if (count === undefined || count <= 0) {{
579 throw new TypeError(`missing/invalid count [${{count}}]`);
580 }}
581
582 const cap = this.capacity;
583 if (count > cap) {{
584 throw new Error(`cannot read [${{count}}] elements from buffer with capacity [${{cap}}]`);
585 }}
586
587 let values = [];
588 if (this.#elemMeta.isNone) {{
589 values = [...new Array(count)].map(() => null);
590 }} else {{
591 if (this.isHostOwned()) {{
592 values = this.#hostOnlyData.slice(0, count);
593 this.#hostOnlyData = this.#hostOnlyData.slice(count);
594 }} else if (this.#elemMeta.payloadTypeName === 'U8') {{
595 values = Array.from(new Uint8Array(this.#memory.buffer, this.#ptr, count));
596 this.#ptr += count;
597 }} else {{
598 let currentCount = count;
599 let startPtr = this.#ptr;
600 if (this.#elemMeta.stringEncoding === undefined) {{
601 throw new Error('string encoding unknown during read');
602 }}
603 let liftCtx = {{
604 storagePtr: startPtr,
605 memory: this.#memory,
606 componentIdx: this.#componentIdx,
607 stringEncoding: this.#elemMeta.stringEncoding,
608 }};
609 if (currentCount < 0) {{ throw new Error('unexpectedly invalid count'); }}
610 while (currentCount > 0) {{
611 const [value, _ctx] = this.#elemMeta.liftFn(liftCtx);
612 values.push(value);
613 currentCount -= 1;
614 }}
615 this.#ptr = liftCtx.storagePtr;
616 }}
617 }}
618
619 this.processed += count;
620 return values;
621 }}
622
623 write(values) {{
624 {debug_log_fn}('[{managed_buffer_class}#write()] args', {{ values }});
625
626 if (!Array.isArray(values)) {{ throw new TypeError('values input to write() must be an array'); }}
627 let rc = this.remaining();
628 if (values.length > rc) {{
629 throw new Error(`cannot write [${{values.length}}] elements to managed buffer with remaining capacity [${{rc}}]`);
630 }}
631
632 if (this.#elemMeta.isNone) {{
633 if (!values.every(v => v === null)) {{
634 throw new Error('non-null values in write() to unit managed buffer');
635 }}
636 }} else {{
637 if (this.isHostOwned()) {{
638 this.#hostOnlyData = this.#hostOnlyData.concat(values);
639 }} else if (this.#elemMeta.payloadTypeName === 'U8') {{
640 new Uint8Array(this.#memory.buffer, this.#ptr, values.length).set(values);
641 this.#ptr += values.length;
642 }} else {{
643 let startPtr = this.#ptr;
644 if (this.#elemMeta.stringEncoding === undefined) {{
645 throw new Error('string encoding unknown during write');
646 }}
647
648 const lowerCtx = {{
649 memory: this.#memory,
650 storagePtr: startPtr,
651 componentIdx: this.#componentIdx,
652 stringEncoding: this.#elemMeta.stringEncoding,
653 realloc: this.#elemMeta.getReallocFn?.(),
654 getReallocFn: this.#elemMeta.getReallocFn,
655 }}
656 for (const v of values) {{
657 lowerCtx.vals = [v];
658 this.#elemMeta.lowerFn(lowerCtx);
659 }}
660
661 this.#ptr = lowerCtx.storagePtr;
662 }}
663 }}
664
665 this.processed += values.length;
666 }}
667
668 }}
669 "#
670 ));
671 }
672
673 Intrinsic::BufferManagerClass => {
674 let debug_log_fn = Intrinsic::DebugLog.name();
675 let buffer_manager_class = Intrinsic::BufferManagerClass.name();
676 let managed_buffer_class = Intrinsic::ManagedBufferClass.name();
677
678 output.push_str(&format!(r#"
679 class {buffer_manager_class} {{
680 #buffers = new Map();
681 #bufferIDs = new Map();
682
683 // NOTE: componentIdx === -1 indicates the host
684 getNextBufferID(componentIdx) {{
685 const current = this.#bufferIDs.get(componentIdx);
686 if (current === undefined) {{
687 this.#bufferIDs.set(componentIdx, 1n);
688 return 1n;
689 }}
690 const next = current + 1n;
691 this.#bufferIDs.set(componentIdx, next);
692 return next;
693 }}
694
695 getBuffer(componentIdx, bufferID) {{
696 {debug_log_fn}('[{buffer_manager_class}#getBuffer()] args', {{ componentIdx, bufferID }});
697 return this.#buffers.get(componentIdx)?.get(bufferID);
698 }}
699
700 createBuffer(args) {{
701 {debug_log_fn}('[{buffer_manager_class}#createBuffer()] args', args);
702 if (!args || typeof args !== 'object') {{ throw new TypeError('missing/invalid argument object'); }}
703
704 if (args.start === undefined && args.data === undefined) {{
705 throw new TypeError('either a starting pointer or initial values must be provided');
706 }}
707
708 if (args.start !== undefined && args.componentIdx === undefined) {{ throw new TypeError('missing/invalid component idx'); }}
709 if (args.count === undefined) {{ throw new TypeError('missing/invalid obj count'); }}
710 if (!args.elemMeta) {{ throw new TypeError('missing/invalid element metadata for use with managed buffer'); }}
711
712 const {{ componentIdx, data, start, count }} = args;
713
714 if (!this.#buffers.has(componentIdx)) {{ this.#buffers.set(componentIdx, new Map()); }}
715 const instanceBuffers = this.#buffers.get(componentIdx);
716
717 const nextBufID = this.getNextBufferID(componentIdx);
718
719 const buffer = new {managed_buffer_class}({{
720 componentIdx,
721 memory: args.memory,
722 start: args.start,
723 capacity: args.count,
724 elemMeta: args.elemMeta,
725 data: args.data,
726 target: args.target,
727 stringEncoding: args.stringEncoding,
728 }});
729
730 if (instanceBuffers.has(nextBufID)) {{
731 throw new Error(`managed buffer with ID [${{nextBufID}}] already exists`);
732 }}
733 instanceBuffers.set(nextBufID, buffer);
734
735 return {{ id: nextBufID, buffer }};
736 }}
737
738 deleteBuffer(componentIdx, bufferID) {{
739 {debug_log_fn}('[{buffer_manager_class}#deleteBuffer()] args', {{ componentIdx, bufferID }});
740 return this.#buffers.get(componentIdx)?.delete(bufferID);
741 }}
742
743 }}
744 "#));
745 }
746
747 Intrinsic::GlobalBufferManager => {
748 let global_buffer_manager = Intrinsic::GlobalBufferManager.name();
749 let buffer_manager_class = Intrinsic::BufferManagerClass.name();
750 output.push_str(&format!(
751 "const {global_buffer_manager} = new {buffer_manager_class}();"
752 ));
753 }
754
755 Intrinsic::RepTableClass => {
756 let debug_log_fn = Intrinsic::DebugLog.name();
757 let rep_table_class = Intrinsic::RepTableClass.name();
758 output.push_str(&format!(r#"
759 class {rep_table_class} {{
760 #data = [0, null];
761 #size = 0;
762 #target;
763
764 constructor(args) {{
765 this.target = args?.target;
766 }}
767
768 data() {{ return this.#data; }}
769
770 insert(val) {{
771 {debug_log_fn}('[{rep_table_class}#insert()] args', {{ val, target: this.target }});
772 const freeIdx = this.#data[0];
773 if (freeIdx === 0) {{
774 this.#data.push(val);
775 this.#data.push(null);
776 const rep = (this.#data.length >> 1) - 1;
777 {debug_log_fn}('[{rep_table_class}#insert()] inserted', {{ val, target: this.target, rep }});
778 this.#size += 1;
779 return rep;
780 }}
781 this.#data[0] = this.#data[freeIdx << 1];
782 const placementIdx = freeIdx << 1;
783 this.#data[placementIdx] = val;
784 this.#data[placementIdx + 1] = null;
785 {debug_log_fn}('[{rep_table_class}#insert()] inserted', {{ val, target: this.target, rep: freeIdx }});
786 this.#size += 1;
787 return freeIdx;
788 }}
789
790 get(rep) {{
791 {debug_log_fn}('[{rep_table_class}#get()] args', {{ rep, target: this.target }});
792 if (rep === 0) {{ throw new Error('invalid resource rep during get, (cannot be 0)'); }}
793
794 const baseIdx = rep << 1;
795 const val = this.#data[baseIdx];
796 return val;
797 }}
798
799 contains(rep) {{
800 {debug_log_fn}('[{rep_table_class}#contains()] args', {{ rep, target: this.target }});
801 if (rep === 0) {{ throw new Error('invalid resource rep during contains, (cannot be 0)'); }}
802
803 const baseIdx = rep << 1;
804 return !!this.#data[baseIdx];
805 }}
806
807 remove(rep) {{
808 {debug_log_fn}('[{rep_table_class}#remove()] args', {{ rep, target: this.target }});
809 if (rep === 0) {{ throw new Error('invalid resource rep during remove, (cannot be 0)'); }}
810 if (this.#data.length === 2) {{ throw new Error('invalid'); }}
811
812 const baseIdx = rep << 1;
813 const val = this.#data[baseIdx];
814
815 this.#data[baseIdx] = this.#data[0];
816 this.#data[0] = rep;
817 this.#size -= 1;
818
819 return val;
820 }}
821
822 size() {{ return this.#size; }}
823
824 clear() {{
825 {debug_log_fn}('[{rep_table_class}#clear()] args', {{ rep, target: this.target }});
826 this.#data = [0, null];
827 }}
828 }}
829 "#));
830 }
831
832 Intrinsic::GlobalComponentMemoryMap => {
833 let global_component_memory_map = Intrinsic::GlobalComponentMemoryMap.name();
834 output.push_str(&format!(
835 "const {global_component_memory_map} = new Map();\n"
836 ));
837 }
838
839 Intrinsic::RegisterGlobalMemoryForComponent => {
840 let global_component_memory_map = Intrinsic::GlobalComponentMemoryMap.name();
841 let register_global_component_memory =
842 Intrinsic::RegisterGlobalMemoryForComponent.name();
843 output.push_str(&format!(
844 r#"
845 function {register_global_component_memory}(args) {{
846 const {{ componentIdx, memory, memoryIdx }} = args ?? {{}};
847 if (componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
848 if (memory === undefined && memoryIdx === undefined) {{ throw new TypeError('missing both memory & memory idx'); }}
849 let inner = {global_component_memory_map}.get(componentIdx);
850 if (!inner) {{
851 inner = {{}};
852 {global_component_memory_map}.set(componentIdx, inner);
853 }}
854
855 inner[memoryIdx] = {{ memory, memoryIdx, componentIdx }};
856 }}
857 "#)
858 );
859 }
860
861 Intrinsic::LookupMemoriesForComponent => {
862 let global_component_memory_map = Intrinsic::GlobalComponentMemoryMap.name();
863 let lookup_global_memories_for_component =
864 Intrinsic::LookupMemoriesForComponent.name();
865 output.push_str(&format!(
866 r#"
867 function {lookup_global_memories_for_component}(args) {{
868 const {{ componentIdx }} = args ?? {{}};
869 if (args.componentIdx === undefined) {{ throw new TypeError("missing component idx"); }}
870
871 const metas = {global_component_memory_map}.get(componentIdx);
872 if (!metas) {{ return []; }}
873
874 if (args.memoryIdx === undefined) {{
875 return Object.values(metas);
876 }}
877
878 const meta = metas[args.memoryIdx];
879 return meta?.memory;
880 }}
881 "#)
882 );
883 }
884
885 Self::GlobalCurrentTaskMeta => {
886 let name = self.name();
887 output.push_str(&format!("const {name} = {{}};\n"));
888 }
889
890 Self::GetGlobalCurrentTaskMetaFn => {
891 let get_current_global_task_meta_fn = Self::GetGlobalCurrentTaskMetaFn.name();
892 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
893
894 uwriteln!(
895 output,
896 r#"
897 function {get_current_global_task_meta_fn}(componentIdx) {{
898 if (componentIdx === null || componentIdx === undefined) {{
899 throw new Error("missing/invalid component idx");
900 }}
901 const v = {global_current_task_meta_obj}[componentIdx];
902 if (v === undefined || v === null) {{
903 return undefined;
904 }}
905 return {{ ...v }};
906 }}
907 "#,
908 );
909 }
910
911 Self::SetGlobalCurrentTaskMetaFn => {
912 let set_global_current_task_meta_fn = self.name();
913 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
914
915 uwriteln!(
916 output,
917 r#"
918 function {set_global_current_task_meta_fn}(args) {{
919 if (!args) {{ throw new TypeError('args missing'); }}
920 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
921 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
922 const {{ taskID, componentIdx }} = args;
923 return {global_current_task_meta_obj}[componentIdx] = {{ taskID, componentIdx }};
924 }}
925 "#,
926 );
927 }
928
929 Self::WithGlobalCurrentTaskMetaFn => {
930 let debug_log_fn = Intrinsic::DebugLog.name();
931 let with_global_current_task_meta_fn = Self::WithGlobalCurrentTaskMetaFn.name();
932 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
933
934 output.push_str(&format!(
935 r#"
936 function {with_global_current_task_meta_fn}(args) {{
937 {debug_log_fn}('[{with_global_current_task_meta_fn}()] args', args);
938 if (!args) {{ throw new TypeError('args missing'); }}
939 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
940 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
941 if (!args.fn) {{ throw new TypeError('missing fn'); }}
942 const {{ taskID, componentIdx, fn }} = args;
943
944 try {{
945 {global_current_task_meta_obj}[componentIdx] = {{ taskID, componentIdx }};
946 return fn();
947 }} catch (err) {{
948 {debug_log_fn}("error while executing sync callee/callback", {{
949 ...args,
950 err,
951 }});
952 throw err;
953 }} finally {{
954 {global_current_task_meta_obj}[componentIdx] = null;
955 }}
956 }}
957 "#,
958 ));
959 }
960
961 Self::WithGlobalCurrentTaskMetaFnAsync => {
988 let debug_log_fn = Intrinsic::DebugLog.name();
989 let with_global_current_task_meta_async_fn =
990 Self::WithGlobalCurrentTaskMetaFnAsync.name();
991 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
992
993 output.push_str(&format!(
994 r#"
995 async function {with_global_current_task_meta_async_fn}(args) {{
996 {debug_log_fn}('[{with_global_current_task_meta_async_fn}()] args', args);
997 if (!args) {{ throw new TypeError('args missing'); }}
998 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
999 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
1000 if (!args.fn) {{ throw new TypeError('missing fn'); }}
1001
1002 const {{ taskID, componentIdx, fn }} = args;
1003
1004 try {{
1005 {global_current_task_meta_obj}[componentIdx] = {{ taskID, componentIdx }};
1006 return await fn();
1007 }} catch (err) {{
1008 {debug_log_fn}("error while executing async callee/callback", {{
1009 ...args,
1010 err,
1011 }});
1012 throw err;
1013 }} finally {{
1014 {global_current_task_meta_obj}[componentIdx] = null;
1015 }}
1016 }}
1017 "#,
1018 ));
1019 }
1020
1021 Self::ClearGlobalCurrentTaskMetaFn => {
1022 let debug_log_fn = Intrinsic::DebugLog.name();
1023 let clear_global_current_task_meta_fn = Self::ClearGlobalCurrentTaskMetaFn.name();
1024 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
1025
1026 output.push_str(&format!(
1027 r#"
1028 async function {clear_global_current_task_meta_fn}(args) {{
1029 {debug_log_fn}('[{clear_global_current_task_meta_fn}()] args', args);
1030 if (!args) {{ throw new TypeError('args missing'); }}
1031 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
1032 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
1033 const {{ taskID, componentIdx }} = args;
1034
1035 const meta = {global_current_task_meta_obj}[componentIdx];
1036 if (!meta) {{ throw new Error(`missing current task meta for component idx [${{componentIdx}}]`); }}
1037
1038 if (meta.taskID !== taskID) {{
1039 throw new Error(`task ID [${{meta.taskID}}] != requested ID [${{taskID}}]`);
1040 }}
1041 if (meta.componentIdx !== componentIdx) {{
1042 throw new Error(`component idx [${{meta.componentIdx}}] != requested idx [${{componentIdx}}]`);
1043 }}
1044
1045 {global_current_task_meta_obj}[componentIdx] = null;
1046 }}
1047 "#,
1048 ));
1049 }
1050
1051 Intrinsic::PlatformReadableStreamClass => {
1053 let name = self.name();
1054 uwriteln!(
1055 output,
1056 r#"
1057 if (!ReadableStream) {{
1058 throw new Error('builtin stream class [ReadableStream] is not available');
1059 }}
1060 const {name} = ReadableStream;
1061 "#
1062 );
1063 }
1064 }
1065 }
1066}
1067
1068#[derive(Debug, Default, PartialEq, Eq)]
1070pub enum AsyncDeterminismProfile {
1071 #[default]
1073 Random,
1074
1075 #[allow(unused)]
1077 Deterministic,
1078}
1079
1080impl std::fmt::Display for AsyncDeterminismProfile {
1081 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1082 write!(
1083 f,
1084 "{}",
1085 match self {
1086 Self::Deterministic => "deterministic",
1087 Self::Random => "random",
1088 }
1089 )
1090 }
1091}
1092
1093#[derive(bon::Builder)]
1095#[non_exhaustive]
1096pub struct RenderIntrinsicsArgs<'a> {
1097 pub(crate) intrinsics: &'a mut BTreeSet<Intrinsic>,
1099 #[builder(default)]
1101 pub(crate) instantiation_occurred: bool,
1102 #[builder(default)]
1104 pub(crate) determinism_profile: AsyncDeterminismProfile,
1105 pub(crate) transpile_opts: &'a TranspileOpts,
1107}
1108
1109const EARLY_INTRINSICS: [Intrinsic; 43] = [
1111 Intrinsic::PromiseWithResolversPonyfill,
1112 Intrinsic::SymbolDispose,
1113 Intrinsic::SymbolAsyncIterator,
1114 Intrinsic::SymbolIterator,
1115 Intrinsic::DebugLog,
1116 Intrinsic::GlobalAsyncDeterminism,
1117 Intrinsic::GlobalComponentMemoryMap,
1118 Intrinsic::GlobalCurrentTaskMeta,
1119 Intrinsic::GetGlobalCurrentTaskMetaFn,
1120 Intrinsic::SetGlobalCurrentTaskMetaFn,
1121 Intrinsic::WithGlobalCurrentTaskMetaFn,
1122 Intrinsic::WithGlobalCurrentTaskMetaFnAsync,
1123 Intrinsic::ClearGlobalCurrentTaskMetaFn,
1124 Intrinsic::LookupMemoriesForComponent,
1125 Intrinsic::RegisterGlobalMemoryForComponent,
1126 Intrinsic::RepTableClass,
1127 Intrinsic::CoinFlip,
1128 Intrinsic::ScopeId,
1129 Intrinsic::ConstantI32Min,
1131 Intrinsic::ConstantI32Max,
1132 Intrinsic::Conversion(ConversionIntrinsic::IsValidNumericPrimitive),
1133 Intrinsic::Conversion(ConversionIntrinsic::RequireValidNumericPrimitive),
1134 Intrinsic::TypeCheckValidI32,
1135 Intrinsic::TypeCheckAsyncFn,
1136 Intrinsic::Resource(ResourceIntrinsic::ResourceCallBorrows),
1138 Intrinsic::AsyncFunctionCtor,
1140 Intrinsic::AsyncTask(AsyncTaskIntrinsic::ClearCurrentTask),
1141 Intrinsic::AsyncTask(AsyncTaskIntrinsic::CurrentTaskMayBlock),
1142 Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskIds),
1143 Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentComponentIdxs),
1144 Intrinsic::AsyncTask(AsyncTaskIntrinsic::UnpackCallbackResult),
1145 Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncSubtaskClass),
1146 Intrinsic::Host(HostIntrinsic::PrepareCall),
1148 Intrinsic::Host(HostIntrinsic::AsyncStartCall),
1149 Intrinsic::Host(HostIntrinsic::SyncStartCall),
1150 Intrinsic::Waitable(WaitableIntrinsic::WaitableClass),
1152 Intrinsic::ErrCtx(ErrCtxIntrinsic::GlobalErrCtxTableMap),
1154 Intrinsic::AsyncTask(AsyncTaskIntrinsic::ContextGet),
1157 Intrinsic::AsyncTask(AsyncTaskIntrinsic::ContextSet),
1158 Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskMap),
1160 Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncTaskClass),
1161 Intrinsic::AsyncEventCodeEnum,
1162 Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask),
1163];
1164
1165pub fn render_intrinsics(args: RenderIntrinsicsArgs) -> Source {
1168 let mut output = Source::default();
1169 let mut rendered_intrinsics = HashSet::new();
1170
1171 for intrinsic in EARLY_INTRINSICS {
1173 intrinsic.render(&mut output, &args);
1174 rendered_intrinsics.insert(intrinsic.name());
1175 }
1176
1177 if args.intrinsics.contains(&Intrinsic::GetErrorPayload)
1179 || args.intrinsics.contains(&Intrinsic::GetErrorPayloadString)
1180 {
1181 args.intrinsics.insert(Intrinsic::HasOwnProperty);
1182 }
1183 if args
1184 .intrinsics
1185 .contains(&Intrinsic::String(StringIntrinsic::Utf16Encode))
1186 {
1187 args.intrinsics.insert(Intrinsic::IsLE);
1188 }
1189
1190 if args
1191 .intrinsics
1192 .contains(&Intrinsic::Conversion(ConversionIntrinsic::F32ToI32))
1193 || args
1194 .intrinsics
1195 .contains(&Intrinsic::Conversion(ConversionIntrinsic::I32ToF32))
1196 {
1197 output.push_str(
1198 "
1199 const i32ToF32I = new Int32Array(1);
1200 const i32ToF32F = new Float32Array(i32ToF32I.buffer);
1201 ",
1202 );
1203 }
1204
1205 if args
1206 .intrinsics
1207 .contains(&Intrinsic::Conversion(ConversionIntrinsic::F64ToI64))
1208 || args
1209 .intrinsics
1210 .contains(&Intrinsic::Conversion(ConversionIntrinsic::I64ToF64))
1211 {
1212 output.push_str(
1213 "
1214 const i64ToF64I = new BigInt64Array(1);
1215 const i64ToF64F = new Float64Array(i64ToF64I.buffer);
1216 ",
1217 );
1218 }
1219
1220 if args.intrinsics.contains(&Intrinsic::Resource(
1221 ResourceIntrinsic::ResourceTransferBorrow,
1222 )) || args.intrinsics.contains(&Intrinsic::Resource(
1223 ResourceIntrinsic::ResourceTransferBorrowValidLifting,
1224 )) {
1225 args.intrinsics.insert(Intrinsic::Resource(
1226 ResourceIntrinsic::ResourceTableCreateBorrow,
1227 ));
1228 }
1229
1230 if args
1231 .intrinsics
1232 .contains(&Intrinsic::String(StringIntrinsic::Utf8Encode))
1233 || args
1234 .intrinsics
1235 .contains(&Intrinsic::String(StringIntrinsic::Utf8EncodeAsync))
1236 {
1237 args.intrinsics.extend([
1238 &Intrinsic::IsLE,
1239 &Intrinsic::String(StringIntrinsic::GlobalTextEncoderUtf8),
1240 ]);
1241 }
1242
1243 if args
1244 .intrinsics
1245 .contains(&Intrinsic::String(StringIntrinsic::Utf16Encode))
1246 || args
1247 .intrinsics
1248 .contains(&Intrinsic::String(StringIntrinsic::Utf16EncodeAsync))
1249 {
1250 args.intrinsics.extend([&Intrinsic::IsLE]);
1251 }
1252
1253 if args.intrinsics.contains(&Intrinsic::ErrCtx(
1255 ErrCtxIntrinsic::ErrorContextDebugMessage,
1256 )) {
1257 args.intrinsics.extend([
1258 &Intrinsic::String(StringIntrinsic::Utf8Encode),
1259 &Intrinsic::String(StringIntrinsic::Utf16Encode),
1260 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GetLocalTable),
1261 ]);
1262 }
1263
1264 if args
1265 .intrinsics
1266 .contains(&Intrinsic::ErrCtx(ErrCtxIntrinsic::ErrorContextNew))
1267 {
1268 args.intrinsics.extend([
1269 &Intrinsic::ErrCtx(ErrCtxIntrinsic::ComponentGlobalTable),
1270 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GlobalRefCountAdd),
1271 &Intrinsic::ErrCtx(ErrCtxIntrinsic::ReserveGlobalRep),
1272 &Intrinsic::ErrCtx(ErrCtxIntrinsic::CreateLocalHandle),
1273 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GetLocalTable),
1274 ]);
1275 }
1276
1277 if args.intrinsics.contains(&Intrinsic::ErrCtx(
1278 ErrCtxIntrinsic::ErrorContextDebugMessage,
1279 )) {
1280 args.intrinsics.extend([
1281 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GlobalRefCountAdd),
1282 &Intrinsic::ErrCtx(ErrCtxIntrinsic::ErrorContextDrop),
1283 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GetLocalTable),
1284 ]);
1285 }
1286
1287 if args
1288 .intrinsics
1289 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::DriverLoop))
1290 {
1291 args.intrinsics.extend([
1292 &Intrinsic::TypeCheckValidI32,
1293 &Intrinsic::Conversion(ConversionIntrinsic::ToInt32),
1294 &Intrinsic::Component(ComponentIntrinsic::ComponentStateSetAllError),
1295 ]);
1296 }
1297
1298 if args.intrinsics.contains(&Intrinsic::Component(
1299 ComponentIntrinsic::GetOrCreateAsyncState,
1300 )) {
1301 args.intrinsics.extend([&Intrinsic::RepTableClass]);
1302 }
1303
1304 if args
1305 .intrinsics
1306 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncTaskClass))
1307 {
1308 args.intrinsics.extend([
1309 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1310 &Intrinsic::Component(ComponentIntrinsic::GlobalAsyncStateMap),
1311 &Intrinsic::RepTableClass,
1312 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncSubtaskClass),
1313 &Intrinsic::Waitable(WaitableIntrinsic::WaitableClass),
1314 ]);
1315 }
1316
1317 if args
1318 .intrinsics
1319 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetNew))
1320 {
1321 args.intrinsics
1322 .extend([&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetClass)]);
1323 }
1324
1325 if args
1326 .intrinsics
1327 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetPoll))
1328 || args
1329 .intrinsics
1330 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetWait))
1331 {
1332 args.intrinsics
1333 .extend([&Intrinsic::Host(HostIntrinsic::StoreEventInComponentMemory)]);
1334 }
1335
1336 if args
1337 .intrinsics
1338 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetDrop))
1339 {
1340 args.intrinsics
1341 .extend([&Intrinsic::Waitable(WaitableIntrinsic::RemoveWaitableSet)]);
1342 }
1343
1344 if args.intrinsics.contains(&Intrinsic::Component(
1345 ComponentIntrinsic::GetOrCreateAsyncState,
1346 )) {
1347 args.intrinsics.extend([
1348 &Intrinsic::Component(ComponentIntrinsic::ComponentAsyncStateClass),
1349 &Intrinsic::Component(ComponentIntrinsic::GlobalAsyncStateMap),
1350 ]);
1351 }
1352
1353 if args.intrinsics.contains(&Intrinsic::Component(
1354 ComponentIntrinsic::ComponentAsyncStateClass,
1355 )) {
1356 args.intrinsics.extend([&Intrinsic::AsyncStream(
1357 AsyncStreamIntrinsic::GlobalStreamMap,
1358 )]);
1359 }
1360
1361 if args
1362 .intrinsics
1363 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatResult))
1364 | args
1365 .intrinsics
1366 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatOption))
1367 | args
1368 .intrinsics
1369 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatEnum))
1370 {
1371 args.intrinsics
1372 .extend([&Intrinsic::Lift(LiftIntrinsic::LiftFlatVariant)]);
1373 }
1374
1375 if args
1376 .intrinsics
1377 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatVariant))
1378 {
1379 args.intrinsics.extend([
1380 &Intrinsic::Lift(LiftIntrinsic::LiftFlatU8),
1381 &Intrinsic::Lift(LiftIntrinsic::LiftFlatU16),
1382 &Intrinsic::Lift(LiftIntrinsic::LiftFlatU32),
1383 &Intrinsic::Lift(LiftIntrinsic::LiftFlatFloat64),
1384 ]);
1385 }
1386
1387 if args
1388 .intrinsics
1389 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatResult))
1390 {
1391 args.intrinsics
1392 .insert(Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant));
1393 }
1394
1395 if args
1396 .intrinsics
1397 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatOption))
1398 {
1399 args.intrinsics
1400 .insert(Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant));
1401 }
1402
1403 if args
1404 .intrinsics
1405 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant))
1406 {
1407 args.intrinsics.extend([
1408 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU8),
1409 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU16),
1410 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU32),
1411 ]);
1412 }
1413
1414 if args
1415 .intrinsics
1416 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatStream))
1417 {
1418 args.intrinsics.extend([
1419 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamMap),
1420 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::ExternalStreamClass),
1421 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::InternalStreamClass),
1422 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::IsStreamLowerableObject),
1423 &Intrinsic::SymbolResourceRep,
1424 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1425 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GenReadFnFromLowerableStream),
1426 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GenStreamHostInjectFn),
1427 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU32),
1428 ])
1429 }
1430
1431 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1432 AsyncStreamIntrinsic::GenStreamHostInjectFn,
1433 )) {
1434 args.intrinsics.insert(Intrinsic::AsyncStream(
1435 AsyncStreamIntrinsic::PendingValueQueueClass,
1436 ));
1437 }
1438
1439 if args
1440 .intrinsics
1441 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatFuture))
1442 {
1443 args.intrinsics.extend([
1444 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureMap),
1445 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1446 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::InternalFutureClass),
1447 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::IsFutureLowerableObject),
1448 &Intrinsic::SymbolResourceRep,
1449 &Intrinsic::GetErrorPayload,
1450 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1451 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GenFutureHostInjectFn),
1452 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU32),
1453 ])
1454 }
1455
1456 if args
1457 .intrinsics
1458 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStringAny))
1459 {
1460 args.intrinsics.extend([
1461 &Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf8),
1462 &Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf16),
1463 ]);
1464 }
1465
1466 if args
1467 .intrinsics
1468 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf8))
1469 {
1470 args.intrinsics
1471 .insert(Intrinsic::String(StringIntrinsic::GlobalTextDecoderUtf8));
1472 }
1473
1474 if args
1475 .intrinsics
1476 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatStringAny))
1477 {
1478 args.intrinsics.extend([
1479 &Intrinsic::Lower(LowerIntrinsic::LowerFlatStringUtf8),
1480 &Intrinsic::Lower(LowerIntrinsic::LowerFlatStringUtf16),
1481 ]);
1482 }
1483
1484 if args
1485 .intrinsics
1486 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatStringUtf8))
1487 {
1488 args.intrinsics
1489 .insert(Intrinsic::String(StringIntrinsic::GlobalTextEncoderUtf8));
1490 }
1491
1492 if args
1493 .intrinsics
1494 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf16))
1495 {
1496 args.intrinsics
1497 .insert(Intrinsic::String(StringIntrinsic::Utf16Decoder));
1498 }
1499
1500 if args
1501 .intrinsics
1502 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStream))
1503 {
1504 args.intrinsics.insert(Intrinsic::AsyncStream(
1505 AsyncStreamIntrinsic::ExternalStreamClass,
1506 ));
1507 }
1508
1509 if args.intrinsics.contains(&Intrinsic::AsyncTask(
1510 AsyncTaskIntrinsic::CreateNewCurrentTask,
1511 )) || args
1512 .intrinsics
1513 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask))
1514 || args
1515 .intrinsics
1516 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::ClearCurrentTask))
1517 {
1518 args.intrinsics.extend([
1519 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncTaskClass),
1520 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskMap),
1521 ]);
1522 }
1523
1524 if args
1525 .intrinsics
1526 .contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamNew))
1527 {
1528 args.intrinsics.extend([
1529 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamMap),
1530 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamTableMap),
1531 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamWritableEndClass),
1532 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamReadableEndClass),
1533 ]);
1534 }
1535
1536 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1537 AsyncStreamIntrinsic::StreamWritableEndClass,
1538 )) || args.intrinsics.contains(&Intrinsic::AsyncStream(
1539 AsyncStreamIntrinsic::StreamReadableEndClass,
1540 )) {
1541 args.intrinsics.extend([
1542 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::InternalStreamClass),
1543 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamEndClass),
1544 &Intrinsic::AsyncEventCodeEnum,
1545 ]);
1546 }
1547
1548 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1549 AsyncStreamIntrinsic::StreamNewFromLift,
1550 )) {
1551 args.intrinsics.extend([
1552 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamMap),
1553 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamTableMap),
1554 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::HostStreamClass),
1555 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::ExternalStreamClass),
1556 &Intrinsic::GlobalBufferManager,
1557 ]);
1558 }
1559
1560 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1561 AsyncStreamIntrinsic::ExternalStreamClass,
1562 )) {
1563 args.intrinsics.insert(Intrinsic::SymbolResourceRep);
1564 }
1565
1566 if args
1567 .intrinsics
1568 .contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamWrite))
1569 || args
1570 .intrinsics
1571 .contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamRead))
1572 || args
1573 .intrinsics
1574 .contains(&Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureWrite))
1575 || args
1576 .intrinsics
1577 .contains(&Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureRead))
1578 {
1579 args.intrinsics.extend([
1580 &Intrinsic::GlobalBufferManager,
1581 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncBlockedConstant),
1582 &Intrinsic::AsyncEventCodeEnum,
1583 ]);
1584 }
1585
1586 if args
1587 .intrinsics
1588 .contains(&Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureNew))
1589 {
1590 args.intrinsics.extend([
1591 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureMap),
1592 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1593 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureTableMap),
1594 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureWritableEndClass),
1595 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureReadableEndClass),
1596 ]);
1597 }
1598
1599 if args.intrinsics.contains(&Intrinsic::AsyncFuture(
1600 AsyncFutureIntrinsic::FutureNewFromLift,
1601 )) {
1602 args.intrinsics.extend([
1603 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1604 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureMap),
1605 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::HostFutureClass),
1606 &Intrinsic::GlobalBufferManager,
1607 ]);
1608 }
1609
1610 if args.intrinsics.contains(&Intrinsic::AsyncFuture(
1611 AsyncFutureIntrinsic::FutureWritableEndClass,
1612 )) || args.intrinsics.contains(&Intrinsic::AsyncFuture(
1613 AsyncFutureIntrinsic::FutureReadableEndClass,
1614 )) {
1615 args.intrinsics.extend([
1616 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1617 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::InternalFutureClass),
1618 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureEndClass),
1619 &Intrinsic::AsyncEventCodeEnum,
1620 ]);
1621 }
1622
1623 if args.intrinsics.contains(&Intrinsic::GlobalBufferManager) {
1624 args.intrinsics.extend([&Intrinsic::BufferManagerClass]);
1625 }
1626
1627 if args.intrinsics.contains(&Intrinsic::BufferManagerClass) {
1628 args.intrinsics.extend([&Intrinsic::ManagedBufferClass]);
1629 }
1630
1631 if args.intrinsics.contains(&Intrinsic::AsyncTask(
1632 AsyncTaskIntrinsic::EnterSymmetricSyncGuestCall,
1633 )) || args.intrinsics.contains(&Intrinsic::AsyncTask(
1634 AsyncTaskIntrinsic::ExitSymmetricSyncGuestCall,
1635 )) {
1636 args.intrinsics.extend([
1637 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentComponentIdxs),
1638 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1639 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask),
1640 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskIds),
1641 &Intrinsic::ClearGlobalCurrentTaskMetaFn,
1642 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::SymmetricSyncGuestCallStack),
1643 ]);
1644 }
1645
1646 for current_intrinsic in args.intrinsics.iter() {
1647 if rendered_intrinsics.contains(current_intrinsic.name()) {
1649 continue;
1650 }
1651
1652 current_intrinsic.render(&mut output, &args);
1653 }
1654
1655 output
1656}
1657
1658impl Intrinsic {
1659 pub fn get_global_names() -> impl IntoIterator<Item = &'static str> {
1660 JsHelperIntrinsic::get_global_names()
1661 .into_iter()
1662 .chain(vec![
1663 "base64Compile",
1665 "clampGuest",
1666 "ComponentError",
1667 "fetchCompile",
1668 "finalizationRegistryCreate",
1669 "getErrorPayload",
1670 "HANDLE_TABLES",
1671 "hasOwnProperty",
1672 "imports",
1673 "instantiateCore",
1674 "isLE",
1675 "scopeId",
1676 "symbolCabiDispose",
1677 "symbolCabiLower",
1678 "symbolDispose",
1679 "symbolAsyncIterator",
1680 "symbolIterator",
1681 "symbolRscHandle",
1682 "symbolRscRep",
1683 "T_FLAG",
1684 "throwInvalidBool",
1685 "throwUninitialized",
1686 "ArrayBuffer",
1688 "BigInt",
1689 "BigInt64Array",
1690 "DataView",
1691 "dv",
1692 "emptyFunc",
1693 "Error",
1694 "fetch",
1695 "Float32Array",
1696 "Float64Array",
1697 "Int32Array",
1698 "Object",
1699 "process",
1700 "String",
1701 "TextDecoder",
1702 "TextEncoder",
1703 "TypeError",
1704 "Uint16Array",
1705 "Uint8Array",
1706 "URL",
1707 "WebAssembly",
1708 "GlobalComponentMemories",
1709 ])
1710 }
1711
1712 pub fn name(&self) -> &'static str {
1713 match self {
1714 Intrinsic::JsHelper(i) => i.name(),
1715 Intrinsic::Conversion(i) => i.name(),
1716 Intrinsic::WebIdl(i) => i.name(),
1717 Intrinsic::String(i) => i.name(),
1718 Intrinsic::ErrCtx(i) => i.name(),
1719 Intrinsic::AsyncTask(i) => i.name(),
1720 Intrinsic::Waitable(i) => i.name(),
1721 Intrinsic::Resource(i) => i.name(),
1722 Intrinsic::Lift(i) => i.name(),
1723 Intrinsic::Lower(i) => i.name(),
1724 Intrinsic::AsyncStream(i) => i.name(),
1725 Intrinsic::AsyncFuture(i) => i.name(),
1726 Intrinsic::Component(i) => i.name(),
1727 Intrinsic::Host(i) => i.name(),
1728
1729 Intrinsic::Base64Compile => "base64Compile",
1730 Intrinsic::ClampGuest => "clampGuest",
1731 Intrinsic::ComponentError => "ComponentError",
1732 Intrinsic::FetchCompile => "fetchCompile",
1733 Intrinsic::FinalizationRegistryCreate => "finalizationRegistryCreate",
1734 Intrinsic::GetErrorPayload => "getErrorPayload",
1735 Intrinsic::GetErrorPayloadString => "getErrorPayloadString",
1736 Intrinsic::HandleTables => "HANDLE_TABLES",
1737 Intrinsic::HasOwnProperty => "hasOwnProperty",
1738 Intrinsic::InstantiateCore => "instantiateCore",
1739 Intrinsic::IsLE => "isLE",
1740 Intrinsic::ScopeId => "SCOPE_ID",
1741
1742 Intrinsic::SymbolCabiDispose => "symbolCabiDispose",
1743 Intrinsic::SymbolCabiLower => "symbolCabiLower",
1744 Intrinsic::SymbolDispose => "symbolDispose",
1745 Intrinsic::SymbolAsyncIterator => "symbolAsyncIterator",
1746 Intrinsic::SymbolIterator => "symbolIterator",
1747 Intrinsic::SymbolResourceHandle => "symbolRscHandle",
1748 Intrinsic::SymbolResourceRep => "symbolRscRep",
1749
1750 Intrinsic::ThrowInvalidBool => "throwInvalidBool",
1751 Intrinsic::ThrowUninitialized => "throwUninitialized",
1752
1753 Intrinsic::DebugLog => "_debugLog",
1755 Intrinsic::PromiseWithResolversPonyfill => "promiseWithResolvers",
1756
1757 Intrinsic::ConstantI32Min => "I32_MIN",
1759 Intrinsic::ConstantI32Max => "I32_MAX",
1760 Intrinsic::TypeCheckValidI32 => "_typeCheckValidI32",
1761 Intrinsic::TypeCheckAsyncFn => "_typeCheckAsyncFn",
1762 Intrinsic::AsyncFunctionCtor => "ASYNC_FN_CTOR",
1763
1764 Intrinsic::PlatformReadableStreamClass => "_PlatformReadableStream",
1766
1767 Intrinsic::GlobalAsyncDeterminism => "ASYNC_DETERMINISM",
1769 Intrinsic::CoinFlip => "_coinFlip",
1770
1771 Self::GlobalCurrentTaskMeta => "CURRENT_TASK_META",
1773 Self::GetGlobalCurrentTaskMetaFn => "_getGlobalCurrentTaskMeta",
1774 Self::SetGlobalCurrentTaskMetaFn => "_setGlobalCurrentTaskMeta",
1775 Self::WithGlobalCurrentTaskMetaFn => "_withGlobalCurrentTaskMeta",
1776 Self::WithGlobalCurrentTaskMetaFnAsync => "_withGlobalCurrentTaskMetaAsync",
1777 Self::ClearGlobalCurrentTaskMetaFn => "_clearCurrentTask",
1778
1779 Intrinsic::GlobalComponentMemoryMap => "GLOBAL_COMPONENT_MEMORY_MAP",
1781 Intrinsic::RegisterGlobalMemoryForComponent => "registerGlobalMemoryForComponent",
1782 Intrinsic::LookupMemoriesForComponent => "lookupMemoriesForComponent",
1783
1784 Intrinsic::RepTableClass => "RepTable",
1786
1787 Intrinsic::ManagedBufferClass => "ManagedBuffer",
1789 Intrinsic::BufferManagerClass => "BufferManager",
1790 Intrinsic::GlobalBufferManager => "BUFFER_MGR",
1791
1792 Intrinsic::AsyncEventCodeEnum => "ASYNC_EVENT_CODE",
1794 }
1795 }
1796}