Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions examples/app-showcase/test/inert-wirings.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,15 @@

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

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

/**
Expand DownExpand Up@@ -59,49 +72,6 @@ const NON_ROUTE_MEMBERS = new Set(['use', 'notFound', 'onError', 'fire', 'fetch'
// Scanning machinery
// ---------------------------------------------------------------------------

/**
* Strip comments before scanning, PRESERVING newlines inside block comments so
* every finding's `file:line` points at the real line — `console.ts` opens with
* a 35-line header, and reporting a mount 35 lines short makes an accurate
* finding read as a wrong one.
*/
export function stripComments(source: string): string {
let out = '';
let i = 0;
while (i < source.length) {
const c = source[i];
const next = source[i + 1];
if (c === '/' && next === '/') {
while (i < source.length && source[i] !== '\n') i++;
continue;
}
if (c === '/' && next === '*') {
i += 2;
while (i < source.length && !(source[i] === '*' && source[i + 1] === '/')) {
if (source[i] === '\n') out += '\n';
i++;
}
i += 2;
continue;
}
if (c === '\'' || c === '"' || c === '`') {
const quote = c;
out += c;
i++;
while (i < source.length) {
if (source[i] === '\\') { out += source.slice(i, i + 2); i += 2; continue; }
out += source[i];
if (source[i] === quote) { i++; break; }
i++;
}
continue;
}
out += c;
i++;
}
return out;
}

/** Module-scope `const NAME = '<literal>';` bindings, exported or not. */
export function constantBindings(code: string): Map<string, string> {
const out = new Map<string, string>();
Expand DownExpand Up@@ -380,13 +350,29 @@ describe('cli console route ledger hygiene', () => {
});

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

it('a doubled slash inside a REGEX LITERAL does not swallow the rest of its line', () => {
// The defect the private scanner this file used to carry was measured
// committing on 7 of this package's 110 sources: string-aware but
// regex-blind, it read the `//` that CLOSES `/^https?:\/\//i` as a
// line-comment opener and deleted to end of line. A mount sharing that
// line went with it, and the census reported clean over text it never
// read. Live in `commands/dev.ts`, `commands/serve.ts` and
// `commands/start.ts` at conversion time.
const stripped = stripComments("const ok = /^https?:\\/\\//i.test(u); app.get('/real', h);\n");
expect(stripped).toContain('/real');
});

it('resolves the spellings this package uses, and refuses the rest', () => {
const b = constantBindings("export const CONSOLE_PATH = '/_console';\n");
expect(b.get('CONSOLE_PATH')).toBe('/_console');
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,14 @@ import { readFileSync, readdirSync } from 'node:fs';
import { SqlDriver } from '../src/index.js';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
// The repo's ONE answer to "is this span a comment, or code?". The naive block
// regex this replaces had no idea what a string literal is: in
// `logger-receiver-detach.test.ts` a fixture STRING quotes a docblock and the
// sweep ate the string. `stripComments` (not `maskComments`) is the projection
// this file wants -- the guard below reports bare file names, never a line or
// an offset. The `.mjs` specifier is deliberate; `scripts/js-comment-mask.d.mts`
// beside it is a hand-written declaration, so this import needs no `allowJs`.
import { stripComments } from '../../../../scripts/js-comment-mask.mjs';
import {
LIVE_SCHEMA_PREFIX,
MYSQL_CELL,
Expand DownExpand Up@@ -127,11 +135,9 @@ describe('live-dialect matrix — per-file schema isolation (#9350)', () => {
});

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

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

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

/**
* Strip comments before scanning. The distinction this file turns on — a
* `import type` versus a value `import` of the same specifier — is invisible to
* a raw-text regex the moment a doc comment quotes an import line, and this
* module's own header quotes several. Handles `//`, block comments and the
* three string forms so a `'http://…'` literal is not mistaken for a comment.
*/
function stripComments(src: string): string {
let out = '';
let i = 0;
while (i < src.length) {
const c = src[i]!;
const next = src[i + 1];
if (c === '/' && next === '/') {
while (i < src.length && src[i] !== '\n') i++;
continue;
}
if (c === '/' && next === '*') {
i += 2;
while (i < src.length && !(src[i] === '*' && src[i + 1] === '/')) i++;
i += 2;
continue;
}
if (c === "'" || c === '"' || c === '`') {
out += c;
i++;
while (i < src.length && src[i] !== c) {
if (src[i] === '\\') {
out += src[i]! + (src[i + 1] ?? '');
i += 2;
continue;
}
out += src[i];
i++;
}
out += c;
i++;
continue;
}
out += c;
i++;
}
return out;
}

interface Ref {
spec: string;
/** `import type … from` / `export type … from` — erased at build, costs nothing at runtime. */
Expand Down
14 changes: 11 additions & 3 deletions packages/runtime/src/error-envelope.conformance.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,16 @@

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

/** Every module that can put a body on this wire surface. */
const MODULES = [
Expand Down
Loading
Loading