PageRenderTime 36ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/test/objects.coffee

http://github.com/jashkenas/coffee-script
CoffeeScript | 932 lines | 735 code | 150 blank | 47 comment | 28 complexity | 9b7bbc9e23478543c04253f154bed6e6 MD5 | raw file
  1. # Object Literals
  2. # ---------------
  3. # TODO: refactor object literal tests
  4. # TODO: add indexing and method invocation tests: {a}['a'] is a, {a}.a()
  5. trailingComma = {k1: "v1", k2: 4, k3: (-> true),}
  6. ok trailingComma.k3() and (trailingComma.k2 is 4) and (trailingComma.k1 is "v1")
  7. ok {a: (num) -> num is 10 }.a 10
  8. moe = {
  9. name: 'Moe'
  10. greet: (salutation) ->
  11. salutation + " " + @name
  12. hello: ->
  13. @['greet'] "Hello"
  14. 10: 'number'
  15. }
  16. ok moe.hello() is "Hello Moe"
  17. ok moe[10] is 'number'
  18. moe.hello = ->
  19. this['greet'] "Hello"
  20. ok moe.hello() is 'Hello Moe'
  21. obj = {
  22. is: -> yes,
  23. 'not': -> no,
  24. }
  25. ok obj.is()
  26. ok not obj.not()
  27. ### Top-level object literal... ###
  28. obj: 1
  29. ### ...doesn't break things. ###
  30. # Object literals should be able to include keywords.
  31. obj = {class: 'höt'}
  32. obj.function = 'dog'
  33. ok obj.class + obj.function is 'hötdog'
  34. # Implicit objects as part of chained calls.
  35. pluck = (x) -> x.a
  36. eq 100, pluck pluck pluck a: a: a: 100
  37. test "YAML-style object literals", ->
  38. obj =
  39. a: 1
  40. b: 2
  41. eq 1, obj.a
  42. eq 2, obj.b
  43. config =
  44. development:
  45. server: 'localhost'
  46. timeout: 10
  47. production:
  48. server: 'dreamboat'
  49. timeout: 1000
  50. ok config.development.server is 'localhost'
  51. ok config.production.server is 'dreamboat'
  52. ok config.development.timeout is 10
  53. ok config.production.timeout is 1000
  54. obj =
  55. a: 1,
  56. b: 2,
  57. ok obj.a is 1
  58. ok obj.b is 2
  59. # Implicit objects nesting.
  60. obj =
  61. options:
  62. value: yes
  63. fn: ->
  64. {}
  65. null
  66. ok obj.options.value is yes
  67. ok obj.fn() is null
  68. # Implicit objects with wacky indentation:
  69. obj =
  70. 'reverse': (obj) ->
  71. Array.prototype.reverse.call obj
  72. abc: ->
  73. @reverse(
  74. @reverse @reverse ['a', 'b', 'c'].reverse()
  75. )
  76. one: [1, 2,
  77. a: 'b'
  78. 3, 4]
  79. red:
  80. orange:
  81. yellow:
  82. green: 'blue'
  83. indigo: 'violet'
  84. misdent: [[],
  85. [],
  86. [],
  87. []]
  88. ok obj.abc().join(' ') is 'a b c'
  89. ok obj.one.length is 5
  90. ok obj.one[4] is 4
  91. ok obj.one[2].a is 'b'
  92. ok (key for key of obj.red).length is 2
  93. ok obj.red.orange.yellow.green is 'blue'
  94. ok obj.red.indigo is 'violet'
  95. ok obj.misdent.toString() is ',,,'
  96. #542: Objects leading expression statement should be parenthesized.
  97. {f: -> ok yes }.f() + 1
  98. # String-keyed objects shouldn't suppress newlines.
  99. one =
  100. '>!': 3
  101. six: -> 10
  102. ok not one.six
  103. # Shorthand objects with property references.
  104. obj =
  105. ### comment one ###
  106. ### comment two ###
  107. one: 1
  108. two: 2
  109. object: -> {@one, @two}
  110. list: -> [@one, @two]
  111. result = obj.object()
  112. eq result.one, 1
  113. eq result.two, 2
  114. eq result.two, obj.list()[1]
  115. third = (a, b, c) -> c
  116. obj =
  117. one: 'one'
  118. two: third 'one', 'two', 'three'
  119. ok obj.one is 'one'
  120. ok obj.two is 'three'
  121. test "invoking functions with implicit object literals", ->
  122. generateGetter = (prop) -> (obj) -> obj[prop]
  123. getA = generateGetter 'a'
  124. getArgs = -> arguments
  125. a = b = 30
  126. result = getA
  127. a: 10
  128. eq 10, result
  129. result = getA
  130. "a": 20
  131. eq 20, result
  132. result = getA a,
  133. b:1
  134. eq undefined, result
  135. result = getA b:1,
  136. a:43
  137. eq 43, result
  138. result = getA b:1,
  139. a:62
  140. eq undefined, result
  141. result = getA
  142. b:1
  143. a
  144. eq undefined, result
  145. result = getA
  146. a:
  147. b:2
  148. b:1
  149. eq 2, result.b
  150. result = getArgs
  151. a:1
  152. b
  153. c:1
  154. ok result.length is 3
  155. ok result[2].c is 1
  156. result = getA b: 13, a: 42, 2
  157. eq 42, result
  158. result = getArgs a:1, (1 + 1)
  159. ok result[1] is 2
  160. result = getArgs a:1, b
  161. ok result.length is 2
  162. ok result[1] is 30
  163. result = getArgs a:1, b, b:1, a
  164. ok result.length is 4
  165. ok result[2].b is 1
  166. throwsCompileError "a = b:1, c"
  167. test "some weird indentation in YAML-style object literals", ->
  168. two = (a, b) -> b
  169. obj = then two 1,
  170. 1: 1
  171. a:
  172. b: ->
  173. fn c,
  174. d: e
  175. f: 1
  176. eq 1, obj[1]
  177. test "#1274: `{} = a()` compiles to `false` instead of `a()`", ->
  178. a = false
  179. fn = -> a = true
  180. {} = fn()
  181. ok a
  182. test "#1436: `for` etc. work as normal property names", ->
  183. obj = {}
  184. eq no, obj.hasOwnProperty 'for'
  185. obj.for = 'foo' of obj
  186. eq yes, obj.hasOwnProperty 'for'
  187. test "#2706, Un-bracketed object as argument causes inconsistent behavior", ->
  188. foo = (x, y) -> y
  189. bar = baz: yes
  190. eq yes, foo x: 1, bar.baz
  191. test "#2608, Allow inline objects in arguments to be followed by more arguments", ->
  192. foo = (x, y) -> y
  193. eq yes, foo x: 1, y: 2, yes
  194. test "#2308, a: b = c:1", ->
  195. foo = a: b = c: yes
  196. eq b.c, yes
  197. eq foo.a.c, yes
  198. test "#2317, a: b c: 1", ->
  199. foo = (x) -> x
  200. bar = a: foo c: yes
  201. eq bar.a.c, yes
  202. test "#1896, a: func b, {c: d}", ->
  203. first = (x) -> x
  204. second = (x, y) -> y
  205. third = (x, y, z) -> z
  206. one = 1
  207. two = 2
  208. three = 3
  209. four = 4
  210. foo = a: second one, {c: two}
  211. eq foo.a.c, two
  212. bar = a: second one, c: two
  213. eq bar.a.c, two
  214. baz = a: second one, {c: two}, e: first first h: three
  215. eq baz.a.c, two
  216. qux = a: third one, {c: two}, e: first first h: three
  217. eq qux.a.e.h, three
  218. quux = a: third one, {c: two}, e: first(three), h: four
  219. eq quux.a.e, three
  220. eq quux.a.h, four
  221. corge = a: third one, {c: two}, e: second three, h: four
  222. eq corge.a.e.h, four
  223. test "Implicit objects, functions and arrays", ->
  224. first = (x) -> x
  225. second = (x, y) -> y
  226. foo = [
  227. 1
  228. one: 1
  229. two: 2
  230. three: 3
  231. more:
  232. four: 4
  233. five: 5, six: 6
  234. 2, 3, 4
  235. 5]
  236. eq foo[2], 2
  237. eq foo[1].more.six, 6
  238. bar = [
  239. 1
  240. first first first second 1,
  241. one: 1, twoandthree: twoandthree: two: 2, three: 3
  242. 2,
  243. 2
  244. one: 1
  245. two: 2
  246. three: first second ->
  247. no
  248. , ->
  249. 3
  250. 3
  251. 4]
  252. eq bar[2], 2
  253. eq bar[1].twoandthree.twoandthree.two, 2
  254. eq bar[3].three(), 3
  255. eq bar[4], 3
  256. test "#2549, Brace-less Object Literal as a Second Operand on a New Line", ->
  257. foo = no or
  258. one: 1
  259. two: 2
  260. three: 3
  261. eq foo.one, 1
  262. bar = yes and one: 1
  263. eq bar.one, 1
  264. baz = null ?
  265. one: 1
  266. two: 2
  267. eq baz.two, 2
  268. test "#2757, Nested", ->
  269. foo =
  270. bar:
  271. one: 1,
  272. eq foo.bar.one, 1
  273. baz =
  274. qux:
  275. one: 1,
  276. corge:
  277. two: 2,
  278. three: three: three: 3,
  279. xyzzy:
  280. thud:
  281. four:
  282. four: 4,
  283. five: 5,
  284. eq baz.qux.one, 1
  285. eq baz.corge.three.three.three, 3
  286. eq baz.xyzzy.thud.four.four, 4
  287. eq baz.xyzzy.five, 5
  288. test "#1865, syntax regression 1.1.3", ->
  289. foo = (x, y) -> y
  290. bar = a: foo (->),
  291. c: yes
  292. eq bar.a.c, yes
  293. baz = a: foo (->), c: yes
  294. eq baz.a.c, yes
  295. test "#1322: implicit call against implicit object with block comments", ->
  296. ((obj, arg) ->
  297. eq obj.x * obj.y, 6
  298. ok not arg
  299. )
  300. ###
  301. x
  302. ###
  303. x: 2
  304. ### y ###
  305. y: 3
  306. test "#1513: Top level bare objs need to be wrapped in parens for unary and existence ops", ->
  307. doesNotThrow -> CoffeeScript.run "{}?", bare: true
  308. doesNotThrow -> CoffeeScript.run "{}.a++", bare: true
  309. test "#1871: Special case for IMPLICIT_END in the middle of an implicit object", ->
  310. result = 'result'
  311. ident = (x) -> x
  312. result = ident one: 1 if false
  313. eq result, 'result'
  314. result = ident
  315. one: 1
  316. two: 2 for i in [1..3]
  317. eq result.two.join(' '), '2 2 2'
  318. test "#1871: implicit object closed by IMPLICIT_END in implicit returns", ->
  319. ob = do ->
  320. a: 1 if no
  321. eq ob, undefined
  322. # instead these return an object
  323. func = ->
  324. key:
  325. i for i in [1, 2, 3]
  326. eq func().key.join(' '), '1 2 3'
  327. func = ->
  328. key: (i for i in [1, 2, 3])
  329. eq func().key.join(' '), '1 2 3'
  330. test "#1961, #1974, regression with compound assigning to an implicit object", ->
  331. obj = null
  332. obj ?=
  333. one: 1
  334. two: 2
  335. eq obj.two, 2
  336. obj = null
  337. obj or=
  338. three: 3
  339. four: 4
  340. eq obj.four, 4
  341. test "#2207: Immediate implicit closes don't close implicit objects", ->
  342. func = ->
  343. key: for i in [1, 2, 3] then i
  344. eq func().key.join(' '), '1 2 3'
  345. test "#3216: For loop declaration as a value of an implicit object", ->
  346. test = [0..2]
  347. ob =
  348. a: for v, i in test then i
  349. b: for v, i in test then i
  350. c: for v in test by 1 then v
  351. d: for v in test when true then v
  352. arrayEq ob.a, test
  353. arrayEq ob.b, test
  354. arrayEq ob.c, test
  355. arrayEq ob.d, test
  356. byFirstKey =
  357. a: for v in test by 1 then v
  358. arrayEq byFirstKey.a, test
  359. whenFirstKey =
  360. a: for v in test when true then v
  361. arrayEq whenFirstKey.a, test
  362. test 'inline implicit object literals within multiline implicit object literals', ->
  363. x =
  364. a: aa: 0
  365. b: 0
  366. eq 0, x.b
  367. eq 0, x.a.aa
  368. test "object keys with interpolations: simple cases", ->
  369. a = 'a'
  370. obj = "#{a}": yes
  371. eq obj.a, yes
  372. obj = {"#{a}": yes}
  373. eq obj.a, yes
  374. obj = {"#{a}"}
  375. eq obj.a, 'a'
  376. obj = {"#{5}"}
  377. eq obj[5], '5' # Note that the value is a string, just like the key.
  378. test "object keys with interpolations: commas in implicit object", ->
  379. obj = "#{'a'}": 1, b: 2
  380. deepEqual obj, {a: 1, b: 2}
  381. obj = a: 1, "#{'b'}": 2
  382. deepEqual obj, {a: 1, b: 2}
  383. obj = "#{'a'}": 1, "#{'b'}": 2
  384. deepEqual obj, {a: 1, b: 2}
  385. test "object keys with interpolations: commas in explicit object", ->
  386. obj = {"#{'a'}": 1, b: 2}
  387. deepEqual obj, {a: 1, b: 2}
  388. obj = {a: 1, "#{'b'}": 2}
  389. deepEqual obj, {a: 1, b: 2}
  390. obj = {"#{'a'}": 1, "#{'b'}": 2}
  391. deepEqual obj, {a: 1, b: 2}
  392. test "object keys with interpolations: commas after key with interpolation", ->
  393. obj = {"#{'a'}": yes,}
  394. eq obj.a, yes
  395. obj = {
  396. "#{'a'}": 1,
  397. "#{'b'}": 2,
  398. ### herecomment ###
  399. "#{'c'}": 3,
  400. }
  401. deepEqual obj, {a: 1, b: 2, c: 3}
  402. obj =
  403. "#{'a'}": 1,
  404. "#{'b'}": 2,
  405. ### herecomment ###
  406. "#{'c'}": 3,
  407. deepEqual obj, {a: 1, b: 2, c: 3}
  408. obj =
  409. "#{'a'}": 1,
  410. "#{'b'}": 2,
  411. ### herecomment ###
  412. "#{'c'}": 3, "#{'d'}": 4,
  413. deepEqual obj, {a: 1, b: 2, c: 3, d: 4}
  414. test "object keys with interpolations: key with interpolation mixed with `@prop`", ->
  415. deepEqual (-> {@a, "#{'b'}": 2}).call(a: 1), {a: 1, b: 2}
  416. test "object keys with interpolations: evaluate only once", ->
  417. count = 0
  418. a = -> count++; 'a'
  419. obj = {"#{a()}"}
  420. eq obj.a, 'a'
  421. eq count, 1
  422. test "object keys with interpolations: evaluation order", ->
  423. arr = []
  424. obj =
  425. a: arr.push 1
  426. b: arr.push 2
  427. "#{'c'}": arr.push 3
  428. "#{'d'}": arr.push 4
  429. e: arr.push 5
  430. "#{'f'}": arr.push 6
  431. g: arr.push 7
  432. arrayEq arr, [1..7]
  433. deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}
  434. test "object keys with interpolations: object starting with dynamic key", ->
  435. obj =
  436. "#{'a'}": 1
  437. b: 2
  438. deepEqual obj, {a: 1, b: 2}
  439. test "object keys with interpolations: comments in implicit object", ->
  440. obj =
  441. ### leading comment ###
  442. "#{'a'}": 1
  443. ### middle ###
  444. "#{'b'}": 2
  445. # regular comment
  446. 'c': 3
  447. ### foo ###
  448. d: 4
  449. "#{'e'}": 5
  450. deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5}
  451. # Comments in explicit object.
  452. obj = {
  453. ### leading comment ###
  454. "#{'a'}": 1
  455. ### middle ###
  456. "#{'b'}": 2
  457. # regular comment
  458. 'c': 3
  459. ### foo ###
  460. d: 4
  461. "#{'e'}": 5
  462. }
  463. deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5}
  464. test "object keys with interpolations: more complicated case", ->
  465. obj = {
  466. "#{'interpolated'}":
  467. """
  468. #{ '''nested''' }
  469. """: 123: 456
  470. }
  471. deepEqual obj,
  472. interpolated:
  473. nested:
  474. 123: 456
  475. test "#4324: Shorthand after interpolated key", ->
  476. a = 2
  477. obj = {"#{1}": 1, a}
  478. eq 1, obj[1]
  479. eq 2, obj.a
  480. test "computed property keys: simple cases", ->
  481. a = 'a'
  482. obj = [a]: yes
  483. eq obj.a, yes
  484. obj = {[a]: yes}
  485. eq obj.a, yes
  486. obj = {[a]}
  487. eq obj.a, 'a'
  488. obj = {[5]}
  489. eq obj[5], 5
  490. obj = {['5']}
  491. eq obj['5'], '5'
  492. test "computed property keys: commas in implicit object", ->
  493. obj = ['a']: 1, b: 2
  494. deepEqual obj, {a: 1, b: 2}
  495. obj = a: 1, ['b']: 2
  496. deepEqual obj, {a: 1, b: 2}
  497. obj = ['a']: 1, ['b']: 2
  498. deepEqual obj, {a: 1, b: 2}
  499. test "computed property keys: commas in explicit object", ->
  500. obj = {['a']: 1, b: 2}
  501. deepEqual obj, {a: 1, b: 2}
  502. obj = {a: 1, ['b']: 2}
  503. deepEqual obj, {a: 1, b: 2}
  504. obj = {['a']: 1, ['b']: 2}
  505. deepEqual obj, {a: 1, b: 2}
  506. test "computed property keys: commas after key with interpolation", ->
  507. obj = {['a']: yes,}
  508. eq obj.a, yes
  509. obj = {
  510. ['a']: 1,
  511. ['b']: 2,
  512. ### herecomment ###
  513. ['c']: 3,
  514. }
  515. deepEqual obj, {a: 1, b: 2, c: 3}
  516. obj =
  517. ['a']: 1,
  518. ['b']: 2,
  519. ### herecomment ###
  520. ['c']: 3,
  521. deepEqual obj, {a: 1, b: 2, c: 3}
  522. obj =
  523. ['a']: 1,
  524. ['b']: 2,
  525. ### herecomment ###
  526. ['c']: 3, ['d']: 4,
  527. deepEqual obj, {a: 1, b: 2, c: 3, d: 4}
  528. test "computed property keys: key with interpolation mixed with `@prop`", ->
  529. deepEqual (-> {@a, ['b']: 2}).call(a: 1), {a: 1, b: 2}
  530. test "computed property keys: evaluate only once", ->
  531. count = 0
  532. a = -> count++; 'a'
  533. obj = {[a()]}
  534. eq obj.a, 'a'
  535. eq count, 1
  536. test "computed property keys: evaluation order", ->
  537. arr = []
  538. obj =
  539. a: arr.push 1
  540. b: arr.push 2
  541. ['c']: arr.push 3
  542. ['d']: arr.push 4
  543. e: arr.push 5
  544. ['f']: arr.push 6
  545. g: arr.push 7
  546. arrayEq arr, [1..7]
  547. deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}
  548. test "computed property keys: object starting with dynamic key", ->
  549. obj =
  550. ['a']: 1
  551. b: 2
  552. deepEqual obj, {a: 1, b: 2}
  553. test "computed property keys: comments in implicit object", ->
  554. obj =
  555. ### leading comment ###
  556. ['a']: 1
  557. ### middle ###
  558. ['b']: 2
  559. # regular comment
  560. 'c': 3
  561. ### foo ###
  562. d: 4
  563. ['e']: 5
  564. deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5}
  565. obj = {
  566. ### leading comment ###
  567. ['a']: 1
  568. ### middle ###
  569. ['b']: 2
  570. # regular comment
  571. 'c': 3
  572. ### foo ###
  573. d: 4
  574. ['e']: 5
  575. }
  576. deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5}
  577. test "computed property keys: more complicated case", ->
  578. obj = {
  579. ['interpolated']:
  580. ['nested']:
  581. 123: 456
  582. }
  583. deepEqual obj,
  584. interpolated:
  585. nested:
  586. 123: 456
  587. test "computed property keys: empty array as key", ->
  588. o1 = { [[]] }
  589. deepEqual o1, { [[]]: [] }
  590. arrayEq o1[[]], []
  591. o2 = { [[]]: 1 }
  592. deepEqual o2, { [[]]: 1 }
  593. eq o2[[]], 1
  594. o3 = [[]]: 1
  595. deepEqual o3, { [[]]: 1 }
  596. deepEqual o3, { [[]]: 1 }
  597. eq o3[[]], 1
  598. o4 = a: 1, [[]]: 2
  599. deepEqual o4, { a: 1, [[]]: 2 }
  600. eq o4.a, 1,
  601. eq o4[[]], 2
  602. o5 = { a: 1, [[]]: 2 }
  603. deepEqual o5, { a: 1, [[]]: 2 }
  604. eq o5.a, 1,
  605. eq o5[[]], 2
  606. test "computed property keys: shorthand after computed property key", ->
  607. a = 2
  608. obj = {[1]: 1, a}
  609. eq 1, obj[1]
  610. eq 2, obj.a
  611. test "computed property keys: shorthand computed property key", ->
  612. a = 'b'
  613. o = {[a]}
  614. p = {a}
  615. r = {['a']}
  616. eq o.b, 'b'
  617. eq p.a, o.b
  618. eq r.a, 'a'
  619. foo = -> "a"
  620. obj = { [foo()] }
  621. eq obj.a, 'a'
  622. test "computed property keys: arrays", ->
  623. b = 'b'
  624. f = (c) -> "#{c}1"
  625. obj =
  626. ['a']: [1, 2, 3]
  627. [b]: [4, 5, 6]
  628. [f(b)]: [7, 8, 9]
  629. arrayEq obj.a, [1, 2, 3]
  630. arrayEq obj.b, [4, 5, 6]
  631. arrayEq obj.b1, [7, 8, 9]
  632. test "computed property keys: examples from developer.mozilla.org (Object initializer)", ->
  633. i = 0
  634. obj =
  635. ['foo' + ++i]: i
  636. ['foo' + ++i]: i
  637. ['foo' + ++i]: i
  638. eq obj.foo1, 1
  639. eq obj.foo2, 2
  640. eq obj.foo3, 3
  641. param = 'size'
  642. config =
  643. [param]: 12,
  644. ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
  645. deepEqual config, {size: 12, mobileSize: 4}
  646. test "computed property keys: [Symbol.iterator]", ->
  647. obj =
  648. [Symbol.iterator]: ->
  649. yield "hello"
  650. yield "world"
  651. arrayEq [obj...], ['hello', 'world']
  652. test "computed property keys: Class property", ->
  653. increment_method = "increment"
  654. decrement_method = "decrement"
  655. class Obs
  656. constructor: (@count) ->
  657. [increment_method]: -> @count += 1
  658. [decrement_method]: -> @count -= 1
  659. ob = new Obs 2
  660. eq ob.increment(), 3
  661. eq ob.decrement(), 2
  662. test "#1263: Braceless object return", ->
  663. fn = ->
  664. return
  665. a: 1
  666. b: 2
  667. c: -> 3
  668. obj = fn()
  669. eq 1, obj.a
  670. eq 2, obj.b
  671. eq 3, obj.c()
  672. test "#4564: indent should close implicit object", ->
  673. f = (x) -> x
  674. arrayEq ['a'],
  675. for key of f a: 1
  676. key
  677. g = null
  678. if f a: 1
  679. g = 3
  680. eq g, 3
  681. h = null
  682. if a: (i for i in [1, 2, 3])
  683. h = 4
  684. eq h, 4
  685. test "#4544: Postfix conditionals in first line of implicit object literals", ->
  686. two =
  687. foo:
  688. bar: 42 if yes
  689. baz: 1337
  690. eq 42, two.foo.bar
  691. eq 1337, two.foo.baz
  692. f = (x) -> x
  693. three =
  694. foo: f
  695. bar: 42 if yes
  696. baz: 1337
  697. eq 42, three.foo.bar
  698. eq 1337, three.foo.baz
  699. four =
  700. f
  701. foo:
  702. bar: 42 if yes
  703. baz: 1337
  704. eq 42, four.foo.bar
  705. eq 1337, four.baz
  706. x = bar: 42 if no
  707. baz: 1337
  708. ok not x?
  709. # Example from #2051
  710. a = null
  711. _alert = (arg) -> a = arg
  712. _alert
  713. val3: "works" if true
  714. val: "hello"
  715. val2: "all good"
  716. eq a.val2, "all good"
  717. test "#4579: Postfix for/while/until in first line of implicit object literals", ->
  718. two =
  719. foo:
  720. bar1: x for x in [1, 2, 3]
  721. bar2: x + y for x, y in [1, 2, 3]
  722. baz: 1337
  723. arrayEq [1, 2, 3], two.foo.bar1
  724. arrayEq [1, 3, 5], two.foo.bar2
  725. eq 1337, two.foo.baz
  726. f = (x) -> x
  727. three =
  728. foo: f
  729. bar1: x + y for x, y of a: 'b', c: 'd'
  730. bar2: x + 'c' for x of a: 1, b: 2
  731. baz: 1337
  732. arrayEq ['ab', 'cd'], three.foo.bar1
  733. arrayEq ['ac', 'bc'], three.foo.bar2
  734. eq 1337, three.foo.baz
  735. four =
  736. f
  737. foo:
  738. "bar_#{x}": x for x of a: 1, b: 2
  739. baz: 1337
  740. eq 'a', four.foo[0].bar_a
  741. eq 'b', four.foo[1].bar_b
  742. eq 1337, four.baz
  743. x = bar: 42 for y in [1]
  744. baz: 1337
  745. eq x.bar, 42
  746. i = 5
  747. five =
  748. foo:
  749. bar: i while i-- > 0
  750. baz: 1337
  751. arrayEq [4, 3, 2, 1, 0], five.foo.bar
  752. eq 1337, five.foo.baz
  753. i = 5
  754. six =
  755. foo:
  756. bar: i until i-- <= 0
  757. baz: 1337
  758. arrayEq [4, 3, 2, 1, 0], six.foo.bar
  759. eq 1337, six.foo.baz
  760. test "#5204: not parsed as static property", ->
  761. doesNotThrowCompileError "@ [b]: 2"
  762. test "#5292: implicit object after line continuer in implicit object property value", ->
  763. a =
  764. b: 0 or
  765. c: 1
  766. eq 1, a.b.c
  767. # following object property
  768. a =
  769. b: null ?
  770. c: 1
  771. d: 2
  772. eq 1, a.b.c
  773. eq 2, a.d
  774. # multiline nested object
  775. a =
  776. b: 0 or
  777. c: 1
  778. d: 2
  779. e: 3
  780. eq 1, a.b.c
  781. eq 2, a.b.d
  782. eq 3, a.e