1 ;; Copying and distribution of this file, with or without modification,
2 ;; are permitted in any medium without royalty provided the copyright
3 ;; notice and this notice are preserved. This file is offered as-is,
4 ;; without any warranty.
7 (named-readtables:in-readtable
:parenscript
)
9 (in-suite output-tests
)
11 (test-ps-js statements-and-expressions-1
15 (test-ps-js statements-and-expressions-2
23 (test-ps-js symbol-conversion-1
25 "bangwhathashatpercent;")
27 (test-ps-js symbol-conversion-2
31 (test-ps-js symbol-conversion-3
35 (test-ps-js symbol-conversion-4
39 (test-ps-js number-literals-1
43 (test-ps-js number-literals-2
47 (test-ps-js number-literals-3
51 (test-ps-js string-literals-1
55 (test-ps-js string-literals-2
59 (test-ps-js string-literals-3
63 (test-ps-js array-literals-1
67 (test-ps-js array-literals-2
71 (test-ps-js array-literals-3
73 (array "foobar" "bratzel bub"))
74 "[ [ 2, 3 ], [ 'foobar', 'bratzel bub' ] ];")
76 (test-ps-js array-literals-4
80 (test-ps-js array-literals-5
82 "new Array(1, 2, 3);")
84 (test-ps-js array-literals-6
87 (make-array "foobar" "bratzel bub"))
88 "new Array(new Array(2, 3), new Array('foobar', 'bratzel bub'));")
90 (test-ps-js object-literals-1
91 (create foo
"bar" :blorg
1)
92 "{ foo : 'bar', 'blorg' : 1 };")
94 (test-ps-js object-literals-2
97 another-object
(create :schtrunz
1))
100 anotherObject : { 'schtrunz' : 1 } };")
102 (test-ps-js object-literals-3
103 (getprop an-object
'foo
)
106 (test-ps-js object-literals-4
107 (@ an-object foo bar
)
110 (test-ps-js object-literals-5
111 (with-slots (a b c
) this
113 "this.a + this.b + this.c;")
115 (test-ps-js regular-expression-literals-1
119 (test-ps-js regular-expression-literals-2
123 (test-ps-js literal-symbols-1
127 (test-ps-js literal-symbols-2
131 (test-ps-js literal-symbols-3
135 (test-ps-js literal-symbols-4
141 (test-ps-js literal-symbols-5
145 (test-ps-js literal-symbols-6
149 (test-ps-js variables-1
153 (test-ps-js variables-2
157 (test-ps-js variables-3
161 (test-ps-js function-calls-and-method-calls-1
165 (test-ps-js function-calls-and-method-calls-2
166 (foobar (blorg 1 2) (blabla 3 4) (array 2 3 4))
167 "foobar(blorg(1, 2), blabla(3, 4), [ 2, 3, 4 ]);")
169 (test-ps-js function-calls-and-method-calls-3
170 ((getprop this
'blorg
) 1 2)
173 (test-ps-js function-calls-and-method-calls-4
177 (test-ps-js function-calls-and-method-calls-5
178 ((getprop (aref foobar
1) 'blorg
) nil t
)
179 "foobar[1].blorg(null, true);")
181 (test-ps-js operator-expressions-1
185 (test-ps-js operator-expressions-2
189 (test-ps-js operator-expressions-3
190 (* 1 (+ 2 3 4) 4 (/ 6 7))
191 "1 * (2 + 3 + 4) * 4 * 6 / 7;")
193 (test-ps-js operator-expressions-4
197 (test-ps-js operator-expressions-5
201 (test-ps-js operator-expressions-6
205 (test-ps-js operator-expressions-7
209 (test-ps-js operator-expressions-8
213 (test-ps-js body-forms-1
214 (progn (blorg i
) (blafoo i
))
218 (test-ps-js body-forms-2
219 (+ i
(progn (blorg i
) (blafoo i
)))
220 "i + (blorg(i), blafoo(i));")
222 (test-ps-js function-definition-1
223 (defun a-function (a b
)
225 "function aFunction(a, b) {
229 (test-ps-js function-definition-2
230 (lambda (a b
) (+ a b
))
235 (test-ps-js assignment-1
239 (test-ps-js assignment-2
240 (setf a
2 b
3 c
4 x
(+ a b c
))
246 (test-ps-js assignment-3
247 (setf a
(+ a
2 3 4 a
))
248 "a = a + 2 + 3 + 4 + a;")
250 (test-ps-js assignment-4
254 (test-ps-js assignment-5
264 (test-ps-js assignment-6
268 (test-ps-js assignment-8
270 (defun (setf color
) (new-color el
)
271 (setf (getprop (getprop el
'style
) 'color
) new-color
))
272 (setf (color some-div
) (+ 23 "em")))
273 "function __setf_color(newColor, el) {
274 return el.style.color = newColor;
276 __setf_color(23 + 'em', someDiv);")
278 (test-ps-js assignment-10
280 (defsetf left
(el) (offset)
281 `(setf (getprop (getprop ,el
'style
) 'left
) ,offset
))
282 (setf (left some-div
) (+ 123 "px")))
284 var _js1 = 123 + 'px';
285 _js2.style.left = _js1;")
287 (test-ps-js assignment-12
288 (macrolet ((left (el)
289 `(getprop ,el
'offset-left
)))
291 "someDiv.offsetLeft;")
293 (test-ps-js nil-block-return-1
299 (test-ps-js single-argument-statements-2
303 (test-ps-js single-argument-expression-1
304 (delete (new (*foobar
2 3 4)))
305 "delete new Foobar(2, 3, 4);")
307 (test-ps-js single-argument-expression-2
308 (if (= (typeof blorg
) *string
)
309 (alert (+ "blorg is a string: " blorg
))
310 (alert "blorg is not a string"))
311 "if (typeof blorg === String) {
312 alert('blorg is a string: ' + blorg);
314 alert('blorg is not a string');
317 (test-ps-js conditional-statements-1
319 (if ((@ blorg is-correct
))
320 (progn (carry-on) (return-from foo i
))
321 (alert "blorg is not correct!")))
323 if (blorg.isCorrect()) {
327 return alert('blorg is not correct!');
331 (test-ps-js conditional-statements-2
332 (+ i
(if ((@ blorg add-one
)) 1 2))
333 "i + (blorg.addOne() ? 1 : 2);")
335 (test-ps-js conditional-statements-3
337 (when ((@ blorg is-correct
))
339 (return-from foo i
)))
341 if (blorg.isCorrect()) {
347 (test-ps-js conditional-statements-4
348 (unless ((@ blorg is-correct
))
349 (alert "blorg is not correct!"))
350 "if (!blorg.isCorrect()) {
351 alert('blorg is not correct!');
354 (test-ps-js variable-declaration-1
355 (defvar *a
* (array 1 2 3))
356 "var A = [ 1, 2, 3 ];")
358 (test-ps-js variable-declaration-2
379 (test-ps-js iteration-constructs-1
380 (do* ((a) b
(c (array "a" "b" "c" "d" "e"))
382 (e (aref c d
) (aref c d
)))
383 ((or (= d
(@ c length
)) (string= e
"x")))
385 (funcall (@ document write
) (+ "a: " a
" b: " b
"<br/>")))
386 "for (var a = null, b = null, c = ['a', 'b', 'c', 'd', 'e'], d = 0, e = c[d]; !(d === c.length || e === 'x'); d += 1, e = c[d]) {
389 document.write('a: ' + a + ' b: ' + b + '<br/>');
392 (test-ps-js iteration-constructs-2
394 (s 0 (+ s i
(1+ i
))))
396 (funcall (@ document write
) (+ "i: " i
" s: " s
"<br/>")))
400 document.write('i: ' + i + ' s: ' + s + '<br/>');
402 var _js2 = s + i + i + 1;
407 (test-ps-js iteration-constructs-3
409 (s 0 (+ s i
(1- i
))))
411 ((@ document write
) (+ "i: " i
" s: " s
"<br/>")))
412 "for (var i = 0, s = 0; i <= 10; i += 1, s = s + i + i - 1) {
413 document.write('i: ' + i + ' s: ' + s + '<br/>');
416 (test-ps-js iteration-constructs-4
417 (let ((arr (array "a" "b" "c" "d" "e")))
418 (dotimes (i (@ arr length
))
419 ((@ document write
) (+ "i: " i
" arr[i]: " (aref arr i
) "<br/>"))))
420 "var arr = ['a', 'b', 'c', 'd', 'e'];
421 for (var i = 0; i < arr.length; i += 1) {
422 document.write('i: ' + i + ' arr[i]: ' + arr[i] + '<br/>');
425 (test-ps-js iteration-constructs-5
427 (alert (+ "Summation to 10 is "
429 (incf res
(1+ i
))))))
431 alert('Summation to 10 is ' + (function () {
432 for (var i = 0; i < 10; i += 1) {
438 (test-ps-js iteration-constructs-6
439 (let ((l (list 1 2 4 8 16 32)))
441 ((@ document write
) (+ "c: " c
"<br/>"))))
442 "var l = [1, 2, 4, 8, 16, 32];
443 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
445 document.write('c: ' + c + '<br/>');
448 (test-ps-js iteration-constructs-7
449 (let ((l '(1 2 4 8 16 32))
451 (alert (+ "Sum of " l
" is: "
454 "var l = [1, 2, 4, 8, 16, 32];
456 alert('Sum of ' + l + ' is: ' + (function () {
457 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
464 (test-ps-js iteration-constructs-8
465 (let ((obj (create a
1 b
2 c
3)))
467 ((@ document write
) (+ i
": " (aref obj i
) "<br/>"))))
468 "var obj = { a : 1, b : 2, c : 3 };
470 document.write(i + ': ' + obj[i] + '<br/>');
473 (test-ps-js iteration-constructs-9
474 (while ((@ film is-not-finished
))
475 ((@ this eat
) (new *popcorn
)))
476 "while (film.isNotFinished()) {
477 this.eat(new Popcorn);
480 (test-ps-js the-case-statement-1
482 ((1 "one") (alert "one"))
484 (t (alert "default clause")))
494 alert('default clause');
497 (test-ps-js the-case-statement-2
498 (switch (aref blorg i
)
499 (1 (alert "If I get here"))
500 (2 (alert "I also get here"))
501 (default (alert "I always get here")))
503 case 1: alert('If I get here');
504 case 2: alert('I also get here');
505 default: alert('I always get here');
508 (test-ps-js the-try-statement-1
511 (alert (+ "an error happened: " error
)))
513 (alert "Leaving the try form")))
517 alert('an error happened: ' + error);
519 alert('Leaving the try form');
522 (test-ps-js the-html-generator-1
523 (ps-html ((:a
:href
"foobar") "blorg"))
524 "'<A HREF=\"foobar\">blorg</A>';")
526 (test-ps-js the-html-generator-2
527 (ps-html ((:a
:href
(generate-a-link)) "blorg"))
528 "['<A HREF=\"', generateALink(), '\">blorg</A>']['join']('');")
530 (test-ps-js the-html-generator-3
531 (funcall (getprop document
'write
)
532 (ps-html ((:a
:href
"#"
533 :onclick
(ps-inline (transport))) "link")))
534 "document.write(['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">link</A>']['join'](''));")
536 (test-ps-js the-html-generator-4
539 (setf (getprop element
'inner-h-t-m-l
)
540 (ps-html ((:textarea
(or disabled
(not authorized
)) :disabled
"disabled")
542 "var disabled = null;
543 var authorized = true;
544 element.innerHTML = ['<TEXTAREA', disabled || !authorized ? [' DISABLED=\"', 'disabled', '\"']['join']('') : '', '>Edit me</TEXTAREA>']['join']('');")
546 (test-ps-js plus-is-not-commutative
547 (setf x
(+ "before" x
"after"))
548 "x = 'before' + x + 'after';")
550 (test-ps-js plus-works-if-first
551 (setf x
(+ x
"middle" "after"))
552 "x = x + 'middle' + 'after';")
554 (test-ps-js setf-side-effects
560 (setf x
(+ 2 (side-effect) x
5))))
562 function sideEffect() {
566 x = 2 + sideEffect() + x + 5;")
568 (test-ps-js method-call-op-form
569 (funcall (getprop (+ "" x
) 'to-string
))
570 "('' + x).toString();")
572 (test-ps-js method-call-op-form-args
573 (funcall (getprop (+ "" x
) 'foo
) 1 2 :baz
3)
574 "('' + x).foo(1, 2, 'baz', 3);")
576 (test-ps-js method-call-string
577 ((getprop "hi" 'to-string
))
580 (test-ps-js method-call-conditional
584 (test-ps-js method-call-variable
588 (test-ps-js method-call-array
589 ((@ (list 10 20) to-string
))
590 "[ 10, 20 ].toString();")
592 (test-ps-js method-call-lambda-call
593 (funcall (getprop (funcall (lambda (x) x
) 10) 'to-string
))
594 "(function (x) { return x; })(10).toString();")
596 (test no-whitespace-before-dot
597 (let* ((str (ps* '((@ ((lambda (x) x
) 10) to-string
))))
598 (dot-pos (position #\. str
:test
#'char
=))
599 (char-before (elt str
(1- dot-pos
)))
601 (is (char= char-before a-parenthesis
))))
603 (test-ps-js simple-getprop
604 (let ((foo (create a
1)))
605 (alert (getprop foo
'a
)))
606 "var foo = { a : 1 };
609 (test-ps-js buggy-getprop
610 (getprop foo slot-name
)
613 (test-ps-js buggy-getprop-two
614 (getprop foo
(get-slot-name))
615 "foo[getSlotName()];")
617 (test-ps-js old-case-is-now-switch
618 ;; Switch was "case" before, but that was very non-lispish.
619 ;; For example, this code makes three messages and not one
620 ;; which may have been expected. This is because a switch
621 ;; statment must have a break statement for it to return
622 ;; after the alert. Otherwise it continues on the next
624 (switch (aref blorg i
)
627 (default (alert "default clause")))
629 case 1: alert('one');
630 case 2: alert('two');
631 default: alert('default clause');
634 (test-ps-js lisp-like-case
638 (default (alert "default clause")))
646 default: alert('default clause');
650 (test-ps-js even-lispier-case
652 ((1 2) (alert "Below three"))
654 (t (alert "Something else")))
658 alert('Below three');
663 default: alert('Something else');
666 (test-ps-js otherwise-case
669 (otherwise (alert "default clause")))
674 default: alert('default clause');
677 (test escape-sequences-in-string
678 (let ((escapes `((#\\ .
#\\)
680 (#\f .
,(code-char 12))
681 ("u000B" .
,(code-char #x000b
));;Vertical tab, too uncommon to bother with
684 (#\' .
#\');;Double quote need not be quoted because parenscript strings are single quoted
686 ("u001F" .
,(code-char #x001f
));; character below 32
687 ("u0080" .
,(code-char 128)) ;;Character over 127. Actually valid, parenscript escapes them to be sure.
688 ("uABCD" .
,(code-char #xabcd
)))));; Really above ascii.
689 (loop for
(js-escape . lisp-char
) in escapes
690 for generated
= (ps-doc* `(let ((x ,(format nil
"hello~ahi" lisp-char
)))))
691 for wanted
= (format nil
"var x = 'hello\\~ahi';" js-escape
)
692 do
(is (string= (normalize-js-code generated
) wanted
)))))
694 (test-ps-js getprop-setf
695 (setf (getprop x
'y
) (+ (+ a
3) 4))
698 (test-ps-js getprop-conditional1
699 (getprop (if zoo foo bar
) 'x
)
700 "(zoo ? foo : bar).x;")
702 (test-ps-js getprop-conditional2
703 (getprop (if (not zoo
) foo bar
) 'x
)
704 "(!zoo ? foo : bar).x;")
706 (test script-star-eval1
707 (is (string= "x = 1; y = 2;" (normalize-js-code (ps* '(setf x
1) '(setf y
2))))))
709 (test script-star-eval2
710 (is (string= "x = 1;" (normalize-js-code (ps* '(setf x
1))))))
712 (test-ps-js list-with-single-nil
716 (test-ps-js quoted-nil-is-array
721 (progn (defsetf baz
(x y
) (newval) `(set-baz ,x
,y
,newval
))
726 setBaz(_js2, _js3, _js1);")
728 (test-ps-js setf-macroexpands1
729 (macrolet ((bar (x y
)
731 (setf (bar foo
2) 3))
734 (test-ps-js defsetf-short
735 (progn (defsetf baz set-baz
"docstring")
736 (setf (baz 1 2 3) "foo"))
737 "setBaz(1, 2, 3, 'foo');")
739 (test-ps-js defun-setf1
740 (progn (defun (setf some-thing
) (new-val i1 i2
)
741 (setf (aref *some-thing
* i1 i2
) new-val
))
742 (setf (some-thing 1 2) "foo"))
743 "function __setf_someThing(newVal, i1, i2) {
744 return SOMETHING[i1][i2] = newVal;
746 __setf_someThing('foo', 1, 2);")
748 (test-ps-js defun-optional1
749 (defun test-opt (&optional x
)
751 "function testOpt(x) {
752 return x ? 'yes' : 'no';
755 (test-ps-js defun-optional2
756 (defun foo (x &optional y
)
758 "function foo(x, y) {
762 (test-ps-js defun-optional3
763 (defun blah (&optional
(x 0))
766 if (x === undefined) {
772 (test-ps-js defun-optional4
773 (lambda (&optional
(x 0 supplied?
))
776 var suppliedwhat = x !== undefined;
783 (test-ps-js return-nothing
784 (defun foo () (return-from foo
))
789 (test-ps-js set-timeout
790 (set-timeout (lambda () (alert "foo")) 10)
791 "setTimeout(function () { return alert('foo'); }, 10);")
793 (test-ps-js operator-precedence
797 (test-ps-js operators-1
817 (test-ps-js setf-conditional
818 (setf foo
(if x
1 2))
821 (test-ps-js obj-literal-numbers
825 (test-ps-js obj-literal-strings
829 (test-ps-js getprop-string
833 (test-ps-js getprop-string1
834 (getprop "bar" 'length
)
837 (test-ps-js getprop-progn
838 (getprop (progn (some-fun "abc") "123") "length")
839 "(someFun('abc'), '123')['length'];")
841 (test-ps-js method-call-block
842 ((@ (progn (some-fun "abc") "123") to-string
))
843 "(someFun('abc'), '123').toString();")
845 (test-ps-js create-blank
849 (test-ps-js blank-object-literal
853 (test-ps-js array-literal1
857 (test-ps-js array-literal2
861 (test-ps-js array-literal3
865 (test-ps-js array-literal4
869 (test-ps-js array-literal5
871 "[[1, 2], ['a', 'b']];")
873 (test-ps-js defun-rest1
874 (defun foo (&rest bar
)
875 (alert (aref bar
1)))
878 for (var i1 = 0; i1 < arguments.length - 0; i1 += 1) {
879 bar[i1] = arguments[i1 + 0];
881 return alert(bar[1]);
884 (test-ps-js defun-rest2
885 (defun foo (baz &rest bar
) (+ baz
(aref bar
1)))
888 for (var i1 = 0; i1 < arguments.length - 1; i1 += 1) {
889 bar[i1] = arguments[i1 + 1];
894 (test-ps-js defun-keyword1
895 (defun zoo (foo bar
&key baz
) (+ foo bar baz
))
896 "function zoo(foo, bar) {
897 var _js2 = arguments.length;
898 for (var n1 = 2; n1 < _js2; n1 += 2) {
899 switch (arguments[n1]) {
901 baz = arguments[n1 + 1];
905 return foo + bar + baz;
908 (test-ps-js defun-keyword2
909 (defun zoo (&key baz
) (* baz baz
))
911 var _js2 = arguments.length;
912 for (var n1 = 0; n1 < _js2; n1 += 2) {
913 switch (arguments[n1]) {
915 baz = arguments[n1 + 1];
922 (test-ps-js defun-keyword3
923 (defun zoo (&key baz
(bar 4)) (* baz bar
))
925 var _js2 = arguments.length;
926 for (var n1 = 0; n1 < _js2; n1 += 2) {
927 switch (arguments[n1]) {
929 baz = arguments[n1 + 1];
932 bar = arguments[n1 + 1];
936 var bar = undefined === bar ? 4 : bar;
940 (test-ps-js defun-keyword4
941 (defun hello-world (&key
((:my-name-key my-name
) 1))
943 "function helloWorld() {
944 var _js2 = arguments.length;
945 for (var n1 = 0; n1 < _js2; n1 += 2) {
946 switch (arguments[n1]) {
948 myName = arguments[n1 + 1];
951 var myName = undefined === myName ? 1 : myName;
955 (test-ps-js defun-keyword-supplied
956 (lambda (&key
(foo 1 supplied?
))
959 var _js2 = arguments.length;
960 for (var n1 = 0; n1 < _js2; n1 += 2) {
961 switch (arguments[n1]) {
963 foo = arguments[n1 + 1];
968 var foo = undefined === foo ? 1 : foo;
972 (test-ps-js keyword-funcall1
976 (test-ps-js keyword-funcall2
977 (func :baz
1 :bar foo
)
978 "func('baz', 1, 'bar', foo);")
980 (test-ps-js keyword-funcall3
982 "fun(a, b, 'baz', c);")
992 ((= y
(* x
4)) (foo "blah") (* x y
)))
995 } else if (y === x * 4) {
1000 (test-ps-js if-exp-without-else-return
1001 (defun foo () (return-from foo
(if x
1)))
1003 return x ? 1 : null;
1006 (test-ps-js progn-expression-single-statement
1007 (defun foo () (return-from foo
(progn (* x y
))))
1012 (test-ps-js cond-expression1
1014 (cond ((< 1 2) (bar "foo") (* 4 5))))
1022 (test-ps-js cond-expression2
1024 (cond ((< 2 1) "foo")
1029 } else if (7 === 7) {
1034 (test-ps-js cond-expression-final-t-clause
1036 (cond ((< 1 2) (bar "foo") (* 4 5))
1047 } else if (a === b) {
1049 } else if (_cmp1 = 2, _cmp2 = 3, _cmp3 = 4, 1 < _cmp1 && _cmp1 < _cmp2 && _cmp2 < _cmp3 && _cmp3 < 5) {
1056 (test-ps-js cond-expression-middle-t-clause
;; should this signal a warning?
1069 (test-ps-js funcall-if-expression
1070 (funcall (getprop document
'write
)
1071 (if (= *linkornot
* 1)
1072 (ps-html ((:a
:href
"#"
1073 :onclick
(ps-inline (transport)))
1076 "document.write(LINKORNOT === 1 ? ['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">', img, '</A>']['join']('') : img);")
1078 (test-ps-js negate-number-literal
1082 (test macro-environment1
1083 (is (string= (normalize-js-code (let* ((macroname (gensym)))
1084 (ps* `(defmacro ,macroname
(x) `(+ ,x
123))
1086 (macrolet ((,macroname
(x) `(aref data
,x
)))
1087 (when (,macroname x
)
1088 (setf (,macroname x
) 123)))))))
1091 return data[x] ? (data[x] = 123) : null;
1094 (test macro-environment2
1095 (is (string= (normalize-js-code (let ((outer-lexical-variable 1))
1096 (defpsmacro macro-environment2-macro
(x)
1097 `(+ ,outer-lexical-variable
,x
))
1098 (ps* '(macro-environment2-macro 2))))
1099 (normalize-js-code "1 + 2;"))))
1101 (test-ps-js ampersand-whole-1
1102 (macrolet ((foo (&whole foo bar baz
)
1103 (declare (ignore bar baz
))
1104 (with-standard-io-syntax (format nil
"~a" foo
))))
1108 (test-ps-js keyword-consistent
1112 (test-ps-js simple-symbol-macrolet
1113 (symbol-macrolet ((x 1)) x
)
1116 (test-ps-js compound-symbol-macrolet
1117 (symbol-macrolet ((x 123)
1122 (test-ps-js define-symbol-macro
1123 (progn (define-symbol-macro tst-sym-macro
2)
1127 (test-ps-js define-symbol-macro1
1128 (progn (define-symbol-macro tst-sym-macro1
2)
1129 (foo tst-sym-macro1
))
1132 (test-ps-js expression-progn
1133 (1+ (progn (foo) (if x
1 2)))
1134 "(foo(), x ? 1 : 2) + 1;")
1136 (test-ps-js let-decl-in-expression
1138 (if x
1 (let* ((foo x
)) foo
)))
1148 (test-ps-js special-var1
1149 (progn (defvar *foo
*)
1155 FOO_TMPSTACK1 = FOO;
1159 FOO = FOO_TMPSTACK1;
1162 (test-ps-js special-var2
1163 (progn (defvar *foo
*)
1171 FOO_TMPSTACK1 = FOO;
1175 FOO = FOO_TMPSTACK1;
1178 (test-ps-js literal1
1182 (test-ps-js literal2
1186 (test-ps-js setf-dec1
1190 (test-ps-js setf-dec2
1194 (test-ps-js special-char-equals
1198 (test-ps-js setf-operator-priority
1200 (or (getprop cache id
)
1201 (setf (getprop cache id
) ((@ document get-element-by-id
) id
))))
1203 return cache[id] || (cache[id] = document.getElementById(id));
1206 (test-ps-js aref-operator-priority
1207 (aref (if (and x
(> (length x
) 0))
1211 "(x && x.length > 0 ? x[0] : y)[z];")
1213 (test-ps-js aref-operator-priority1
1214 (aref (or (getprop x
'y
)
1219 (test-ps-js aref-operator-priority2
1223 (test-ps-js negate-operator-priority
1232 (delete (if a
(or b c
) d
))
1233 "delete (a ? b || c : d);")
1236 (not (if (or x
(not y
)) z
))
1237 "!(x || !y ? z : null);")
1244 (instanceof (or a b
) (if x y z
))
1245 "((a || b) instanceof (x ? y : z));")
1248 (or x
(if (= x
0) "zero" "empty"))
1249 "x || (x === 0 ? 'zero' : 'empty');")
1251 (test-ps-js named-op-expression
1255 (test-ps-js named-op-expression1
1259 (test-ps-js aref-array-expression
1261 "(a || b || c)[0];")
1263 (test-ps-js getprop-operator
1264 (getprop (or a b c
) 'd
)
1267 (test-ps-js getprop-parens
1268 (getprop (getprop foo
'bar
) 'baz
)
1271 (test-ps-js funcall-funcall
1275 (test-ps-js expression-funcall
1276 ((or (@ window eval
) eval
) foo nil
)
1277 "(window.eval || eval)(foo, null);")
1279 (test-ps-js expression-funcall1
1280 (((or (@ window eval
) eval
) foo nil
))
1281 "(window.eval || eval)(foo, null)();")
1283 (test-ps-js expression-funcall2
1284 (((or (@ window eval
) eval
)) foo nil
)
1285 "(window.eval || eval)()(foo, null);")
1287 (test-ps-js who-html1
1288 (who-ps-html (:span
:class
"ticker-symbol"
1289 :ticker-symbol symbol
1290 (:a
:href
"http://foo.com"
1292 (:span
:class
"ticker-symbol-popup")))
1293 "['<SPAN CLASS=\"ticker-symbol\" TICKER-SYMBOL=\"', symbol, '\"><A HREF=\"http://foo.com\">', symbol, '</A><SPAN CLASS=\"ticker-symbol-popup\"></SPAN></SPAN>']['join']('');")
1296 ((lambda () (flet ((foo (x)
1300 var foo = function (x) {
1307 (flet ((foo (x) (1+ x
))
1310 "var foo = function (x) {
1313 var bar = function (y) {
1319 (flet ((foo (x) (+ 2 x
)))
1320 (flet ((foo (x) (1+ x
))
1321 (bar (y) (+ 2 (foo y
))))
1323 "var foo = function (x) {
1326 var foo1 = function (x) {
1329 var bar = function (y) {
1335 ((lambda () (labels ((foo (x)
1338 (+ x
(foo (1- x
))))))
1341 var foo = function (x) {
1342 return 0 === x ? 0 : x + foo(x - 1);
1348 (labels ((foo (x) (1+ (bar x
)))
1349 (bar (y) (+ 2 (foo y
))))
1351 "var foo = function (x) {
1354 var bar = function (y) {
1360 (labels ((foo (x) (1+ x
))
1361 (bar (y) (+ 2 (foo y
))))
1363 "var foo = function (x) {
1366 var bar = function (y) {
1371 (test-ps-js for-loop-var-init-exp
1373 (do* ((y (if x
0 1) (1+ y
))
1378 return (function () {
1379 for (var y = x ? 0 : 1, z = 0; y !== 3; y += 1, z += 1) {
1389 (test-ps-js literal-array
1393 (test-ps-js literal-array-1
1397 (test ps-lisp-expands-in-lexical-environment
1398 (is (string= "5;" (let ((x 5)) (ps (lisp x
))))))
1400 (test ps
*-lisp-expands-in-null-lexical-environment
1401 (signals error
(let ((x 5)) (declare (ignore x
)) (ps* '(lisp x
)))))
1403 (test ps
*-lisp-expands-in-dynamic-environment
1404 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo
)) (ps* '(+ 1 (lisp (locally (declare (special foo
)) foo
))))))))
1406 (test ps-lisp-dynamic-environment
1407 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo
)) (ps (+ 1 (lisp foo
)))))))
1409 (test-ps-js nested-if-expressions1
1411 (return-from foo
(if (if x y z
) a b
)))
1413 return (x ? y : z) ? a : b;
1416 (test-ps-js nested-if-expressions2
1418 (if x y
(if z a b
)))
1483 (test-ps-js let-exp1
1526 (test-ps-js symbol-macrolet-var
1527 (symbol-macrolet ((x y
))
1531 (test-ps-js setf-conditional1
1532 (setf x
(unless (null a
) (1+ a
)))
1533 "x = a != null ? a + 1 : null;")
1535 (test-ps-js setf-let1
1536 (setf x
(let ((a 1)) a
))
1539 (test-ps-js setf-let2
1540 (setf x
(let ((a (foo)))
1543 "x = (a = foo(), a != null ? a + 1 : null);")
1545 (test-ps-js symbol-macro-env1
1546 (symbol-macrolet ((bar 1))
1547 (macrolet ((bar (x y
) `(+ ,x
,y
)))
1551 (test-ps-js symbol-macrolet-fun1
1552 (symbol-macrolet ((baz +))
1556 (test-ps-js lisp2-namespaces1
1558 (setf list
(list 1 2 3)))
1562 (test-ps-js let-shadows-symbol-macrolet
1563 (symbol-macrolet ((x y
))
1571 (test-ps-js let-rename-optimization1
1577 (test-ps-js let-rename-optimization2
1586 (test-ps-js symbol-macro-array
1587 (symbol-macrolet ((x 1))
1591 (test-ps-js symbol-macro-obj
1592 (symbol-macrolet ((x y
))
1596 (test-ps-js symbol-macro-conditional1
1597 (symbol-macrolet ((x y
))
1605 (test-ps-js symbol-macro-conditional2
1606 (symbol-macrolet ((x y
))
1610 (test-ps-js flet-apply
1611 (flet ((foo () 'bar
))
1612 (apply (function foo
) nil
))
1613 "var foo = function () {
1616 foo.apply(this, null);")
1618 (test-ps-js let-apply
1619 (let ((foo (lambda () 1)))
1620 (let ((foo (lambda () 2)))
1622 "var foo = function () {
1625 var foo1 = function () {
1628 foo1.apply(this, null);")
1630 (test-ps-js flet-let
1631 (flet ((x (x) (1+ x
)))
1634 "var x = function (x) {
1640 (test-ps-js let-flet
1642 (flet ((x (x) (1+ x
)))
1645 var x1 = function (x) {
1650 (test-ps-js labels-let
1651 (labels ((x (x) (1+ x
)))
1654 "var x = function (x) {
1660 (test-ps-js let-labels
1662 (labels ((x (x) (1+ x
)))
1665 var x1 = function (x) {
1670 (test-ps-js macrolet-let-inteference
1671 (macrolet ((a (n) `(+ ,n
5)))
1673 (let ((b (a (- a
4))))
1679 (test-ps-js let-subtract-add
1693 (test-ps-js create-reserved-word
1695 "{ 'default' : 1 };")
1697 (test-ps-js getprop-reserved-word
1698 (getprop foo
:default
)
1701 (test-ps-js getprop-reserved-word1
1702 (getprop foo
'default
)
1705 (test-ps-js eval-when-ps-side
1706 (eval-when (:execute
)
1710 (defvar *lisp-output
* nil
)
1712 (test eval-when-lisp-side
()
1713 (setf *lisp-output
* 'original-value
)
1714 (let ((js-output (normalize-js-code
1715 (ps-doc* `(eval-when (:compile-toplevel
)
1716 (setf *lisp-output
* 'it-works
))))))
1717 (is (eql 'it-works
*lisp-output
*))
1718 (is (string= "" js-output
))))
1720 (defpsmacro my-in-package
(package-name)
1721 `(eval-when (:compile-toplevel
)
1722 (setf *lisp-output
* ,package-name
)))
1724 (test eval-when-macro-expansion
()
1725 (setf *lisp-output
* 'original-value
)
1726 (let ((js-output (normalize-js-code
1728 (my-in-package :cl-user
)
1730 (declare (ignore js-output
))
1731 (is (eql :cl-user
*lisp-output
*))))
1733 (test eval-when-macrolet-expansion
()
1734 (setf *lisp-output
* 'original-value
)
1735 (let ((js-output (normalize-js-code
1736 (ps-doc* `(macrolet ((my-in-package2 (package-name)
1737 `(eval-when (:compile-toplevel
)
1738 (setf *lisp-output
* ,package-name
))))
1739 (my-in-package2 :cl-user
)
1741 (declare (ignore js-output
))
1742 (is (eql :cl-user
*lisp-output
*))))
1744 (test-ps-js getprop-keyword
1748 (test-ps-js nary-comparison1
1749 (lambda () (< 1 2 3))
1752 return (_cmp1 = 2, 1 < _cmp1 && _cmp1 < 3);
1755 (test-ps-js chain-getprop1
1756 (chain ($
"foo") (bar x z
) frob
(baz 5))
1757 "$('foo').bar(x, z).frob.baz(5);")
1759 (test-ps-js chain-getprop2
1760 (chain ($
"foo") bar baz
)
1761 "$('foo').bar.baz;")
1763 (test-ps-js chain-getprop3
1764 (chain ($
"foo") bar
(x y
) baz
)
1765 "$('foo').bar.x(y).baz;")
1767 (test-ps-js flet-expression
1768 (1+ (flet ((foo (x) (1+ x
)))
1770 "(foo = function (x) {
1774 (test-ps-js return-case-break-elimination
1789 (test-ps-js aplusplus
1793 (test-ps-js astarstar
1797 (test-ps-js switch-return-fallthrough
1815 (test-ps-js return-last-case
1830 (test-ps-js return-macrolet
1833 (macrolet ((x () 1))
1846 (test-ps-js mv-bind1
1847 (multiple-value-bind (a b
)
1853 "var prevMv2 = null;
1855 prevMv2 = arguments['callee']['mv'];
1857 arguments['callee']['mv'] = true;
1859 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1864 if (undefined === prevMv2) {
1865 delete arguments['callee']['mv'];
1867 arguments['callee']['mv'] = prevMv2;
1871 (test-ps-js mv-bind2
1872 (multiple-value-bind (a b
)
1878 "var prevMv2 = null;
1881 prevMv2 = arguments['callee']['mv'];
1883 arguments['callee']['mv'] = true;
1885 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1890 if (undefined === prevMv2) {
1891 delete arguments['callee']['mv'];
1893 arguments['callee']['mv'] = prevMv2;
1898 (lambda () (values))
1911 if (undefined !== arguments['callee']['caller']['mv']) {
1912 arguments['callee']['caller']['mv'] = valrest2;
1919 var valrest2 = [y, z];
1920 if (undefined !== arguments['callee']['caller']['mv']) {
1921 arguments['callee']['caller']['mv'] = valrest2;
1925 (test-ps-js values-return
1927 (return-from foo
(values x y
)))
1931 if (undefined !== arguments['callee']['caller']['mv']) {
1932 arguments['callee']['caller']['mv'] = valrest2;
1937 (test-ps-js return-macrolet
1940 (symbol-macrolet ((x 2))
1941 (loop do
(+ x x
)))))
1949 (test-ps-js return-cond
1952 (cond ((foo? x
) (loop for y in x do
(foo y
)))
1957 var _js2 = x.length;
1971 } else if (barwhat(x)) {
1978 (test-ps-js switch-loop
1983 for (var a = null, _js_idx1 = 0; _js_idx1 < b.length; _js_idx1 += 1) {
1988 (test-ps-js switch-folds-blocks
1990 (1 (loop repeat
3 do
(alert "foo"))))
1993 for (var _js1 = 0; _js1 < 3; _js1 += 1) {
1998 (test-ps-js setf-places-before-macros
2000 (defsetf left
(el) (offset)
2001 `(setf (@ ,el style left
) ,offset
))
2002 (macrolet ((left (el)
2003 `(@ ,el offset-left
)))
2008 _js2.style.left = _js1;
2011 (test-ps-js for-return
2012 (lambda () (dolist (arg args
) (foo arg
)))
2014 for (var arg = null, _js_idx1 = 0; _js_idx1 < args.length; _js_idx1 += 1) {
2015 arg = args[_js_idx1];
2020 (test-ps-js try-catch-return
2038 (test-ps-js defun-setf-optional
2039 (defun (setf foo
) (new-value b
&optional c
)
2040 (setf (aref b
(or c
0)) new-value
))
2041 "function __setf_foo(newValue, b, c) {
2042 return b[c || 0] = newValue;
2045 (test-ps-js defun-setf-rest
2046 (progn (defun (setf foo
) (new-value b
&rest foo
)
2047 (do-something b foo new-value
))
2048 (setf (foo x
1 2 3 4) 5))
2049 "function __setf_foo(newValue, b) {
2051 for (var i1 = 0; i1 < arguments.length - 2; i1 += 1) {
2052 foo[i1] = arguments[i1 + 2];
2054 return doSomething(b, foo, newValue);
2056 __setf_foo(5, x, 1, 2, 3, 4);")
2058 (test-ps-js return-null
2059 (defun foo () (return-from foo nil
))
2064 (test-ps-js implicit-return-null
2071 (test-ps-js implicit-return-null
2078 (test-ps-js return-conditional-nested
2079 (defun blep (ss x y
)
2083 (destructuring-bind (a b
) pair
2084 (unless (or (null a
) (null b
))
2085 (let ((val (baz a b
)))
2090 "function blep(ss, x, y) {
2096 if (!(a == null || b == null)) {
2097 var val = baz(a, b);
2100 return !blee() ? true : null;
2108 ;; this test needs to be rewritten when named blocks are implemented!!!!
2109 (test-ps-js return-when-returns-broken-return
2111 (return-from foo
(when x
1))
2114 return x ? 1 : null;
2118 (test-ps-js return-case-conditional
2122 (123 (when (bar) t
))
2127 return bar() ? true : null;
2133 (test-ps-js return-try-conditional
2141 return x ? 1 : null;
2149 (test-ps-js function-declare-special
2151 (declare (special *foo
*))
2157 FOO_TMPSTACK1 = FOO;
2161 FOO = FOO_TMPSTACK1;
2165 (test-ps-js declare-special-let
2167 (declare (special *foo
*))
2171 FOO_TMPSTACK1 = FOO;
2175 FOO = FOO_TMPSTACK1;
2178 (test-ps-js macro-null-toplevel
2180 (defmacro macro-null-toplevel
()
2182 (macro-null-toplevel))
2185 (test-ps-js define-symbol-macro-let
2187 (define-symbol-macro test-symbol-macro
1)
2188 (let ((test-symbol-macro 2))
2189 (1+ test-symbol-macro
))
2190 (1+ test-symbol-macro
))
2191 "var testSymbolMacro1 = 2;
2192 testSymbolMacro1 + 1;
2195 (test-ps-js define-symbol-macro-flet
2197 (define-symbol-macro test-symbol-macro1
1)
2198 (flet ((test-symbol-macro1 () 2))
2199 (foo test-symbol-macro1
)
2200 (test-symbol-macro1))
2201 (bar test-symbol-macro1
))
2202 "var testSymbolMacro1_1 = function () {
2206 testSymbolMacro1_1();
2209 (test compile-stream-nulls
2212 (with-input-from-string (s "
2213 (defmacro macro-null-toplevel ()
2215 (macro-null-toplevel)")
2216 (ps-compile-stream s
)))))
2218 (test compile-stream1
2220 "var testSymbolMacro1_1 = function () {
2224 testSymbolMacro1_1();
2227 (with-input-from-string (s "
2228 (define-symbol-macro test-symbol-macro1 1)
2229 (flet ((test-symbol-macro1 () 2))
2230 (foo test-symbol-macro1)
2231 (test-symbol-macro1))
2232 (bar test-symbol-macro1)")
2233 (ps::with-blank-compilation-environment
(ps-compile-stream s
))))))
2235 (test-ps-js equality-nary1
2236 (let ((x 10) (y 10) (z 10))
2242 x === _cmp1 && _cmp1 === z;")
2244 (test-ps-js equality1
2255 (test-ps-js getprop-quote-reserved
2256 (getprop foo
':break
)
2259 (test-ps-js defun-block-return-from
2270 (test-ps-js block-return-from
2274 (return-from scope
))
2284 (test-ps-js let-funcall
2296 (test-ps-js symbol-macrolet-funcall
2297 (symbol-macrolet ((foo bar
))
2298 (funcall foo
1 2 3))
2301 (test-ps-js times-assign
2305 (test-ps-js vector-literal
2310 (+ 1 (rem 2 (+ 3 4)))
2313 (test-ps-js non-associative
2314 (+ (/ 1 (/ 2 3)) (- 1 (- 2 3)))
2315 "1 / (2 / 3) + 1 - (2 - 3);")
2317 (test-ps-js lambda-apply
2319 (apply (lambda (y) (bar (1+ y
))) x
))
2321 return (function (y) {
2326 (test-ps-js operator-expressions-nested-let
2327 (let ((x (let ((y 1))
2330 "var x = (y = 1, y); x;")
2332 (test-ps-js operator-expressions-array-nested-let
2333 (list (let ((y 1)) y
) 2)
2336 (test-ps-js add-subtract-precedence
2340 (test-ps-js ps-inline-toplevel
2342 "'javascript:' + 'foo()';")
2344 (test-ps-js no-clause-progn-exp
2348 (test-ps-js no-clause-progn-return
2350 (return-from foo
(progn)))
2355 (test-ps-js empty-cond-clause
2356 (setf x
(cond ((foo))))
2357 "x = foo() ? null : null;")
2359 (test-ps-js empty-cond-clause1
2360 (setf x
(cond ((foo) 123)
2363 "x = foo() ? 123 : (bar() ? null : 456);")
2365 (test-ps-js let-no-body
2367 (return-from foo
(let ((foo bar
)))))
2373 (test-ps-js dont-hoist-lexical-dupes
2375 (list (let ((foo 12)) (* foo
2))
2376 (let ((foo 13)) (* foo
3))))
2379 return [(foo = 12, foo * 2), (foo = 13, foo * 3)];
2382 (test-ps-js defun-comment1
2384 "BARBAR is a revolutionary new foobar.
2388 * BARBAR is a revolutionary new foobar.
2395 (test-ps-js var-comment
2400 (test-ps-js case-return-break-broken-return
2403 ("bar" (if y
(return-from foo t
) nil
))
2417 (test-ps-js case-return-break1-broken-return
2420 ("bar" (if y
(return-from foo t
)))
2434 (test-ps-js setf-progn
2435 (setf foo
(progn (bar) (baz) 3))
2440 ;; (test-ps-js var-progn
2441 ;; (var x (progn (foo) (bar)))
2445 (test-ps-js implicit-return-loop
2449 (loop :repeat
100 :do
(bar))
2455 for (var _js2 = 0; _js2 < 100; _js2 += 1) {
2462 ;; closures in loops need a new binding per loop iteration (idea borrowed from Scheme2JS)
2463 (test-ps-js loop-closures
2464 (dotimes (i 10) (lambda () (+ i
1)))
2465 "for (var i = 0; i < 10; i += 1) {
2473 (test-ps-js loop-closures-let
2474 (dotimes (i 10) (let ((x (+ i
1))) (lambda () (+ i x
))))
2475 "for (var i = 0; i < 10; i += 1) {
2476 with ({ x : null, i : i }) {
2484 (test-ps-js loop-closures-flet
2485 (dotimes (i 10) (flet ((foo (x) (+ i x
))) (lambda () (foo i
))))
2486 "for (var i = 0; i < 10; i += 1) {
2487 with ({ foo : null, i : i }) {
2488 var foo = function (x) {
2497 (test-ps-js while-closures-let
2500 (lambda () (+ 1 x
))))
2502 with ({ x : null }) {
2510 (test-ps-js dotted-list-form
2513 (destructuring-bind (b . c
)
2519 var c = bar.length > 1 ? bar.slice(1) : [];
2524 (test-ps-js return-from-loop
2525 (dolist (x '(2 1 3))
2528 (chain console
(log x
)))
2529 "for (var x = null, _js_arrvar2 = [2, 1, 3], _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
2530 x = _js_arrvar2[_js_idx1];
2537 (test-ps-js explicit-nil-block
2538 (block nil
(return) (+ 1 2))
2544 (test-ps-js dynamic-extent-function-return
2545 (defun foo () ((lambda () (return-from foo
))))
2548 return (function () {
2549 throw { 'ps-block-tag' : 'foo', 'ps-return-value' : null };
2552 if (err && 'foo' === err['ps-block-tag']) {
2553 err['ps-return-value'];
2560 (test-ps-js block-dynamic-return
2561 (block nil
((lambda () (return))) (+ 1 2))
2565 throw { 'ps-block-tag' : 'nilBlock', 'ps-return-value' : null };
2569 if (err && 'nilBlock' === err['ps-block-tag']) {
2570 err['ps-return-value'];
2577 (test-ps-js iteration-lambda-capture-no-need
2578 (dolist (x y
) (lambda (x) (1+ x
))) ;; there's really no need to create a 'with' scope in this case
2579 "for (var x = null, _js_idx1 = 0; _js_idx1 < y.length; _js_idx1 += 1) {
2588 (test-ps-js case-invert1
2589 (encodeURIComponent fooBar
)
2590 "encodeURIComponent(fooBar);")
2592 (test-ps-js simple-ash
2593 (+ (ash 4 1) (ash 4 -
1))
2594 "(4 << 1) + (4 >> 1);")
2596 (test-ps-js progn-nil-expression
2597 (bar (progn (foo) nil
))
2598 "bar((foo(), null));")
2600 (test-ps-js other-progn-nil-exp
2602 (or (foo) (progn (bar) nil
)))
2604 return foo() || (bar(), null);
2607 (test-ps-js lambda-nil-return
2620 (test-ps-js lambda-nil-return-implicit-nested
2632 for (var i = 0; i < 4; i += 1) {
2639 (test-ps-js throw-is-a-statement
2641 (let ((result (foo)))
2642 (unless (null result
)
2646 if (result != null) {
2651 (test-ps-js expressify1
2653 (when (some-condition)
2658 if (someCondition()) {