1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Flags: --harmony-modules --harmony-scoping
29
30// Test basic module linking and initialization.
31
32"use strict";
33
34module R {
35  // At this point, only functions and modules are initialized.
36  assertEquals(undefined, v)
37  assertEquals(undefined, vv)
38  assertEquals(undefined, R.v)
39  assertEquals(undefined, M.v)
40  assertEquals(undefined, MM.v)
41  assertEquals(undefined, F.v)
42  assertEquals(undefined, G.v)
43  assertThrows(function() { l }, ReferenceError)
44  assertThrows(function() { ll }, ReferenceError)
45  assertThrows(function() { R.l }, ReferenceError)
46  assertThrows(function() { M.l }, ReferenceError)
47  assertThrows(function() { MM.l }, ReferenceError)
48  assertThrows(function() { F.l }, ReferenceError)
49  assertThrows(function() { G.l }, ReferenceError)
50  assertThrows(function() { c }, ReferenceError)
51  assertThrows(function() { cc }, ReferenceError)
52  assertThrows(function() { R.c }, ReferenceError)
53  assertThrows(function() { M.c }, ReferenceError)
54  assertThrows(function() { MM.c }, ReferenceError)
55  assertThrows(function() { F.c }, ReferenceError)
56  assertThrows(function() { G.c }, ReferenceError)
57  assertEquals(4, f())
58  assertEquals(24, ff())
59  assertEquals(4, R.f())
60  assertEquals(14, M.f())
61  assertEquals(34, MM.f())
62  assertEquals(44, F.f())
63  assertEquals(14, G.f())
64
65  // All properties should already exist on the instance objects, though.
66  assertTrue("v" in R)
67  assertTrue("v" in RR)
68  assertTrue("v" in M)
69  assertTrue("v" in MM)
70  assertTrue("v" in F)
71  assertTrue("v" in G)
72  assertTrue("l" in R)
73  assertTrue("l" in RR)
74  assertTrue("l" in M)
75  assertTrue("l" in MM)
76  assertTrue("l" in F)
77  assertTrue("l" in G)
78  assertTrue("c" in R)
79  assertTrue("c" in RR)
80  assertTrue("c" in M)
81  assertTrue("c" in MM)
82  assertTrue("c" in F)
83  assertTrue("c" in G)
84  assertTrue("f" in R)
85  assertTrue("f" in RR)
86  assertTrue("f" in M)
87  assertTrue("f" in MM)
88  assertTrue("f" in F)
89  assertTrue("f" in G)
90  assertTrue("M" in R)
91  assertTrue("M" in RR)
92  assertTrue("RR" in R)
93  assertTrue("RR" in RR)
94
95  // And aliases should be identical.
96  assertSame(R, RR)
97  assertSame(R, R.RR)
98  assertSame(M, R.M)
99  assertSame(M, G)
100
101  // We can only assign to var.
102  assertEquals(-1, v = -1)
103  assertEquals(-2, R.v = -2)
104  assertEquals(-2, v)
105  assertEquals(-2, R.v)
106
107  assertThrows(function() { l = -1 }, ReferenceError)
108  assertThrows(function() { R.l = -2 }, ReferenceError)
109  assertThrows(function() { l }, ReferenceError)
110  assertThrows(function() { R.l }, ReferenceError)
111
112  assertThrows(function() { eval("c = -1") }, SyntaxError)
113  assertThrows(function() { R.c = -2 }, TypeError)
114
115  // Initialize first bunch of variables.
116  export var v = 1
117  export let l = 2
118  export const c = 3
119  export function f() { return 4 }
120
121  assertEquals(1, v)
122  assertEquals(1, R.v)
123  assertEquals(2, l)
124  assertEquals(2, R.l)
125  assertEquals(3, c)
126  assertEquals(3, R.c)
127
128  assertEquals(-3, v = -3)
129  assertEquals(-4, R.v = -4)
130  assertEquals(-3, l = -3)
131  assertEquals(-4, R.l = -4)
132  assertThrows(function() { eval("c = -3") }, SyntaxError)
133  assertThrows(function() { R.c = -4 }, TypeError)
134
135  assertEquals(-4, v)
136  assertEquals(-4, R.v)
137  assertEquals(-4, l)
138  assertEquals(-4, R.l)
139  assertEquals(3, c)
140  assertEquals(3, R.c)
141
142  // Initialize nested module.
143  export module M {
144    export var v = 11
145    export let l = 12
146    export const c = 13
147    export function f() { return 14 }
148  }
149
150  assertEquals(11, M.v)
151  assertEquals(11, G.v)
152  assertEquals(12, M.l)
153  assertEquals(12, G.l)
154  assertEquals(13, M.c)
155  assertEquals(13, G.c)
156
157  // Initialize non-exported variables.
158  var vv = 21
159  let ll = 22
160  const cc = 23
161  function ff() { return 24 }
162
163  assertEquals(21, vv)
164  assertEquals(22, ll)
165  assertEquals(23, cc)
166
167  // Initialize non-exported module.
168  module MM {
169    export var v = 31
170    export let l = 32
171    export const c = 33
172    export function f() { return 34 }
173  }
174
175  assertEquals(31, MM.v)
176  assertEquals(32, MM.l)
177  assertEquals(33, MM.c)
178
179  // Recursive self reference.
180  export module RR = R
181}
182
183// Initialize sibling module that was forward-used.
184module F {
185  assertEquals(undefined, v)
186  assertEquals(undefined, F.v)
187  assertThrows(function() { l }, ReferenceError)
188  assertThrows(function() { F.l }, ReferenceError)
189  assertThrows(function() { c }, ReferenceError)
190  assertThrows(function() { F.c }, ReferenceError)
191
192  export var v = 41
193  export let l = 42
194  export const c = 43
195  export function f() { return 44 }
196
197  assertEquals(41, v)
198  assertEquals(41, F.v)
199  assertEquals(42, l)
200  assertEquals(42, F.l)
201  assertEquals(43, c)
202  assertEquals(43, F.c)
203}
204
205// Define recursive module alias.
206module G = R.M
207
208
209
210// Second test with side effects and more module nesting.
211
212let log = "";
213
214export let x = (log += "1");
215
216export module B = A.B
217
218export module A {
219  export let x = (log += "2");
220  let y = (log += "3");
221  export function f() { log += "5" };
222  export module B {
223    module BB = B;
224    export BB, x;
225    let x = (log += "4");
226    f();
227    let y = (log += "6");
228  }
229  export let z = (log += "7");
230  export module C {
231    export let z = (log += "8");
232    export module D = B
233    export module C = A.C
234  }
235  module D {}
236}
237
238export module M1 {
239  export module A2 = M2;
240  export let x = (log += "9");
241}
242export module M2 {
243  export module A1 = M1;
244  export let x = (log += "0");
245}
246
247assertEquals("object", typeof A);
248assertTrue('x' in A);
249assertFalse('y' in A);
250assertTrue('f' in A);
251assertTrue('B' in A);
252assertTrue('z' in A);
253assertTrue('C' in A);
254assertFalse('D' in A);
255
256assertEquals("object", typeof B);
257assertTrue('BB' in B);
258assertTrue('x' in B);
259assertFalse('y' in B);
260
261assertEquals("object", typeof A.B);
262assertTrue('BB' in A.B);
263assertTrue('x' in A.B);
264assertFalse('y' in A.B);
265
266assertEquals("object", typeof A.B.BB);
267assertTrue('BB' in A.B.BB);
268assertTrue('x' in A.B.BB);
269assertFalse('y' in A.B.BB);
270
271assertEquals("object", typeof A.C);
272assertTrue('z' in A.C);
273assertTrue('D' in A.C);
274assertTrue('C' in A.C);
275
276assertEquals("object", typeof M1);
277assertEquals("object", typeof M2);
278assertTrue('A2' in M1);
279assertTrue('A1' in M2);
280assertEquals("object", typeof M1.A2);
281assertEquals("object", typeof M2.A1);
282assertTrue('A1' in M1.A2);
283assertTrue('A2' in M2.A1);
284assertEquals("object", typeof M1.A2.A1);
285assertEquals("object", typeof M2.A1.A2);
286
287assertSame(B, A.B);
288assertSame(B, B.BB);
289assertSame(B, A.C.D);
290assertSame(A.C, A.C.C);
291assertFalse(A.D === A.C.D);
292
293assertSame(M1, M2.A1);
294assertSame(M2, M1.A2);
295assertSame(M1, M1.A2.A1);
296assertSame(M2, M2.A1.A2);
297
298assertEquals("1234567890", log);
299