Skip to content

dtm2: introduce parsed runtime template manager#27011

Open
GGRei wants to merge 3 commits intovlang:masterfrom
GGRei:master
Open

dtm2: introduce parsed runtime template manager#27011
GGRei wants to merge 3 commits intovlang:masterfrom
GGRei:master

Conversation

@GGRei
Copy link
Copy Markdown
Contributor

@GGRei GGRei commented Apr 27, 2026

This PR introduces x.templating.dtm2, a modernized runtime template manager for V.

The existing x.templating.dtm module was originally my older contribution. I wanted to revisit it now with a cleaner architecture, better performance characteristics, and a simpler migration path for existing users.

DTM2 keeps the same core idea: templates remain normal files on disk and can be changed without recompiling the application. The main architectural change is that DTM2 caches parsed template trees instead of rendered HTML responses, removing the old async rendered-cache server from the main rendering path.

The legacy x.templating.dtm API remains available for compatibility and now delegates rendering internally to the DTM2 engine, so existing users can migrate progressively.

Main points:

  • Adds x.templating.dtm2
  • Keeps x.templating.dtm source-compatible
  • Adds parsed-template caching
  • Supports HTML/XML-like templates and text templates
  • Supports JSON-based extension configuration
  • Keeps placeholder values escaped by default
  • Restricts templates and includes to the configured template_dir
  • Adds tests and a DTM2 benchmark runner

Validation run locally:

  • ./v fmt -w on touched V files
  • ./v vet vlib/x/templating/dtm2
  • ./v test vlib/x/templating/dtm2
  • ./v test vlib/x/templating/dtm
  • ./v -prod test vlib/x/templating/dtm2
  • ./v -prod test vlib/x/templating/dtm
  • DTM2 benchmark wrapper in dev, prod, and prod_o2 modes

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@GGRei GGRei marked this pull request as draft April 28, 2026 18:49
@GGRei GGRei marked this pull request as ready for review April 28, 2026 18:49
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb544c3fcc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +310 to +311
if source_path := m.resolved_template_paths[template_path] {
return source_path
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Revalidate cached template paths before reuse

This returns a previously cached source path without re-running os.real_path/ensure_path_inside_template_dir, so the safety check is effectively one-time. If a template file is valid on first render and later replaced with a symlink to a file outside template_dir, subsequent renders can read outside content via os.read_file during recompilation, violating the module's documented directory restriction.

Useful? React with 👍 / 👎.

}
path := signature[second_sep + 1..line_end]
stat := os.stat(path) or { return false }
if stat.mtime != signature[offset..first_sep].i64() || stat.size != u64(size) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Invalidate cache on content changes, not only mtime+size

Freshness checking relies only on stat.mtime and stat.size. A template/include rewrite that keeps the same byte length within the same filesystem second will be treated as unchanged, so expand() can keep serving a stale compiled tree even though file contents changed. This is a real runtime correctness issue for rapid edits and autosave workflows.

Useful? React with 👍 / 👎.

@GGRei
Copy link
Copy Markdown
Contributor Author

GGRei commented Apr 28, 2026

I reworked the points raised by Codex.

If there is anything else that needs to be changed, let me know. Otherwise, from my side this is ready for review/integration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant