Skip to main content

boa_engine/bytecompiler/
mod.rs

1//! This module contains the bytecode compiler.
2
3mod class;
4mod declaration;
5mod declarations;
6mod env;
7mod expression;
8mod function;
9mod jump_control;
10mod module;
11mod register;
12mod statement;
13mod utils;
14
15use std::{
16    borrow::{Borrow, BorrowMut},
17    cell::Cell,
18    ops::{Deref, DerefMut},
19};
20
21use crate::{
22    JsBigInt, JsStr, JsString, SourceText, SpannedSourceText,
23    builtins::function::{ThisMode, arguments::MappedArguments},
24    js_string,
25    vm::{
26        CallFrame, CodeBlock, CodeBlockFlags, Constant, GeneratorResumeKind, Handler, InlineCache,
27        opcode::{BindingOpcode, ByteCodeEmitter, VaryingOperand},
28        source_info::{SourceInfo, SourceMap, SourceMapBuilder, SourcePath},
29    },
30};
31use boa_ast::{
32    Declaration, Expression, LinearSpan, Position, Spanned, Statement, StatementList,
33    StatementListItem,
34    declaration::{Binding, LexicalDeclaration, VarDeclaration},
35    expression::{
36        Call, Identifier, New, Optional, OptionalOperationKind,
37        access::{PropertyAccess, PropertyAccessField},
38        literal::ObjectMethodDefinition,
39        operator::{assign::AssignTarget, update::UpdateTarget},
40    },
41    function::{
42        ArrowFunction, AsyncArrowFunction, AsyncFunctionDeclaration, AsyncFunctionExpression,
43        AsyncGeneratorDeclaration, AsyncGeneratorExpression, ClassMethodDefinition,
44        FormalParameterList, FunctionBody, FunctionDeclaration, FunctionExpression,
45        GeneratorDeclaration, GeneratorExpression, PrivateName,
46    },
47    operations::returns_value,
48    pattern::Pattern,
49    property::MethodDefinitionKind,
50    scope::{BindingLocator, BindingLocatorError, FunctionScopes, IdentifierReference, Scope},
51};
52use boa_gc::Gc;
53use boa_interner::{Interner, Sym};
54use boa_macros::js_str;
55use rustc_hash::FxHashMap;
56use thin_vec::ThinVec;
57
58pub(crate) use declarations::{
59    eval_declaration_instantiation_context, global_declaration_instantiation_context,
60};
61pub(crate) use function::FunctionCompiler;
62pub(crate) use jump_control::JumpControlInfo;
63pub(crate) use register::*;
64
65pub(crate) trait ToJsString {
66    fn to_js_string(&self, interner: &Interner) -> JsString;
67}
68
69impl ToJsString for Sym {
70    fn to_js_string(&self, interner: &Interner) -> JsString {
71        // TODO: Identify latin1 encodeable strings during parsing to avoid this check.
72        let string = interner.resolve_expect(*self).utf16();
73        for c in string {
74            if u8::try_from(*c).is_err() {
75                return js_string!(string);
76            }
77        }
78        let string = string.iter().map(|c| *c as u8).collect::<Vec<_>>();
79        js_string!(JsStr::latin1(&string))
80    }
81}
82
83impl ToJsString for Identifier {
84    fn to_js_string(&self, interner: &Interner) -> JsString {
85        self.sym().to_js_string(interner)
86    }
87}
88
89/// Describes how a node has been defined in the source code.
90#[derive(Debug, Clone, Copy, PartialEq)]
91pub(crate) enum NodeKind {
92    Declaration,
93    Expression,
94}
95
96/// Describes the type of a function.
97#[derive(Debug, Clone, Copy, PartialEq)]
98pub(crate) enum FunctionKind {
99    Ordinary,
100    Arrow,
101    AsyncArrow,
102    Async,
103    Generator,
104    AsyncGenerator,
105}
106
107impl FunctionKind {
108    pub(crate) const fn is_arrow(self) -> bool {
109        matches!(self, Self::Arrow | Self::AsyncArrow)
110    }
111
112    pub(crate) const fn is_async(self) -> bool {
113        matches!(self, Self::Async | Self::AsyncGenerator | Self::AsyncArrow)
114    }
115
116    pub(crate) const fn is_generator(self) -> bool {
117        matches!(self, Self::Generator | Self::AsyncGenerator)
118    }
119}
120
121/// Describes the complete specification of a function node.
122#[derive(Debug, Clone, Copy)]
123pub(crate) struct FunctionSpec<'a> {
124    pub(crate) kind: FunctionKind,
125    pub(crate) name: Option<Identifier>,
126    parameters: &'a FormalParameterList,
127    body: &'a FunctionBody,
128    pub(crate) scopes: &'a FunctionScopes,
129    pub(crate) name_scope: Option<&'a Scope>,
130    linear_span: Option<LinearSpan>,
131    pub(crate) contains_direct_eval: bool,
132}
133
134impl PartialEq for FunctionSpec<'_> {
135    fn eq(&self, other: &Self) -> bool {
136        // all fields except `linear_span`
137        self.kind == other.kind
138            && self.name == other.name
139            && self.parameters == other.parameters
140            && self.body == other.body
141            && self.scopes == other.scopes
142            && self.name_scope == other.name_scope
143    }
144}
145
146impl<'a> From<&'a FunctionDeclaration> for FunctionSpec<'a> {
147    fn from(function: &'a FunctionDeclaration) -> Self {
148        FunctionSpec {
149            kind: FunctionKind::Ordinary,
150            name: Some(function.name()),
151            parameters: function.parameters(),
152            body: function.body(),
153            scopes: function.scopes(),
154            name_scope: None,
155            linear_span: Some(function.linear_span()),
156            contains_direct_eval: function.contains_direct_eval(),
157        }
158    }
159}
160
161impl<'a> From<&'a GeneratorDeclaration> for FunctionSpec<'a> {
162    fn from(function: &'a GeneratorDeclaration) -> Self {
163        FunctionSpec {
164            kind: FunctionKind::Generator,
165            name: Some(function.name()),
166            parameters: function.parameters(),
167            body: function.body(),
168            scopes: function.scopes(),
169            name_scope: None,
170            linear_span: Some(function.linear_span()),
171            contains_direct_eval: function.contains_direct_eval(),
172        }
173    }
174}
175
176impl<'a> From<&'a AsyncFunctionDeclaration> for FunctionSpec<'a> {
177    fn from(function: &'a AsyncFunctionDeclaration) -> Self {
178        FunctionSpec {
179            kind: FunctionKind::Async,
180            name: Some(function.name()),
181            parameters: function.parameters(),
182            body: function.body(),
183            scopes: function.scopes(),
184            name_scope: None,
185            linear_span: Some(function.linear_span()),
186            contains_direct_eval: function.contains_direct_eval(),
187        }
188    }
189}
190
191impl<'a> From<&'a AsyncGeneratorDeclaration> for FunctionSpec<'a> {
192    fn from(function: &'a AsyncGeneratorDeclaration) -> Self {
193        FunctionSpec {
194            kind: FunctionKind::AsyncGenerator,
195            name: Some(function.name()),
196            parameters: function.parameters(),
197            body: function.body(),
198            scopes: function.scopes(),
199            name_scope: None,
200            linear_span: Some(function.linear_span()),
201            contains_direct_eval: function.contains_direct_eval(),
202        }
203    }
204}
205
206impl<'a> From<&'a FunctionExpression> for FunctionSpec<'a> {
207    fn from(function: &'a FunctionExpression) -> Self {
208        FunctionSpec {
209            kind: FunctionKind::Ordinary,
210            name: function.name(),
211            parameters: function.parameters(),
212            body: function.body(),
213            scopes: function.scopes(),
214            name_scope: function.name_scope(),
215            linear_span: function.linear_span(),
216            contains_direct_eval: function.contains_direct_eval(),
217        }
218    }
219}
220
221impl<'a> From<&'a ArrowFunction> for FunctionSpec<'a> {
222    fn from(function: &'a ArrowFunction) -> Self {
223        FunctionSpec {
224            kind: FunctionKind::Arrow,
225            name: function.name(),
226            parameters: function.parameters(),
227            body: function.body(),
228            scopes: function.scopes(),
229            name_scope: None,
230            linear_span: Some(function.linear_span()),
231            contains_direct_eval: function.contains_direct_eval(),
232        }
233    }
234}
235
236impl<'a> From<&'a AsyncArrowFunction> for FunctionSpec<'a> {
237    fn from(function: &'a AsyncArrowFunction) -> Self {
238        FunctionSpec {
239            kind: FunctionKind::AsyncArrow,
240            name: function.name(),
241            parameters: function.parameters(),
242            body: function.body(),
243            scopes: function.scopes(),
244            name_scope: None,
245            linear_span: Some(function.linear_span()),
246            contains_direct_eval: function.contains_direct_eval(),
247        }
248    }
249}
250
251impl<'a> From<&'a AsyncFunctionExpression> for FunctionSpec<'a> {
252    fn from(function: &'a AsyncFunctionExpression) -> Self {
253        FunctionSpec {
254            kind: FunctionKind::Async,
255            name: function.name(),
256            parameters: function.parameters(),
257            body: function.body(),
258            scopes: function.scopes(),
259            name_scope: function.name_scope(),
260            linear_span: Some(function.linear_span()),
261            contains_direct_eval: function.contains_direct_eval(),
262        }
263    }
264}
265
266impl<'a> From<&'a GeneratorExpression> for FunctionSpec<'a> {
267    fn from(function: &'a GeneratorExpression) -> Self {
268        FunctionSpec {
269            kind: FunctionKind::Generator,
270            name: function.name(),
271            parameters: function.parameters(),
272            body: function.body(),
273            scopes: function.scopes(),
274            name_scope: function.name_scope(),
275            linear_span: Some(function.linear_span()),
276            contains_direct_eval: function.contains_direct_eval(),
277        }
278    }
279}
280
281impl<'a> From<&'a AsyncGeneratorExpression> for FunctionSpec<'a> {
282    fn from(function: &'a AsyncGeneratorExpression) -> Self {
283        FunctionSpec {
284            kind: FunctionKind::AsyncGenerator,
285            name: function.name(),
286            parameters: function.parameters(),
287            body: function.body(),
288            scopes: function.scopes(),
289            name_scope: function.name_scope(),
290            linear_span: Some(function.linear_span()),
291            contains_direct_eval: function.contains_direct_eval(),
292        }
293    }
294}
295
296impl<'a> From<&'a ClassMethodDefinition> for FunctionSpec<'a> {
297    fn from(method: &'a ClassMethodDefinition) -> Self {
298        let kind = match method.kind() {
299            MethodDefinitionKind::Generator => FunctionKind::Generator,
300            MethodDefinitionKind::AsyncGenerator => FunctionKind::AsyncGenerator,
301            MethodDefinitionKind::Async => FunctionKind::Async,
302            _ => FunctionKind::Ordinary,
303        };
304
305        FunctionSpec {
306            kind,
307            name: None,
308            parameters: method.parameters(),
309            body: method.body(),
310            scopes: method.scopes(),
311            name_scope: None,
312            linear_span: Some(method.linear_span()),
313            contains_direct_eval: method.contains_direct_eval(),
314        }
315    }
316}
317
318impl<'a> From<&'a ObjectMethodDefinition> for FunctionSpec<'a> {
319    fn from(method: &'a ObjectMethodDefinition) -> Self {
320        let kind = match method.kind() {
321            MethodDefinitionKind::Generator => FunctionKind::Generator,
322            MethodDefinitionKind::AsyncGenerator => FunctionKind::AsyncGenerator,
323            MethodDefinitionKind::Async => FunctionKind::Async,
324            _ => FunctionKind::Ordinary,
325        };
326
327        FunctionSpec {
328            kind,
329            name: method.name().literal(),
330            parameters: method.parameters(),
331            body: method.body(),
332            scopes: method.scopes(),
333            name_scope: None,
334            linear_span: Some(method.linear_span()),
335            contains_direct_eval: method.contains_direct_eval(),
336        }
337    }
338}
339
340#[derive(Debug, Clone, Copy)]
341pub(crate) enum MethodKind {
342    Get,
343    Set,
344    Ordinary,
345}
346
347/// Represents a callable expression, like `f()` or `new Cl()`
348#[derive(Debug, Clone, Copy)]
349enum Callable<'a> {
350    Call(&'a Call),
351    New(&'a New),
352}
353
354#[derive(Debug, Clone, PartialEq, Eq, Hash)]
355enum Literal {
356    String(JsString),
357    BigInt(JsBigInt),
358}
359
360#[must_use]
361#[derive(Debug, Clone, Copy, PartialEq, Eq)]
362pub(crate) struct Label {
363    index: u32,
364}
365
366#[derive(Debug, Clone, Copy)]
367#[allow(variant_size_differences)]
368enum Access<'a> {
369    Variable { name: Identifier },
370    Property { access: &'a PropertyAccess },
371    This,
372}
373
374impl Access<'_> {
375    const fn from_assign_target(target: &AssignTarget) -> Result<Access<'_>, &Pattern> {
376        match target {
377            AssignTarget::Identifier(ident) => Ok(Access::Variable { name: *ident }),
378            AssignTarget::Access(access) => Ok(Access::Property { access }),
379            AssignTarget::Pattern(pat) => Err(pat),
380        }
381    }
382
383    const fn from_expression(expr: &Expression) -> Option<Access<'_>> {
384        match expr {
385            Expression::Identifier(name) => Some(Access::Variable { name: *name }),
386            Expression::PropertyAccess(access) => Some(Access::Property { access }),
387            Expression::This(_this) => Some(Access::This),
388            Expression::Parenthesized(expr) => Self::from_expression(expr.expression()),
389            _ => None,
390        }
391    }
392
393    const fn from_update_target(target: &UpdateTarget) -> Access<'_> {
394        match target {
395            UpdateTarget::Identifier(name) => Access::Variable { name: *name },
396            UpdateTarget::PropertyAccess(access) => Access::Property { access },
397        }
398    }
399}
400
401#[derive(Copy, Clone, Debug)]
402pub(crate) enum BindingAccessOpcode {
403    PutLexicalValue,
404    DefInitVar,
405    SetName,
406    SetNameByLocator,
407    GetName,
408    GetNameAndLocator,
409    GetNameOrUndefined,
410    DeleteName,
411    GetLocator,
412    DefVar,
413}
414
415/// Manages the source position scope, push on creation, pop on drop.
416pub(crate) struct SourcePositionGuard<'a, 'b> {
417    compiler: &'a mut ByteCompiler<'b>,
418}
419impl<'a, 'b> SourcePositionGuard<'a, 'b> {
420    fn new(compiler: &'a mut ByteCompiler<'b>, position: Position) -> Self {
421        compiler.push_source_position(position);
422        Self { compiler }
423    }
424}
425impl Drop for SourcePositionGuard<'_, '_> {
426    fn drop(&mut self) {
427        self.pop_source_position();
428    }
429}
430impl<'a> Deref for SourcePositionGuard<'_, 'a> {
431    type Target = ByteCompiler<'a>;
432    fn deref(&self) -> &Self::Target {
433        self.compiler
434    }
435}
436impl DerefMut for SourcePositionGuard<'_, '_> {
437    fn deref_mut(&mut self) -> &mut Self::Target {
438        self.compiler
439    }
440}
441impl<'a> Borrow<ByteCompiler<'a>> for SourcePositionGuard<'_, 'a> {
442    fn borrow(&self) -> &ByteCompiler<'a> {
443        self.compiler
444    }
445}
446impl<'a> BorrowMut<ByteCompiler<'a>> for SourcePositionGuard<'_, 'a> {
447    fn borrow_mut(&mut self) -> &mut ByteCompiler<'a> {
448        self.compiler
449    }
450}
451
452/// The [`ByteCompiler`] is used to compile ECMAScript AST from [`boa_ast`] to bytecode.
453#[derive(Debug)]
454#[allow(clippy::struct_excessive_bools)]
455pub struct ByteCompiler<'ctx> {
456    /// Name of this function.
457    pub(crate) function_name: JsString,
458
459    /// The number of arguments expected.
460    pub(crate) length: u32,
461
462    pub(crate) register_allocator: RegisterAllocator,
463
464    /// `[[ThisMode]]`
465    pub(crate) this_mode: ThisMode,
466
467    /// Parameters passed to this function.
468    pub(crate) params: FormalParameterList,
469
470    /// Scope of the function parameters.
471    pub(crate) parameter_scope: Scope,
472
473    /// Bytecode
474    pub(crate) bytecode: ByteCodeEmitter,
475
476    pub(crate) source_map_builder: SourceMapBuilder,
477    pub(crate) source_path: SourcePath,
478
479    pub(crate) constants: ThinVec<Constant>,
480
481    /// Locators for all bindings in the codeblock.
482    pub(crate) bindings: Vec<BindingLocator>,
483
484    pub(crate) local_binding_registers: FxHashMap<IdentifierReference, u32>,
485
486    /// The current variable scope.
487    pub(crate) variable_scope: Scope,
488
489    /// The current lexical scope.
490    pub(crate) lexical_scope: Scope,
491
492    pub(crate) current_open_environments_count: u32,
493    code_block_flags: CodeBlockFlags,
494    handlers: ThinVec<Handler>,
495    pub(crate) ic: Vec<InlineCache>,
496    literals_map: FxHashMap<Literal, u32>,
497    names_map: FxHashMap<Sym, u32>,
498    bindings_map: FxHashMap<BindingLocator, u32>,
499    jump_info: Vec<JumpControlInfo>,
500
501    /// Used to handle exception throws that escape the async function types.
502    ///
503    /// Async functions and async generator functions, need to be closed and resolved.
504    pub(crate) async_handler: Option<u32>,
505    json_parse: bool,
506
507    /// Whether the function is in a `with` statement.
508    pub(crate) in_with: bool,
509
510    /// Used to determine if a we emited a `CreateUnmappedArgumentsObject` opcode
511    pub(crate) emitted_mapped_arguments_object_opcode: bool,
512
513    pub(crate) interner: &'ctx mut Interner,
514    spanned_source_text: SpannedSourceText,
515
516    #[cfg(feature = "annex-b")]
517    pub(crate) annex_b_function_names: Vec<Sym>,
518}
519
520pub(crate) enum BindingKind {
521    Stack(u32),
522    Local(Option<u32>),
523    Global(u32),
524}
525
526impl<'ctx> ByteCompiler<'ctx> {
527    /// Represents a placeholder address that will be patched later.
528    const DUMMY_ADDRESS: u32 = u32::MAX;
529    const DUMMY_LABEL: Label = Label { index: u32::MAX };
530
531    /// Creates a new [`ByteCompiler`].
532    #[inline]
533    #[allow(clippy::too_many_arguments)]
534    #[allow(clippy::fn_params_excessive_bools)]
535    pub(crate) fn new(
536        name: JsString,
537        strict: bool,
538        json_parse: bool,
539        variable_scope: Scope,
540        lexical_scope: Scope,
541        is_async: bool,
542        is_generator: bool,
543        interner: &'ctx mut Interner,
544        in_with: bool,
545        spanned_source_text: SpannedSourceText,
546        source_path: SourcePath,
547    ) -> ByteCompiler<'ctx> {
548        let mut code_block_flags = CodeBlockFlags::empty();
549        code_block_flags.set(CodeBlockFlags::STRICT, strict);
550        code_block_flags.set(CodeBlockFlags::IS_ASYNC, is_async);
551        code_block_flags.set(CodeBlockFlags::IS_GENERATOR, is_generator);
552        code_block_flags |= CodeBlockFlags::HAS_PROTOTYPE_PROPERTY;
553
554        let mut register_allocator = RegisterAllocator::default();
555        if is_async {
556            let promise_register = register_allocator.alloc_persistent();
557            let resolve_register = register_allocator.alloc_persistent();
558            let reject_register = register_allocator.alloc_persistent();
559
560            debug_assert_eq!(
561                promise_register.index(),
562                CallFrame::PROMISE_CAPABILITY_PROMISE_REGISTER_INDEX as u32
563            );
564            debug_assert_eq!(
565                resolve_register.index(),
566                CallFrame::PROMISE_CAPABILITY_RESOLVE_REGISTER_INDEX as u32
567            );
568            debug_assert_eq!(
569                reject_register.index(),
570                CallFrame::PROMISE_CAPABILITY_REJECT_REGISTER_INDEX as u32
571            );
572
573            if is_generator {
574                let async_function_object_register = register_allocator.alloc_persistent();
575                debug_assert_eq!(
576                    async_function_object_register.index(),
577                    CallFrame::ASYNC_GENERATOR_OBJECT_REGISTER_INDEX as u32
578                );
579            }
580        }
581
582        Self {
583            function_name: name,
584            length: 0,
585            bytecode: ByteCodeEmitter::new(),
586            source_map_builder: SourceMapBuilder::default(),
587            constants: ThinVec::default(),
588            bindings: Vec::default(),
589            local_binding_registers: FxHashMap::default(),
590            this_mode: ThisMode::Global,
591            params: FormalParameterList::default(),
592            parameter_scope: Scope::default(),
593            current_open_environments_count: 0,
594
595            register_allocator,
596            code_block_flags,
597            handlers: ThinVec::default(),
598            ic: Vec::default(),
599
600            literals_map: FxHashMap::default(),
601            names_map: FxHashMap::default(),
602            bindings_map: FxHashMap::default(),
603            jump_info: Vec::new(),
604            async_handler: None,
605            json_parse,
606            variable_scope,
607            lexical_scope,
608            interner,
609            spanned_source_text,
610            source_path,
611
612            #[cfg(feature = "annex-b")]
613            annex_b_function_names: Vec::new(),
614            in_with,
615            emitted_mapped_arguments_object_opcode: false,
616        }
617    }
618
619    pub(crate) fn source_text(&self) -> SourceText {
620        self.spanned_source_text.source_text()
621    }
622
623    pub(crate) const fn strict(&self) -> bool {
624        self.code_block_flags.contains(CodeBlockFlags::STRICT)
625    }
626
627    pub(crate) const fn is_async(&self) -> bool {
628        self.code_block_flags.contains(CodeBlockFlags::IS_ASYNC)
629    }
630
631    pub(crate) const fn is_generator(&self) -> bool {
632        self.code_block_flags.contains(CodeBlockFlags::IS_GENERATOR)
633    }
634
635    pub(crate) const fn is_async_generator(&self) -> bool {
636        self.is_async() && self.is_generator()
637    }
638
639    pub(crate) fn interner(&self) -> &Interner {
640        self.interner
641    }
642
643    fn get_or_insert_literal(&mut self, literal: Literal) -> u32 {
644        if let Some(index) = self.literals_map.get(&literal) {
645            return *index;
646        }
647
648        let value = match literal.clone() {
649            Literal::String(value) => Constant::String(value),
650            Literal::BigInt(value) => Constant::BigInt(value),
651        };
652
653        let index = self.constants.len() as u32;
654        self.constants.push(value);
655        self.literals_map.insert(literal, index);
656        index
657    }
658
659    fn get_or_insert_name(&mut self, name: Sym) -> u32 {
660        if let Some(index) = self.names_map.get(&name) {
661            return *index;
662        }
663
664        let index = self.constants.len() as u32;
665        let string = name.to_js_string(self.interner());
666        self.constants.push(Constant::String(string));
667        self.names_map.insert(name, index);
668        index
669    }
670
671    fn get_or_insert_string(&mut self, value: JsString) -> u32 {
672        self.get_or_insert_literal(Literal::String(value))
673    }
674
675    #[inline]
676    fn get_or_insert_private_name(&mut self, name: PrivateName) -> u32 {
677        self.get_or_insert_name(name.description())
678    }
679
680    // TODO: Make this return `Option<BindingKind>` instead of making BindingKind::Local
681    //       inner field optional.
682    #[inline]
683    pub(crate) fn get_binding(&mut self, binding: &IdentifierReference) -> BindingKind {
684        if binding.is_global_object() {
685            if let Some(index) = self.bindings_map.get(&binding.locator()) {
686                return BindingKind::Global(*index);
687            }
688
689            let index = self.bindings.len() as u32;
690            self.bindings.push(binding.locator().clone());
691            self.bindings_map.insert(binding.locator(), index);
692            return BindingKind::Global(index);
693        }
694
695        if binding.local() {
696            return BindingKind::Local(self.local_binding_registers.get(binding).copied());
697        }
698
699        if let Some(index) = self.bindings_map.get(&binding.locator()) {
700            return BindingKind::Stack(*index);
701        }
702
703        let index = self.bindings.len() as u32;
704        self.bindings.push(binding.locator().clone());
705        self.bindings_map.insert(binding.locator(), index);
706        BindingKind::Stack(index)
707    }
708
709    #[inline]
710    pub(crate) fn insert_binding(&mut self, binding: IdentifierReference) -> BindingKind {
711        if binding.is_global_object() {
712            if let Some(index) = self.bindings_map.get(&binding.locator()) {
713                return BindingKind::Global(*index);
714            }
715
716            let index = self.bindings.len() as u32;
717            self.bindings.push(binding.locator().clone());
718            self.bindings_map.insert(binding.locator(), index);
719            return BindingKind::Global(index);
720        }
721
722        if binding.local() {
723            return BindingKind::Local(Some(
724                *self
725                    .local_binding_registers
726                    .entry(binding)
727                    .or_insert_with(|| self.register_allocator.alloc_persistent().index()),
728            ));
729        }
730
731        if let Some(index) = self.bindings_map.get(&binding.locator()) {
732            return BindingKind::Stack(*index);
733        }
734
735        let index = self.bindings.len() as u32;
736        self.bindings.push(binding.locator().clone());
737        self.bindings_map.insert(binding.locator(), index);
738        BindingKind::Stack(index)
739    }
740
741    #[inline]
742    #[must_use]
743    pub(crate) fn push_function_to_constants(&mut self, function: Gc<CodeBlock>) -> u32 {
744        let index = self.constants.len() as u32;
745        self.constants.push(Constant::Function(function));
746        index
747    }
748
749    fn emit_binding(&mut self, opcode: BindingOpcode, name: JsString, value: &Register) {
750        match opcode {
751            BindingOpcode::Var => {
752                let binding = self.variable_scope.get_identifier_reference(name);
753                if !binding.locator().is_global() {
754                    let index = self.insert_binding(binding);
755                    self.emit_binding_access(BindingAccessOpcode::DefVar, &index, value);
756                }
757            }
758            BindingOpcode::InitVar => match self.lexical_scope.set_mutable_binding(name.clone()) {
759                Ok(binding) => {
760                    let index = self.insert_binding(binding);
761                    self.emit_binding_access(BindingAccessOpcode::DefInitVar, &index, value);
762                }
763                Err(BindingLocatorError::MutateImmutable) => {
764                    let index = self.get_or_insert_string(name);
765                    self.bytecode.emit_throw_mutate_immutable(index.into());
766                }
767                Err(BindingLocatorError::Silent) => {}
768            },
769            BindingOpcode::InitLexical => {
770                let binding = self.lexical_scope.get_identifier_reference(name);
771                let index = self.insert_binding(binding);
772                self.emit_binding_access(BindingAccessOpcode::PutLexicalValue, &index, value);
773            }
774            BindingOpcode::SetName => match self.lexical_scope.set_mutable_binding(name.clone()) {
775                Ok(binding) => {
776                    let index = self.insert_binding(binding);
777                    self.emit_binding_access(BindingAccessOpcode::SetName, &index, value);
778                }
779                Err(BindingLocatorError::MutateImmutable) => {
780                    let index = self.get_or_insert_string(name);
781                    self.bytecode.emit_throw_mutate_immutable(index.into());
782                }
783                Err(BindingLocatorError::Silent) => {}
784            },
785        }
786    }
787
788    fn next_opcode_location(&mut self) -> u32 {
789        self.bytecode.next_opcode_location()
790    }
791
792    pub(crate) fn position_guard(
793        &mut self,
794        spanned: impl Spanned,
795    ) -> SourcePositionGuard<'_, 'ctx> {
796        SourcePositionGuard::new(self, spanned.span().start())
797    }
798
799    pub(crate) fn push_source_position<T>(&mut self, position: T)
800    where
801        T: Into<Option<Position>>,
802    {
803        let start_pc = self.next_opcode_location();
804        self.source_map_builder
805            .push_source_position(start_pc, position.into());
806    }
807
808    pub(crate) fn pop_source_position(&mut self) {
809        let start_pc = self.next_opcode_location();
810        self.source_map_builder.pop_source_position(start_pc);
811    }
812
813    pub(crate) fn emit_get_function(&mut self, dst: &Register, index: u32) {
814        self.bytecode
815            .emit_get_function(dst.variable(), index.into());
816    }
817
818    fn pop_into_register(&mut self, dst: &Register) {
819        self.bytecode.emit_pop_into_register(dst.variable());
820    }
821
822    pub(crate) fn push_from_register(&mut self, src: &Register) {
823        self.bytecode.emit_push_from_register(src.variable());
824    }
825
826    pub(crate) fn emit_binding_access(
827        &mut self,
828        opcode: BindingAccessOpcode,
829        binding: &BindingKind,
830        value: &Register,
831    ) {
832        match binding {
833            BindingKind::Global(index) => match opcode {
834                BindingAccessOpcode::SetNameByLocator => {
835                    self.bytecode.emit_set_name_by_locator(value.variable());
836                }
837                BindingAccessOpcode::GetName => {
838                    let ic_index = self.ic.len() as u32;
839                    let name = self.bindings[*index as usize].name().clone();
840                    self.ic.push(InlineCache::new(name));
841                    self.bytecode.emit_get_name_global(
842                        value.variable(),
843                        (*index).into(),
844                        ic_index.into(),
845                    );
846                }
847                BindingAccessOpcode::GetLocator => self.bytecode.emit_get_locator((*index).into()),
848                BindingAccessOpcode::DefVar => self.bytecode.emit_def_var((*index).into()),
849                BindingAccessOpcode::PutLexicalValue => self
850                    .bytecode
851                    .emit_put_lexical_value(value.variable(), (*index).into()),
852                BindingAccessOpcode::DefInitVar => self
853                    .bytecode
854                    .emit_def_init_var(value.variable(), (*index).into()),
855                BindingAccessOpcode::SetName => self
856                    .bytecode
857                    .emit_set_name(value.variable(), (*index).into()),
858                BindingAccessOpcode::GetNameAndLocator => self
859                    .bytecode
860                    .emit_get_name_and_locator(value.variable(), (*index).into()),
861                BindingAccessOpcode::GetNameOrUndefined => self
862                    .bytecode
863                    .emit_get_name_or_undefined(value.variable(), (*index).into()),
864                BindingAccessOpcode::DeleteName => self
865                    .bytecode
866                    .emit_delete_name(value.variable(), (*index).into()),
867            },
868            BindingKind::Stack(index) => match opcode {
869                BindingAccessOpcode::SetNameByLocator => {
870                    self.bytecode.emit_set_name_by_locator(value.variable());
871                }
872                BindingAccessOpcode::GetLocator => self.bytecode.emit_get_locator((*index).into()),
873                BindingAccessOpcode::DefVar => self.bytecode.emit_def_var((*index).into()),
874                BindingAccessOpcode::PutLexicalValue => self
875                    .bytecode
876                    .emit_put_lexical_value(value.variable(), (*index).into()),
877                BindingAccessOpcode::DefInitVar => self
878                    .bytecode
879                    .emit_def_init_var(value.variable(), (*index).into()),
880                BindingAccessOpcode::SetName => self
881                    .bytecode
882                    .emit_set_name(value.variable(), (*index).into()),
883                BindingAccessOpcode::GetName => self
884                    .bytecode
885                    .emit_get_name(value.variable(), (*index).into()),
886                BindingAccessOpcode::GetNameAndLocator => self
887                    .bytecode
888                    .emit_get_name_and_locator(value.variable(), (*index).into()),
889                BindingAccessOpcode::GetNameOrUndefined => self
890                    .bytecode
891                    .emit_get_name_or_undefined(value.variable(), (*index).into()),
892                BindingAccessOpcode::DeleteName => self
893                    .bytecode
894                    .emit_delete_name(value.variable(), (*index).into()),
895            },
896            BindingKind::Local(None) => {
897                let error_msg = self.get_or_insert_literal(Literal::String(js_string!(
898                    "access of uninitialized binding"
899                )));
900                self.bytecode
901                    .emit_throw_new_reference_error(error_msg.into());
902            }
903            BindingKind::Local(Some(index)) => match opcode {
904                BindingAccessOpcode::GetName
905                | BindingAccessOpcode::GetNameOrUndefined
906                | BindingAccessOpcode::GetNameAndLocator => {
907                    self.bytecode.emit_move(value.variable(), (*index).into());
908                }
909                BindingAccessOpcode::GetLocator | BindingAccessOpcode::DefVar => {}
910                BindingAccessOpcode::SetName
911                | BindingAccessOpcode::DefInitVar
912                | BindingAccessOpcode::PutLexicalValue
913                | BindingAccessOpcode::SetNameByLocator => {
914                    self.bytecode.emit_move((*index).into(), value.variable());
915                }
916                BindingAccessOpcode::DeleteName => self.bytecode.emit_push_false(value.variable()),
917            },
918        }
919    }
920
921    fn emit_get_property_by_name(
922        &mut self,
923        dst: &Register,
924        receiver: &Register,
925        value: &Register,
926        ident: Sym,
927    ) {
928        let ic_index = self.ic.len() as u32;
929
930        let name_index = self.get_or_insert_name(ident);
931        let Constant::String(ref name) = self.constants[name_index as usize].clone() else {
932            unreachable!("there should be a string at index")
933        };
934        self.ic.push(InlineCache::new(name.clone()));
935
936        self.bytecode.emit_get_property_by_name(
937            dst.variable(),
938            receiver.variable(),
939            value.variable(),
940            ic_index.into(),
941        );
942    }
943
944    fn emit_set_property_by_name(
945        &mut self,
946        value: &Register,
947        receiver: &Register,
948        object: &Register,
949        ident: Sym,
950    ) {
951        let ic_index = self.ic.len() as u32;
952
953        let name_index = self.get_or_insert_name(ident);
954        let Constant::String(ref name) = self.constants[name_index as usize].clone() else {
955            unreachable!("there should be a string at index")
956        };
957        self.ic.push(InlineCache::new(name.clone()));
958
959        self.bytecode.emit_set_property_by_name(
960            value.variable(),
961            receiver.variable(),
962            object.variable(),
963            ic_index.into(),
964        );
965    }
966
967    fn emit_type_error(&mut self, message: &str) {
968        let error_msg = self.get_or_insert_literal(Literal::String(js_string!(message)));
969        self.bytecode.emit_throw_new_type_error(error_msg.into());
970    }
971    fn emit_syntax_error(&mut self, message: &str) {
972        let error_msg = self.get_or_insert_literal(Literal::String(js_string!(message)));
973        self.bytecode.emit_throw_new_syntax_error(error_msg.into());
974    }
975
976    fn emit_push_integer(&mut self, value: i32, dst: &Register) {
977        self.emit_push_integer_with_index(value, dst.variable());
978    }
979
980    fn emit_push_integer_with_index(&mut self, value: i32, dst: VaryingOperand) {
981        match value {
982            0 => self.bytecode.emit_push_zero(dst),
983            1 => self.bytecode.emit_push_one(dst),
984            x if i32::from(x as i8) == x => self.bytecode.emit_push_int8(dst, x as i8),
985            x if i32::from(x as i16) == x => {
986                self.bytecode.emit_push_int16(dst, x as i16);
987            }
988            x => self.bytecode.emit_push_int32(dst, x),
989        }
990    }
991
992    fn emit_push_literal(&mut self, literal: Literal, dst: &Register) {
993        let index = self.get_or_insert_literal(literal);
994        self.bytecode
995            .emit_push_literal(dst.variable(), index.into());
996    }
997
998    fn emit_push_rational(&mut self, value: f64, dst: &Register) {
999        if value.is_nan() {
1000            return self.bytecode.emit_push_nan(dst.variable());
1001        }
1002
1003        if value.is_infinite() {
1004            if value.is_sign_positive() {
1005                return self.bytecode.emit_push_positive_infinity(dst.variable());
1006            }
1007            return self.bytecode.emit_push_negative_infinity(dst.variable());
1008        }
1009
1010        // Check if the f64 value can fit in an i32.
1011        if f64::from(value as i32).to_bits() == value.to_bits() {
1012            self.emit_push_integer(value as i32, dst);
1013        } else {
1014            let f32_value = value as f32;
1015
1016            #[allow(clippy::float_cmp)]
1017            if f64::from(f32_value) == value {
1018                self.bytecode.emit_push_float(dst.variable(), f32_value);
1019            } else {
1020                self.bytecode.emit_push_double(dst.variable(), value);
1021            }
1022        }
1023    }
1024
1025    fn jump(&mut self) -> Label {
1026        let index = self.next_opcode_location();
1027        self.bytecode.emit_jump(Self::DUMMY_ADDRESS);
1028        Label { index }
1029    }
1030
1031    pub(crate) fn jump_if_true(&mut self, value: &Register) -> Label {
1032        let index = self.next_opcode_location();
1033        self.bytecode
1034            .emit_jump_if_true(Self::DUMMY_ADDRESS, value.variable());
1035        Label { index }
1036    }
1037
1038    pub(crate) fn jump_if_false(&mut self, value: &Register) -> Label {
1039        let index = self.next_opcode_location();
1040        self.bytecode
1041            .emit_jump_if_false(Self::DUMMY_ADDRESS, value.variable());
1042        Label { index }
1043    }
1044
1045    pub(crate) fn jump_if_null_or_undefined(&mut self, value: &Register) -> Label {
1046        let index = self.next_opcode_location();
1047        self.bytecode
1048            .emit_jump_if_null_or_undefined(Self::DUMMY_ADDRESS, value.variable());
1049        Label { index }
1050    }
1051
1052    pub(crate) fn emit_jump_if_not_undefined(&mut self, value: &Register) -> Label {
1053        let index = self.next_opcode_location();
1054        self.bytecode
1055            .emit_jump_if_not_undefined(Self::DUMMY_ADDRESS, value.variable());
1056        Label { index }
1057    }
1058
1059    pub(crate) fn case(&mut self, value: &Register, condition: &Register) -> Label {
1060        let index = self.next_opcode_location();
1061        self.bytecode
1062            .emit_case(Self::DUMMY_ADDRESS, value.variable(), condition.variable());
1063        Label { index }
1064    }
1065
1066    pub(crate) fn template_lookup(&mut self, dst: &Register, site: u64) -> Label {
1067        let index = self.next_opcode_location();
1068        self.bytecode
1069            .emit_template_lookup(Self::DUMMY_ADDRESS, site, dst.variable());
1070        Label { index }
1071    }
1072
1073    fn emit_resume_kind(&mut self, resume_kind: GeneratorResumeKind, dst: &Register) {
1074        self.emit_push_integer(resume_kind as i32, dst);
1075    }
1076
1077    fn jump_if_not_resume_kind(
1078        &mut self,
1079        resume_kind: GeneratorResumeKind,
1080        value: &Register,
1081    ) -> Label {
1082        let index = self.next_opcode_location();
1083        self.bytecode.emit_jump_if_not_resume_kind(
1084            Self::DUMMY_ADDRESS,
1085            (resume_kind as u8).into(),
1086            value.variable(),
1087        );
1088        Label { index }
1089    }
1090
1091    #[track_caller]
1092    pub(crate) fn patch_jump_with_target(&mut self, label: Label, target: u32) {
1093        self.bytecode.patch_jump(label.index, target);
1094    }
1095
1096    fn patch_jump(&mut self, label: Label) {
1097        let target = self.next_opcode_location();
1098        self.patch_jump_with_target(label, target);
1099    }
1100
1101    fn resolve_identifier_expect(&self, identifier: Identifier) -> JsString {
1102        identifier.to_js_string(self.interner())
1103    }
1104
1105    fn access_get(&mut self, access: Access<'_>, dst: &Register) {
1106        match access {
1107            Access::Variable { name } => {
1108                let name = self.resolve_identifier_expect(name);
1109                let binding = self.lexical_scope.get_identifier_reference(name);
1110                let index = self.get_binding(&binding);
1111                self.emit_binding_access(BindingAccessOpcode::GetName, &index, dst);
1112            }
1113            Access::Property { access } => match access {
1114                PropertyAccess::Simple(access) => {
1115                    let mut compiler = self.position_guard(access.field());
1116
1117                    let object = compiler.register_allocator.alloc();
1118                    compiler.compile_expr(access.target(), &object);
1119
1120                    match access.field() {
1121                        PropertyAccessField::Const(ident) => {
1122                            compiler.emit_get_property_by_name(dst, &object, &object, ident.sym());
1123                        }
1124                        PropertyAccessField::Expr(expr) => {
1125                            let key = compiler.register_allocator.alloc();
1126                            compiler.compile_expr(expr, &key);
1127                            compiler.bytecode.emit_get_property_by_value(
1128                                dst.variable(),
1129                                key.variable(),
1130                                object.variable(),
1131                                object.variable(),
1132                            );
1133                            compiler.register_allocator.dealloc(key);
1134                        }
1135                    }
1136                    compiler.register_allocator.dealloc(object);
1137                }
1138                PropertyAccess::Private(access) => {
1139                    let mut compiler = self.position_guard(access.field());
1140
1141                    let index = compiler.get_or_insert_private_name(access.field());
1142                    let object = compiler.register_allocator.alloc();
1143                    compiler.compile_expr(access.target(), &object);
1144                    compiler.bytecode.emit_get_private_field(
1145                        dst.variable(),
1146                        object.variable(),
1147                        index.into(),
1148                    );
1149                    compiler.register_allocator.dealloc(object);
1150                }
1151                PropertyAccess::Super(access) => {
1152                    let mut compiler = self.position_guard(access.field());
1153
1154                    let value = compiler.register_allocator.alloc();
1155                    let receiver = compiler.register_allocator.alloc();
1156                    compiler.bytecode.emit_super(value.variable());
1157                    compiler.bytecode.emit_this(receiver.variable());
1158                    match access.field() {
1159                        PropertyAccessField::Const(ident) => {
1160                            compiler.emit_get_property_by_name(dst, &receiver, &value, ident.sym());
1161                        }
1162                        PropertyAccessField::Expr(expr) => {
1163                            let key = compiler.register_allocator.alloc();
1164                            compiler.compile_expr(expr, &key);
1165                            compiler.bytecode.emit_get_property_by_value(
1166                                dst.variable(),
1167                                key.variable(),
1168                                receiver.variable(),
1169                                value.variable(),
1170                            );
1171                            compiler.register_allocator.dealloc(key);
1172                        }
1173                    }
1174                    compiler.register_allocator.dealloc(receiver);
1175                    compiler.register_allocator.dealloc(value);
1176                }
1177            },
1178            Access::This => {
1179                self.bytecode.emit_this(dst.variable());
1180            }
1181        }
1182    }
1183
1184    fn access_set<'a, F>(&mut self, access: Access<'_>, expr_fn: F)
1185    where
1186        F: FnOnce(&mut ByteCompiler<'_>) -> &'a Register,
1187    {
1188        match access {
1189            Access::Variable { name } => {
1190                let name = self.resolve_identifier_expect(name);
1191                let binding = self.lexical_scope.get_identifier_reference(name.clone());
1192                let is_lexical = binding.is_lexical();
1193                let index = self.get_binding(&binding);
1194
1195                let value = self.register_allocator.alloc();
1196                if !is_lexical {
1197                    self.emit_binding_access(BindingAccessOpcode::GetLocator, &index, &value);
1198                }
1199                self.register_allocator.dealloc(value);
1200
1201                let value = expr_fn(self);
1202
1203                if is_lexical {
1204                    match self.lexical_scope.set_mutable_binding(name.clone()) {
1205                        Ok(binding) => {
1206                            let index = self.insert_binding(binding);
1207                            self.emit_binding_access(BindingAccessOpcode::SetName, &index, value);
1208                        }
1209                        Err(BindingLocatorError::MutateImmutable) => {
1210                            let index = self.get_or_insert_string(name);
1211                            self.bytecode.emit_throw_mutate_immutable(index.into());
1212                        }
1213                        Err(BindingLocatorError::Silent) => {}
1214                    }
1215                } else {
1216                    self.emit_binding_access(BindingAccessOpcode::SetNameByLocator, &index, value);
1217                }
1218            }
1219            Access::Property { access } => match access {
1220                PropertyAccess::Simple(access) => match access.field() {
1221                    PropertyAccessField::Const(name) => {
1222                        let object = self.register_allocator.alloc();
1223                        self.compile_expr(access.target(), &object);
1224                        let value = expr_fn(self);
1225                        self.emit_set_property_by_name(value, &object, &object, name.sym());
1226                        self.register_allocator.dealloc(object);
1227                    }
1228                    PropertyAccessField::Expr(expr) => {
1229                        let object = self.register_allocator.alloc();
1230                        self.compile_expr(access.target(), &object);
1231
1232                        let key = self.register_allocator.alloc();
1233                        self.compile_expr(expr, &key);
1234
1235                        let value = expr_fn(self);
1236
1237                        self.bytecode.emit_set_property_by_value(
1238                            value.variable(),
1239                            key.variable(),
1240                            object.variable(),
1241                            object.variable(),
1242                        );
1243
1244                        self.register_allocator.dealloc(object);
1245                        self.register_allocator.dealloc(key);
1246                    }
1247                },
1248                PropertyAccess::Private(access) => {
1249                    let index = self.get_or_insert_private_name(access.field());
1250
1251                    let object = self.register_allocator.alloc();
1252                    self.compile_expr(access.target(), &object);
1253
1254                    let value = expr_fn(self);
1255
1256                    self.bytecode.emit_set_private_field(
1257                        value.variable(),
1258                        object.variable(),
1259                        index.into(),
1260                    );
1261
1262                    self.register_allocator.dealloc(object);
1263                }
1264                PropertyAccess::Super(access) => match access.field() {
1265                    PropertyAccessField::Const(name) => {
1266                        let object = self.register_allocator.alloc();
1267                        self.bytecode.emit_super(object.variable());
1268
1269                        let receiver = self.register_allocator.alloc();
1270                        self.bytecode.emit_this(receiver.variable());
1271
1272                        let value = expr_fn(self);
1273
1274                        self.emit_set_property_by_name(value, &receiver, &object, name.sym());
1275
1276                        self.register_allocator.dealloc(receiver);
1277                        self.register_allocator.dealloc(object);
1278                    }
1279                    PropertyAccessField::Expr(expr) => {
1280                        let object = self.register_allocator.alloc();
1281                        self.bytecode.emit_super(object.variable());
1282
1283                        let receiver = self.register_allocator.alloc();
1284                        self.bytecode.emit_this(receiver.variable());
1285
1286                        let key = self.register_allocator.alloc();
1287                        self.compile_expr(expr, &key);
1288
1289                        let value = expr_fn(self);
1290
1291                        self.bytecode.emit_set_property_by_value(
1292                            value.variable(),
1293                            key.variable(),
1294                            receiver.variable(),
1295                            object.variable(),
1296                        );
1297
1298                        self.register_allocator.dealloc(key);
1299                        self.register_allocator.dealloc(receiver);
1300                        self.register_allocator.dealloc(object);
1301                    }
1302                },
1303            },
1304            Access::This => todo!("access_set `this`"),
1305        }
1306    }
1307
1308    fn access_delete(&mut self, access: Access<'_>, dst: &Register) {
1309        match access {
1310            Access::Property { access } => match access {
1311                PropertyAccess::Simple(access) => match access.field() {
1312                    PropertyAccessField::Const(name) => {
1313                        let index = self.get_or_insert_name(name.sym());
1314                        self.compile_expr(access.target(), dst);
1315                        self.bytecode
1316                            .emit_delete_property_by_name(dst.variable(), index.into());
1317                    }
1318                    PropertyAccessField::Expr(expr) => {
1319                        self.compile_expr(access.target(), dst);
1320                        let key = self.register_allocator.alloc();
1321                        self.compile_expr(expr, &key);
1322                        self.bytecode
1323                            .emit_delete_property_by_value(dst.variable(), key.variable());
1324                        self.register_allocator.dealloc(key);
1325                    }
1326                },
1327                PropertyAccess::Super(_) => self.bytecode.emit_delete_super_throw(),
1328                PropertyAccess::Private(_) => {
1329                    unreachable!("deleting private properties should always throw early errors.")
1330                }
1331            },
1332            Access::Variable { name } => {
1333                let name = name.to_js_string(self.interner());
1334                let binding = self.lexical_scope.get_identifier_reference(name);
1335                let index = self.get_binding(&binding);
1336                self.emit_binding_access(BindingAccessOpcode::DeleteName, &index, dst);
1337            }
1338            Access::This => self.bytecode.emit_push_true(dst.variable()),
1339        }
1340    }
1341
1342    /// Compile a [`StatementList`].
1343    pub fn compile_statement_list(&mut self, list: &StatementList, use_expr: bool, block: bool) {
1344        if use_expr || self.jump_control_info_has_use_expr() {
1345            let mut use_expr_index = 0;
1346            for (i, statement) in list.statements().iter().enumerate() {
1347                match statement {
1348                    StatementListItem::Statement(statement) => match statement.as_ref() {
1349                        Statement::Break(_) | Statement::Continue(_) => break,
1350                        Statement::Empty | Statement::Var(_) => {}
1351                        Statement::Block(block) if !returns_value(block) => {}
1352                        _ => use_expr_index = i,
1353                    },
1354                    StatementListItem::Declaration(_) => {}
1355                }
1356            }
1357
1358            for (i, item) in list.statements().iter().enumerate() {
1359                self.compile_stmt_list_item(item, i == use_expr_index, block);
1360            }
1361        } else {
1362            for item in list.statements() {
1363                self.compile_stmt_list_item(item, false, block);
1364            }
1365        }
1366    }
1367
1368    /// Compile an [`Expression`].
1369    #[inline]
1370    pub(crate) fn compile_expr(&mut self, expr: &Expression, dst: &'_ Register) {
1371        self.compile_expr_impl(expr, dst);
1372    }
1373
1374    /// Compile a property access expression, prepending `this` to the property value in the stack.
1375    ///
1376    /// This compiles the access in a way that the state of the stack after executing the property
1377    /// access becomes `...rest, this, value`. where `...rest` is the rest of the stack, `this` is the
1378    /// `this` value of the access, and `value` is the final result of the access.
1379    ///
1380    /// This is mostly useful for optional chains with calls (`a.b?.()`) and for regular chains
1381    /// with calls (`a.b()`), since both of them must have `a` be the value of `this` for the function
1382    /// call `b()`, but a regular compilation of the access would lose the `this` value after accessing
1383    /// `b`.
1384    fn compile_access_preserve_this(
1385        &mut self,
1386        access: &PropertyAccess,
1387        this: &Register,
1388        dst: &Register,
1389    ) {
1390        match access {
1391            PropertyAccess::Simple(access) => {
1392                self.compile_expr(access.target(), this);
1393
1394                match access.field() {
1395                    PropertyAccessField::Const(ident) => {
1396                        self.emit_get_property_by_name(dst, this, this, ident.sym());
1397                    }
1398                    PropertyAccessField::Expr(field) => {
1399                        let key = self.register_allocator.alloc();
1400                        self.compile_expr(field, &key);
1401                        self.bytecode.emit_get_property_by_value(
1402                            dst.variable(),
1403                            key.variable(),
1404                            this.variable(),
1405                            this.variable(),
1406                        );
1407                        self.register_allocator.dealloc(key);
1408                    }
1409                }
1410            }
1411            PropertyAccess::Private(access) => {
1412                self.compile_expr(access.target(), this);
1413
1414                let index = self.get_or_insert_private_name(access.field());
1415                self.bytecode
1416                    .emit_get_private_field(dst.variable(), this.variable(), index.into());
1417            }
1418            PropertyAccess::Super(access) => {
1419                let object = self.register_allocator.alloc();
1420                self.bytecode.emit_this(this.variable());
1421                self.bytecode.emit_super(object.variable());
1422
1423                match access.field() {
1424                    PropertyAccessField::Const(ident) => {
1425                        self.emit_get_property_by_name(dst, this, &object, ident.sym());
1426                    }
1427                    PropertyAccessField::Expr(expr) => {
1428                        let key = self.register_allocator.alloc();
1429                        self.compile_expr(expr, &key);
1430                        self.bytecode.emit_get_property_by_value(
1431                            dst.variable(),
1432                            key.variable(),
1433                            this.variable(),
1434                            object.variable(),
1435                        );
1436                        self.register_allocator.dealloc(key);
1437                    }
1438                }
1439                self.register_allocator.dealloc(object);
1440            }
1441        }
1442    }
1443
1444    /// Compile an optional chain expression, prepending `this` to the property value in the stack.
1445    ///
1446    /// This compiles the access in a way that the state of the stack after executing the optional
1447    /// chain becomes `...rest, this, value`. where `...rest` is the rest of the stack, `this` is the
1448    /// `this` value of the chain, and `value` is the result of the chain.
1449    ///
1450    /// This is mostly useful for inner optional chains with external calls (`(a?.b)()`), because the
1451    /// external call is not in the optional chain, and compiling an optional chain in the usual way
1452    /// would only return the result of the chain without preserving the `this` value. In other words,
1453    /// `this` would be set to `undefined` for that call, which is incorrect since `a` should be the
1454    /// `this` value of the call.
1455    fn compile_optional_preserve_this(
1456        &mut self,
1457        optional: &Optional,
1458        this: &Register,
1459        value: &Register,
1460    ) {
1461        let mut jumps = Vec::with_capacity(optional.chain().len());
1462
1463        match optional.target().flatten() {
1464            Expression::PropertyAccess(access) => {
1465                self.compile_access_preserve_this(access, this, value);
1466            }
1467            Expression::Optional(opt) => self.compile_optional_preserve_this(opt, this, value),
1468            expr => {
1469                self.bytecode.emit_push_undefined(this.variable());
1470                self.compile_expr(expr, value);
1471            }
1472        }
1473
1474        jumps.push(self.jump_if_null_or_undefined(value));
1475
1476        let (first, rest) = optional
1477            .chain()
1478            .split_first()
1479            .expect("chain must have at least one element");
1480        assert!(first.shorted());
1481
1482        self.compile_optional_item_kind(first.kind(), this, value);
1483
1484        for item in rest {
1485            if item.shorted() {
1486                jumps.push(self.jump_if_null_or_undefined(value));
1487            }
1488            self.compile_optional_item_kind(item.kind(), this, value);
1489        }
1490
1491        let skip_undef = self.jump();
1492
1493        for label in jumps {
1494            self.patch_jump(label);
1495            self.bytecode.emit_push_undefined(value.variable());
1496        }
1497
1498        self.patch_jump(skip_undef);
1499    }
1500
1501    /// Compile a single operation in an optional chain.
1502    ///
1503    /// On successful compilation, the state of the stack on execution will become `...rest, this, value`,
1504    /// where `this` is the target of the property access (`undefined` on calls), and `value` is the
1505    /// result of executing the action.
1506    /// For example, in the expression `a?.b.c()`, after compiling and executing:
1507    ///
1508    /// - `a?.b`, the state of the stack will become `...rest, a, b`.
1509    /// - `b.c`, the state of the stack will become `...rest, b, c`.
1510    /// - `c()`, the state of the stack will become `...rest, undefined, c()`.
1511    ///
1512    /// # Requirements
1513    /// - This should only be called after verifying that the previous value of the chain
1514    ///   is not null or undefined (if the operator `?.` was used).
1515    /// - This assumes that the state of the stack before compiling is `...rest, this, value`,
1516    ///   since the operation compiled by this function could be a call.
1517    fn compile_optional_item_kind(
1518        &mut self,
1519        kind: &OptionalOperationKind,
1520        this: &Register,
1521        value: &Register,
1522    ) {
1523        match kind {
1524            OptionalOperationKind::SimplePropertyAccess { field } => {
1525                self.bytecode.emit_move(this.variable(), value.variable());
1526                match field {
1527                    PropertyAccessField::Const(name) => {
1528                        self.emit_get_property_by_name(value, value, value, name.sym());
1529                    }
1530                    PropertyAccessField::Expr(expr) => {
1531                        let key = self.register_allocator.alloc();
1532                        self.compile_expr(expr, &key);
1533                        self.bytecode.emit_get_property_by_value(
1534                            value.variable(),
1535                            key.variable(),
1536                            value.variable(),
1537                            value.variable(),
1538                        );
1539                        self.register_allocator.dealloc(key);
1540                    }
1541                }
1542            }
1543            OptionalOperationKind::PrivatePropertyAccess { field } => {
1544                self.bytecode.emit_move(this.variable(), value.variable());
1545                let index = self.get_or_insert_private_name(*field);
1546                self.bytecode.emit_get_private_field(
1547                    value.variable(),
1548                    value.variable(),
1549                    index.into(),
1550                );
1551            }
1552            OptionalOperationKind::Call { args } => {
1553                self.push_from_register(this);
1554                self.push_from_register(value);
1555
1556                let args = &**args;
1557                let contains_spread = args.iter().any(|arg| matches!(arg, Expression::Spread(_)));
1558
1559                if contains_spread {
1560                    let array = self.register_allocator.alloc();
1561                    let value = self.register_allocator.alloc();
1562
1563                    self.bytecode.emit_push_new_array(array.variable());
1564
1565                    for arg in args {
1566                        self.compile_expr(arg, &value);
1567                        if let Expression::Spread(_) = arg {
1568                            self.bytecode.emit_get_iterator(value.variable());
1569                            self.bytecode.emit_push_iterator_to_array(array.variable());
1570                        } else {
1571                            self.bytecode
1572                                .emit_push_value_to_array(value.variable(), array.variable());
1573                        }
1574                    }
1575
1576                    self.push_from_register(&array);
1577
1578                    self.register_allocator.dealloc(value);
1579                    self.register_allocator.dealloc(array);
1580
1581                    self.bytecode.emit_call_spread();
1582                } else {
1583                    for arg in args {
1584                        let value = self.register_allocator.alloc();
1585                        self.compile_expr(arg, &value);
1586                        self.push_from_register(&value);
1587                        self.register_allocator.dealloc(value);
1588                    }
1589                    self.bytecode.emit_call((args.len() as u32).into());
1590                }
1591
1592                self.pop_into_register(value);
1593                self.bytecode.emit_push_undefined(this.variable());
1594            }
1595        }
1596    }
1597
1598    /// Compile a [`VarDeclaration`].
1599    fn compile_var_decl(&mut self, decl: &VarDeclaration) {
1600        for variable in decl.0.as_ref() {
1601            match variable.binding() {
1602                Binding::Identifier(ident) => {
1603                    let ident = ident.to_js_string(self.interner());
1604                    if let Some(expr) = variable.init() {
1605                        let binding = self.lexical_scope.get_identifier_reference(ident.clone());
1606                        let index = self.insert_binding(binding);
1607                        let value = self.register_allocator.alloc();
1608                        self.emit_binding_access(BindingAccessOpcode::GetLocator, &index, &value);
1609                        self.compile_expr(expr, &value);
1610                        self.emit_binding_access(
1611                            BindingAccessOpcode::SetNameByLocator,
1612                            &index,
1613                            &value,
1614                        );
1615                        self.register_allocator.dealloc(value);
1616                    } else {
1617                        let value = self.register_allocator.alloc();
1618                        self.emit_binding(BindingOpcode::Var, ident, &value);
1619                        self.register_allocator.dealloc(value);
1620                    }
1621                }
1622                Binding::Pattern(pattern) => {
1623                    let value = self.register_allocator.alloc();
1624                    if let Some(init) = variable.init() {
1625                        self.compile_expr(init, &value);
1626                    } else {
1627                        self.bytecode.emit_push_undefined(value.variable());
1628                    }
1629                    self.compile_declaration_pattern(pattern, BindingOpcode::InitVar, &value);
1630                    self.register_allocator.dealloc(value);
1631                }
1632            }
1633        }
1634    }
1635
1636    /// Compile a [`LexicalDeclaration`].
1637    fn compile_lexical_decl(&mut self, decl: &LexicalDeclaration) {
1638        match decl {
1639            LexicalDeclaration::Let(decls) => {
1640                for variable in decls.as_ref() {
1641                    match variable.binding() {
1642                        Binding::Identifier(ident) => {
1643                            let ident = ident.to_js_string(self.interner());
1644                            let value = self.register_allocator.alloc();
1645                            if let Some(init) = variable.init() {
1646                                self.compile_expr(init, &value);
1647                            } else {
1648                                self.bytecode.emit_push_undefined(value.variable());
1649                            }
1650                            self.emit_binding(BindingOpcode::InitLexical, ident, &value);
1651                            self.register_allocator.dealloc(value);
1652                        }
1653                        Binding::Pattern(pattern) => {
1654                            let value = self.register_allocator.alloc();
1655                            if let Some(init) = variable.init() {
1656                                self.compile_expr(init, &value);
1657                            } else {
1658                                self.bytecode.emit_push_undefined(value.variable());
1659                            }
1660                            self.compile_declaration_pattern(
1661                                pattern,
1662                                BindingOpcode::InitLexical,
1663                                &value,
1664                            );
1665                            self.register_allocator.dealloc(value);
1666                        }
1667                    }
1668                }
1669            }
1670            LexicalDeclaration::Const(decls) => {
1671                for variable in decls.as_ref() {
1672                    match variable.binding() {
1673                        Binding::Identifier(ident) => {
1674                            let ident = ident.to_js_string(self.interner());
1675                            let init = variable
1676                                .init()
1677                                .expect("const declaration must have initializer");
1678                            let value = self.register_allocator.alloc();
1679                            self.compile_expr(init, &value);
1680                            self.emit_binding(BindingOpcode::InitLexical, ident, &value);
1681                            self.register_allocator.dealloc(value);
1682                        }
1683                        Binding::Pattern(pattern) => {
1684                            let value = self.register_allocator.alloc();
1685                            if let Some(init) = variable.init() {
1686                                self.compile_expr(init, &value);
1687                            } else {
1688                                self.bytecode.emit_push_undefined(value.variable());
1689                            }
1690                            self.compile_declaration_pattern(
1691                                pattern,
1692                                BindingOpcode::InitLexical,
1693                                &value,
1694                            );
1695                            self.register_allocator.dealloc(value);
1696                        }
1697                    }
1698                }
1699            }
1700        }
1701    }
1702
1703    /// Compile a [`StatementListItem`].
1704    fn compile_stmt_list_item(&mut self, item: &StatementListItem, use_expr: bool, block: bool) {
1705        match item {
1706            StatementListItem::Statement(stmt) => {
1707                self.compile_stmt(stmt, use_expr, false);
1708            }
1709            StatementListItem::Declaration(decl) => self.compile_decl(decl, block),
1710        }
1711    }
1712
1713    /// Compile a [`Declaration`].
1714    #[allow(unused_variables)]
1715    pub fn compile_decl(&mut self, decl: &Declaration, block: bool) {
1716        match decl {
1717            #[cfg(feature = "annex-b")]
1718            Declaration::FunctionDeclaration(function) if block => {
1719                let name = function.name();
1720                if self.annex_b_function_names.contains(&name.sym()) {
1721                    let name = name.to_js_string(self.interner());
1722                    let binding = self.lexical_scope.get_identifier_reference(name.clone());
1723                    let index = self.get_binding(&binding);
1724
1725                    let value = self.register_allocator.alloc();
1726                    self.emit_binding_access(BindingAccessOpcode::GetName, &index, &value);
1727                    match self.variable_scope.set_mutable_binding_var(name.clone()) {
1728                        Ok(binding) => {
1729                            let index = self.get_binding(&binding);
1730                            self.emit_binding_access(BindingAccessOpcode::SetName, &index, &value);
1731                        }
1732                        Err(BindingLocatorError::MutateImmutable) => {
1733                            let index = self.get_or_insert_string(name);
1734                            self.bytecode.emit_throw_mutate_immutable(index.into());
1735                        }
1736                        Err(BindingLocatorError::Silent) => {}
1737                    }
1738                    self.register_allocator.dealloc(value);
1739                }
1740            }
1741            Declaration::ClassDeclaration(class) => self.compile_class(class.as_ref().into(), None),
1742            Declaration::Lexical(lexical) => self.compile_lexical_decl(lexical),
1743            _ => {}
1744        }
1745    }
1746
1747    /// Compiles a function AST Node into bytecode, and returns its index into
1748    /// the `functions` array.
1749    pub(crate) fn function(&mut self, function: FunctionSpec<'_>) -> u32 {
1750        let (generator, r#async, arrow) = (
1751            function.kind.is_generator(),
1752            function.kind.is_async(),
1753            function.kind.is_arrow(),
1754        );
1755
1756        let FunctionSpec {
1757            name,
1758            parameters,
1759            body,
1760            scopes,
1761            name_scope,
1762            linear_span,
1763            ..
1764        } = function;
1765
1766        let name = if let Some(name) = name {
1767            Some(name.sym().to_js_string(self.interner()))
1768        } else {
1769            Some(js_string!())
1770        };
1771
1772        let spanned_source_text = SpannedSourceText::new(self.source_text(), linear_span);
1773
1774        let code = FunctionCompiler::new(spanned_source_text)
1775            .name(name)
1776            .generator(generator)
1777            .r#async(r#async)
1778            .strict(self.strict())
1779            .arrow(arrow)
1780            .in_with(self.in_with)
1781            .name_scope(name_scope.cloned())
1782            .source_path(self.source_path.clone())
1783            .compile(
1784                parameters,
1785                body,
1786                self.variable_scope.clone(),
1787                self.lexical_scope.clone(),
1788                scopes,
1789                function.contains_direct_eval,
1790                self.interner,
1791            );
1792
1793        self.push_function_to_constants(code)
1794    }
1795
1796    /// Compiles a function AST Node into bytecode, setting its corresponding binding or
1797    /// pushing it to the stack if necessary.
1798    pub(crate) fn function_with_binding(
1799        &mut self,
1800        function: FunctionSpec<'_>,
1801        node_kind: NodeKind,
1802        dst: &Register,
1803    ) {
1804        let name = function.name;
1805        let index = self.function(function);
1806        self.emit_get_function(dst, index);
1807        match node_kind {
1808            NodeKind::Declaration => {
1809                self.emit_binding(
1810                    BindingOpcode::InitVar,
1811                    name.expect("function declaration must have a name")
1812                        .to_js_string(self.interner()),
1813                    dst,
1814                );
1815            }
1816            NodeKind::Expression => {}
1817        }
1818    }
1819
1820    /// Compile an object method AST Node into bytecode.
1821    pub(crate) fn object_method(
1822        &mut self,
1823        function: FunctionSpec<'_>,
1824        kind: MethodKind,
1825    ) -> Register {
1826        let (generator, r#async, arrow) = (
1827            function.kind.is_generator(),
1828            function.kind.is_async(),
1829            function.kind.is_arrow(),
1830        );
1831        let FunctionSpec {
1832            name,
1833            parameters,
1834            body,
1835            scopes,
1836            name_scope,
1837            linear_span,
1838            ..
1839        } = function;
1840
1841        let name = if let Some(name) = name {
1842            let name = name.sym().to_js_string(self.interner());
1843            match kind {
1844                MethodKind::Ordinary => Some(name),
1845                MethodKind::Get => Some(js_string!(js_str!("get "), &name)),
1846                MethodKind::Set => Some(js_string!(js_str!("set "), &name)),
1847            }
1848        } else {
1849            Some(js_string!())
1850        };
1851
1852        let spanned_source_text = SpannedSourceText::new(self.source_text(), linear_span);
1853
1854        let code = FunctionCompiler::new(spanned_source_text)
1855            .name(name)
1856            .generator(generator)
1857            .r#async(r#async)
1858            .strict(self.strict())
1859            .arrow(arrow)
1860            .method(true)
1861            .in_with(self.in_with)
1862            .name_scope(name_scope.cloned())
1863            .source_path(self.source_path.clone())
1864            .compile(
1865                parameters,
1866                body,
1867                self.variable_scope.clone(),
1868                self.lexical_scope.clone(),
1869                scopes,
1870                function.contains_direct_eval,
1871                self.interner,
1872            );
1873
1874        let index = self.push_function_to_constants(code);
1875        let dst = self.register_allocator.alloc();
1876        self.emit_get_function(&dst, index);
1877        dst
1878    }
1879
1880    /// Compile a class method AST Node into bytecode.
1881    fn method(&mut self, function: FunctionSpec<'_>) -> Register {
1882        let (generator, r#async, arrow) = (
1883            function.kind.is_generator(),
1884            function.kind.is_async(),
1885            function.kind.is_arrow(),
1886        );
1887        let FunctionSpec {
1888            name,
1889            parameters,
1890            body,
1891            scopes,
1892            linear_span,
1893            ..
1894        } = function;
1895
1896        let name = if let Some(name) = name {
1897            Some(name.sym().to_js_string(self.interner()))
1898        } else {
1899            Some(js_string!())
1900        };
1901
1902        let spanned_source_text = SpannedSourceText::new(self.source_text(), linear_span);
1903
1904        let code = FunctionCompiler::new(spanned_source_text)
1905            .name(name)
1906            .generator(generator)
1907            .r#async(r#async)
1908            .strict(true)
1909            .arrow(arrow)
1910            .method(true)
1911            .in_with(self.in_with)
1912            .name_scope(function.name_scope.cloned())
1913            .source_path(self.source_path.clone())
1914            .compile(
1915                parameters,
1916                body,
1917                self.variable_scope.clone(),
1918                self.lexical_scope.clone(),
1919                scopes,
1920                function.contains_direct_eval,
1921                self.interner,
1922            );
1923
1924        let index = self.push_function_to_constants(code);
1925        let dst = self.register_allocator.alloc();
1926        self.emit_get_function(&dst, index);
1927        dst
1928    }
1929
1930    fn call(&mut self, callable: Callable<'_>, dst: &Register) {
1931        #[derive(PartialEq)]
1932        enum CallKind {
1933            CallEval,
1934            Call,
1935            New,
1936        }
1937
1938        let (call, mut kind) = match callable {
1939            Callable::Call(call) => (call, CallKind::Call),
1940            Callable::New(new) => (new.call(), CallKind::New),
1941        };
1942
1943        match call.function().flatten() {
1944            Expression::PropertyAccess(access) if kind == CallKind::Call => {
1945                let this = self.register_allocator.alloc();
1946                let dst = self.register_allocator.alloc();
1947                self.compile_access_preserve_this(access, &this, &dst);
1948                self.push_from_register(&this);
1949                self.push_from_register(&dst);
1950                self.register_allocator.dealloc(this);
1951                self.register_allocator.dealloc(dst);
1952            }
1953            Expression::Optional(opt) if kind == CallKind::Call => {
1954                let this = self.register_allocator.alloc();
1955                let dst = self.register_allocator.alloc();
1956                self.compile_optional_preserve_this(opt, &this, &dst);
1957                self.push_from_register(&this);
1958                self.push_from_register(&dst);
1959                self.register_allocator.dealloc(this);
1960                self.register_allocator.dealloc(dst);
1961            }
1962            expr if kind == CallKind::Call => {
1963                if let Expression::Identifier(ident) = expr {
1964                    if ident.sym() == Sym::EVAL {
1965                        kind = CallKind::CallEval;
1966                    }
1967
1968                    if self.in_with {
1969                        let name = self.resolve_identifier_expect(*ident);
1970                        let binding = self.lexical_scope.get_identifier_reference(name);
1971                        let index = self.get_binding(&binding);
1972                        let index = match index {
1973                            BindingKind::Global(index) | BindingKind::Stack(index) => index,
1974                            BindingKind::Local(_) => {
1975                                unreachable!("with binding cannot be local")
1976                            }
1977                        };
1978                        let value = self.register_allocator.alloc();
1979                        self.bytecode
1980                            .emit_this_for_object_environment_name(value.variable(), index.into());
1981                        self.push_from_register(&value);
1982                        self.register_allocator.dealloc(value);
1983                    } else {
1984                        let value = self.register_allocator.alloc();
1985                        self.bytecode.emit_push_undefined(value.variable());
1986                        self.push_from_register(&value);
1987                        self.register_allocator.dealloc(value);
1988                    }
1989                } else {
1990                    let value = self.register_allocator.alloc();
1991                    self.bytecode.emit_push_undefined(value.variable());
1992                    self.push_from_register(&value);
1993                    self.register_allocator.dealloc(value);
1994                }
1995
1996                let value = self.register_allocator.alloc();
1997                self.compile_expr(expr, &value);
1998                self.push_from_register(&value);
1999                self.register_allocator.dealloc(value);
2000            }
2001            expr => {
2002                let this = self.register_allocator.alloc();
2003                let value = self.register_allocator.alloc();
2004                self.compile_expr(expr, &value);
2005                self.bytecode.emit_push_undefined(this.variable());
2006                self.push_from_register(&this);
2007                self.push_from_register(&value);
2008                self.register_allocator.dealloc(this);
2009                self.register_allocator.dealloc(value);
2010            }
2011        }
2012
2013        let mut compiler = self.position_guard(call);
2014
2015        let contains_spread = call
2016            .args()
2017            .iter()
2018            .any(|arg| matches!(arg, Expression::Spread(_)));
2019
2020        if contains_spread {
2021            let array = compiler.register_allocator.alloc();
2022            let value = compiler.register_allocator.alloc();
2023
2024            compiler.bytecode.emit_push_new_array(array.variable());
2025
2026            for arg in call.args() {
2027                compiler.compile_expr(arg, &value);
2028                if let Expression::Spread(_) = arg {
2029                    compiler.bytecode.emit_get_iterator(value.variable());
2030                    compiler
2031                        .bytecode
2032                        .emit_push_iterator_to_array(array.variable());
2033                } else {
2034                    compiler
2035                        .bytecode
2036                        .emit_push_value_to_array(value.variable(), array.variable());
2037                }
2038            }
2039
2040            compiler.push_from_register(&array);
2041
2042            compiler.register_allocator.dealloc(array);
2043            compiler.register_allocator.dealloc(value);
2044        } else {
2045            for arg in call.args() {
2046                let value = compiler.register_allocator.alloc();
2047                compiler.compile_expr(arg, &value);
2048                compiler.push_from_register(&value);
2049                compiler.register_allocator.dealloc(value);
2050            }
2051        }
2052
2053        match kind {
2054            CallKind::CallEval => {
2055                let scope_index = compiler.constants.len() as u32;
2056                let lexical_scope = compiler.lexical_scope.clone();
2057                compiler.constants.push(Constant::Scope(lexical_scope));
2058                if contains_spread {
2059                    compiler.bytecode.emit_call_eval_spread(scope_index.into());
2060                } else {
2061                    compiler
2062                        .bytecode
2063                        .emit_call_eval((call.args().len() as u32).into(), scope_index.into());
2064                }
2065            }
2066            CallKind::Call if contains_spread => compiler.bytecode.emit_call_spread(),
2067            CallKind::Call => {
2068                compiler
2069                    .bytecode
2070                    .emit_call((call.args().len() as u32).into());
2071            }
2072            CallKind::New if contains_spread => compiler.bytecode.emit_new_spread(),
2073            CallKind::New => compiler
2074                .bytecode
2075                .emit_new((call.args().len() as u32).into()),
2076        }
2077        compiler.pop_into_register(dst);
2078    }
2079
2080    /// Finish compiling code with the [`ByteCompiler`] and return the generated [`CodeBlock`].
2081    #[inline]
2082    #[must_use]
2083    #[allow(clippy::missing_const_for_fn)]
2084    pub fn finish(mut self) -> CodeBlock {
2085        // Push return at the end of the function compilation.
2086        if let Some(async_handler) = self.async_handler {
2087            self.patch_handler(async_handler);
2088        }
2089        self.r#return(false);
2090
2091        let final_bytecode_len = self.next_opcode_location();
2092
2093        let mapped_arguments_binding_indices = if self.emitted_mapped_arguments_object_opcode {
2094            MappedArguments::binding_indices(&self.params, &self.parameter_scope, self.interner)
2095        } else {
2096            ThinVec::default()
2097        };
2098
2099        let register_count = self.register_allocator.finish();
2100
2101        let source_map_entries = self.source_map_builder.build(final_bytecode_len);
2102
2103        CodeBlock {
2104            length: self.length,
2105            register_count,
2106            this_mode: self.this_mode,
2107            parameter_length: self.params.as_ref().len() as u32,
2108            mapped_arguments_binding_indices,
2109            bytecode: self.bytecode.into_bytecode(),
2110            constants: self.constants,
2111            bindings: self.bindings.into_boxed_slice(),
2112            handlers: self.handlers,
2113            flags: Cell::new(self.code_block_flags),
2114            ic: self.ic.into_boxed_slice(),
2115            source_info: SourceInfo::new(
2116                SourceMap::new(source_map_entries, self.source_path),
2117                self.function_name,
2118                self.spanned_source_text,
2119            ),
2120        }
2121    }
2122
2123    fn compile_declaration_pattern(
2124        &mut self,
2125        pattern: &Pattern,
2126        def: BindingOpcode,
2127        object: &Register,
2128    ) {
2129        self.compile_declaration_pattern_impl(pattern, def, object);
2130    }
2131}