@hyperfixi/testing-framework 4.0.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -376,8 +376,15 @@ export async function initDirectPathHosts(): Promise<DirectPathHosts> {
376
376
  for (const steps of scriptOf(c)) parts.push(await run(host, c, code, lang, steps));
377
377
  return parts.join(' ‖ ');
378
378
  };
379
- const rejects = (host: ScriptHost, code: string): string | undefined =>
380
- host.parse(code)?.errors?.[0]?.message.split('\n')[0];
379
+ // Two failure channels: parse errors, and the tokenizer THROWING on a
380
+ // character it does not know (the text a refused translation leaves as written).
381
+ const rejects = (host: ScriptHost, code: string): string | undefined => {
382
+ try {
383
+ return host.parse(code)?.errors?.[0]?.message.split('\n')[0];
384
+ } catch (e) {
385
+ return (e as Error).message.split('\n')[0] ?? 'threw';
386
+ }
387
+ };
381
388
 
382
389
  return {
383
390
  async runCase(c) {
@@ -4,7 +4,7 @@
4
4
  * leaves out; the matrix shards run the names themselves.
5
5
  */
6
6
  import { describe, it, expect } from 'vitest';
7
- import { collidingNames, generateCells } from './value-matrix';
7
+ import { KEYWORD_NAMES, collidingNames, generateCells } from './value-matrix';
8
8
 
9
9
  const names = new Map(collidingNames().map(entry => [entry.name, entry]));
10
10
 
@@ -29,6 +29,16 @@ describe('value matrix: colliding names', () => {
29
29
  expect(names.has('an')).toBe(true);
30
30
  });
31
31
 
32
+ // Upstream runs each as a variable; English's own parse dropped `set input
33
+ // to "a"`, and every language wrote `when` as its keyword (P49).
34
+ it('takes the English words upstream runs as variables (KEYWORD_NAMES)', () => {
35
+ for (const name of KEYWORD_NAMES) expect(names.has(name), name).toBe(true);
36
+ expect(KEYWORD_NAMES).toContain('input'); // an event name
37
+ expect(KEYWORD_NAMES).toContain('when'); // a structure word
38
+ expect(KEYWORD_NAMES).toContain('index'); // a value-lexicon word (P28)
39
+ expect(names.has('if')).toBe(false); // P53
40
+ });
41
+
32
42
  it("leaves out upstream's `no` and the templates' variables", () => {
33
43
  expect(names.has('no')).toBe(false);
34
44
  expect(names.has('i')).toBe(false);
@@ -550,6 +550,30 @@ let collidingNamesMemo: readonly CollidingName[] | undefined;
550
550
  */
551
551
  const CODE_NAMES: readonly string[] = ['userData'];
552
552
 
553
+ /**
554
+ * Names spelled like English vocabulary that upstream and the engine run as
555
+ * variables where a value stands: event names, which every tokenizer reads as
556
+ * an event (`set input to "a"` dropped from English's own parse), structure
557
+ * words (`when`, which every language wrote as its keyword), and words of the
558
+ * value lexicon (`index`, which bn and four others wrote natively) — P49, P28.
559
+ * Not a name the window already holds (`focus`, `length`), nor `then`: the
560
+ * fixture sets each name there, and a `then` on the window makes upstream
561
+ * take it for a promise. Not yet `if` or `end`, which open and close a block
562
+ * in every language's reader (OPEN_ITEMS P53: 93 and 505 failing pairs).
563
+ */
564
+ export const KEYWORD_NAMES: readonly string[] = [
565
+ 'click',
566
+ 'input',
567
+ 'change',
568
+ 'keyup',
569
+ 'submit',
570
+ 'load',
571
+ 'drop',
572
+ 'when',
573
+ 'index',
574
+ 'value',
575
+ ];
576
+
553
577
  /**
554
578
  * Variables spelled like a structure word of a language the matrix translates
555
579
  * into: every one- or two-letter name semantic's `nameCollision` finds
@@ -580,14 +604,15 @@ export function collidingNames(): readonly CollidingName[] {
580
604
  const tokens = tokenize(word, 'en').tokens;
581
605
  return tokens.length === 1 && tokens[0]?.kind !== 'identifier';
582
606
  };
583
- collidingNamesMemo = candidates
584
- .filter(word => !reserved.has(word) && !englishKeyword(word))
607
+ collidingNamesMemo = [...new Set([...candidates, ...KEYWORD_NAMES])]
608
+ .filter(word => !reserved.has(word) && (KEYWORD_NAMES.includes(word) || !englishKeyword(word)))
585
609
  .flatMap(name => {
586
610
  const readings = FOREIGN_LANGUAGES.map(language => ({
587
611
  language,
588
612
  collision: nameCollision(name, language),
589
613
  }));
590
- if (!readings.some(reading => reading.collision === 'structure')) return [];
614
+ const structure = readings.some(reading => reading.collision === 'structure');
615
+ if (!structure && !KEYWORD_NAMES.includes(name)) return [];
591
616
  const pronounIn = readings.filter(r => r.collision === 'pronoun').map(r => r.language);
592
617
  return [{ name, pronounIn }];
593
618
  });