REQUIRED WORK
99% complete.
77 / 78 required criteria
7 workstreams / 1 release target
Product target
postcss-go is an independent Go-backed implementation of the PostCSS public
API and plugin model. Production source, published packages, the CLI, and every
runtime backend must work without installing or loading the postcss package.
The target Node.js package will provide a PostCSS-compatible public surface implemented and owned by postcss-go. This includes the entry point and processor, AST classes and constructors, parsing and stringifying helpers, plugin helpers, results, inputs, warnings, errors, source maps, and public TypeScript contracts.
PostCSS remains available only in development fixtures, differential tests, the vendored upstream compatibility suite, and benchmarks. Unsupported behavior must produce a stable diagnostic; it must never silently fall back to PostCSS.
Current status
- Go tokenizer, parser, AST, processor, stringifier, source-map layer, native Node service, and WASM service are implemented.
- The Node N-API addon provides async-work and synchronous parse, process, no-work, stringify, and builder-stringify operations with a compact binary AST.
- The JavaScript plugin runtime implements the PostCSS plugin lifecycle over the postcss-go AST, including context, messages, sync thenable rejection, and the native/WASM/upstream contract suite.
- Remove every production runtime and type dependency on the
postcsspackage. - Complete the documented PostCSS-compatible public API using postcss-go-owned implementations.
- Export and validate the complete N-API synchronous API.
- Build, test, and publish every declared native platform package.
Required completion criteria
Zero PostCSS production dependency
- Remove every production
import,require, and type reference topostcss. - Remove the
postcssruntime, peer, optional, and transitive dependency frompostcss-go. - Replace
postcss-load-configandpostcss-reporterwith postcss-go-owned configuration loading and reporting. - Implement plugin helpers, AST classes, parsing, stringifying, results, warnings, and errors without loading PostCSS.
- Remove PostCSS class
Symbol.hasInstancepatches and other runtime coupling. - Remove every execution path that falls back to the
postcsspackage. - Keep PostCSS only as a development/test dependency for differential tests, upstream fixtures, and benchmarks.
- Verify a clean packed-package installation with
npm ls postcss.
Public JavaScript API
- Implement the PostCSS-compatible entry point and processor lifecycle within the documented compatibility scope.
- Complete postcss-go-owned
Processor, result, input, previous-map, warning, and syntax-error parity. - Export postcss-go-owned plugin, result, input, warning, syntax, parser, stringifier, source-map, and process-option types.
- Provide explicit asynchronous
parse,process, andstringifyAPIs. - Provide explicit synchronous
parseSync,processSync,stringifySync, andnoWorkSyncAPIs. - Document compatibility differences instead of reproducing implicit
LazyResultbehavior where it conflicts with explicit sync/async APIs. - Implement the baseline Node/Container method, mutation, traversal, JSON, and proxy surface.
- Complete Node/Container behavior and type parity through a dedicated upstream contract suite.
- Support
fromJSONand custom AST nodes in the JavaScript/DTO AST layer. - Preserve or explicitly diagnose custom AST nodes across native binary and WASM boundaries.
- Complete error and warning object parity, including source, input, plugin, node, line, and column metadata.
- Define a postcss-go-owned custom parser, syntax, and stringifier contract.
- Reject unsupported custom syntax with a stable error instead of falling back to PostCSS.
Plugin execution
This section is the JavaScript plugin runtime used by Node, the CLI, and the
browser WASM Worker. Go-native Plugin/Visitor values in pkg/api are a
separate API: they share parse, stringify, and source maps with the JavaScript
path, but they walk the tree once and do not dirty-rewalk.
- Support plugin normalization,
postcssPlugin,prepare,Once, node enter/exit visitors, andOnceExitordering. - Support synchronous and asynchronous plugin callbacks and Promise rejection on the asynchronous path.
- Preserve baseline AST mutation, dirty rewalk, traversal, and visitor ordering semantics.
- Implement
helpers.postcssentirely with postcss-go-owned classes and services. - Preserve complete plugin context:
result,root,opts,from,to, source/input data, custom messages, andlastPlugin. - Complete warning, dependency message, directory-dependency message, and plugin error behavior.
- Detect thenables returned by supported synchronous extension points: plugin creators,
prepare, visitors,Once,OnceExit, and annotation callbacks. - Throw a stable asynchronous-plugin error from
processSync()instead of waiting or switching execution modes. - Provide stable diagnostics for unsupported plugin features without loading PostCSS.
- Validate
postcss-importon native against upstream PostCSS, and mutation-heavy plus asynchronous plugin fixtures across native and WASM Worker. - Land the plugin contract suite against native, WASM Worker, and upstream PostCSS. Re-running it at publish time is a Validation gate.
Node N-API and synchronous execution
- Implement an in-process Node N-API addon for parse, process, no-work, and stringify operations.
- Use the compact binary AST codec for the native path.
- Hydrate and serialize live JavaScript AST nodes on the native plugin path.
- Add synchronous native parse and stringify service methods.
- Add synchronous process, no-work, and source-map generation service methods.
- Add a fully synchronous plugin runner that does not enter a Promise or microtask path.
- Run Go compute for Promise-returning native operations through Node-API async work instead of on the Node.js main thread.
- Use the same native-required asynchronous backend for CLI and public JavaScript APIs.
- Export
parseSync,processSync,stringifySync, andnoWorkSyncfrom the public package. - Expose service and default backend capabilities so callers can determine whether synchronous execution is available.
- Throw a stable
SyncBackendUnavailableErrorwhen a synchronous API is used without the N-API backend. - Keep
process()asynchronous and able to run both synchronous and asynchronous plugins on every supported async backend. - Document that synchronous processing blocks the Node.js event loop and recommend async or Worker Thread execution for server workloads.
- Define Worker Thread ownership, native cleanup, panic/error translation, and process shutdown behavior.
- Add the build, package, and smoke-test matrix for supported macOS, Linux glibc, and Windows targets.
- Add Linux musl native packages after Go supports loading c-archive/c-shared runtimes through
dlopen(golang/go#54805). - Verify that the native matrix succeeds on every declared target.
- Make missing native runtime artifacts fatal; Node has no transport fallback.
- Pack, install, load, and smoke-test every platform package before publication.
Core CSS pipeline
- Tokenizer implementation in
internal/tokenizerwith bridge support. - Parser support for Root, Rule, AtRule, Declaration, and Comment nodes.
- AST, codec, bridge, processor, and stringifier support for Document containers.
- AST mutation: append, prepend, insert, remove, replace, clone, traversal, and raw formatting helpers.
- Stringifier support for raw formatting and source maps on the main path.
- Structured syntax errors and bridge serialization.
- Source-map generation, previous maps, annotations, and source locations on the main path.
- Route all compatibility tokenizer behavior through Go.
- Implement the supported builder callback adapter with node and boundary metadata.
- Move map-generator, previous-map, no-work-result, and annotation normalization into the Go-owned path.
- Ensure Node, CLI, WASM, Go API, and source-map behavior share the same documented compatibility contract.
Node CLI and package boundary
- Replace the previous PostCSS plugin-chain execution in
packages/postcss-go/src/engine.tswith the postcss-go plugin runtime. - Define a standalone configuration contract for plugins, parser, syntax, stringifier, maps, and environment context.
- Load
.js,.mjs, and.cjsconfiguration withoutpostcss-load-config. - Format warnings, errors, and dependency messages without
postcss-reporter. - Remove the
postcsspeer dependency without replacing it with another runtime path to PostCSS. - Report native backend availability and the backend used for processing.
- Update package README, type declarations, examples, compatibility tables, and migration documentation.
Browser and WASM
- Provide the current Worker/WASM JSON service surface.
- Provide a Worker-backed asynchronous WASM backend.
- Run real WASM Worker-protocol parse, process, no-work, stringify, source-map, error, and shutdown tests.
- Support asynchronous plugins through the browser runtime within the documented contract.
- Define stable errors for synchronous APIs and other unsupported Worker features (
SyncBackendUnavailableError,WasmWorkerError). - Rebuild structured
CssSyntaxErrormetadata from the Worker ErrorDTO (line, column, reason, source, file). - Decide that an initialized main-thread WASM backend is not required; browser remains async Worker-only (no opt-in sync WASM in v1).
- Document CSP, cross-origin isolation, asset loading,
SharedArrayBuffer, and non-SAB behavior. - Cover native Node and browser Worker backends with an expanded shared smoke contract (parse/process/stringify/noWork, source maps, syntax errors, async plugins, visitor ordering). Plugin contract coverage against native, WASM Worker, and upstream PostCSS is recorded under Plugin execution; repeating those suites at publish time remains a Validation gate.
Optional performance work
The current compact binary AST transfers the tree once before JavaScript plugin execution and once before final stringification. A persistent opaque-handle AST is an optimization, not a prerequisite for removing PostCSS or exposing the N-API synchronous API.
The Go handle ABI lives in internal/asthandle and is measured by
pnpm bench:boundary Part E. Production Node N-API exports the same handle
surface (handleParse, batched field I/O, cursors) for declaration-only plugin
pipelines; cached native handles beat bulk binary transfer on that visitor shape
at 1–30 plugins. They are not a full PostCSS node facade (raws, custom nodes,
dirty rewalk, Result/helpers), and the WASM Worker path still needs a
serializable tree. Production therefore keeps the compact binary AST and DTO
protocols for compatibility boundaries.
- Benchmark real one-, three-, five-, ten-, and thirty-plugin pipelines before replacing binary whole-tree transfer.
- Prototype an opaque Go AST handle ABI with stable identity, generation checks, explicit disposal, and detached-node lifetime.
- Prototype cached field reads, batched reads, mutation batches, and visitor cursors.
- Compare native handles, cached handles, binary transfer, a synthetic JSON DTO baseline, and WASM using real plugins.
- Adopt handle-backed nodes only where measured end-to-end results outperform the binary AST path.
- Retain the binary AST and DTO protocols for the native and WASM compatibility boundaries.
Validation and release gates
These boxes are the publication checklist. A checked item was verified during implementation. Unchecked items stay open until they are re-run or completed as part of a release.
- Re-run the complete Go, TypeScript, package, CLI, WASM, and upstream differential suites.
- Re-run the shared plugin and AST contract suite across every supported backend.
- Pack
postcss-goand all platform packages into tarballs. - Install the tarballs in clean projects without workspace links.
- Verify the packed dependency tree contains no
postcss,postcss-load-config, orpostcss-reporter. - Verify async processing with synchronous and asynchronous plugins.
- Verify N-API
parseSync,processSync,stringifySync, andnoWorkSync. - Verify
processSync()rejects every Promise-returning extension point. - Verify missing native artifacts produce stable async and sync diagnostics without changing transports.
- Verify native artifact presence and loading on every published target.
- Publish only after all required completion criteria and release gates pass.
Implementation order
- Establish the Go CSS data-path baseline.
- Implement the JavaScript AST facade and plugin runtime.
- Implement the compact binary N-API transport.
- Introduce postcss-go-owned public contracts and remove production PostCSS types.
- Replace
helpers.postcss, class coupling, custom-syntax fallback, configuration loading, and reporting. - Remove all production and published-package dependencies on PostCSS.
- Implement the explicit synchronous service and plugin execution path.
- Export and test the complete sync and async public APIs.
- Complete result, input, warning, error, plugin-context, and custom-syntax compatibility.
- Run real-plugin and cross-backend contract suites.
- Complete the native build, packaging, installation, and publication matrix.
- Update public compatibility and migration documentation.
- Evaluate opaque AST handles only after the required replacement target is complete and benchmarked.