From cbb2d7966ec7d8a71f045c4af5101d3f1e73c730 Mon Sep 17 00:00:00 2001 From: Nikita-str Date: Thu, 9 Jan 2025 19:29:15 +0300 Subject: [PATCH] change way of passing the `SpannedSourceText` --- core/engine/src/builtins/eval/mod.rs | 8 ++- core/engine/src/builtins/function/mod.rs | 12 ++-- core/engine/src/builtins/json/mod.rs | 7 ++- core/engine/src/bytecompiler/class.rs | 16 +++-- core/engine/src/bytecompiler/declarations.rs | 10 +-- core/engine/src/bytecompiler/function.rs | 31 ++------- core/engine/src/bytecompiler/mod.rs | 32 +++++----- core/engine/src/module/source.rs | 3 + core/engine/src/module/synthetic.rs | 4 +- core/engine/src/script.rs | 5 +- core/engine/src/spanned_source_text.rs | 66 ++++++++++++++++---- core/engine/src/vm/code_block.rs | 4 +- 12 files changed, 120 insertions(+), 78 deletions(-) diff --git a/core/engine/src/builtins/eval/mod.rs b/core/engine/src/builtins/eval/mod.rs index 1e6a0dc39a4..67023a0d2c9 100644 --- a/core/engine/src/builtins/eval/mod.rs +++ b/core/engine/src/builtins/eval/mod.rs @@ -21,7 +21,7 @@ use crate::{ spanned_source_text::SourceText, string::StaticJsStrings, vm::{CallFrame, CallFrameFlags, Constant, Opcode}, - Context, JsArgs, JsResult, JsString, JsValue, + Context, JsArgs, JsResult, JsString, JsValue, SpannedSourceText, }; use boa_ast::{ operations::{contains, contains_arguments, ContainsSymbol}, @@ -262,6 +262,9 @@ impl Eval { let in_with = context.vm.environments.has_object_environment(); + let source_text = SourceText::new(source); + let spanned_source_text = SpannedSourceText::new_source_only(source_text); + let mut compiler = ByteCompiler::new( js_string!("
"), body.strict(), @@ -272,9 +275,8 @@ impl Eval { false, context.interner_mut(), in_with, + spanned_source_text, ); - let source_text = SourceText::new(source); - compiler.set_source_text(source_text); compiler.current_open_environments_count += 1; diff --git a/core/engine/src/builtins/function/mod.rs b/core/engine/src/builtins/function/mod.rs index ba4963a442f..c27d28842ac 100644 --- a/core/engine/src/builtins/function/mod.rs +++ b/core/engine/src/builtins/function/mod.rs @@ -34,7 +34,7 @@ use crate::{ symbol::JsSymbol, value::IntegerOrInfinity, vm::{ActiveRunnable, CallFrame, CallFrameFlags, CodeBlock}, - Context, JsArgs, JsResult, JsStr, JsString, JsValue, + Context, JsArgs, JsResult, JsStr, JsString, JsValue, SpannedSourceText, }; use boa_ast::{ function::{FormalParameterList, FunctionBody}, @@ -646,7 +646,9 @@ impl BuiltInFunctionObject { } let in_with = context.vm.environments.has_object_environment(); - let code = FunctionCompiler::new() + let spanned_source_text = SpannedSourceText::new_pseudo(); + + let code = FunctionCompiler::new(spanned_source_text) .name(js_string!("anonymous")) .generator(generator) .r#async(r#async) @@ -868,10 +870,8 @@ impl BuiltInFunctionObject { .ok_or_else(|| JsNativeError::typ().with_message("not a function"))?; let code = function.codeblock(); - if let Some(source) = &code.source_text_spanned { - if !source.is_empty() { - return Ok(JsString::from(source.to_code_points()).into()); - } + if let Some(code_points) = code.source_text_spanned.to_code_points() { + return Ok(JsString::from(code_points).into()); } Ok(js_string!( diff --git a/core/engine/src/builtins/json/mod.rs b/core/engine/src/builtins/json/mod.rs index ce4af91bad2..5bb9ad34d95 100644 --- a/core/engine/src/builtins/json/mod.rs +++ b/core/engine/src/builtins/json/mod.rs @@ -32,7 +32,7 @@ use crate::{ symbol::JsSymbol, value::IntegerOrInfinity, vm::{CallFrame, CallFrameFlags}, - Context, JsArgs, JsBigInt, JsResult, JsString, JsValue, + Context, JsArgs, JsBigInt, JsResult, JsString, JsValue, SpannedSourceText, }; use boa_gc::Gc; use boa_parser::{Parser, Source}; @@ -112,9 +112,13 @@ impl Json { // 10. Assert: unfiltered is either a String, Number, Boolean, Null, or an Object that is defined by either an ArrayLiteral or an ObjectLiteral. let mut parser = Parser::new(Source::from_bytes(&script_string)); parser.set_json_parse(); + // In json we don't need the source: there no way to pass an object that needs a source text + // But if it's incorrect, just call `parser.parse_script_with_source` here let script = parser.parse_script(&Scope::new_global(), context.interner_mut())?; let code_block = { let in_with = context.vm.environments.has_object_environment(); + // If the source is needed then call `parser.parse_script_with_source` and pass `source_text` here. + let spanned_source_text = SpannedSourceText::new_pseudo(); let mut compiler = ByteCompiler::new( js_string!("
"), script.strict(), @@ -125,6 +129,7 @@ impl Json { false, context.interner_mut(), in_with, + spanned_source_text, ); compiler.compile_statement_list(script.statements(), true, false); Gc::new(compiler.finish()) diff --git a/core/engine/src/bytecompiler/class.rs b/core/engine/src/bytecompiler/class.rs index 318599efa85..92d872cc766 100644 --- a/core/engine/src/bytecompiler/class.rs +++ b/core/engine/src/bytecompiler/class.rs @@ -2,6 +2,7 @@ use super::{ByteCompiler, Literal, Operand, ToJsString}; use crate::{ js_string, vm::{BindingOpcode, CodeBlock, CodeBlockFlags, Opcode}, + SpannedSourceText, }; use boa_ast::{ expression::Identifier, @@ -88,6 +89,8 @@ impl ByteCompiler<'_> { None }; + // The new span is not the same as the parent `ByteCompiler` have. + let spanned_source_text = self.spanned_source_text.clone_only_source(); let mut compiler = ByteCompiler::new( class_name.clone(), true, @@ -98,12 +101,9 @@ impl ByteCompiler<'_> { false, self.interner, self.in_with, + spanned_source_text, ); - if let Some(source_text) = &self.source_text { - compiler.set_source_text(source_text.clone()); - } - compiler.code_block_flags |= CodeBlockFlags::IS_CLASS_CONSTRUCTOR; if let Some(expr) = &class.constructor { @@ -294,6 +294,8 @@ impl ByteCompiler<'_> { false, self.interner, self.in_with, + // if you need the source text then pass `self.spanned_source_text.clone_only_source()` here + SpannedSourceText::new_pseudo(), ); // Function environment @@ -330,6 +332,8 @@ impl ByteCompiler<'_> { false, self.interner, self.in_with, + // if you need the source text then pass `self.spanned_source_text.clone_only_source()` here + SpannedSourceText::new_pseudo(), ); let _ = field_compiler.push_scope(field.scope()); if let Some(node) = field.field() { @@ -371,6 +375,8 @@ impl ByteCompiler<'_> { false, self.interner, self.in_with, + // if you need the source text then pass `self.spanned_source_text.clone_only_source()` here + SpannedSourceText::new_pseudo(), ); let _ = field_compiler.push_scope(field.scope()); let is_anonymous_function = if let Some(node) = &field.field() { @@ -414,6 +420,8 @@ impl ByteCompiler<'_> { false, self.interner, self.in_with, + // if you need the source text then pass `self.spanned_source_text.clone_only_source()` here + SpannedSourceText::new_pseudo(), ); let _ = compiler.push_scope(block.scopes().function_scope()); diff --git a/core/engine/src/bytecompiler/declarations.rs b/core/engine/src/bytecompiler/declarations.rs index b88d2e17a18..57b2400aba7 100644 --- a/core/engine/src/bytecompiler/declarations.rs +++ b/core/engine/src/bytecompiler/declarations.rs @@ -1,7 +1,7 @@ use crate::{ bytecompiler::{ByteCompiler, FunctionCompiler, FunctionSpec, NodeKind}, vm::{BindingOpcode, Opcode}, - Context, JsNativeError, JsResult, + Context, JsNativeError, JsResult, SpannedSourceText, }; use boa_ast::{ declaration::Binding, @@ -516,14 +516,14 @@ impl ByteCompiler<'_> { }; let func_span = function.linear_span(); + let spanned_source_text = SpannedSourceText::new(self.source_text(), func_span); - let code = FunctionCompiler::new() + let code = FunctionCompiler::new(spanned_source_text) .name(name.sym().to_js_string(self.interner())) .generator(generator) .r#async(r#async) .strict(self.strict()) .in_with(self.in_with) - .linear_span(func_span, self.source_text.clone()) .compile( parameters, body, @@ -779,14 +779,14 @@ impl ByteCompiler<'_> { }; let func_span = function.linear_span(); + let spanned_source_text = SpannedSourceText::new(self.source_text(), func_span); - let code = FunctionCompiler::new() + let code = FunctionCompiler::new(spanned_source_text) .name(name.sym().to_js_string(self.interner())) .generator(generator) .r#async(r#async) .strict(self.strict()) .in_with(self.in_with) - .linear_span(func_span, self.source_text.clone()) .name_scope(None) .compile( parameters, diff --git a/core/engine/src/bytecompiler/function.rs b/core/engine/src/bytecompiler/function.rs index 38c0bcae88b..0f72371fffb 100644 --- a/core/engine/src/bytecompiler/function.rs +++ b/core/engine/src/bytecompiler/function.rs @@ -3,12 +3,11 @@ use crate::{ bytecompiler::ByteCompiler, js_string, vm::{CodeBlock, CodeBlockFlags, Opcode}, - JsString, SourceText, SpannedSourceText, + JsString, SpannedSourceText, }; use boa_ast::{ function::{FormalParameterList, FunctionBody}, scope::{FunctionScopes, Scope}, - LinearSpan, }; use boa_gc::Gc; use boa_interner::Interner; @@ -25,13 +24,12 @@ pub(crate) struct FunctionCompiler { method: bool, in_with: bool, name_scope: Option, - source_text: Option, - source_text_span: Option, + spanned_source_text: SpannedSourceText, } impl FunctionCompiler { /// Create a new `FunctionCompiler`. - pub(crate) fn new() -> Self { + pub(crate) fn new(spanned_source_text: SpannedSourceText) -> Self { Self { name: js_string!(), generator: false, @@ -41,8 +39,7 @@ impl FunctionCompiler { method: false, in_with: false, name_scope: None, - source_text: None, - source_text_span: None, + spanned_source_text, } } @@ -98,17 +95,6 @@ impl FunctionCompiler { self } - /// Indicate if the function is in a `with` statement. - pub(crate) fn linear_span( - mut self, - linear_span: Option, - source_text: Option, - ) -> Self { - self.source_text = source_text; - self.source_text_span = linear_span; - self - } - /// Compile a function statement list and it's parameters into bytecode. pub(crate) fn compile( mut self, @@ -133,16 +119,9 @@ impl FunctionCompiler { self.generator, interner, self.in_with, + self.spanned_source_text, ); - if let Some(source_text) = self.source_text { - compiler.set_source_text(source_text.clone()); - if let Some(span) = self.source_text_span { - let source_text_spanned = SpannedSourceText::new(source_text, span); - compiler.set_source_text_spanned(source_text_spanned); - } - } - compiler.length = length; compiler.code_block_flags.set( CodeBlockFlags::HAS_PROTOTYPE_PROPERTY, diff --git a/core/engine/src/bytecompiler/mod.rs b/core/engine/src/bytecompiler/mod.rs index 85ca11ec0b1..da4978ffb3f 100644 --- a/core/engine/src/bytecompiler/mod.rs +++ b/core/engine/src/bytecompiler/mod.rs @@ -452,8 +452,7 @@ pub struct ByteCompiler<'ctx> { pub(crate) emitted_mapped_arguments_object_opcode: bool, pub(crate) interner: &'ctx mut Interner, - pub(crate) source_text: Option, - pub(crate) source_text_spanned: Option, + spanned_source_text: SpannedSourceText, #[cfg(feature = "annex-b")] pub(crate) annex_b_function_names: Vec, @@ -483,6 +482,7 @@ impl<'ctx> ByteCompiler<'ctx> { is_generator: bool, interner: &'ctx mut Interner, in_with: bool, + spanned_source_text: SpannedSourceText, ) -> ByteCompiler<'ctx> { let mut code_block_flags = CodeBlockFlags::empty(); code_block_flags.set(CodeBlockFlags::STRICT, strict); @@ -544,8 +544,7 @@ impl<'ctx> ByteCompiler<'ctx> { variable_scope, lexical_scope, interner, - source_text: None, - source_text_spanned: None, + spanned_source_text, #[cfg(feature = "annex-b")] annex_b_function_names: Vec::new(), @@ -554,12 +553,8 @@ impl<'ctx> ByteCompiler<'ctx> { } } - pub(crate) fn set_source_text(&mut self, source_text: SourceText) { - self.source_text = Some(source_text); - } - - pub(crate) fn set_source_text_spanned(&mut self, source_text_spanned: SpannedSourceText) { - self.source_text_spanned = Some(source_text_spanned); + pub(crate) fn source_text(&self) -> SourceText { + self.spanned_source_text.source_text() } pub(crate) const fn strict(&self) -> bool { @@ -1543,7 +1538,9 @@ impl<'ctx> ByteCompiler<'ctx> { Some(js_string!()) }; - let code = FunctionCompiler::new() + let spanned_source_text = SpannedSourceText::new(self.source_text(), linear_span); + + let code = FunctionCompiler::new(spanned_source_text) .name(name) .generator(generator) .r#async(r#async) @@ -1551,7 +1548,6 @@ impl<'ctx> ByteCompiler<'ctx> { .arrow(arrow) .in_with(self.in_with) .name_scope(name_scope.cloned()) - .linear_span(linear_span, self.source_text.clone()) .compile( parameters, body, @@ -1621,7 +1617,9 @@ impl<'ctx> ByteCompiler<'ctx> { Some(js_string!()) }; - let code = FunctionCompiler::new() + let spanned_source_text = SpannedSourceText::new(self.source_text(), linear_span); + + let code = FunctionCompiler::new(spanned_source_text) .name(name) .generator(generator) .r#async(r#async) @@ -1630,7 +1628,6 @@ impl<'ctx> ByteCompiler<'ctx> { .method(true) .in_with(self.in_with) .name_scope(name_scope.cloned()) - .linear_span(linear_span, self.source_text.clone()) .compile( parameters, body, @@ -1666,7 +1663,9 @@ impl<'ctx> ByteCompiler<'ctx> { Some(js_string!()) }; - let code = FunctionCompiler::new() + let spanned_source_text = SpannedSourceText::new(self.source_text(), linear_span); + + let code = FunctionCompiler::new(spanned_source_text) .name(name) .generator(generator) .r#async(r#async) @@ -1675,7 +1674,6 @@ impl<'ctx> ByteCompiler<'ctx> { .method(true) .in_with(self.in_with) .name_scope(function.name_scope.cloned()) - .linear_span(linear_span, self.source_text.clone()) .compile( parameters, body, @@ -1830,7 +1828,7 @@ impl<'ctx> ByteCompiler<'ctx> { handlers: self.handlers, flags: Cell::new(self.code_block_flags), ic: self.ic.into_boxed_slice(), - source_text_spanned: self.source_text_spanned, + source_text_spanned: self.spanned_source_text, } } diff --git a/core/engine/src/module/source.rs b/core/engine/src/module/source.rs index e7f10c7f102..97f2b8842e3 100644 --- a/core/engine/src/module/source.rs +++ b/core/engine/src/module/source.rs @@ -30,6 +30,7 @@ use crate::{ CompletionRecord, Opcode, }, Context, JsArgs, JsError, JsNativeError, JsObject, JsResult, JsString, JsValue, NativeFunction, + SpannedSourceText, }; use super::{ @@ -1434,6 +1435,8 @@ impl SourceTextModule { false, context.interner_mut(), false, + // TODO: need source text + SpannedSourceText::new_pseudo(), ); compiler.async_handler = Some(compiler.push_handler()); diff --git a/core/engine/src/module/synthetic.rs b/core/engine/src/module/synthetic.rs index 5e8309e0b6c..90c49b7e893 100644 --- a/core/engine/src/module/synthetic.rs +++ b/core/engine/src/module/synthetic.rs @@ -9,7 +9,7 @@ use crate::{ js_string, object::JsPromise, vm::{ActiveRunnable, CallFrame, CodeBlock}, - Context, JsNativeError, JsResult, JsString, JsValue, Module, + Context, JsNativeError, JsResult, JsString, JsValue, Module, SpannedSourceText, }; use super::{BindingName, ResolveExportError, ResolvedBinding}; @@ -295,6 +295,8 @@ impl SyntheticModule { false, context.interner_mut(), false, + // TODO: need source text + SpannedSourceText::new_pseudo(), ); // 4. For each String exportName in module.[[ExportNames]], do diff --git a/core/engine/src/script.rs b/core/engine/src/script.rs index b4190b0a978..684408f1145 100644 --- a/core/engine/src/script.rs +++ b/core/engine/src/script.rs @@ -22,7 +22,7 @@ use crate::{ realm::Realm, spanned_source_text::SourceText, vm::{ActiveRunnable, CallFrame, CallFrameFlags, CodeBlock}, - Context, HostDefined, JsResult, JsString, JsValue, Module, + Context, HostDefined, JsResult, JsString, JsValue, Module, SpannedSourceText, }; /// ECMAScript's [**Script Record**][spec]. @@ -134,6 +134,7 @@ impl Script { context, )?; + let spanned_source_text = SpannedSourceText::new_source_only(self.get_source()); let mut compiler = ByteCompiler::new( js_string!("
"), self.inner.source.strict(), @@ -144,8 +145,8 @@ impl Script { false, context.interner_mut(), false, + spanned_source_text, ); - compiler.set_source_text(self.get_source()); #[cfg(feature = "annex-b")] { diff --git a/core/engine/src/spanned_source_text.rs b/core/engine/src/spanned_source_text.rs index e97ed8230aa..395b57e6836 100644 --- a/core/engine/src/spanned_source_text.rs +++ b/core/engine/src/spanned_source_text.rs @@ -14,19 +14,28 @@ impl Inner { #[derive(Trace, Finalize, Clone)] pub(crate) struct SourceText { - source_text: Gc, + source_text: Option>, } impl SourceText { #[must_use] pub(crate) fn new(source_text: boa_ast::SourceText) -> Self { Self { - source_text: Gc::new(Inner::new(source_text)), + source_text: Some(Gc::new(Inner::new(source_text))), } } - fn inner(&self) -> &boa_ast::SourceText { - &self.source_text.source_text + fn new_pseudo() -> Self { + Self { source_text: None } + } + + #[inline] + fn inner(&self) -> Option<&boa_ast::SourceText> { + self.source_text.as_ref().map(|x| &x.source_text) + } + + fn is_empty(&self) -> bool { + self.source_text.is_none() } } @@ -35,26 +44,61 @@ impl SourceText { pub struct SpannedSourceText { source_text: SourceText, #[unsafe_ignore_trace] - span: LinearSpan, + span: Option, } impl SpannedSourceText { - pub(crate) fn new(source_text: SourceText, span: LinearSpan) -> Self { + pub(crate) fn new(source_text: SourceText, span: Option) -> Self { Self { source_text, span } } + pub(crate) fn new_source_only(source_text: SourceText) -> Self { + Self { + source_text, + span: None, + } + } + + pub(crate) fn new_pseudo() -> Self { + Self { + source_text: SourceText::new_pseudo(), + span: None, + } + } + + /// Creates new [`SpannedSourceText`] with the same [`SourceText`] and witohut `span`. + pub(crate) fn clone_only_source(&self) -> Self { + Self { + source_text: self.source_text.clone(), + span: None, + } + } + + /// Returns the [`SourceText`]. + #[must_use] + pub(crate) fn source_text(&self) -> SourceText { + self.source_text.clone() + } + /// Test if the span is empty. #[inline] #[must_use] pub fn is_empty(&self) -> bool { - self.span.is_empty() + let span_is_empty = if let Some(x) = self.span { + x.is_empty() + } else { + true + }; + span_is_empty || self.source_text.is_empty() } /// Gets inner code points. #[must_use] - pub fn to_code_points(&self) -> &[u16] { - self.source_text - .inner() - .get_code_points_from_span(self.span) + pub fn to_code_points(&self) -> Option<&[u16]> { + if let (Some(source_text), Some(span)) = (self.source_text.inner(), self.span) { + Some(source_text.get_code_points_from_span(span)) + } else { + None + } } } diff --git a/core/engine/src/vm/code_block.rs b/core/engine/src/vm/code_block.rs index f8e30ab56f3..4aa60a0f8f1 100644 --- a/core/engine/src/vm/code_block.rs +++ b/core/engine/src/vm/code_block.rs @@ -165,7 +165,7 @@ pub struct CodeBlock { pub(crate) ic: Box<[InlineCache]>, /// source text of the code block - pub(crate) source_text_spanned: Option, + pub(crate) source_text_spanned: SpannedSourceText, } /// ---- `CodeBlock` public API ---- @@ -189,7 +189,7 @@ impl CodeBlock { parameter_length: 0, handlers: ThinVec::default(), ic: Box::default(), - source_text_spanned: None, + source_text_spanned: SpannedSourceText::new_pseudo(), } }