{"record":{"id":"4c4cb87d7a7d0a48","repo":"libnyanpasu/clash-nyanpasu","slug":"parse-error","errorCode":null,"errorMessage":"parse error: {}","messagePattern":"parse error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/enhance/script/js.rs","lineNumber":373,"sourceCode":"        }\n    }\n\n    /// This is a tool function to wrap the script if it is not a ESM script.\n    pub fn wrap_script_if_not_esm(script: &str) -> Result<Cow<'_, str>, anyhow::Error> {\n        let allocator = Allocator::default();\n        let source_type = SourceType::default().with_module(true);\n        let source_text = script.trim_matches(['\\t', '\\n', '\\r', ' ']);\n        let result = Parser::new(&allocator, source_text, source_type).parse();\n\n        if !result.diagnostics.is_empty() {\n            let mut errors = String::new();\n            for error in result.diagnostics {\n                errors.push_str(&format!(\n                    \"{:?}\\n\",\n                    error.with_source_code(source_text.to_string())\n                ));\n            }\n            return Err(anyhow::anyhow!(\"parse error: {}\", errors));\n        }\n        #[cfg(test)]\n        eprintln!(\"result: {:#?}\", result.program);\n        let mut visitor = FunctionVisitor::default();\n        visitor.visit_program(&result.program);\n        #[cfg(test)]\n        eprintln!(\"visitor: {:#?}\", visitor);\n        if visitor.default_export.is_some() {\n            return Ok(Cow::Borrowed(script));\n        }\n        // check whether `function main` exists\n        match visitor\n            .declared_functions\n            .iter()\n            .find(|(name, _)| name.contains(\"main\"))\n        {\n            Some((_, span)) => {\n                // just insert `export default` before the function","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/enhance/script/js.rs#L355-L391","documentation":"wrap_script_if_not_esm parses user JavaScript with the SWC parser; when parsing produces diagnostics (syntax errors), it collects them with source context into a single string and throws anyhow \"parse error: {errors}\". This means the script text itself is not valid JavaScript for the parser.","triggerScenarios":"Calling wrap_script_if_not_esm with script text containing syntax errors: unbalanced braces, reserved words as identifiers, or TypeScript/JSX syntax fed to a plain-JS parser.","commonSituations":"Users paste TypeScript or JSX into the JS enhancement editor, truncate the script, or copy code containing smart quotes or invisible characters.","solutions":["Read the diagnostics in the error message - they include line/column and a code snippet.","Fix the reported syntax error in the script editor.","Remove TypeScript-only syntax (type annotations, interfaces); only plain JS/ESM is supported.","Validate the script in Node or an online JS parser before saving."],"exampleFix":"// before (invalid)\nfunction main(config: Object) { return config; }\n// after (valid)\nfunction main(config) { return config; }","handlingStrategy":"validation","validationCode":"// caller-side syntax check before submitting the script\ntry { new Function(scriptSource); } catch (e) { alert(`syntax error: ${e.message}`); }","typeGuard":null,"tryCatchPattern":"try {\n  await saveScript(src);\n} catch (e) {\n  if (String(e).startsWith('parse error:')) showEditorDiagnostics(e.message);\n  else throw e;\n}","preventionTips":["Validate script syntax in an editor with JS linting before saving","Never paste TypeScript into the plain-JS editor","Check for smart quotes after copy-pasting code","Keep scripts ESM-compatible with a default export"],"tags":["javascript","parser","syntax-error","swc"],"backgroundTag":"json-parse-error","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}