#lang racket/base (require "../main.rkt" "jsmaker-executors.rkt" "jsmaker-test-framework.rkt") (define dom-preamble (string-append "const window = {};\n" "const logs = [];\n" "const attrs = {};\n" "const console = { log: (...xs) => logs.push(xs.length === 1 ? xs[0] : xs) };\n" "const document = {\n" " getElementById: (id) => id === 'hi'\n" " ? { setAttribute: (k, v) => { attrs[k] = v; }, getAttribute: (k) => attrs[k] || '' }\n" " : false\n" "};")) (define t1-program (js (set! window.myfunc (λ (x) (let* ((el (send document getElementById 'hi)) (old (send el getAttribute "x")) (y (+ old (* x x)))) (send el setAttribute "x" (+ y ""))) (send console log "dit set attribute x on element hi"))))) (define t2-program (js (define (f x) (if (and (> x 10) (< x 15)) (begin (console.log x) (return x)) (return (* x x)))))) (define t3-program (js (define (f x y z) (send console log (cons x (cons y (list z)))) (let* ((l (cons x (cons y (list z))))) (return (send l map (λ (a) (return (+ a 10))))))))) (define tail-loop-expression (js/expression (let loop ([i 0] [s 0]) (if (< i 5) (loop (+ i 1) (+ s i)) s)))) (unless (regexp-match? #rx"while \\(true\\)" tail-loop-expression) (error 'jsmaker-program-regression "tail-recursive named let was not lowered to while(true): ~a" tail-loop-expression)) (unless (regexp-match? #rx"\n " t1-program) (error 'jsmaker-program-regression "generated statement code does not appear to contain indentation: ~a" t1-program)) (unless (regexp-match? #rx"if \\(\\(x > 10\\) && \\(x < 15\\)\\)" t2-program) (error 'jsmaker-program-regression "boolean and should compile directly in if test: ~a" t2-program)) (define program-tests (list (js-program-test 'dom-style-set-attribute t1-program "(() => { attrs.x = 'old:'; window.myfunc(4); return [attrs.x, logs]; })()" "[\"old:16\",[\"dit set attribute x on element hi\"]]" #:preamble dom-preamble) (js-program-test 'define-if-return-console t2-program "(() => { const a = f(12); const b = f(5); return [a, b, logs]; })()" "[12,25,[12]]" #:preamble "const logs = []; const console = { log: (...xs) => logs.push(xs.length === 1 ? xs[0] : xs) };" ) (js-program-test 'define-send-map-return t3-program "(() => { const r = f(1, 2, 3); return [r, logs]; })()" "[[11,12,13],[[1,2,3]]]" #:preamble "const logs = []; const console = { log: (...xs) => logs.push(xs.length === 1 ? xs[0] : xs) };" ) (js-expression-test 'named-let-tail-big (js/expression (let loop ([i 0] [s 0]) (if (< i 100000) (loop (+ i 1) (+ s 1)) s))) "100000") (js-expression-test 'named-let-tail-accumulator tail-loop-expression "10") (js-expression-test 'explicit-while-form (js/expression (let ([i 0] [s 0]) (while (< i 4) (set! s (+ s i)) (set! i (+ i 1))) s)) "6") (js-expression-test 'bare-return (js/expression ((lambda (x) (if x (return) (return 7))) #t)) "undefined") (js-expression-test 'implicit-last-expression-return (js/expression ((lambda (x) (+ x 10)) 5)) "15") (js-program-test 'with-handlers-rest-lambda-statement (js (with-handlers ([exn? (λ args (displayln (length args)))]) (/ 10 0))) "logs" "[1]" #:preamble "const logs = []; const console = { log: (...xs) => logs.push(xs.length === 1 ? xs[0] : xs) };"))) (define engine (find-js-engine)) (run-jsmaker-regression 'jsmaker-program-regression program-tests "/tmp/jsmaker-program-regression.js" #:engine engine)