Skip to content

Commit 7bc8f19

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-12829-human-s-hours
2 parents dd57803 + 944d798 commit 7bc8f19

8 files changed

Lines changed: 169 additions & 117 deletions

File tree

examples/app-showcase/test/inert-wirings.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
import { readdirSync, readFileSync } from 'node:fs';
44
import { describe, it, expect } from 'vitest';
5+
// The repo's ONE answer to "is this span a comment, or code?". The naive block
6+
// regex this replaces had no idea what a string literal is: it opened a phantom
7+
// comment at a block-comment opener sitting INSIDE a string and ran to the next
8+
// terminator far below, deleting live code on 5 of this app's 91 sources.
9+
// `stripComments` (not `maskComments`) is the projection this file wants -- the
10+
// one guard below reports bare file paths, never a line or an offset. The
11+
// `.mjs` specifier is deliberate; `scripts/js-comment-mask.d.mts` beside it is a
12+
// hand-written declaration, so this import needs no `allowJs`.
13+
import { stripComments } from '../../../scripts/js-comment-mask.mjs';
514
import stack from '../objectstack.config.js';
615
import { PLATFORM_CAPABILITY_NAMES } from '@objectstack/spec/security';
716
import { FILE_REFERENCE_TYPES, valueSchemaFor } from '@objectstack/spec/data';
@@ -44,15 +53,10 @@ function sourceFiles(dir: string = SRC_ROOT): string[] {
4453
* Source text with comments removed, so a source-scan guard judges CODE.
4554
* Documentation must stay free to name a retired key (this file's own comments
4655
* do, and so do the ones explaining the rename) without tripping the guard that
47-
* bans authoring it. Block comments go first; then whole-line `//` comments —
48-
* never a trailing `//`, which would eat the `//` in a URL inside a string.
56+
* bans authoring it.
4957
*/
5058
function codeOf(file: string): string {
51-
return readFileSync(file, 'utf8')
52-
.replace(/\/\*[\s\S]*?\*\//g, '')
53-
.split('\n')
54-
.filter((line: string) => !line.trimStart().startsWith('//'))
55-
.join('\n');
59+
return stripComments(readFileSync(file, 'utf8'));
5660
}
5761

5862
/** Every `functions` entry, whichever spelling it was authored in. */

packages/cli/src/utils/console-route-ledger.conformance.test.ts

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ import { readdirSync, readFileSync, statSync } from 'node:fs';
2424
import { dirname, join, relative, sep } from 'node:path';
2525
import { fileURLToPath } from 'node:url';
2626
import { describe, it, expect } from 'vitest';
27+
// The repo's ONE answer to "is this span a comment, or code?" — its header
28+
// carries the two private-stripper families that drifted apart and the
29+
// parser-differential sweep that measured which way each fails. The private
30+
// scanner this replaces was string-aware but REGEX-BLIND: the doubled slash
31+
// closing `/^https?:\/\//i` read as a line-comment opener and took the rest of
32+
// the line with it, which is the same defect #12398 found live in two sibling
33+
// guards. `stripComments` (not `maskComments`) is the projection this file
34+
// wants: it deletes comment characters but keeps every newline, so the
35+
// `file:line` every finding here reports still points at the real line, and
36+
// nothing in this file reports an offset. The `.mjs` specifier is deliberate;
37+
// `scripts/js-comment-mask.d.mts` beside it is a hand-written declaration, so
38+
// this import needs no `allowJs`.
39+
import { stripComments } from '../../../../scripts/js-comment-mask.mjs';
2740
import { CONSOLE_ROUTE_LEDGER } from './console-route-ledger.js';
2841

2942
/**
@@ -59,49 +72,6 @@ const NON_ROUTE_MEMBERS = new Set(['use', 'notFound', 'onError', 'fire', 'fetch'
5972
// Scanning machinery
6073
// ---------------------------------------------------------------------------
6174

62-
/**
63-
* Strip comments before scanning, PRESERVING newlines inside block comments so
64-
* every finding's `file:line` points at the real line — `console.ts` opens with
65-
* a 35-line header, and reporting a mount 35 lines short makes an accurate
66-
* finding read as a wrong one.
67-
*/
68-
export function stripComments(source: string): string {
69-
let out = '';
70-
let i = 0;
71-
while (i < source.length) {
72-
const c = source[i];
73-
const next = source[i + 1];
74-
if (c === '/' && next === '/') {
75-
while (i < source.length && source[i] !== '\n') i++;
76-
continue;
77-
}
78-
if (c === '/' && next === '*') {
79-
i += 2;
80-
while (i < source.length && !(source[i] === '*' && source[i + 1] === '/')) {
81-
if (source[i] === '\n') out += '\n';
82-
i++;
83-
}
84-
i += 2;
85-
continue;
86-
}
87-
if (c === '\'' || c === '"' || c === '`') {
88-
const quote = c;
89-
out += c;
90-
i++;
91-
while (i < source.length) {
92-
if (source[i] === '\\') { out += source.slice(i, i + 2); i += 2; continue; }
93-
out += source[i];
94-
if (source[i] === quote) { i++; break; }
95-
i++;
96-
}
97-
continue;
98-
}
99-
out += c;
100-
i++;
101-
}
102-
return out;
103-
}
104-
10575
/** Module-scope `const NAME = '<literal>';` bindings, exported or not. */
10676
export function constantBindings(code: string): Map<string, string> {
10777
const out = new Map<string, string>();
@@ -380,13 +350,29 @@ describe('cli console route ledger hygiene', () => {
380350
});
381351

382352
describe('scan machinery, pinned in both directions', () => {
383-
it('the comment stripper drops prose paths, keeps code paths, and preserves line numbers', () => {
353+
it('the shared stripper drops prose paths, keeps code paths, and preserves line numbers', () => {
354+
// Not a re-pin of `js-comment-mask.mjs` -- that module pins its own
355+
// behaviour. This pins the PROPERTY this census rests on: comment
356+
// characters go, every newline stays, so `lineOf()` below still counts
357+
// the real line.
384358
const stripped = stripComments("// app.get('/ghost', h)\n/* a\nb */\napp.get(`/real`, h);\n");
385359
expect(stripped).not.toContain('ghost');
386360
expect(stripped).toContain('/real');
387361
expect(censusOf(['f.ts'], () => "/* a\nb\nc */\napp.get('/x', h);\n").routes[0].line).toBe(4);
388362
});
389363

364+
it('a doubled slash inside a REGEX LITERAL does not swallow the rest of its line', () => {
365+
// The defect the private scanner this file used to carry was measured
366+
// committing on 7 of this package's 110 sources: string-aware but
367+
// regex-blind, it read the `//` that CLOSES `/^https?:\/\//i` as a
368+
// line-comment opener and deleted to end of line. A mount sharing that
369+
// line went with it, and the census reported clean over text it never
370+
// read. Live in `commands/dev.ts`, `commands/serve.ts` and
371+
// `commands/start.ts` at conversion time.
372+
const stripped = stripComments("const ok = /^https?:\\/\\//i.test(u); app.get('/real', h);\n");
373+
expect(stripped).toContain('/real');
374+
});
375+
390376
it('resolves the spellings this package uses, and refuses the rest', () => {
391377
const b = constantBindings("export const CONSOLE_PATH = '/_console';\n");
392378
expect(b.get('CONSOLE_PATH')).toBe('/_console');

packages/drivers/driver-sql/src/live-dialect-matrix.isolation.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ import { readFileSync, readdirSync } from 'node:fs';
4343
import { SqlDriver } from '../src/index.js';
4444
import { dirname, join } from 'node:path';
4545
import { fileURLToPath } from 'node:url';
46+
// The repo's ONE answer to "is this span a comment, or code?". The naive block
47+
// regex this replaces had no idea what a string literal is: in
48+
// `logger-receiver-detach.test.ts` a fixture STRING quotes a docblock and the
49+
// sweep ate the string. `stripComments` (not `maskComments`) is the projection
50+
// this file wants -- the guard below reports bare file names, never a line or
51+
// an offset. The `.mjs` specifier is deliberate; `scripts/js-comment-mask.d.mts`
52+
// beside it is a hand-written declaration, so this import needs no `allowJs`.
53+
import { stripComments } from '../../../../scripts/js-comment-mask.mjs';
4654
import {
4755
LIVE_SCHEMA_PREFIX,
4856
MYSQL_CELL,
@@ -127,11 +135,9 @@ describe('live-dialect matrix — per-file schema isolation (#9350)', () => {
127135
});
128136

129137
describe('live-dialect matrix — the cell is the only route to a live server (#9350)', () => {
130-
/** Source with line and block comments removed, so prose about the env var is not a hit. */
138+
/** Source with comments removed, so prose about the env var is not a hit. */
131139
const codeOf = (file: string): string =>
132-
readFileSync(join(SRC_DIR, file), 'utf8')
133-
.replace(/\/\*[\s\S]*?\*\//g, '')
134-
.replace(/^[ \t]*\/\/.*$/gm, '');
140+
stripComments(readFileSync(join(SRC_DIR, file), 'utf8'));
135141

136142
/**
137143
* The needle is ASSEMBLED rather than written as a literal.

packages/plugins/plugin-auth/src/rate-limit-storage-isolation.test.ts

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@
4242
import { describe, it, expect } from 'vitest';
4343
import { readFileSync, existsSync, readdirSync } from 'node:fs';
4444
import { dirname, join, relative, resolve } from 'node:path';
45+
// The repo's ONE answer to "is this span a comment, or code?". The private
46+
// scanner this replaces tracked the three string forms but was REGEX-BLIND, so
47+
// the doubled slash closing a literal like `/^https?:\/\//i` read as a
48+
// line-comment opener and took the rest of the line -- `auth-manager.ts` in this
49+
// very package was losing that line. `stripComments` (not `maskComments`) is the
50+
// projection this file wants: every finding reports a package-relative FILE PATH
51+
// and a specifier, never a line or an offset into the original. The `.mjs`
52+
// specifier is deliberate; `scripts/js-comment-mask.d.mts` beside it is a
53+
// hand-written declaration, so this import needs no `allowJs`.
54+
import { stripComments } from '../../../../scripts/js-comment-mask.mjs';
4555

4656
/**
4757
* Seeded from `__dirname`, not from a `findUp` walk of `process.cwd()`, and not
@@ -109,51 +119,6 @@ const SRC = HERE;
109119
const RUNTIME_SRC = resolve(REPO, 'packages/runtime/src');
110120
const SERVICE_SMS_SRC = resolve(REPO, 'packages/services/service-sms/src');
111121

112-
/**
113-
* Strip comments before scanning. The distinction this file turns on — a
114-
* `import type` versus a value `import` of the same specifier — is invisible to
115-
* a raw-text regex the moment a doc comment quotes an import line, and this
116-
* module's own header quotes several. Handles `//`, block comments and the
117-
* three string forms so a `'http://…'` literal is not mistaken for a comment.
118-
*/
119-
function stripComments(src: string): string {
120-
let out = '';
121-
let i = 0;
122-
while (i < src.length) {
123-
const c = src[i]!;
124-
const next = src[i + 1];
125-
if (c === '/' && next === '/') {
126-
while (i < src.length && src[i] !== '\n') i++;
127-
continue;
128-
}
129-
if (c === '/' && next === '*') {
130-
i += 2;
131-
while (i < src.length && !(src[i] === '*' && src[i + 1] === '/')) i++;
132-
i += 2;
133-
continue;
134-
}
135-
if (c === "'" || c === '"' || c === '`') {
136-
out += c;
137-
i++;
138-
while (i < src.length && src[i] !== c) {
139-
if (src[i] === '\\') {
140-
out += src[i]! + (src[i + 1] ?? '');
141-
i += 2;
142-
continue;
143-
}
144-
out += src[i];
145-
i++;
146-
}
147-
out += c;
148-
i++;
149-
continue;
150-
}
151-
out += c;
152-
i++;
153-
}
154-
return out;
155-
}
156-
157122
interface Ref {
158123
spec: string;
159124
/** `import type … from` / `export type … from` — erased at build, costs nothing at runtime. */

packages/runtime/src/error-envelope.conformance.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@
2727

2828
import { describe, it, expect, vi } from 'vitest';
2929
import { readFileSync } from 'node:fs';
30+
// The repo's ONE answer to "is this span a comment, or code?". The naive pair
31+
// this replaces had an UNANCHORED trailing arm, so a doubled slash anywhere on a
32+
// line opened a phantom comment and the rest of the line went -- measured
33+
// eating route paths inside template literals in `dispatcher-plugin.ts` and an
34+
// https URL that `domains/mcp.ts` builds. `stripComments` (not `maskComments`)
35+
// is the projection these guards want: they report match counts and matched
36+
// text, never a line or an offset. The `.mjs` specifier is deliberate;
37+
// `scripts/js-comment-mask.d.mts` beside it is a hand-written declaration, so
38+
// this import needs no `allowJs`.
39+
import { stripComments } from '../../../scripts/js-comment-mask.mjs';
3040
import {
3141
ApiErrorSchema,
3242
BaseResponseSchema,
@@ -455,9 +465,7 @@ describe('#3842 — no dispatcher module may reintroduce the drift', () => {
455465
// Comments stripped first: these modules' own prose quotes the old shape,
456466
// and a doc comment is not a code path.
457467
const read = (file: string) =>
458-
readFileSync(new URL(file, import.meta.url), 'utf8')
459-
.replace(/\/\*[\s\S]*?\*\//g, '')
460-
.replace(/\/\/[^\n]*/g, '');
468+
stripComments(readFileSync(new URL(file, import.meta.url), 'utf8'));
461469

462470
/** Every module that can put a body on this wire surface. */
463471
const MODULES = [

0 commit comments

Comments
 (0)