mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
perf(transformer): memoize rope instance (#5518)
Currently only used in `jsx-source`, so memorize rope in JSXSource enough for now. close: #5500
This commit is contained in:
parent
ed8ab6d7c8
commit
ed8937e978
3 changed files with 95 additions and 77 deletions
|
|
@ -11,7 +11,7 @@ use oxc_syntax::{
|
|||
};
|
||||
use oxc_traverse::{Traverse, TraverseCtx};
|
||||
|
||||
use super::{diagnostics, utils::get_line_column};
|
||||
use super::diagnostics;
|
||||
pub use super::{
|
||||
jsx_self::ReactJsxSelf,
|
||||
jsx_source::ReactJsxSource,
|
||||
|
|
@ -560,7 +560,7 @@ impl<'a> ReactJsx<'a> {
|
|||
if let Some(span) = source_attr_span {
|
||||
self.jsx_source.report_error(span);
|
||||
} else {
|
||||
let (line, column) = get_line_column(e.span().start, self.ctx.source_text);
|
||||
let (line, column) = self.jsx_source.get_line_column(e.span().start);
|
||||
properties.push(
|
||||
self.jsx_source.get_object_property_kind_for_jsx_plugin(line, column, ctx),
|
||||
);
|
||||
|
|
@ -614,7 +614,7 @@ impl<'a> ReactJsx<'a> {
|
|||
if let Some(span) = source_attr_span {
|
||||
self.jsx_source.report_error(span);
|
||||
} else {
|
||||
let (line, column) = get_line_column(e.span().start, self.ctx.source_text);
|
||||
let (line, column) = self.jsx_source.get_line_column(e.span().start);
|
||||
let expr = self.jsx_source.get_source_object(line, column, ctx);
|
||||
arguments.push(Argument::from(expr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use oxc_diagnostics::OxcDiagnostic;
|
|||
use oxc_span::{Span, SPAN};
|
||||
use oxc_syntax::{number::NumberBase, symbol::SymbolFlags};
|
||||
use oxc_traverse::{Traverse, TraverseCtx};
|
||||
use ropey::Rope;
|
||||
|
||||
use super::utils::get_line_column;
|
||||
use crate::{context::Ctx, helpers::bindings::BoundIdentifier};
|
||||
|
|
@ -19,13 +20,14 @@ const FILE_NAME_VAR: &str = "jsxFileName";
|
|||
/// In: `<sometag />`
|
||||
/// Out: `<sometag __source={ { fileName: 'this/file.js', lineNumber: 10, columnNumber: 1 } } />`
|
||||
pub struct ReactJsxSource<'a> {
|
||||
ctx: Ctx<'a>,
|
||||
filename_var: Option<BoundIdentifier<'a>>,
|
||||
source_rope: Option<Rope>,
|
||||
ctx: Ctx<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ReactJsxSource<'a> {
|
||||
pub fn new(ctx: Ctx<'a>) -> Self {
|
||||
Self { ctx, filename_var: None }
|
||||
Self { filename_var: None, source_rope: None, ctx }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -40,6 +42,13 @@ impl<'a> Traverse<'a> for ReactJsxSource<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ReactJsxSource<'a> {
|
||||
pub fn get_line_column(&mut self, offset: u32) -> (usize, usize) {
|
||||
if self.source_rope.is_none() {
|
||||
self.source_rope = Some(Rope::from_str(self.ctx.source_text));
|
||||
}
|
||||
get_line_column(self.source_rope.as_ref().unwrap(), offset, self.ctx.source_text)
|
||||
}
|
||||
|
||||
pub fn get_object_property_kind_for_jsx_plugin(
|
||||
&mut self,
|
||||
line: usize,
|
||||
|
|
@ -87,7 +96,7 @@ impl<'a> ReactJsxSource<'a> {
|
|||
// TODO: We shouldn't calculate line + column from scratch each time as it's expensive.
|
||||
// Build a table of byte indexes of each line's start on first usage, and save it.
|
||||
// Then calculate line and column from that.
|
||||
let (line, column) = get_line_column(elem.span.start, self.ctx.source_text);
|
||||
let (line, column) = self.get_line_column(elem.span.start);
|
||||
let object = self.get_source_object(line, column, ctx);
|
||||
let value = self
|
||||
.ctx
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ use ropey::Rope;
|
|||
/// Column number is in UTF-16 characters, and starts at 1.
|
||||
///
|
||||
/// This matches Babel's output.
|
||||
pub fn get_line_column(offset: u32, source_text: &str) -> (usize, usize) {
|
||||
pub fn get_line_column(rope: &Rope, offset: u32, source_text: &str) -> (usize, usize) {
|
||||
let offset = offset as usize;
|
||||
let rope = Rope::from_str(source_text);
|
||||
// Get line number and byte offset of start of line
|
||||
let line_index = rope.byte_to_line(offset);
|
||||
let line_offset = rope.line_to_byte(line_index);
|
||||
|
|
@ -18,74 +17,84 @@ pub fn get_line_column(offset: u32, source_text: &str) -> (usize, usize) {
|
|||
(line_index + 1, column_index + 1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_file() {
|
||||
assert_eq!(get_line_column(0, ""), (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_line_start() {
|
||||
assert_eq!(get_line_column(0, "foo\nbar\n"), (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_line_middle() {
|
||||
assert_eq!(get_line_column(5, "blahblahblah\noops\n"), (1, 6));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn later_line_start() {
|
||||
assert_eq!(get_line_column(8, "foo\nbar\nblahblahblah"), (3, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn later_line_middle() {
|
||||
assert_eq!(get_line_column(12, "foo\nbar\nblahblahblah"), (3, 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_2_byte_unicode() {
|
||||
assert_eq!("£".len(), 2);
|
||||
assert_eq!(utf16_len("£"), 1);
|
||||
assert_eq!(get_line_column(4, "£abc"), (1, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_3_byte_unicode() {
|
||||
assert_eq!("अ".len(), 3);
|
||||
assert_eq!(utf16_len("अ"), 1);
|
||||
assert_eq!(get_line_column(5, "अabc"), (1, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_4_byte_unicode() {
|
||||
assert_eq!("🍄".len(), 4);
|
||||
assert_eq!(utf16_len("🍄"), 2);
|
||||
assert_eq!(get_line_column(6, "🍄abc"), (1, 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_2_byte_unicode_on_previous_line() {
|
||||
assert_eq!("£".len(), 2);
|
||||
assert_eq!(utf16_len("£"), 1);
|
||||
assert_eq!(get_line_column(4, "£\nabc"), (2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_3_byte_unicode_on_previous_line() {
|
||||
assert_eq!("अ".len(), 3);
|
||||
assert_eq!(utf16_len("अ"), 1);
|
||||
assert_eq!(get_line_column(5, "अ\nabc"), (2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_4_byte_unicode_on_previous_line() {
|
||||
assert_eq!("🍄".len(), 4);
|
||||
assert_eq!(utf16_len("🍄"), 2);
|
||||
assert_eq!(get_line_column(6, "🍄\nabc"), (2, 2));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn utf16_len(s: &str) -> usize {
|
||||
s.encode_utf16().count()
|
||||
mod test {
|
||||
use ropey::Rope;
|
||||
|
||||
fn test_line_column(offset: u32, source_text: &str) -> (usize, usize) {
|
||||
let rope = Rope::from_str(source_text);
|
||||
super::get_line_column(&rope, offset, source_text)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_file() {
|
||||
assert_eq!(test_line_column(0, ""), (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_line_start() {
|
||||
assert_eq!(test_line_column(0, "foo\nbar\n"), (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_line_middle() {
|
||||
assert_eq!(test_line_column(5, "blahblahblah\noops\n"), (1, 6));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn later_line_start() {
|
||||
assert_eq!(test_line_column(8, "foo\nbar\nblahblahblah"), (3, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn later_line_middle() {
|
||||
assert_eq!(test_line_column(12, "foo\nbar\nblahblahblah"), (3, 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_2_byte_unicode() {
|
||||
assert_eq!("£".len(), 2);
|
||||
assert_eq!(utf16_len("£"), 1);
|
||||
assert_eq!(test_line_column(4, "£abc"), (1, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_3_byte_unicode() {
|
||||
assert_eq!("अ".len(), 3);
|
||||
assert_eq!(utf16_len("अ"), 1);
|
||||
assert_eq!(test_line_column(5, "अabc"), (1, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_4_byte_unicode() {
|
||||
assert_eq!("🍄".len(), 4);
|
||||
assert_eq!(utf16_len("🍄"), 2);
|
||||
assert_eq!(test_line_column(6, "🍄abc"), (1, 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_2_byte_unicode_on_previous_line() {
|
||||
assert_eq!("£".len(), 2);
|
||||
assert_eq!(utf16_len("£"), 1);
|
||||
assert_eq!(test_line_column(4, "£\nabc"), (2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_3_byte_unicode_on_previous_line() {
|
||||
assert_eq!("अ".len(), 3);
|
||||
assert_eq!(utf16_len("अ"), 1);
|
||||
assert_eq!(test_line_column(5, "अ\nabc"), (2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_4_byte_unicode_on_previous_line() {
|
||||
assert_eq!("🍄".len(), 4);
|
||||
assert_eq!(utf16_len("🍄"), 2);
|
||||
assert_eq!(test_line_column(6, "🍄\nabc"), (2, 2));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn utf16_len(s: &str) -> usize {
|
||||
s.encode_utf16().count()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue