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 #target;
762
763 constructor(args) {{
764 this.target = args?.target;
765 }}
766
767 data() {{ return this.#data; }}
768
769 insert(val) {{
770 {debug_log_fn}('[{rep_table_class}#insert()] args', {{ val, target: this.target }});
771 const freeIdx = this.#data[0];
772 if (freeIdx === 0) {{
773 this.#data.push(val);
774 this.#data.push(null);
775 const rep = (this.#data.length >> 1) - 1;
776 {debug_log_fn}('[{rep_table_class}#insert()] inserted', {{ val, target: this.target, rep }});
777 return rep;
778 }}
779 this.#data[0] = this.#data[freeIdx << 1];
780 const placementIdx = freeIdx << 1;
781 this.#data[placementIdx] = val;
782 this.#data[placementIdx + 1] = null;
783 {debug_log_fn}('[{rep_table_class}#insert()] inserted', {{ val, target: this.target, rep: freeIdx }});
784 return freeIdx;
785 }}
786
787 get(rep) {{
788 {debug_log_fn}('[{rep_table_class}#get()] args', {{ rep, target: this.target }});
789 if (rep === 0) {{ throw new Error('invalid resource rep during get, (cannot be 0)'); }}
790
791 const baseIdx = rep << 1;
792 const val = this.#data[baseIdx];
793 return val;
794 }}
795
796 contains(rep) {{
797 {debug_log_fn}('[{rep_table_class}#contains()] args', {{ rep, target: this.target }});
798 if (rep === 0) {{ throw new Error('invalid resource rep during contains, (cannot be 0)'); }}
799
800 const baseIdx = rep << 1;
801 return !!this.#data[baseIdx];
802 }}
803
804 remove(rep) {{
805 {debug_log_fn}('[{rep_table_class}#remove()] args', {{ rep, target: this.target }});
806 if (rep === 0) {{ throw new Error('invalid resource rep during remove, (cannot be 0)'); }}
807 if (this.#data.length === 2) {{ throw new Error('invalid'); }}
808
809 const baseIdx = rep << 1;
810 const val = this.#data[baseIdx];
811
812 this.#data[baseIdx] = this.#data[0];
813 this.#data[0] = rep;
814
815 return val;
816 }}
817
818 clear() {{
819 {debug_log_fn}('[{rep_table_class}#clear()] args', {{ rep, target: this.target }});
820 this.#data = [0, null];
821 }}
822 }}
823 "#));
824 }
825
826 Intrinsic::GlobalComponentMemoryMap => {
827 let global_component_memory_map = Intrinsic::GlobalComponentMemoryMap.name();
828 output.push_str(&format!(
829 "const {global_component_memory_map} = new Map();\n"
830 ));
831 }
832
833 Intrinsic::RegisterGlobalMemoryForComponent => {
834 let global_component_memory_map = Intrinsic::GlobalComponentMemoryMap.name();
835 let register_global_component_memory =
836 Intrinsic::RegisterGlobalMemoryForComponent.name();
837 output.push_str(&format!(
838 r#"
839 function {register_global_component_memory}(args) {{
840 const {{ componentIdx, memory, memoryIdx }} = args ?? {{}};
841 if (componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
842 if (memory === undefined && memoryIdx === undefined) {{ throw new TypeError('missing both memory & memory idx'); }}
843 let inner = {global_component_memory_map}.get(componentIdx);
844 if (!inner) {{
845 inner = {{}};
846 {global_component_memory_map}.set(componentIdx, inner);
847 }}
848
849 inner[memoryIdx] = {{ memory, memoryIdx, componentIdx }};
850 }}
851 "#)
852 );
853 }
854
855 Intrinsic::LookupMemoriesForComponent => {
856 let global_component_memory_map = Intrinsic::GlobalComponentMemoryMap.name();
857 let lookup_global_memories_for_component =
858 Intrinsic::LookupMemoriesForComponent.name();
859 output.push_str(&format!(
860 r#"
861 function {lookup_global_memories_for_component}(args) {{
862 const {{ componentIdx }} = args ?? {{}};
863 if (args.componentIdx === undefined) {{ throw new TypeError("missing component idx"); }}
864
865 const metas = {global_component_memory_map}.get(componentIdx);
866 if (!metas) {{ return []; }}
867
868 if (args.memoryIdx === undefined) {{
869 return Object.values(metas);
870 }}
871
872 const meta = metas[args.memoryIdx];
873 return meta?.memory;
874 }}
875 "#)
876 );
877 }
878
879 Self::GlobalCurrentTaskMeta => {
880 let name = self.name();
881 output.push_str(&format!("const {name} = {{}};\n"));
882 }
883
884 Self::GetGlobalCurrentTaskMetaFn => {
885 let get_current_global_task_meta_fn = Self::GetGlobalCurrentTaskMetaFn.name();
886 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
887
888 uwriteln!(
889 output,
890 r#"
891 function {get_current_global_task_meta_fn}(componentIdx) {{
892 const v = {global_current_task_meta_obj}[componentIdx];
893 if (v === undefined || v === null) {{ return undefined; }}
894 return {{ ...v }};
895 }}
896 "#,
897 );
898 }
899
900 Self::SetGlobalCurrentTaskMetaFn => {
901 let set_global_current_task_meta_fn = self.name();
902 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
903
904 uwriteln!(
905 output,
906 r#"
907 function {set_global_current_task_meta_fn}(args) {{
908 if (!args) {{ throw new TypeError('args missing'); }}
909 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
910 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
911 const {{ taskID, componentIdx }} = args;
912 return {global_current_task_meta_obj}[componentIdx] = {{ taskID, componentIdx }};
913 }}
914 "#,
915 );
916 }
917
918 Self::WithGlobalCurrentTaskMetaFn => {
919 let debug_log_fn = Intrinsic::DebugLog.name();
920 let with_global_current_task_meta_fn = Self::WithGlobalCurrentTaskMetaFn.name();
921 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
922
923 output.push_str(&format!(
924 r#"
925 function {with_global_current_task_meta_fn}(args) {{
926 {debug_log_fn}('[{with_global_current_task_meta_fn}()] args', args);
927 if (!args) {{ throw new TypeError('args missing'); }}
928 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
929 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
930 if (!args.fn) {{ throw new TypeError('missing fn'); }}
931 const {{ taskID, componentIdx, fn }} = args;
932
933 try {{
934 {global_current_task_meta_obj}[componentIdx] = {{ taskID, componentIdx }};
935 return fn();
936 }} catch (err) {{
937 {debug_log_fn}("error while executing sync callee/callback", {{
938 ...args,
939 err,
940 }});
941 throw err;
942 }} finally {{
943 {global_current_task_meta_obj}[componentIdx] = null;
944 }}
945 }}
946 "#,
947 ));
948 }
949
950 Self::WithGlobalCurrentTaskMetaFnAsync => {
977 let debug_log_fn = Intrinsic::DebugLog.name();
978 let with_global_current_task_meta_async_fn =
979 Self::WithGlobalCurrentTaskMetaFnAsync.name();
980 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
981
982 output.push_str(&format!(
983 r#"
984 async function {with_global_current_task_meta_async_fn}(args) {{
985 {debug_log_fn}('[{with_global_current_task_meta_async_fn}()] args', args);
986 if (!args) {{ throw new TypeError('args missing'); }}
987 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
988 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
989 if (!args.fn) {{ throw new TypeError('missing fn'); }}
990
991 const {{ taskID, componentIdx, fn }} = args;
992
993 try {{
994 {global_current_task_meta_obj}[componentIdx] = {{ taskID, componentIdx }};
995 return await fn();
996 }} catch (err) {{
997 {debug_log_fn}("error while executing async callee/callback", {{
998 ...args,
999 err,
1000 }});
1001 throw err;
1002 }} finally {{
1003 {global_current_task_meta_obj}[componentIdx] = null;
1004 }}
1005 }}
1006 "#,
1007 ));
1008 }
1009
1010 Self::ClearGlobalCurrentTaskMetaFn => {
1011 let debug_log_fn = Intrinsic::DebugLog.name();
1012 let clear_global_current_task_meta_fn = Self::ClearGlobalCurrentTaskMetaFn.name();
1013 let global_current_task_meta_obj = Self::GlobalCurrentTaskMeta.name();
1014
1015 output.push_str(&format!(
1016 r#"
1017 async function {clear_global_current_task_meta_fn}(args) {{
1018 {debug_log_fn}('[{clear_global_current_task_meta_fn}()] args', args);
1019 if (!args) {{ throw new TypeError('args missing'); }}
1020 if (args.taskID === undefined) {{ throw new TypeError('missing task ID'); }}
1021 if (args.componentIdx === undefined) {{ throw new TypeError('missing component idx'); }}
1022 const {{ taskID, componentIdx }} = args;
1023
1024 const meta = {global_current_task_meta_obj}[componentIdx];
1025 if (!meta) {{ throw new Error(`missing current task meta for component idx [${{componentIdx}}]n`); }}
1026
1027 if (meta.taskID !== taskID) {{
1028 throw new Error(`task ID [${{meta.taskID}}] != requested ID [${{taskID}}]`);
1029 }}
1030 if (meta.componentIdx !== componentIdx) {{
1031 throw new Error(`component idx [${{meta.componentIdx}}] != requested idx [${{componentIdx}}]`);
1032 }}
1033
1034 {global_current_task_meta_obj}[componentIdx] = null;
1035 }}
1036 "#,
1037 ));
1038 }
1039
1040 Intrinsic::PlatformReadableStreamClass => {
1042 let name = self.name();
1043 uwriteln!(
1044 output,
1045 r#"
1046 if (!ReadableStream) {{
1047 throw new Error('builtin stream class [ReadableStream] is not available');
1048 }}
1049 const {name} = ReadableStream;
1050 "#
1051 );
1052 }
1053 }
1054 }
1055}
1056
1057#[derive(Debug, Default, PartialEq, Eq)]
1059pub enum AsyncDeterminismProfile {
1060 #[default]
1062 Random,
1063
1064 #[allow(unused)]
1066 Deterministic,
1067}
1068
1069impl std::fmt::Display for AsyncDeterminismProfile {
1070 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1071 write!(
1072 f,
1073 "{}",
1074 match self {
1075 Self::Deterministic => "deterministic",
1076 Self::Random => "random",
1077 }
1078 )
1079 }
1080}
1081
1082#[derive(bon::Builder)]
1084#[non_exhaustive]
1085pub struct RenderIntrinsicsArgs<'a> {
1086 pub(crate) intrinsics: &'a mut BTreeSet<Intrinsic>,
1088 #[builder(default)]
1090 pub(crate) instantiation_occurred: bool,
1091 #[builder(default)]
1093 pub(crate) determinism_profile: AsyncDeterminismProfile,
1094 pub(crate) transpile_opts: &'a TranspileOpts,
1096}
1097
1098const EARLY_INTRINSICS: [Intrinsic; 37] = [
1100 Intrinsic::PromiseWithResolversPonyfill,
1101 Intrinsic::SymbolDispose,
1102 Intrinsic::SymbolAsyncIterator,
1103 Intrinsic::SymbolIterator,
1104 Intrinsic::DebugLog,
1105 Intrinsic::GlobalAsyncDeterminism,
1106 Intrinsic::GlobalComponentMemoryMap,
1107 Intrinsic::GlobalCurrentTaskMeta,
1108 Intrinsic::GetGlobalCurrentTaskMetaFn,
1109 Intrinsic::SetGlobalCurrentTaskMetaFn,
1110 Intrinsic::WithGlobalCurrentTaskMetaFn,
1111 Intrinsic::WithGlobalCurrentTaskMetaFnAsync,
1112 Intrinsic::ClearGlobalCurrentTaskMetaFn,
1113 Intrinsic::LookupMemoriesForComponent,
1114 Intrinsic::RegisterGlobalMemoryForComponent,
1115 Intrinsic::RepTableClass,
1116 Intrinsic::CoinFlip,
1117 Intrinsic::ScopeId,
1118 Intrinsic::ConstantI32Min,
1120 Intrinsic::ConstantI32Max,
1121 Intrinsic::Conversion(ConversionIntrinsic::IsValidNumericPrimitive),
1122 Intrinsic::Conversion(ConversionIntrinsic::RequireValidNumericPrimitive),
1123 Intrinsic::TypeCheckValidI32,
1124 Intrinsic::TypeCheckAsyncFn,
1125 Intrinsic::Resource(ResourceIntrinsic::ResourceCallBorrows),
1127 Intrinsic::AsyncFunctionCtor,
1129 Intrinsic::AsyncTask(AsyncTaskIntrinsic::ClearCurrentTask),
1130 Intrinsic::AsyncTask(AsyncTaskIntrinsic::CurrentTaskMayBlock),
1131 Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskIds),
1132 Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentComponentIdxs),
1133 Intrinsic::AsyncTask(AsyncTaskIntrinsic::UnpackCallbackResult),
1134 Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncSubtaskClass),
1135 Intrinsic::Host(HostIntrinsic::PrepareCall),
1137 Intrinsic::Host(HostIntrinsic::AsyncStartCall),
1138 Intrinsic::Host(HostIntrinsic::SyncStartCall),
1139 Intrinsic::Waitable(WaitableIntrinsic::WaitableClass),
1141 Intrinsic::ErrCtx(ErrCtxIntrinsic::GlobalErrCtxTableMap),
1143];
1144
1145pub fn render_intrinsics(args: RenderIntrinsicsArgs) -> Source {
1148 let mut output = Source::default();
1149 let mut rendered_intrinsics = HashSet::new();
1150
1151 for intrinsic in EARLY_INTRINSICS {
1153 intrinsic.render(&mut output, &args);
1154 rendered_intrinsics.insert(intrinsic.name());
1155 }
1156
1157 if args.intrinsics.contains(&Intrinsic::GetErrorPayload)
1159 || args.intrinsics.contains(&Intrinsic::GetErrorPayloadString)
1160 {
1161 args.intrinsics.insert(Intrinsic::HasOwnProperty);
1162 }
1163 if args
1164 .intrinsics
1165 .contains(&Intrinsic::String(StringIntrinsic::Utf16Encode))
1166 {
1167 args.intrinsics.insert(Intrinsic::IsLE);
1168 }
1169
1170 if args
1171 .intrinsics
1172 .contains(&Intrinsic::Conversion(ConversionIntrinsic::F32ToI32))
1173 || args
1174 .intrinsics
1175 .contains(&Intrinsic::Conversion(ConversionIntrinsic::I32ToF32))
1176 {
1177 output.push_str(
1178 "
1179 const i32ToF32I = new Int32Array(1);
1180 const i32ToF32F = new Float32Array(i32ToF32I.buffer);
1181 ",
1182 );
1183 }
1184
1185 if args
1186 .intrinsics
1187 .contains(&Intrinsic::Conversion(ConversionIntrinsic::F64ToI64))
1188 || args
1189 .intrinsics
1190 .contains(&Intrinsic::Conversion(ConversionIntrinsic::I64ToF64))
1191 {
1192 output.push_str(
1193 "
1194 const i64ToF64I = new BigInt64Array(1);
1195 const i64ToF64F = new Float64Array(i64ToF64I.buffer);
1196 ",
1197 );
1198 }
1199
1200 if args.intrinsics.contains(&Intrinsic::Resource(
1201 ResourceIntrinsic::ResourceTransferBorrow,
1202 )) || args.intrinsics.contains(&Intrinsic::Resource(
1203 ResourceIntrinsic::ResourceTransferBorrowValidLifting,
1204 )) {
1205 args.intrinsics.insert(Intrinsic::Resource(
1206 ResourceIntrinsic::ResourceTableCreateBorrow,
1207 ));
1208 }
1209
1210 if args
1211 .intrinsics
1212 .contains(&Intrinsic::String(StringIntrinsic::Utf8Encode))
1213 || args
1214 .intrinsics
1215 .contains(&Intrinsic::String(StringIntrinsic::Utf8EncodeAsync))
1216 {
1217 args.intrinsics.extend([
1218 &Intrinsic::IsLE,
1219 &Intrinsic::String(StringIntrinsic::GlobalTextEncoderUtf8),
1220 ]);
1221 }
1222
1223 if args
1224 .intrinsics
1225 .contains(&Intrinsic::String(StringIntrinsic::Utf16Encode))
1226 || args
1227 .intrinsics
1228 .contains(&Intrinsic::String(StringIntrinsic::Utf16EncodeAsync))
1229 {
1230 args.intrinsics.extend([&Intrinsic::IsLE]);
1231 }
1232
1233 if args.intrinsics.contains(&Intrinsic::ErrCtx(
1235 ErrCtxIntrinsic::ErrorContextDebugMessage,
1236 )) {
1237 args.intrinsics.extend([
1238 &Intrinsic::String(StringIntrinsic::Utf8Encode),
1239 &Intrinsic::String(StringIntrinsic::Utf16Encode),
1240 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GetLocalTable),
1241 ]);
1242 }
1243
1244 if args
1245 .intrinsics
1246 .contains(&Intrinsic::ErrCtx(ErrCtxIntrinsic::ErrorContextNew))
1247 {
1248 args.intrinsics.extend([
1249 &Intrinsic::ErrCtx(ErrCtxIntrinsic::ComponentGlobalTable),
1250 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GlobalRefCountAdd),
1251 &Intrinsic::ErrCtx(ErrCtxIntrinsic::ReserveGlobalRep),
1252 &Intrinsic::ErrCtx(ErrCtxIntrinsic::CreateLocalHandle),
1253 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GetLocalTable),
1254 ]);
1255 }
1256
1257 if args.intrinsics.contains(&Intrinsic::ErrCtx(
1258 ErrCtxIntrinsic::ErrorContextDebugMessage,
1259 )) {
1260 args.intrinsics.extend([
1261 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GlobalRefCountAdd),
1262 &Intrinsic::ErrCtx(ErrCtxIntrinsic::ErrorContextDrop),
1263 &Intrinsic::ErrCtx(ErrCtxIntrinsic::GetLocalTable),
1264 ]);
1265 }
1266
1267 if args
1268 .intrinsics
1269 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::ContextGet))
1270 || args
1271 .intrinsics
1272 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::ContextSet))
1273 {
1274 args.intrinsics.extend([
1275 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskMap),
1276 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncTaskClass),
1277 &Intrinsic::AsyncEventCodeEnum,
1278 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask),
1279 ]);
1280 }
1281
1282 if args
1283 .intrinsics
1284 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::DriverLoop))
1285 {
1286 args.intrinsics.extend([
1287 &Intrinsic::TypeCheckValidI32,
1288 &Intrinsic::Conversion(ConversionIntrinsic::ToInt32),
1289 &Intrinsic::Component(ComponentIntrinsic::ComponentStateSetAllError),
1290 ]);
1291 }
1292
1293 if args.intrinsics.contains(&Intrinsic::Component(
1294 ComponentIntrinsic::GetOrCreateAsyncState,
1295 )) {
1296 args.intrinsics.extend([&Intrinsic::RepTableClass]);
1297 }
1298
1299 if args
1300 .intrinsics
1301 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncTaskClass))
1302 {
1303 args.intrinsics.extend([
1304 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1305 &Intrinsic::Component(ComponentIntrinsic::GlobalAsyncStateMap),
1306 &Intrinsic::RepTableClass,
1307 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncSubtaskClass),
1308 &Intrinsic::Waitable(WaitableIntrinsic::WaitableClass),
1309 ]);
1310 }
1311
1312 if args
1313 .intrinsics
1314 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetNew))
1315 {
1316 args.intrinsics
1317 .extend([&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetClass)]);
1318 }
1319
1320 if args
1321 .intrinsics
1322 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetPoll))
1323 || args
1324 .intrinsics
1325 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetWait))
1326 {
1327 args.intrinsics
1328 .extend([&Intrinsic::Host(HostIntrinsic::StoreEventInComponentMemory)]);
1329 }
1330
1331 if args
1332 .intrinsics
1333 .contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetDrop))
1334 {
1335 args.intrinsics
1336 .extend([&Intrinsic::Waitable(WaitableIntrinsic::RemoveWaitableSet)]);
1337 }
1338
1339 if args.intrinsics.contains(&Intrinsic::Component(
1340 ComponentIntrinsic::GetOrCreateAsyncState,
1341 )) {
1342 args.intrinsics.extend([
1343 &Intrinsic::Component(ComponentIntrinsic::ComponentAsyncStateClass),
1344 &Intrinsic::Component(ComponentIntrinsic::GlobalAsyncStateMap),
1345 ]);
1346 }
1347
1348 if args.intrinsics.contains(&Intrinsic::Component(
1349 ComponentIntrinsic::ComponentAsyncStateClass,
1350 )) {
1351 args.intrinsics.extend([&Intrinsic::AsyncStream(
1352 AsyncStreamIntrinsic::GlobalStreamMap,
1353 )]);
1354 }
1355
1356 if args
1357 .intrinsics
1358 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatResult))
1359 | args
1360 .intrinsics
1361 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatOption))
1362 | args
1363 .intrinsics
1364 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatOption))
1365 {
1366 args.intrinsics
1367 .extend([&Intrinsic::Lift(LiftIntrinsic::LiftFlatVariant)]);
1368 }
1369
1370 if args
1371 .intrinsics
1372 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatVariant))
1373 {
1374 args.intrinsics.extend([
1375 &Intrinsic::Lift(LiftIntrinsic::LiftFlatU8),
1376 &Intrinsic::Lift(LiftIntrinsic::LiftFlatU16),
1377 &Intrinsic::Lift(LiftIntrinsic::LiftFlatU32),
1378 ]);
1379 }
1380
1381 if args
1382 .intrinsics
1383 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatResult))
1384 {
1385 args.intrinsics
1386 .insert(Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant));
1387 }
1388
1389 if args
1390 .intrinsics
1391 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatOption))
1392 {
1393 args.intrinsics
1394 .insert(Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant));
1395 }
1396
1397 if args
1398 .intrinsics
1399 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant))
1400 {
1401 args.intrinsics.extend([
1402 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU8),
1403 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU16),
1404 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU32),
1405 ]);
1406 }
1407
1408 if args
1409 .intrinsics
1410 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatStream))
1411 {
1412 args.intrinsics.extend([
1413 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamMap),
1414 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::ExternalStreamClass),
1415 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::InternalStreamClass),
1416 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::IsStreamLowerableObject),
1417 &Intrinsic::SymbolResourceRep,
1418 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1419 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GenReadFnFromLowerableStream),
1420 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GenStreamHostInjectFn),
1421 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU32),
1422 ])
1423 }
1424
1425 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1426 AsyncStreamIntrinsic::GenStreamHostInjectFn,
1427 )) {
1428 args.intrinsics.insert(Intrinsic::AsyncStream(
1429 AsyncStreamIntrinsic::PendingValueQueueClass,
1430 ));
1431 }
1432
1433 if args
1434 .intrinsics
1435 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatFuture))
1436 {
1437 args.intrinsics.extend([
1438 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureMap),
1439 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1440 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::InternalFutureClass),
1441 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::IsFutureLowerableObject),
1442 &Intrinsic::SymbolResourceRep,
1443 &Intrinsic::GetErrorPayload,
1444 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1445 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GenFutureHostInjectFn),
1446 &Intrinsic::Lower(LowerIntrinsic::LowerFlatU32),
1447 ])
1448 }
1449
1450 if args
1451 .intrinsics
1452 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStringAny))
1453 {
1454 args.intrinsics.extend([
1455 &Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf8),
1456 &Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf16),
1457 ]);
1458 }
1459
1460 if args
1461 .intrinsics
1462 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf8))
1463 {
1464 args.intrinsics
1465 .insert(Intrinsic::String(StringIntrinsic::GlobalTextDecoderUtf8));
1466 }
1467
1468 if args
1469 .intrinsics
1470 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatStringAny))
1471 {
1472 args.intrinsics.extend([
1473 &Intrinsic::Lower(LowerIntrinsic::LowerFlatStringUtf8),
1474 &Intrinsic::Lower(LowerIntrinsic::LowerFlatStringUtf16),
1475 ]);
1476 }
1477
1478 if args
1479 .intrinsics
1480 .contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatStringUtf8))
1481 {
1482 args.intrinsics
1483 .insert(Intrinsic::String(StringIntrinsic::GlobalTextEncoderUtf8));
1484 }
1485
1486 if args
1487 .intrinsics
1488 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStringUtf16))
1489 {
1490 args.intrinsics
1491 .insert(Intrinsic::String(StringIntrinsic::Utf16Decoder));
1492 }
1493
1494 if args
1495 .intrinsics
1496 .contains(&Intrinsic::Lift(LiftIntrinsic::LiftFlatStream))
1497 {
1498 args.intrinsics.insert(Intrinsic::AsyncStream(
1499 AsyncStreamIntrinsic::ExternalStreamClass,
1500 ));
1501 }
1502
1503 if args.intrinsics.contains(&Intrinsic::AsyncTask(
1504 AsyncTaskIntrinsic::CreateNewCurrentTask,
1505 )) || args
1506 .intrinsics
1507 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask))
1508 || args
1509 .intrinsics
1510 .contains(&Intrinsic::AsyncTask(AsyncTaskIntrinsic::ClearCurrentTask))
1511 {
1512 args.intrinsics.extend([
1513 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncTaskClass),
1514 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskMap),
1515 ]);
1516 }
1517
1518 if args
1519 .intrinsics
1520 .contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamNew))
1521 {
1522 args.intrinsics.extend([
1523 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamMap),
1524 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamTableMap),
1525 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamWritableEndClass),
1526 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamReadableEndClass),
1527 ]);
1528 }
1529
1530 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1531 AsyncStreamIntrinsic::StreamWritableEndClass,
1532 )) || args.intrinsics.contains(&Intrinsic::AsyncStream(
1533 AsyncStreamIntrinsic::StreamReadableEndClass,
1534 )) {
1535 args.intrinsics.extend([
1536 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::InternalStreamClass),
1537 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamEndClass),
1538 &Intrinsic::AsyncEventCodeEnum,
1539 ]);
1540 }
1541
1542 if args.intrinsics.contains(&Intrinsic::AsyncStream(
1543 AsyncStreamIntrinsic::StreamNewFromLift,
1544 )) {
1545 args.intrinsics.extend([
1546 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamMap),
1547 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::GlobalStreamTableMap),
1548 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::HostStreamClass),
1549 &Intrinsic::AsyncStream(AsyncStreamIntrinsic::ExternalStreamClass),
1550 &Intrinsic::GlobalBufferManager,
1551 ]);
1552 }
1553
1554 if args
1555 .intrinsics
1556 .contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamWrite))
1557 || args
1558 .intrinsics
1559 .contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamRead))
1560 || args
1561 .intrinsics
1562 .contains(&Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureWrite))
1563 || args
1564 .intrinsics
1565 .contains(&Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureRead))
1566 {
1567 args.intrinsics.extend([
1568 &Intrinsic::GlobalBufferManager,
1569 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncBlockedConstant),
1570 &Intrinsic::AsyncEventCodeEnum,
1571 ]);
1572 }
1573
1574 if args
1575 .intrinsics
1576 .contains(&Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureNew))
1577 {
1578 args.intrinsics.extend([
1579 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureMap),
1580 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1581 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureTableMap),
1582 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureWritableEndClass),
1583 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureReadableEndClass),
1584 ]);
1585 }
1586
1587 if args.intrinsics.contains(&Intrinsic::AsyncFuture(
1588 AsyncFutureIntrinsic::FutureNewFromLift,
1589 )) {
1590 args.intrinsics.extend([
1591 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1592 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::GlobalFutureMap),
1593 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::HostFutureClass),
1594 &Intrinsic::GlobalBufferManager,
1595 ]);
1596 }
1597
1598 if args.intrinsics.contains(&Intrinsic::AsyncFuture(
1599 AsyncFutureIntrinsic::FutureWritableEndClass,
1600 )) || args.intrinsics.contains(&Intrinsic::AsyncFuture(
1601 AsyncFutureIntrinsic::FutureReadableEndClass,
1602 )) {
1603 args.intrinsics.extend([
1604 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::NestedFutureSymbol),
1605 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::InternalFutureClass),
1606 &Intrinsic::AsyncFuture(AsyncFutureIntrinsic::FutureEndClass),
1607 &Intrinsic::AsyncEventCodeEnum,
1608 ]);
1609 }
1610
1611 if args.intrinsics.contains(&Intrinsic::GlobalBufferManager) {
1612 args.intrinsics.extend([&Intrinsic::BufferManagerClass]);
1613 }
1614
1615 if args.intrinsics.contains(&Intrinsic::BufferManagerClass) {
1616 args.intrinsics.extend([&Intrinsic::ManagedBufferClass]);
1617 }
1618
1619 if args.intrinsics.contains(&Intrinsic::AsyncTask(
1620 AsyncTaskIntrinsic::EnterSymmetricSyncGuestCall,
1621 )) || args.intrinsics.contains(&Intrinsic::AsyncTask(
1622 AsyncTaskIntrinsic::ExitSymmetricSyncGuestCall,
1623 )) {
1624 args.intrinsics.extend([
1625 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentComponentIdxs),
1626 &Intrinsic::Component(ComponentIntrinsic::GetOrCreateAsyncState),
1627 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask),
1628 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::GlobalAsyncCurrentTaskIds),
1629 &Intrinsic::ClearGlobalCurrentTaskMetaFn,
1630 &Intrinsic::AsyncTask(AsyncTaskIntrinsic::SymmetricSyncGuestCallStack),
1631 ]);
1632 }
1633
1634 for current_intrinsic in args.intrinsics.iter() {
1635 if rendered_intrinsics.contains(current_intrinsic.name()) {
1637 continue;
1638 }
1639
1640 current_intrinsic.render(&mut output, &args);
1641 }
1642
1643 output
1644}
1645
1646impl Intrinsic {
1647 pub fn get_global_names() -> impl IntoIterator<Item = &'static str> {
1648 JsHelperIntrinsic::get_global_names()
1649 .into_iter()
1650 .chain(vec![
1651 "base64Compile",
1653 "clampGuest",
1654 "ComponentError",
1655 "fetchCompile",
1656 "finalizationRegistryCreate",
1657 "getErrorPayload",
1658 "HANDLE_TABLES",
1659 "hasOwnProperty",
1660 "imports",
1661 "instantiateCore",
1662 "isLE",
1663 "scopeId",
1664 "symbolCabiDispose",
1665 "symbolCabiLower",
1666 "symbolDispose",
1667 "symbolAsyncIterator",
1668 "symbolIterator",
1669 "symbolRscHandle",
1670 "symbolRscRep",
1671 "T_FLAG",
1672 "throwInvalidBool",
1673 "throwUninitialized",
1674 "ArrayBuffer",
1676 "BigInt",
1677 "BigInt64Array",
1678 "DataView",
1679 "dv",
1680 "emptyFunc",
1681 "Error",
1682 "fetch",
1683 "Float32Array",
1684 "Float64Array",
1685 "Int32Array",
1686 "Object",
1687 "process",
1688 "String",
1689 "TextDecoder",
1690 "TextEncoder",
1691 "TypeError",
1692 "Uint16Array",
1693 "Uint8Array",
1694 "URL",
1695 "WebAssembly",
1696 "GlobalComponentMemories",
1697 ])
1698 }
1699
1700 pub fn name(&self) -> &'static str {
1701 match self {
1702 Intrinsic::JsHelper(i) => i.name(),
1703 Intrinsic::Conversion(i) => i.name(),
1704 Intrinsic::WebIdl(i) => i.name(),
1705 Intrinsic::String(i) => i.name(),
1706 Intrinsic::ErrCtx(i) => i.name(),
1707 Intrinsic::AsyncTask(i) => i.name(),
1708 Intrinsic::Waitable(i) => i.name(),
1709 Intrinsic::Resource(i) => i.name(),
1710 Intrinsic::Lift(i) => i.name(),
1711 Intrinsic::Lower(i) => i.name(),
1712 Intrinsic::AsyncStream(i) => i.name(),
1713 Intrinsic::AsyncFuture(i) => i.name(),
1714 Intrinsic::Component(i) => i.name(),
1715 Intrinsic::Host(i) => i.name(),
1716
1717 Intrinsic::Base64Compile => "base64Compile",
1718 Intrinsic::ClampGuest => "clampGuest",
1719 Intrinsic::ComponentError => "ComponentError",
1720 Intrinsic::FetchCompile => "fetchCompile",
1721 Intrinsic::FinalizationRegistryCreate => "finalizationRegistryCreate",
1722 Intrinsic::GetErrorPayload => "getErrorPayload",
1723 Intrinsic::GetErrorPayloadString => "getErrorPayloadString",
1724 Intrinsic::HandleTables => "HANDLE_TABLES",
1725 Intrinsic::HasOwnProperty => "hasOwnProperty",
1726 Intrinsic::InstantiateCore => "instantiateCore",
1727 Intrinsic::IsLE => "isLE",
1728 Intrinsic::ScopeId => "SCOPE_ID",
1729
1730 Intrinsic::SymbolCabiDispose => "symbolCabiDispose",
1731 Intrinsic::SymbolCabiLower => "symbolCabiLower",
1732 Intrinsic::SymbolDispose => "symbolDispose",
1733 Intrinsic::SymbolAsyncIterator => "symbolAsyncIterator",
1734 Intrinsic::SymbolIterator => "symbolIterator",
1735 Intrinsic::SymbolResourceHandle => "symbolRscHandle",
1736 Intrinsic::SymbolResourceRep => "symbolRscRep",
1737
1738 Intrinsic::ThrowInvalidBool => "throwInvalidBool",
1739 Intrinsic::ThrowUninitialized => "throwUninitialized",
1740
1741 Intrinsic::DebugLog => "_debugLog",
1743 Intrinsic::PromiseWithResolversPonyfill => "promiseWithResolvers",
1744
1745 Intrinsic::ConstantI32Min => "I32_MIN",
1747 Intrinsic::ConstantI32Max => "I32_MAX",
1748 Intrinsic::TypeCheckValidI32 => "_typeCheckValidI32",
1749 Intrinsic::TypeCheckAsyncFn => "_typeCheckAsyncFn",
1750 Intrinsic::AsyncFunctionCtor => "ASYNC_FN_CTOR",
1751
1752 Intrinsic::PlatformReadableStreamClass => "_PlatformReadableStream",
1754
1755 Intrinsic::GlobalAsyncDeterminism => "ASYNC_DETERMINISM",
1757 Intrinsic::CoinFlip => "_coinFlip",
1758
1759 Self::GlobalCurrentTaskMeta => "CURRENT_TASK_META",
1761 Self::GetGlobalCurrentTaskMetaFn => "_getGlobalCurrentTaskMeta",
1762 Self::SetGlobalCurrentTaskMetaFn => "_setGlobalCurrentTaskMeta",
1763 Self::WithGlobalCurrentTaskMetaFn => "_withGlobalCurrentTaskMeta",
1764 Self::WithGlobalCurrentTaskMetaFnAsync => "_withGlobalCurrentTaskMetaAsync",
1765 Self::ClearGlobalCurrentTaskMetaFn => "_clearCurrentTask",
1766
1767 Intrinsic::GlobalComponentMemoryMap => "GLOBAL_COMPONENT_MEMORY_MAP",
1769 Intrinsic::RegisterGlobalMemoryForComponent => "registerGlobalMemoryForComponent",
1770 Intrinsic::LookupMemoriesForComponent => "lookupMemoriesForComponent",
1771
1772 Intrinsic::RepTableClass => "RepTable",
1774
1775 Intrinsic::ManagedBufferClass => "ManagedBuffer",
1777 Intrinsic::BufferManagerClass => "BufferManager",
1778 Intrinsic::GlobalBufferManager => "BUFFER_MGR",
1779
1780 Intrinsic::AsyncEventCodeEnum => "ASYNC_EVENT_CODE",
1782 }
1783 }
1784}