tjs-lang 0.6.19 → 0.6.26
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.
- package/CLAUDE.md +29 -24
- package/bin/dev.ts +9 -0
- package/demo/docs.json +49 -1
- package/demo/src/playground-shared.ts +8 -39
- package/demo/src/tjs-playground.ts +8 -0
- package/demo/src/tjs-runtime-iframe.ts +10 -0
- package/demo/src/ts-playground.ts +8 -0
- package/package.json +1 -1
- package/src/cli/commands/run.ts +4 -1
- package/src/cli/tjs.ts +1 -1
- package/src/lang/codegen.test.ts +26 -27
- package/src/lang/emitters/dts.test.ts +22 -0
- package/src/lang/emitters/dts.ts +5 -1
- package/src/lang/emitters/js-tests.ts +13 -19
- package/src/lang/emitters/js.ts +39 -7
- package/src/lang/parser-transforms.ts +18 -5
- package/src/lang/roundtrip.test.ts +1 -1
- package/src/lang/runtime.ts +88 -2
- package/src/lang/wasm.ts +1 -1
- package/dist/bin/benchmarks.d.ts +0 -9
- package/dist/bin/dev.d.ts +0 -1
- package/dist/bin/docs.d.ts +0 -1
- package/dist/bin/select-local-models.d.ts +0 -1
- package/dist/examples/modules/dist/main.d.ts +0 -34
- package/dist/examples/modules/dist/math.d.ts +0 -120
- package/dist/index.js +0 -426
- package/dist/index.js.map +0 -45
- package/dist/scripts/build-demo.d.ts +0 -2
- package/dist/scripts/build.d.ts +0 -11
- package/dist/scripts/seed-blog-rules.d.ts +0 -2
- package/dist/scripts/seed-stored-function.d.ts +0 -2
- package/dist/src/atoms/batteries.d.ts +0 -4
- package/dist/src/atoms/browser.d.ts +0 -4
- package/dist/src/atoms/index.d.ts +0 -4
- package/dist/src/batteries/audit.d.ts +0 -9
- package/dist/src/batteries/index.d.ts +0 -28
- package/dist/src/batteries/llm.d.ts +0 -18
- package/dist/src/batteries/models.d.ts +0 -19
- package/dist/src/batteries/store.d.ts +0 -13
- package/dist/src/builder.d.ts +0 -127
- package/dist/src/bun-plugin/tjs-plugin.d.ts +0 -12
- package/dist/src/cli/commands/check.d.ts +0 -4
- package/dist/src/cli/commands/convert.d.ts +0 -20
- package/dist/src/cli/commands/emit.d.ts +0 -34
- package/dist/src/cli/commands/run.d.ts +0 -6
- package/dist/src/cli/commands/test.d.ts +0 -21
- package/dist/src/cli/commands/types.d.ts +0 -4
- package/dist/src/cli/create-app.d.ts +0 -9
- package/dist/src/cli/playground.d.ts +0 -9
- package/dist/src/cli/tjs.d.ts +0 -15
- package/dist/src/cli/tjsx.d.ts +0 -16
- package/dist/src/index.d.ts +0 -11
- package/dist/src/inference.types.d.ts +0 -1
- package/dist/src/lang/core.d.ts +0 -56
- package/dist/src/lang/docs.d.ts +0 -69
- package/dist/src/lang/emitters/ast.d.ts +0 -24
- package/dist/src/lang/emitters/dts.d.ts +0 -48
- package/dist/src/lang/emitters/from-ts.d.ts +0 -94
- package/dist/src/lang/emitters/js-tests.d.ts +0 -70
- package/dist/src/lang/emitters/js-wasm.d.ts +0 -15
- package/dist/src/lang/emitters/js.d.ts +0 -175
- package/dist/src/lang/eval.d.ts +0 -63
- package/dist/src/lang/index.d.ts +0 -216
- package/dist/src/lang/inference.d.ts +0 -40
- package/dist/src/lang/linter.d.ts +0 -53
- package/dist/src/lang/metadata-cache.d.ts +0 -172
- package/dist/src/lang/parser-params.d.ts +0 -37
- package/dist/src/lang/parser-transforms.d.ts +0 -281
- package/dist/src/lang/parser-types.d.ts +0 -175
- package/dist/src/lang/parser.d.ts +0 -56
- package/dist/src/lang/runtime.d.ts +0 -454
- package/dist/src/lang/schema.d.ts +0 -35
- package/dist/src/lang/tests.d.ts +0 -94
- package/dist/src/lang/transpiler.d.ts +0 -25
- package/dist/src/lang/types.d.ts +0 -147
- package/dist/src/lang/wasm.d.ts +0 -83
- package/dist/src/rbac/index.d.ts +0 -85
- package/dist/src/rbac/rules.d.ts +0 -184
- package/dist/src/runtime.d.ts +0 -4
- package/dist/src/store/index.d.ts +0 -3
- package/dist/src/store/indexeddb.d.ts +0 -6
- package/dist/src/store/interface.d.ts +0 -90
- package/dist/src/store/memory.d.ts +0 -10
- package/dist/src/test-examples.d.ts +0 -41
- package/dist/src/test-utils.d.ts +0 -86
- package/dist/src/transpiler/index.d.ts +0 -6
- package/dist/src/transpiler/parser.d.ts +0 -4
- package/dist/src/transpiler/transformer.d.ts +0 -4
- package/dist/src/transpiler/type-system/inference.d.ts +0 -1
- package/dist/src/transpiler/types.d.ts +0 -4
- package/dist/src/types/LegalDate.d.ts +0 -241
- package/dist/src/types/Timestamp.d.ts +0 -233
- package/dist/src/types/Type.d.ts +0 -234
- package/dist/src/types/index.d.ts +0 -8
- package/dist/src/vm/atoms/batteries.d.ts +0 -6
- package/dist/src/vm/atoms/browser.d.ts +0 -18
- package/dist/src/vm/atoms/index.d.ts +0 -10
- package/dist/src/vm/index.d.ts +0 -12
- package/dist/src/vm/runtime.d.ts +0 -333
- package/dist/src/vm/vm.d.ts +0 -28
- package/dist/src/vm.d.ts +0 -4
- package/dist/test-preprocess.d.ts +0 -1
- package/dist/tjs-batteries.js +0 -4
- package/dist/tjs-batteries.js.map +0 -15
- package/dist/tjs-full.js +0 -426
- package/dist/tjs-full.js.map +0 -45
- package/dist/tjs-src/runtime.d.ts +0 -1
- package/dist/tjs-transpiler.js +0 -3
- package/dist/tjs-transpiler.js.map +0 -11
- package/dist/tjs-vm.js +0 -54
- package/dist/tjs-vm.js.map +0 -22
|
@@ -364,6 +364,28 @@ export class Counter {
|
|
|
364
364
|
expect(dts).not.toContain('for(')
|
|
365
365
|
expect(dts).not.toContain('while(')
|
|
366
366
|
})
|
|
367
|
+
|
|
368
|
+
it('should not emit onstructor (constructor with missing c)', () => {
|
|
369
|
+
const source = `
|
|
370
|
+
export class Foo {
|
|
371
|
+
constructor(x: 0) {
|
|
372
|
+
this.x = x
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
bar() {
|
|
376
|
+
return this.x
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
`
|
|
380
|
+
const result = transpileToJS(source, { runTests: false })
|
|
381
|
+
const dts = generateDTS(result, source)
|
|
382
|
+
|
|
383
|
+
// constructor should appear exactly once, correctly spelled
|
|
384
|
+
const ctorMatches = dts.match(/constructor/g)
|
|
385
|
+
expect(ctorMatches).toHaveLength(1)
|
|
386
|
+
expect(dts).toContain('constructor(x: number)')
|
|
387
|
+
expect(dts).toContain('bar(')
|
|
388
|
+
})
|
|
367
389
|
})
|
|
368
390
|
|
|
369
391
|
describe('generateDTS — Type declarations', () => {
|
package/src/lang/emitters/dts.ts
CHANGED
|
@@ -331,7 +331,11 @@ function detectClasses(source: string): Map<string, ClassInfo> {
|
|
|
331
331
|
const methodMatch = classBody.slice(pos).match(/^(\w+)\s*\(/)
|
|
332
332
|
if (methodMatch) {
|
|
333
333
|
const name = methodMatch[1]
|
|
334
|
-
if (name
|
|
334
|
+
if (name === 'constructor' || name === 'get' || name === 'set') {
|
|
335
|
+
// Skip past the keyword to avoid re-matching a suffix
|
|
336
|
+
pos += name.length
|
|
337
|
+
continue
|
|
338
|
+
} else {
|
|
335
339
|
// Find matching close paren
|
|
336
340
|
const parenStart = pos + methodMatch[0].length - 1
|
|
337
341
|
let depth = 1
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { transformExtensionCalls } from '../parser'
|
|
8
|
+
import { installRuntime } from '../runtime'
|
|
8
9
|
import type { TypeDescriptor } from '../types'
|
|
9
10
|
import type { ExtractedTest, ExtractedMock } from '../tests'
|
|
10
11
|
|
|
@@ -299,15 +300,12 @@ export function stripModuleSyntax(code: string): string {
|
|
|
299
300
|
export function stripTjsPreamble(code: string): string {
|
|
300
301
|
// Remove the __tjs runtime setup lines:
|
|
301
302
|
// const __tjs = globalThis.__tjs?.createRuntime?.() ?? globalThis.__tjs;
|
|
302
|
-
// const { Is, IsNot } = __tjs ?? {};
|
|
303
|
+
// const { Is, IsNot, Eq, NotEq } = __tjs ?? {};
|
|
303
304
|
let result = code.replace(
|
|
304
305
|
/^const __tjs = globalThis\.__tjs\?\.createRuntime\?\.\(\) \?\? globalThis\.__tjs;\n?/m,
|
|
305
306
|
''
|
|
306
307
|
)
|
|
307
|
-
result = result.replace(
|
|
308
|
-
/^const \{ (?:Is|IsNot|Is, IsNot) \} = __tjs \?\? \{\};\n?/m,
|
|
309
|
-
''
|
|
310
|
-
)
|
|
308
|
+
result = result.replace(/^const \{ [\w, ]+ \} = __tjs \?\? \{\};\n?/m, '')
|
|
311
309
|
return result
|
|
312
310
|
}
|
|
313
311
|
|
|
@@ -333,10 +331,7 @@ function buildResolvedImportsCode(
|
|
|
333
331
|
|
|
334
332
|
for (const [specifier, moduleCode] of Object.entries(resolvedImports)) {
|
|
335
333
|
// Strip module syntax from the imported code too (it may have exports)
|
|
336
|
-
|
|
337
|
-
// Strip __tjs preamble to avoid duplicate declarations
|
|
338
|
-
// (test execution context provides its own __tjs stub)
|
|
339
|
-
cleanCode = stripTjsPreamble(cleanCode)
|
|
334
|
+
const cleanCode = stripModuleSyntax(moduleCode)
|
|
340
335
|
|
|
341
336
|
lines.push(`// Resolved import: ${specifier}`)
|
|
342
337
|
lines.push(cleanCode)
|
|
@@ -554,9 +549,9 @@ export function runAllTests(
|
|
|
554
549
|
})
|
|
555
550
|
|
|
556
551
|
// Strip import/export for test execution (can't use modules in new Function)
|
|
557
|
-
|
|
552
|
+
const executableCode = stripModuleSyntax(transpiledCode)
|
|
558
553
|
// Strip __tjs preamble - test context provides its own stub
|
|
559
|
-
|
|
554
|
+
// Real runtime installed via installRuntime() — preamble finds it via globalThis.__tjs
|
|
560
555
|
|
|
561
556
|
// Build resolved imports code - inject imported module code into execution context
|
|
562
557
|
const importedCode = buildResolvedImportsCode(resolvedImports)
|
|
@@ -619,12 +614,11 @@ export function runAllTests(
|
|
|
619
614
|
)
|
|
620
615
|
.join('\n')
|
|
621
616
|
|
|
622
|
-
// TJS
|
|
617
|
+
// Install real TJS runtime for test execution
|
|
618
|
+
installRuntime()
|
|
619
|
+
|
|
623
620
|
const tjsStub = `
|
|
624
621
|
const __saved_tjs = globalThis.__tjs;
|
|
625
|
-
class __MonadicError extends Error { constructor(m,p,e,a,c){super(m);this.name='MonadicError';this.path=p;this.expected=e;this.actual=a;this.callStack=c;} }
|
|
626
|
-
const __stub_tjs = { version: '0.0.0', MonadicError: __MonadicError, pushStack: () => {}, popStack: () => {}, getStack: () => [], typeError: (path, expected, value) => new __MonadicError(\`Type error at \${path}: expected \${expected}\`, path, expected, typeof value), createRuntime: function() { return this; } };
|
|
627
|
-
globalThis.__tjs = __stub_tjs;
|
|
628
622
|
`
|
|
629
623
|
const tjsRestore = `globalThis.__tjs = __saved_tjs;`
|
|
630
624
|
|
|
@@ -815,9 +809,9 @@ function runTestBlocks(
|
|
|
815
809
|
const results: TestResult[] = []
|
|
816
810
|
|
|
817
811
|
// Strip import/export for test execution (can't use modules in new Function)
|
|
818
|
-
|
|
812
|
+
const executableCode = stripModuleSyntax(transpiledCode)
|
|
819
813
|
// Strip __tjs preamble - test context provides its own stub
|
|
820
|
-
|
|
814
|
+
// Real runtime installed via installRuntime() — preamble finds it via globalThis.__tjs
|
|
821
815
|
|
|
822
816
|
// Build resolved imports code - inject imported module code into execution context
|
|
823
817
|
const importedCode = buildResolvedImportsCode(resolvedImports)
|
|
@@ -1176,9 +1170,9 @@ function runSignatureTest(
|
|
|
1176
1170
|
const description = `${funcName} signature example`
|
|
1177
1171
|
|
|
1178
1172
|
// Strip import/export for test execution (can't use modules in new Function)
|
|
1179
|
-
|
|
1173
|
+
const executableCode = stripModuleSyntax(transpiledCode)
|
|
1180
1174
|
// Strip __tjs preamble - test context provides its own stub
|
|
1181
|
-
|
|
1175
|
+
// Real runtime installed via installRuntime() — preamble finds it via globalThis.__tjs
|
|
1182
1176
|
|
|
1183
1177
|
// Build resolved imports code - inject imported module code into execution context
|
|
1184
1178
|
const importedCode = buildResolvedImportsCode(resolvedImports)
|
package/src/lang/emitters/js.ts
CHANGED
|
@@ -787,20 +787,52 @@ export function transpileToJS(
|
|
|
787
787
|
const needsStack = code.includes('__tjs.pushStack(')
|
|
788
788
|
const needsIs = code.includes('Is(')
|
|
789
789
|
const needsIsNot = code.includes('IsNot(')
|
|
790
|
+
const needsEq = code.includes('Eq(')
|
|
791
|
+
const needsNotEq = code.includes('NotEq(')
|
|
792
|
+
// Type system constructors (from Type/Generic/FunctionPredicate/Enum/Union declarations)
|
|
793
|
+
const needsType = /\bType\(/.test(code)
|
|
794
|
+
const needsGeneric = /\bGeneric\(/.test(code)
|
|
795
|
+
const needsFunctionPredicate = /\bFunctionPredicate\(/.test(code)
|
|
796
|
+
const needsEnum = /\bEnum\(/.test(code)
|
|
797
|
+
const needsUnion = /\bUnion\(/.test(code)
|
|
790
798
|
const needsSafeEval = preprocessed.tjsModes.tjsSafeEval
|
|
791
799
|
|
|
792
|
-
|
|
800
|
+
const needsRuntime =
|
|
801
|
+
needsTypeError ||
|
|
802
|
+
needsStack ||
|
|
803
|
+
needsIs ||
|
|
804
|
+
needsIsNot ||
|
|
805
|
+
needsEq ||
|
|
806
|
+
needsNotEq ||
|
|
807
|
+
needsType ||
|
|
808
|
+
needsGeneric ||
|
|
809
|
+
needsFunctionPredicate ||
|
|
810
|
+
needsEnum ||
|
|
811
|
+
needsUnion ||
|
|
812
|
+
needsSafeEval
|
|
813
|
+
|
|
814
|
+
if (needsRuntime) {
|
|
793
815
|
// Create isolated runtime instance for this module
|
|
794
816
|
// Falls back to shared global if createRuntime not available
|
|
795
817
|
let preamble =
|
|
796
818
|
'const __tjs = globalThis.__tjs?.createRuntime?.() ?? globalThis.__tjs;\n'
|
|
797
819
|
|
|
798
|
-
// Add destructured imports for
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
820
|
+
// Add destructured imports for runtime functions if used
|
|
821
|
+
const runtimeImports = [
|
|
822
|
+
needsIs && 'Is',
|
|
823
|
+
needsIsNot && 'IsNot',
|
|
824
|
+
needsEq && 'Eq',
|
|
825
|
+
needsNotEq && 'NotEq',
|
|
826
|
+
needsType && 'Type',
|
|
827
|
+
needsGeneric && 'Generic',
|
|
828
|
+
needsFunctionPredicate && 'FunctionPredicate',
|
|
829
|
+
needsEnum && 'Enum',
|
|
830
|
+
needsUnion && 'Union',
|
|
831
|
+
]
|
|
832
|
+
.filter(Boolean)
|
|
833
|
+
.join(', ')
|
|
834
|
+
if (runtimeImports) {
|
|
835
|
+
preamble += `const { ${runtimeImports} } = __tjs ?? {};\n`
|
|
804
836
|
}
|
|
805
837
|
|
|
806
838
|
code = preamble + code
|
|
@@ -764,7 +764,7 @@ export function transformEqualityToStructural(source: string): string {
|
|
|
764
764
|
let result = source
|
|
765
765
|
for (let k = equalityOps.length - 1; k >= 0; k--) {
|
|
766
766
|
const { pos, op } = equalityOps[k]
|
|
767
|
-
const funcName = op === '==' ? '
|
|
767
|
+
const funcName = op === '==' ? 'Eq' : 'NotEq'
|
|
768
768
|
|
|
769
769
|
// Find left operand boundary
|
|
770
770
|
const leftBoundary = findLeftOperandBoundary(result, pos)
|
|
@@ -827,8 +827,8 @@ function findLeftOperandBoundary(source: string, opPos: number): number {
|
|
|
827
827
|
continue
|
|
828
828
|
}
|
|
829
829
|
|
|
830
|
-
// Track depth of parens/brackets (reversed since we're going backwards)
|
|
831
|
-
if (char === ')' || char === ']') {
|
|
830
|
+
// Track depth of parens/brackets/braces (reversed since we're going backwards)
|
|
831
|
+
if (char === ')' || char === ']' || char === '}') {
|
|
832
832
|
depth++
|
|
833
833
|
i--
|
|
834
834
|
continue
|
|
@@ -843,6 +843,15 @@ function findLeftOperandBoundary(source: string, opPos: number): number {
|
|
|
843
843
|
// The expression starts AFTER it, not including it
|
|
844
844
|
return i + 1
|
|
845
845
|
}
|
|
846
|
+
if (char === '{') {
|
|
847
|
+
if (depth > 0) {
|
|
848
|
+
depth--
|
|
849
|
+
i--
|
|
850
|
+
continue
|
|
851
|
+
}
|
|
852
|
+
// Opening brace at depth 0 — could be block statement boundary
|
|
853
|
+
return i + 1
|
|
854
|
+
}
|
|
846
855
|
|
|
847
856
|
// Inside nested expression - keep scanning
|
|
848
857
|
if (depth > 0) {
|
|
@@ -852,7 +861,7 @@ function findLeftOperandBoundary(source: string, opPos: number): number {
|
|
|
852
861
|
|
|
853
862
|
// At depth 0 - check for expression boundaries
|
|
854
863
|
// Statement delimiters
|
|
855
|
-
if (char === ';'
|
|
864
|
+
if (char === ';') {
|
|
856
865
|
return i + 1
|
|
857
866
|
}
|
|
858
867
|
|
|
@@ -880,11 +889,15 @@ function findLeftOperandBoundary(source: string, opPos: number): number {
|
|
|
880
889
|
'delete',
|
|
881
890
|
'await',
|
|
882
891
|
'yield',
|
|
883
|
-
'new',
|
|
884
892
|
].includes(word)
|
|
885
893
|
) {
|
|
886
894
|
return wordEnd
|
|
887
895
|
}
|
|
896
|
+
// 'new' is part of the operand (new Foo() == bar),
|
|
897
|
+
// so include it by continuing the scan
|
|
898
|
+
if (word === 'new') {
|
|
899
|
+
return wordStart
|
|
900
|
+
}
|
|
888
901
|
}
|
|
889
902
|
}
|
|
890
903
|
|
package/src/lang/runtime.ts
CHANGED
|
@@ -381,6 +381,15 @@ export function Is(a: unknown, b: unknown): boolean {
|
|
|
381
381
|
return (b as any).Equals(a)
|
|
382
382
|
}
|
|
383
383
|
|
|
384
|
+
// Unwrap boxed primitives (new String, new Number, new Boolean)
|
|
385
|
+
// so structural equality honors the intent: new String('foo') == 'foo'
|
|
386
|
+
if (a instanceof String || a instanceof Number || a instanceof Boolean) {
|
|
387
|
+
a = a.valueOf()
|
|
388
|
+
}
|
|
389
|
+
if (b instanceof String || b instanceof Number || b instanceof Boolean) {
|
|
390
|
+
b = b.valueOf()
|
|
391
|
+
}
|
|
392
|
+
|
|
384
393
|
// Identical references or primitives
|
|
385
394
|
if (a === b) return true
|
|
386
395
|
|
|
@@ -401,6 +410,36 @@ export function Is(a: unknown, b: unknown): boolean {
|
|
|
401
410
|
// Primitives that aren't === are not equal
|
|
402
411
|
if (typeof a !== 'object') return false
|
|
403
412
|
|
|
413
|
+
// Sets — order-independent element equality
|
|
414
|
+
if (a instanceof Set && b instanceof Set) {
|
|
415
|
+
if ((a as Set<unknown>).size !== (b as Set<unknown>).size) return false
|
|
416
|
+
for (const v of a as Set<unknown>) {
|
|
417
|
+
if (!(b as Set<unknown>).has(v)) return false
|
|
418
|
+
}
|
|
419
|
+
return true
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Maps — key-value structural equality
|
|
423
|
+
if (a instanceof Map && b instanceof Map) {
|
|
424
|
+
if ((a as Map<unknown, unknown>).size !== (b as Map<unknown, unknown>).size)
|
|
425
|
+
return false
|
|
426
|
+
for (const [k, v] of a as Map<unknown, unknown>) {
|
|
427
|
+
if (!(b as Map<unknown, unknown>).has(k)) return false
|
|
428
|
+
if (!Is(v, (b as Map<unknown, unknown>).get(k))) return false
|
|
429
|
+
}
|
|
430
|
+
return true
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Dates — compare timestamps
|
|
434
|
+
if (a instanceof Date && b instanceof Date) {
|
|
435
|
+
return a.getTime() === b.getTime()
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// RegExps — compare string representation
|
|
439
|
+
if (a instanceof RegExp && b instanceof RegExp) {
|
|
440
|
+
return a.toString() === b.toString()
|
|
441
|
+
}
|
|
442
|
+
|
|
404
443
|
// Arrays
|
|
405
444
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
406
445
|
if (a.length !== b.length) return false
|
|
@@ -424,6 +463,47 @@ export function IsNot(a: unknown, b: unknown): boolean {
|
|
|
424
463
|
return !Is(a, b)
|
|
425
464
|
}
|
|
426
465
|
|
|
466
|
+
/**
|
|
467
|
+
* Honest equality — what == should have been.
|
|
468
|
+
*
|
|
469
|
+
* Like === but fixes the two remaining footguns:
|
|
470
|
+
* 1. Unwraps boxed primitives: new String('foo') Eq 'foo' → true
|
|
471
|
+
* 2. Nullish equality: null Eq undefined → true
|
|
472
|
+
*
|
|
473
|
+
* Does NOT do deep structural comparison on objects/arrays (that's O(n)).
|
|
474
|
+
* Use Is/IsNot for explicit structural comparison when you need it.
|
|
475
|
+
*
|
|
476
|
+
* Usage: `a == b` with TjsEquals transforms to `Eq(a, b)`
|
|
477
|
+
*/
|
|
478
|
+
export function Eq(a: unknown, b: unknown): boolean {
|
|
479
|
+
// Unwrap boxed primitives
|
|
480
|
+
if (a instanceof String || a instanceof Number || a instanceof Boolean) {
|
|
481
|
+
a = a.valueOf()
|
|
482
|
+
}
|
|
483
|
+
if (b instanceof String || b instanceof Number || b instanceof Boolean) {
|
|
484
|
+
b = b.valueOf()
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Identical references or primitives
|
|
488
|
+
if (a === b) return true
|
|
489
|
+
|
|
490
|
+
// null and undefined are equal to each other
|
|
491
|
+
if ((a === null || a === undefined) && (b === null || b === undefined)) {
|
|
492
|
+
return true
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return false
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Honest inequality — what != should have been.
|
|
500
|
+
*
|
|
501
|
+
* Usage: `a != b` with TjsEquals transforms to `NotEq(a, b)`
|
|
502
|
+
*/
|
|
503
|
+
export function NotEq(a: unknown, b: unknown): boolean {
|
|
504
|
+
return !Eq(a, b)
|
|
505
|
+
}
|
|
506
|
+
|
|
427
507
|
/**
|
|
428
508
|
* Check if a value is a TJS error
|
|
429
509
|
*/
|
|
@@ -739,7 +819,7 @@ export function wrap<T extends (...args: any[]) => any>(
|
|
|
739
819
|
meta: FunctionMeta
|
|
740
820
|
): T {
|
|
741
821
|
// Always attach metadata for introspection/autocomplete
|
|
742
|
-
|
|
822
|
+
(fn as any).__tjs = meta
|
|
743
823
|
|
|
744
824
|
// Determine if we need a wrapper at all
|
|
745
825
|
// Polymorphic dispatchers handle their own routing — no wrapping needed
|
|
@@ -1199,6 +1279,9 @@ export function createRuntime() {
|
|
|
1199
1279
|
// Structural equality
|
|
1200
1280
|
Is,
|
|
1201
1281
|
IsNot,
|
|
1282
|
+
// Honest equality (== / != with TjsEquals)
|
|
1283
|
+
Eq,
|
|
1284
|
+
NotEq,
|
|
1202
1285
|
tjsEquals,
|
|
1203
1286
|
// Extensions
|
|
1204
1287
|
registerExtension: instanceRegisterExtension,
|
|
@@ -1272,9 +1355,12 @@ export const runtime = {
|
|
|
1272
1355
|
LegalDate,
|
|
1273
1356
|
TPair,
|
|
1274
1357
|
TRecord,
|
|
1275
|
-
// Structural equality (used by
|
|
1358
|
+
// Structural equality (used by Is/IsNot operators)
|
|
1276
1359
|
Is,
|
|
1277
1360
|
IsNot,
|
|
1361
|
+
// Honest equality (used by == and != with TjsEquals)
|
|
1362
|
+
Eq,
|
|
1363
|
+
NotEq,
|
|
1278
1364
|
}
|
|
1279
1365
|
|
|
1280
1366
|
/**
|
package/src/lang/wasm.ts
CHANGED
package/dist/bin/benchmarks.d.ts
DELETED
package/dist/bin/dev.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/bin/docs.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export function calculate(x?: number, y?: number): any;
|
|
2
|
-
export namespace calculate {
|
|
3
|
-
namespace __tjs {
|
|
4
|
-
namespace params {
|
|
5
|
-
namespace x {
|
|
6
|
-
export namespace type {
|
|
7
|
-
let kind: string;
|
|
8
|
-
}
|
|
9
|
-
export let required: boolean;
|
|
10
|
-
let _default: null;
|
|
11
|
-
export { _default as default };
|
|
12
|
-
}
|
|
13
|
-
namespace y {
|
|
14
|
-
export namespace type_1 {
|
|
15
|
-
let kind_1: string;
|
|
16
|
-
export { kind_1 as kind };
|
|
17
|
-
}
|
|
18
|
-
export { type_1 as type };
|
|
19
|
-
let required_1: boolean;
|
|
20
|
-
export { required_1 as required };
|
|
21
|
-
let _default_1: null;
|
|
22
|
-
export { _default_1 as default };
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
namespace returns {
|
|
26
|
-
export namespace type_2 {
|
|
27
|
-
let kind_2: string;
|
|
28
|
-
export { kind_2 as kind };
|
|
29
|
-
}
|
|
30
|
-
export { type_2 as type };
|
|
31
|
-
}
|
|
32
|
-
let source: string;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
export function add(a?: number, b?: number): any;
|
|
2
|
-
export namespace add {
|
|
3
|
-
namespace __tjs {
|
|
4
|
-
namespace params {
|
|
5
|
-
namespace a {
|
|
6
|
-
export namespace type {
|
|
7
|
-
let kind: string;
|
|
8
|
-
}
|
|
9
|
-
export let required: boolean;
|
|
10
|
-
let _default: null;
|
|
11
|
-
export { _default as default };
|
|
12
|
-
}
|
|
13
|
-
namespace b {
|
|
14
|
-
export namespace type_1 {
|
|
15
|
-
let kind_1: string;
|
|
16
|
-
export { kind_1 as kind };
|
|
17
|
-
}
|
|
18
|
-
export { type_1 as type };
|
|
19
|
-
let required_1: boolean;
|
|
20
|
-
export { required_1 as required };
|
|
21
|
-
let _default_1: null;
|
|
22
|
-
export { _default_1 as default };
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
namespace returns {
|
|
26
|
-
export namespace type_2 {
|
|
27
|
-
let kind_2: string;
|
|
28
|
-
export { kind_2 as kind };
|
|
29
|
-
}
|
|
30
|
-
export { type_2 as type };
|
|
31
|
-
}
|
|
32
|
-
let source: string;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export function subtract(a?: number, b?: number): any;
|
|
36
|
-
export namespace subtract {
|
|
37
|
-
export namespace __tjs_1 {
|
|
38
|
-
export namespace params_1 {
|
|
39
|
-
export namespace a_1 {
|
|
40
|
-
export namespace type_3 {
|
|
41
|
-
let kind_3: string;
|
|
42
|
-
export { kind_3 as kind };
|
|
43
|
-
}
|
|
44
|
-
export { type_3 as type };
|
|
45
|
-
let required_2: boolean;
|
|
46
|
-
export { required_2 as required };
|
|
47
|
-
let _default_2: null;
|
|
48
|
-
export { _default_2 as default };
|
|
49
|
-
}
|
|
50
|
-
export { a_1 as a };
|
|
51
|
-
export namespace b_1 {
|
|
52
|
-
export namespace type_4 {
|
|
53
|
-
let kind_4: string;
|
|
54
|
-
export { kind_4 as kind };
|
|
55
|
-
}
|
|
56
|
-
export { type_4 as type };
|
|
57
|
-
let required_3: boolean;
|
|
58
|
-
export { required_3 as required };
|
|
59
|
-
let _default_3: null;
|
|
60
|
-
export { _default_3 as default };
|
|
61
|
-
}
|
|
62
|
-
export { b_1 as b };
|
|
63
|
-
}
|
|
64
|
-
export { params_1 as params };
|
|
65
|
-
export namespace returns_1 {
|
|
66
|
-
export namespace type_5 {
|
|
67
|
-
let kind_5: string;
|
|
68
|
-
export { kind_5 as kind };
|
|
69
|
-
}
|
|
70
|
-
export { type_5 as type };
|
|
71
|
-
}
|
|
72
|
-
export { returns_1 as returns };
|
|
73
|
-
let source_1: string;
|
|
74
|
-
export { source_1 as source };
|
|
75
|
-
}
|
|
76
|
-
export { __tjs_1 as __tjs };
|
|
77
|
-
}
|
|
78
|
-
export function multiply(a?: number, b?: number): any;
|
|
79
|
-
export namespace multiply {
|
|
80
|
-
export namespace __tjs_2 {
|
|
81
|
-
export namespace params_2 {
|
|
82
|
-
export namespace a_2 {
|
|
83
|
-
export namespace type_6 {
|
|
84
|
-
let kind_6: string;
|
|
85
|
-
export { kind_6 as kind };
|
|
86
|
-
}
|
|
87
|
-
export { type_6 as type };
|
|
88
|
-
let required_4: boolean;
|
|
89
|
-
export { required_4 as required };
|
|
90
|
-
let _default_4: null;
|
|
91
|
-
export { _default_4 as default };
|
|
92
|
-
}
|
|
93
|
-
export { a_2 as a };
|
|
94
|
-
export namespace b_2 {
|
|
95
|
-
export namespace type_7 {
|
|
96
|
-
let kind_7: string;
|
|
97
|
-
export { kind_7 as kind };
|
|
98
|
-
}
|
|
99
|
-
export { type_7 as type };
|
|
100
|
-
let required_5: boolean;
|
|
101
|
-
export { required_5 as required };
|
|
102
|
-
let _default_5: null;
|
|
103
|
-
export { _default_5 as default };
|
|
104
|
-
}
|
|
105
|
-
export { b_2 as b };
|
|
106
|
-
}
|
|
107
|
-
export { params_2 as params };
|
|
108
|
-
export namespace returns_2 {
|
|
109
|
-
export namespace type_8 {
|
|
110
|
-
let kind_8: string;
|
|
111
|
-
export { kind_8 as kind };
|
|
112
|
-
}
|
|
113
|
-
export { type_8 as type };
|
|
114
|
-
}
|
|
115
|
-
export { returns_2 as returns };
|
|
116
|
-
let source_2: string;
|
|
117
|
-
export { source_2 as source };
|
|
118
|
-
}
|
|
119
|
-
export { __tjs_2 as __tjs };
|
|
120
|
-
}
|