Skip to content

Real GraphQL executor, native List[T], Anneal; 0.4.16#23

Merged
loreste merged 4 commits into
mainfrom
feat/graphql-executor-native-list-0416
Jul 24, 2026
Merged

Real GraphQL executor, native List[T], Anneal; 0.4.16#23
loreste merged 4 commits into
mainfrom
feat/graphql-executor-native-list-0416

Conversation

@loreste

@loreste loreste commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • GraphQL — full query executor behind the existing graphql_schema_resolve API (C + native, no ABI change): nested projection over objects/arrays, aliases, arguments + operation variable defaults, __typename, __schema/__type introspection, named + inline fragments, field validation, spec-shaped {"data":…,"errors":[…]}.
  • Fixed a pre-existing per-request memory leak in graphql_schema_resolve (owned result + query-arg temp were never reclaimed). Allowlisted owned-string-returning builtins in scope-drop cleanup; gated the arg-free by ownership to avoid double-free.
  • Native backend List[T] now lowers for any element type (structs, nested List[List[int]], strings, pointer arrays) by aliasing []T.
  • Anneal — named the adaptive-optimization loop; added scripts/anneal-cycle.sh; broadened hot_site_test.mko (boundary ids, top reassignment, enable transitions, concurrent atomic-counter tallies).
  • Version 0.4.15 → 0.4.16 with CHANGELOG + doc/tip-marker updates.

Verification

  • Full suite 378 passed / 0 failed (C + native).
  • GraphQL: ASan (UAF/OOB) clean, UBSan clean, and leak-free per request (flat under LeakSanitizer over 500 resolves) on Linux; new graphql_exec_test.mko (13 cases).
  • List[T]: correct on both backends, C↔native differential identical, ASan/UBSan clean; new native_list_generic_test.mko.
  • Sanitizers validated on Linux (local macOS ASan runtime is unusable — deadlocks at startup).

Known follow-up (pre-existing, not introduced here)

Owned values returned from user functions and dropped locally are not reclaimed (a general per-call leak, same class as the GraphQL return leak). The naive fix (treat user-fn owned returns as scope-drop-safe) double-frees generic-enum returns, so it needs deeper move-analysis work and is left for a focused, separately-validated pass. List[Struct] inherits the existing []Struct behavior here — this change does not worsen it.

Summary by CodeRabbit

  • New Features

    • GraphQL execution now supports nested selections, aliases, fragments, variable defaults, introspection, validation, and standard data/error responses.
    • Generic lists now support structures, strings, nested lists, and other non-scalar values in the native backend.
    • Adaptive optimization is now branded “Anneal,” with a streamlined cycle command for offline performance improvements.
  • Bug Fixes

    • Improved GraphQL memory handling and field-level error reporting.
    • Improved list ownership and replacement behavior for safer native execution.
  • Documentation

    • Updated release, performance, optimization, native backend, and GraphQL documentation for version 0.4.16.

loreste and others added 3 commits July 23, 2026 18:53
Two memory-safety bugs in owned slice fields (both surfaced by
collections_mako_test on the native backend):

- `self.xs = self.xs[a:b]` stored a view that aliases the field's own buffer,
  then freed that buffer while overwriting — use-after-free (garbage reads,
  SIGABRT). Clone the view's data into an independent slice before dropping the
  old field, matching the local-assignment path.
- `self.xs = append(self.xs, v)` leaked the original field header/buffer. A
  field read is a borrow, so append clones it and consumes the clone; the stale
  "consumes old field" exception then skipped dropping the original. Always drop
  the old field. Affects every slice-backed struct (stacks, lists, queues).

Native corpus now 376/376; every native fixture is 0-leak and GuardMalloc-clean.
Replace the terse ADAPTIVE_OPT.md draft with clear prose describing the offline
feedback loop: a fully compiled binary plus opt-in hot-site counters
(off by default, 256 sites) exported at /debug/hot_sites and folded into the
next build via an offline PGO cycle. Frame it as ahead-of-time with an offline
loop; drop the runtime-code-generation phrasing from the README compilation
section.
GraphQL: replace the placeholder resolver with a real recursive executor
behind graphql_schema_resolve (both C and native backends, no ABI change):
nested projection over objects/arrays, aliases, arguments + operation
variable defaults, __typename, __schema/__type introspection, named and
inline fragments, field validation, and spec-shaped {data,errors} output.
Fix a pre-existing per-request leak: resolve results and owned query-arg
temporaries were never reclaimed (allowlist owned-string-returning builtins
in scope-drop cleanup; gate the query-arg free by ownership to avoid double
free). Verified leak-free per request and ASan/UBSan-clean on Linux; new
graphql_exec_test.mko (13 cases).

Native backend: List[T] now lowers for any element type (structs, nested
List[List[int]], strings, pointer arrays) by aliasing []T instead of erroring
for non-scalar T; new native_list_generic_test.mko, differential vs C.

Anneal: name the adaptive-optimization loop; add scripts/anneal-cycle.sh over
adaptive-opt-cycle.sh (stable hot_site_* API unchanged); broaden hot_site_test
with boundary ids, top reassignment, enable transitions, and concurrent
atomic-counter tallies.

Version: 0.4.15 -> 0.4.16; update CHANGELOG, docs, and tip markers.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@loreste, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8aa8b003-3e2a-41d4-bef0-1d17d6f66890

📥 Commits

Reviewing files that changed from the base of the PR and between b6a3795 and fb01d6b.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • examples/testing/owned_return_drop_test.mko
  • src/codegen/mod.rs
📝 Walkthrough

Walkthrough

This release bumps Mako to 0.4.16, adds a recursive GraphQL executor, broadens native List[T] lowering, renames adaptive optimization to Anneal, expands hot-site tests, and updates related documentation, scripts, and release metadata.

Changes

GraphQL query execution

Layer / File(s) Summary
GraphQL executor and ownership
runtime/mako_std.h, src/codegen/mod.rs
graphql_schema_resolve now executes nested selections, aliases, fragments, introspection, variable defaults, validation, and spec-shaped responses with updated string ownership handling.
GraphQL behavior documentation and tests
examples/testing/graphql_exec_test.mko, docs/MESSAGING_GRAPHQL.md, CHANGELOG.md
Examples and documentation cover projections, aliases, fragments, introspection, variables, multiple root fields, and partial errors.

Generic native lists

Layer / File(s) Summary
List lowering and slice ownership
src/native_ir.rs
List[T] uses slice lowering for arbitrary element types, and slice field assignments materialize independent views before owned replacement.
Generic list coverage and roadmap
examples/testing/native_list_generic_test.mko, docs/NATIVE_COMPILER_PLAN.md, CHANGELOG.md
Tests cover struct, nested-list, string, and ownership-churn cases, and the roadmap records generic List support as complete.

Anneal and 0.4.16 release

Layer / File(s) Summary
Anneal workflow and hot-site validation
docs/ADAPTIVE_OPT.md, examples/testing/hot_site_test.mko, scripts/*, docs/PERFORMANCE.md
Anneal documentation and scripts describe offline optimization cycles, while hot-site tests cover boundaries, state transitions, rankings, concurrency, and JSON export.
0.4.16 release metadata
Cargo.toml, CHANGELOG.md, README.md, docs/{LONG_RUNNING,ROADMAP,SPEED_SAFE,STATUS,VERSIONING}.md, runtime/mako_std.h
Version markers, release notes, status pages, documentation, and the NATS client frame are updated for 0.4.16.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant mako_graphql_schema_resolve
  participant GraphQLSchema
  participant Resolver
  Caller->>mako_graphql_schema_resolve: Query and variables
  mako_graphql_schema_resolve->>GraphQLSchema: Parse selections and validate fields
  GraphQLSchema->>Resolver: Resolve requested field
  Resolver-->>mako_graphql_schema_resolve: JSON payload
  mako_graphql_schema_resolve-->>Caller: data and errors response
Loading

Possibly related PRs

  • loreste/mako#20: Related slice view cloning, dropping, and ownership lowering changes in src/native_ir.rs.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main changes: GraphQL executor, native List[T], Anneal, and the version bump.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/graphql-executor-native-list-0416

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/native_ir.rs (1)

15496-15500: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale doc comment left over after removing field_base_same_local.

/// True when both expressions name the same local (field-assign consume). now sits directly above fn drop_owned_locals, an unrelated function, since the helper it documented was deleted. This is misleading and should be removed as part of this cleanup.

🧹 Suggested cleanup
     }
 
-    /// True when both expressions name the same local (field-assign consume).
-
     fn drop_owned_locals(&mut self) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/native_ir.rs` around lines 15496 - 15500, Remove the stale doc comment
immediately before drop_owned_locals, since it documents the deleted
field_base_same_local helper rather than drop_owned_locals. Leave the function
implementation unchanged.
🧹 Nitpick comments (2)
src/native_ir.rs (2)

1478-1482: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Correct List[T] fix — but leaves the old scalar-only List[T] arm in scalar_type dead.

This new arm in resolve_type correctly aliases List[T] to full slice resolution (structs, nested lists, pointer arrays), matching the PR goal. However, scalar_type still has its own narrower List[T] arm (lines ~1234-1246, int/string/float/byte/bool only). Since resolve_type now intercepts every List[T] before reaching the _ => scalar_type(ty) fallback (line 1499), that arm in scalar_type is unreachable for any type resolved through resolve_type — the only path that reaches scalar_type with a List generic.

♻️ Suggested cleanup
-        // List[T] aliases []T for the common int/string specializations.
-        TypeExpr::Generic(name, args) if name == "List" && args.len() == 1 => {
-            match args[0] {
-                TypeExpr::Named(ref n) if n == "int" || n == "int64" => Ok(Type::IntSlice),
-                TypeExpr::Named(ref n) if n == "string" => Ok(Type::StrSlice),
-                TypeExpr::Named(ref n) if n == "float" || n == "float64" => Ok(Type::FloatSlice),
-                TypeExpr::Named(ref n) if n == "byte" || n == "uint8" => Ok(Type::ByteSlice),
-                TypeExpr::Named(ref n) if n == "bool" => Ok(Type::BoolSlice),
-                _ => Err(IrError::new(format!(
-                    "native IR: List[{}] is not supported yet",
-                    args[0]
-                ))),
-            }
-        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/native_ir.rs` around lines 1478 - 1482, Remove the obsolete scalar-only
List[T] match arm from scalar_type, since resolve_type now handles every
one-parameter List generic by converting it to an Array before the scalar_type
fallback. Preserve scalar_type’s remaining scalar resolution behavior and let
unsupported cases continue through its existing fallback.

3846-3905: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Correctly fixes both the reslice UAF and the append leak — consider adding a regression test.

Traced the two target bugs end-to-end:

  • self.xs = self.xs[a:b]: the materialize block clones the borrowed view before dropping the temporary view header and before loading/dropping the old field, so the clone always reads live backing. No UAF.
  • self.xs = append(self.xs, v): append's source_owned check only special-cases Expr::Ident sources, so a field-sourced arg is always cloned inside append. The old field is therefore never truly consumed, and the new unconditional "always drop old field" logic correctly frees it instead of leaking it.

Both fixes look sound. Given this is a memory-safety fix (UAF + leak), it would be valuable to add an IR-level unit test for these two FieldAssign patterns here, mirroring the existing style used for local scope (e.g. drops_borrowed_slice_headers_and_clones_escaping_views, clones_and_drops_int_slice_struct_fields) — asserting a SliceClone/DropSlice pair around the reslice, and a DropSlice after append into a field.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/native_ir.rs` around lines 3846 - 3905, Add IR-level regression tests for
the field-assignment paths in the existing native IR test module, mirroring
drops_borrowed_slice_headers_and_clones_escaping_views and
clones_and_drops_int_slice_struct_fields. Cover self.xs = self.xs[a:b] by
asserting SliceClone occurs before DropSlice for the temporary view, and cover
self.xs = append(self.xs, v) by asserting the old field receives a DropSlice
after the append assignment.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/ADAPTIVE_OPT.md`:
- Line 26: Update the availability statement in ADAPTIVE_OPT to distinguish
hot-site/offline-PGO capability availability in 0.4.14 from the Anneal naming
introduced in 0.4.16, rather than claiming all functionality starts in 0.4.15.

In `@docs/NATIVE_COMPILER_PLAN.md`:
- Around line 137-141: Reconcile the nested-list status between the completed
“3-List” entry and the deferred note around nested slices. Since the entry
claims List[List[int]] support, update the deferred note to remove or qualify
nested slices accordingly, or narrow the completion claim if nested lists remain
unsupported.

In `@runtime/mako_std.h`:
- Around line 4217-4222: Update mako_gqlx_qws to skip GraphQL comments from '#'
through the next newline, in addition to existing whitespace and commas. Ensure
mako_gqlx_qbalance handles comments encountered inside balanced argument blocks,
reusing the same comment-skipping behavior so comments work before operations,
fields, selections, and arguments. Add a regression test covering these comment
positions.

---

Outside diff comments:
In `@src/native_ir.rs`:
- Around line 15496-15500: Remove the stale doc comment immediately before
drop_owned_locals, since it documents the deleted field_base_same_local helper
rather than drop_owned_locals. Leave the function implementation unchanged.

---

Nitpick comments:
In `@src/native_ir.rs`:
- Around line 1478-1482: Remove the obsolete scalar-only List[T] match arm from
scalar_type, since resolve_type now handles every one-parameter List generic by
converting it to an Array before the scalar_type fallback. Preserve
scalar_type’s remaining scalar resolution behavior and let unsupported cases
continue through its existing fallback.
- Around line 3846-3905: Add IR-level regression tests for the field-assignment
paths in the existing native IR test module, mirroring
drops_borrowed_slice_headers_and_clones_escaping_views and
clones_and_drops_int_slice_struct_fields. Cover self.xs = self.xs[a:b] by
asserting SliceClone occurs before DropSlice for the temporary view, and cover
self.xs = append(self.xs, v) by asserting the old field receives a DropSlice
after the append assignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 135881cb-0f5f-4424-95dc-fce97d8aac5c

📥 Commits

Reviewing files that changed from the base of the PR and between d267bb6 and b6a3795.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • CHANGELOG.md
  • Cargo.toml
  • README.md
  • docs/ADAPTIVE_OPT.md
  • docs/LONG_RUNNING.md
  • docs/MESSAGING_GRAPHQL.md
  • docs/NATIVE_COMPILER_PLAN.md
  • docs/PERFORMANCE.md
  • docs/ROADMAP.md
  • docs/SPEED_SAFE.md
  • docs/STATUS.md
  • docs/VERSIONING.md
  • examples/testing/graphql_exec_test.mko
  • examples/testing/hot_site_test.mko
  • examples/testing/native_list_generic_test.mko
  • runtime/mako_std.h
  • scripts/adaptive-opt-cycle.sh
  • scripts/anneal-cycle.sh
  • src/codegen/mod.rs
  • src/native_ir.rs

Comment thread docs/ADAPTIVE_OPT.md
binary, let it tell you (cheaply) which paths actually run hot in production,
then fold that knowledge into the *next* build and swap it in. The process never
patches itself; the next artifact is simply better shaped for the work it's
doing. Available in **0.4.15+**.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Align the availability claim with the documented release timeline.

This says 0.4.15+, while the roadmap places hot-site/offline-PGO support in 0.4.14 and the Anneal naming in 0.4.16. Distinguish capability availability from the new name.

Proposed wording
- doing. Available in **0.4.15+**.
+ doing. Hot-site/PGO support is available in **0.4.14+**; the Anneal name
+ arrives in **0.4.16**.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
doing. Available in **0.4.15+**.
doing. Hot-site/PGO support is available in **0.4.14+**; the Anneal name
arrives in **0.4.16**.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ADAPTIVE_OPT.md` at line 26, Update the availability statement in
ADAPTIVE_OPT to distinguish hot-site/offline-PGO capability availability in
0.4.14 from the Anneal naming introduced in 0.4.16, rather than claiming all
functionality starts in 0.4.15.

Comment on lines +137 to +141
- *3-List [done]* — `List[T]` is a transparent alias for `[]T` and lowers for
**any** element type (structs, nested `List[List[int]]`, strings, pointer
arrays), reusing the full slice support instead of the scalar-only set.
Fixture `examples/testing/native_list_generic_test.mko`, differentially
valid vs the C backend.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reconcile the nested-list support status.

This entry marks List[List[int]] as supported, but Line 184 still says nested slices are deferred. Since List[T] is a transparent alias for []T, update the deferred note or narrow this completion claim.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/NATIVE_COMPILER_PLAN.md` around lines 137 - 141, Reconcile the
nested-list status between the completed “3-List” entry and the deferred note
around nested slices. Since the entry claims List[List[int]] support, update the
deferred note to remove or qualify nested slices accordingly, or narrow the
completion claim if nested lists remain unsupported.

Comment thread runtime/mako_std.h
Comment on lines +4217 to +4222
static size_t mako_gqlx_qws(MakoString q, size_t i) {
while (i < q.len && (q.data[i] == ' ' || q.data[i] == '\t' || q.data[i] == '\n'
|| q.data[i] == '\r' || q.data[i] == ','))
i++;
return i;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP '#' --type-add 'mko:*.mko' -t mko examples/testing/graphql_exec_test.mko | rg -n '#' | head -50
fd -e mko . examples/testing | xargs rg -nl 'query|mutation' 2>/dev/null

Repository: loreste/mako

Length of output: 828


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '## files of interest\n'
git ls-files | rg '(^|/)runtime/mako_std\.h$|graphql(_exec|_http)?test\.mk|graphql' | head -120

printf '\n## qws/qbalance/lexical helpers around runtime/mako_std.h:4180-4260\n'
sed -n '4180,4260p' runtime/mako_std.h | nl -ba -v4180

printf '\n## mako_gqlx_qws usages and scanner loop context\n'
rg -n 'mako_gqlx_qws|mako_gqlx_id0|mako_gqlx_qbalance|mako_gqlx_qid|qbalance|qws' runtime/mako_std.h

Repository: loreste/mako

Length of output: 583


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '## qws/qbalance/tokenizer helpers in runtime/mako_std.h\n'
sed -n '4180,4260p' runtime/mako_std.h | sed -n '=' | xargs -I{} sh -c 'echo "---- lines {} ----"; sed -n "{ {}, {}+35p" runtime/mako_std.h | cat -n'

printf '\n## relevant tests containing GraphQL with # comments\n'
for f in examples/testing/graphql_exec_test.mko examples/testing/graphql_http_test.mko examples/testing/graphql_seed_test.mko examples/testing/lang_queue_graphql_test.mko std/graphql/graphql.mko std/graphql/schema.mko; do
  [ -f "$f" ] || continue
  printf '\n### %s\n' "$f"
  rg -n '^#|[0-9]+:#|query|mutation|query\s*\(|mutation\s*\(' "$f" | head -40 || true
done

printf '\n## all # comments in GraphQL-related files\n'
rg -n '^#|[0-9]+:#' examples/testing/graphql_exec_test.mko examples/testing/graphql_http_test.mko examples/testing/graphql_seed_test.mko examples/testing/lang_queue_graphql_test.mko std/graphql/graphql.mko std/graphql/schema.mko || true

Repository: loreste/mako

Length of output: 9000


🏁 Script executed:

#!/bin/bash
set -euo pipefail

P='runtime/mako_std.h'
printf '%s\n' 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 > /tmp/lines.txt
while read -r L; do
  sed -n "${L}p" "$P" | cat -n
done < /tmp/lines.txt

printf '\n## mako_gqlx functions and qws usage\n'
rg -n 'mako_gqlx_qws|mako_gqlx_id0|mako_gqlx_qbalance|mako_gqlx_qid|qbalance|qws' runtime/mako_std.h

printf '\n## read-only behavioral probe: current qws on comment-containing inputs\n'
python3 - <<'PY'
def qws(q, i):
    while i < len(q) and q[i] in (' ', '\t', '\n', '\r', ','):
        i += 1
    return i

cases = [
    ' { name }',
    ' # comment\n { name }',
    ' { id # comment\n  name }',
    ' { id\nname }',
]
for q in cases:
    print(repr(q), 'current qws=# ->', qws(q, 0), 'expected qws=# ->', qws(q,0), 'with comment handling ->', 0))
PY

Repository: loreste/mako

Length of output: 6476


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '4220,4236p' runtime/mako_std.h | cat -n
sed -n '4228,4248p' runtime/mako_std.h | cat -n
rg -n 'mako_gqlx_qbalance|MakoString|static size_t mako_gqlx_qws' runtime/mako_std.h | head -80

printf '\n## deterministic tokenizer probe from source semantics\n'
python3 - <<'PY'
def qws(q, i):
    while i < len(q) and q[i] in (' ', '\t', '\n', '\r', ','):
        i += 1
    return i

def qws_comment(q, i):
    while i < len(q):
        c = q[i]
        if c in (' ', '\t', '\n', '\r', ','):
            i += 1
        elif c == '#':
            while i < len(q) and q[i] != '\n':
                i += 1
        else:
            break
    return i

cases = [
    'query user { name }',
    '# comment\nquery user { name }',
    'query # comment\n user { name }',
    'query user{ # comment\nname }',
    'query(user: 1) # comment\n { name }',
]
for q in cases:
    print(q)
    i = qws(q, 0)
    print('  current_next=', repr(q[i:i+30]), 'qws_qws=', repr(q[qws(q, i+len(q.split()[0]+(' ' if (i + len(q.split()[0]+(' ')) < len(q)) else '') else ('')) for _ in range(0): None]))
PY

Repository: loreste/mako

Length of output: 7046


Skip # comments in the GraphQL lexer.

GraphQL treats # through the end of the line as insignificant to both lexing and parsing, and mako_gqlx_qws currently skips only space/tab/newline/carriage-return/comma. Queries with comments before operation names, fields, selected fields, or arguments are therefore misparsed. Skip #\n here; mako_gqlx_id0 does not accept #, so argument parsing through mako_gqlx_qbalance also needs comment handling inside balanced (...) blocks. Add a GraphQL comment test so regressions are caught.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@runtime/mako_std.h` around lines 4217 - 4222, Update mako_gqlx_qws to skip
GraphQL comments from '#' through the next newline, in addition to existing
whitespace and commas. Ensure mako_gqlx_qbalance handles comments encountered
inside balanced argument blocks, reusing the same comment-skipping behavior so
comments work before operations, fields, selections, and arguments. Add a
regression test covering these comment positions.

@attahn

attahn commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review verdict: not mergeable yet. The native ownership and List[T] work looks solid, but the GraphQL executor has two schema-boundary bypasses.

Critical

  1. Undeclared fields can be returned from resolver data (runtime/mako_std.h:4700-4731). Root resolution accepts any registered resolver even if the field is absent from Query. Nested resolution reads a JSON property first and ignores a failed schema lookup when that property exists. A resolver named undeclared is therefore queryable without a schema field, and { user { secret } } returns secret whenever it exists in the resolver JSON even if User does not declare it. Validate the field against cur_type before looking up either the resolver or JSON property.

  2. Object fields can bypass projection entirely (runtime/mako_std.h:4735-4777). { user } returns the complete raw resolver object, including unrequested properties. Conversely, { health { anything } } accepts a sub-selection on a scalar. Object/list fields must require a selection set, and scalar fields must reject one. This likely requires retaining field-kind/wrapper information instead of reducing return types to a stripped base name.

Important

  • Named fragment type conditions are ignored (runtime/mako_std.h:4578). Inline fragments check on Type; named fragments are expanded unconditionally. Return the fragment condition from mako_gqlx_find_fragment and apply the same check.
  • Introspection reports every field type as kind: OBJECT (runtime/mako_std.h:4441-4463). Scalars need SCALAR; lists and non-null types need their wrappers preserved. Normal GraphQL tooling will receive incorrect type information.
  • Standard GraphQL # comments are not skipped by the scanner. CodeRabbit also flagged this; comments need handling in whitespace and balanced-block scanning.
  • Error requests still leak internally (runtime/mako_std.h:3110, 4785-4790). mako_graphql_error does not free the escaped message, and these early paths also allocate messages with mako_str_from_cstr without reclaiming them. Add an invalid-query LSan loop before calling the resolve path leak-free.

Cleanup and coverage

  • Remove the stale field_base_same_local doc comment now attached to drop_owned_locals.
  • Reconcile List[List[int]] being marked complete while nested slices remain documented as deferred.
  • Correct the Anneal availability/version wording.
  • Parse and assert exact GraphQL JSON in tests; substring assertions cannot detect malformed JSON or duplicate keys.
  • Add adversarial cases for undeclared root/nested fields, object-without-selection, scalar-with-selection, mismatched named fragments, comments, and introspection kinds.
  • Mention the included slice-field UAF/leak fix in the PR description because it is a separate substantive change.

Verification

  • cargo test --bin mako: 126 passed.
  • ASan, UBSan, TSan, GCC, cross-compile, LLVM, native macOS memory safety, benchmark, and claims gates were green when reviewed; the three native platform jobs were still running.
  • The native slice-field and List[T] changes look logically sound. The blockers are in GraphQL schema enforcement and selection validation.

A string/slice/map returned from a user-defined function and bound to a
local was never freed when dropped (one allocation leaked per call — a
per-request leak in long-running servers). Recognize such call results as
owned producers in scope-drop cleanup so they free at scope exit; move
analysis still suppresses the drop on return/pass-on/store. Enums are
excluded (match consumes them — an unconditional free double-frees) and
structs are excluded (field-by-field frees).

Verified on Linux: full suite green under AddressSanitizer (no
double-free/UAF), leak eliminated for []int / string / List[Struct]
returns, generic-enum tests still pass. New owned_return_drop_test.mko.
@loreste
loreste merged commit c1bdbdb into main Jul 24, 2026
14 checks passed
@loreste
loreste deleted the feat/graphql-executor-native-list-0416 branch July 24, 2026 15:26
loreste added a commit that referenced this pull request Jul 25, 2026
…-0416

Real GraphQL executor, native List[T], Anneal; 0.4.16
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.

3 participants