Repository: jaytaph/gosub-browser
File: src/testing/tree_construction.rs (Rust)

Code before:
#[derive(Default)]
pub struct Harness {
    // Test that is currently being run
    test: Test,
    /// Next line in the document array
    next_document_line: usize,
}

impl Harness {
    /// Generated a new harness instance. It uses a dummy test that is replaced when run_test is called
    pub fn new() -> Self {
        Self::default()
    }

    /// Runs a single test and returns the test result of that run
    pub fn run_test(&mut self, test: Test, scripting_enabled: bool) -> Result<TestResult> {
        self.test = test;
        self.next_document_line = 0;

        let (actual_document, actual_errors) = self.do_parse(scripting_enabled)?;
        let result = self.generate_test_result(Document::clone(&actual_document), &actual_errors);

        Ok(result)
    }

    /// Run the html5 parser and return the document tree and errors
    fn do_parse(&mut self, scripting_enabled: bool) -> Result<(DocumentHandle, Vec<ParseError>)> {
        let options = Html5ParserOptions { scripting_enabled };
        let mut chars = CharIterator::new();
        chars.read_from_str(self.test.spec_data(), None);

        let (document, parse_errors) = if let Some(fragment) =
            self.test.spec.document_fragment.clone()
        {
            self.parse_fragment(fragment, chars, options)?
        } else {
            let document = DocumentBuilder::new_document();
            let parser_errors =
                Html5Parser::parse_document(&mut chars, Document::clone(&document), Some(options))?;
            (document, parser_errors)
        };

        Ok((document, parse_errors))
    }

    fn parse_fragment(
        &mut self,
        fragment: String,
        mut chars: CharIterator,
        options: Html5ParserOptions,
    ) -> Result<(DocumentHandle, Vec<ParseError>)> {

Review comment (refactor):
@emwalker discovered we needed to move this code to fix `Weak` pointer's lifetime struggles. Earlier it kept going out of scope too early and we were losing the pointer to the document before we get to the parser

Code after:
    }
}

impl Harness {
    /// Generated a new harness instance. It uses a dummy test that is replaced when run_test is called
    #[must_use]
    pub fn new() -> Self {
        Self {
            test: Test::default(),
            next_document_line: 0,
        }
    }

    /// Runs a single test and returns the test result of that run
    pub fn run_test(&mut self, test: Test, scripting_enabled: bool) -> Result<TestResult> {
        self.test = test;
        self.next_document_line = 0;

        let (actual_document, actual_errors) = self.do_parse(scripting_enabled)?;
        let result = self.generate_test_result(Document::clone(&actual_document), &actual_errors);

        Ok(result)
    }

    /// Run the html5 parser and return the document tree and errors
    fn do_parse(&mut self, scripting_enabled: bool) -> Result<(DocumentHandle, Vec<ParseError>)> {
        let options = Html5ParserOptions { scripting_enabled };
        let mut chars = CharIterator::new();
        chars.read_from_str(self.test.spec_data(), None);

        let (document, parse_errors) = if let Some(fragment) =
            self.test.spec.document_fragment.clone()
        {
            self.parse_fragment(fragment, chars, options)?
        } else {
            let document = DocumentBuilder::new_document();
            let parser_errors =
                Html5Parser::parse_document(&mut chars, Document::clone(&document), Some(options))?;
            (document, parser_errors)
        };

        Ok((document, parse_errors))
    }

    fn parse_fragment(
        &mut self,
        fragment: String,
        mut chars: CharIterator,
        options: Html5ParserOptions,
    ) -> Result<(DocumentHandle, Vec<ParseError>)> {
        // First, create a (fake) main document that contains only the fragment as node