{"record":{"id":"d4e5952fa51d770f","repo":"sinelaw/fresh","slug":"editor-spawnprocess-is-not-implemented-missing","errorCode":null,"errorMessage":"editor.spawnProcess is not implemented (missing _spawnProcessStart)","messagePattern":"editor\\.spawnProcess is not implemented \\(missing _spawnProcessStart\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs","lineNumber":8603,"sourceCode":"                            },\n                            catch(onRejected) {\n                                return resultPromise.catch(onRejected);\n                            }\n                        };\n                    };\n                };\n\n                // Apply wrappers to async functions on editor\n                // spawnProcess accepts either form for the 4th arg:\n                //   editor.spawnProcess(cmd, args, cwd?, stdoutTo?: string)\n                //   editor.spawnProcess(cmd, args, cwd?, { stdoutTo?: string })\n                // The first matches the auto-generated TS signature\n                // (flat positional from the Rust binding's `Opt<String>`\n                // args); the second is the structured options form\n                // plugin authors often prefer.\n                editor.spawnProcess = function(command, argsArr, cwdOrOpts, fourth) {\n                    if (typeof editor._spawnProcessStart !== 'function') {\n                        throw new Error('editor.spawnProcess is not implemented (missing _spawnProcessStart)');\n                    }\n                    // The 3rd arg is either cwd (string) or an options\n                    // object when cwd is omitted; the 4th is either a\n                    // stdoutTo string or an options object.\n                    let cwd = \"\";\n                    let stdoutTo = \"\";\n                    if (typeof cwdOrOpts === \"string\") {\n                        cwd = cwdOrOpts;\n                    } else if (cwdOrOpts && typeof cwdOrOpts === \"object\") {\n                        if (typeof cwdOrOpts.stdoutTo === \"string\") stdoutTo = cwdOrOpts.stdoutTo;\n                    }\n                    if (typeof fourth === \"string\") {\n                        stdoutTo = fourth;\n                    } else if (fourth && typeof fourth === \"object\") {\n                        if (typeof fourth.stdoutTo === \"string\") stdoutTo = fourth.stdoutTo;\n                    }\n                    const callbackId = editor._spawnProcessStart(\n                        command,","sourceCodeStart":8585,"sourceCodeEnd":8621,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs#L8585-L8621","documentation":"editor.spawnProcess is a JS shim installed by the QuickJS plugin backend that delegates process spawning to a Rust-provided host function editor._spawnProcessStart. If that host binding was never injected into the editor object (backend built without the spawn capability, or an older runtime), the shim throws rather than silently returning a dead handle.","triggerScenarios":"A plugin calls editor.spawnProcess(cmd, args, cwdOrOpts, fourth) in the QuickJS backend when editor._spawnProcessStart is not a function — i.e. the quickjs_backend.rs runtime did not register the _spawnProcessStart host binding (unsupported/older runtime, feature-disabled build).","commonSituations":"Plugins using process spawning against a runtime compiled without process-spawn support; running the plugin in an embedded/sandboxed QuickJS context where host bindings were partially installed; version mismatch between plugin expectations and the editor backend.","solutions":["Upgrade/verify the fresh-plugin-runtime build so the _spawnProcessStart binding is registered before plugin code runs.","Feature-detect before calling: if (typeof editor._spawnProcessStart !== 'function') fall back to another mechanism.","Check whether the platform/backend in use actually supports child processes (some sandboxed targets do not).","Guard the plugin call site so the plugin degrades gracefully instead of crashing."],"exampleFix":"// before\nconst handle = editor.spawnProcess(\"git\", [\"status\"]);\n\n// after\nif (typeof editor._spawnProcessStart !== \"function\") {\n  throw new Error(\"process spawning unsupported in this runtime\");\n}\nconst handle = editor.spawnProcess(\"git\", [\"status\"]);","handlingStrategy":"type-guard","validationCode":"if (typeof editor._spawnProcessStart !== \"function\") {\n  throw new Error(\"process spawning not supported in this runtime\");\n}","typeGuard":"function supportsSpawn(editor) {\n  return typeof editor._spawnProcessStart === \"function\" &&\n         typeof editor.spawnProcess === \"function\";\n}","tryCatchPattern":"try {\n  handle = editor.spawnProcess(cmd, args, cwd);\n} catch (e) {\n  if (String(e.message).includes(\"_spawnProcessStart\")) {\n    // fall back: run without subprocess support\n  } else throw e;\n}","preventionTips":["Feature-detect editor._spawnProcessStart before any spawn call.","Verify the runtime/backend build includes process-spawn host bindings.","Declare spawn capability requirements in the plugin manifest and check at startup.","Keep the plugin runtime and editor versions in sync."],"tags":["method-not-implemented","plugins","quickjs","process-spawn"],"backgroundTag":"method-not-implemented","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}