1// Copyright 2011 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: --allow-natives-syntax
29
30var y = 3;
31
32function get_y() { return this.y; }
33function strict_get_y() { "use strict"; return this.y; }
34
35// Test calls to strict mode function as methods.
36for (var i = 0; i < 10; i++) assertEquals(3, strict_get_y.call(this));
37var o = { y: 42 };
38for (var i = 0; i < 10; i++) assertEquals(42, strict_get_y.call(o));
39
40// Test calls to strict mode function with implicit receiver.
41function g() {
42  var exception = false;
43  try { strict_get_y(); } catch(e) { exception = true; }
44  assertTrue(exception);
45}
46for (var i = 0; i < 3; i++) g();
47
48// Test calls to local strict mode function with implicit receiver.
49function local_function_test() {
50  function get_y() { return this.y; }
51  function strict_get_y() { "use strict"; return this.y; }
52  assertEquals(3, get_y());
53  assertEquals(3, get_y(23));
54  var exception = false;
55  try {
56    strict_get_y();
57  } catch(e) {
58    exception = true;
59  }
60  assertTrue(exception);
61}
62
63for (var i = 0; i < 10; i++) {
64  local_function_test();
65}
66
67// Test call to catch variable strict-mode function. Implicit
68// receiver.
69var exception = false;
70try {
71  throw strict_get_y;
72} catch(f) {
73  try {
74    f();
75  } catch(e) {
76    exception = true;
77  }
78  assertTrue(exception);
79}
80
81
82// Test calls to strict-mode function with the object from a with
83// statement as the receiver.
84with(this) {
85  assertEquals(3, strict_get_y());
86  assertEquals(3, strict_get_y(32));
87}
88
89var o = { y: 27 };
90o.f = strict_get_y;
91with(o) {
92  assertEquals(27, f());
93  assertEquals(27, f(23));
94}
95
96
97// Check calls to eval within a function with 'undefined' as receiver.
98function implicit_receiver_eval() {
99  "use strict";
100  return eval("this");
101}
102
103assertEquals(void 0, implicit_receiver_eval());
104assertEquals(void 0, implicit_receiver_eval(32));
105
106
107// Strict mode function to get inlined.
108function strict_return_receiver() {
109  "use strict";
110  return this;
111}
112
113// Inline with implicit receiver.
114function g() {
115  return strict_return_receiver();
116}
117
118for (var i = 0; i < 5; i++) {
119  assertEquals(void 0, g());
120  assertEquals(void 0, g(42));
121}
122%OptimizeFunctionOnNextCall(g);
123assertEquals(void 0, g(42));
124assertEquals(void 0, g());
125
126// Inline with explicit receiver.
127function g2() {
128  var o = {};
129  o.f = strict_return_receiver;
130  return o.f();
131}
132
133for (var i = 0; i < 5; i++) {
134  assertTrue(typeof g2() == "object");
135  assertTrue(typeof g2(42) == "object");
136}
137%OptimizeFunctionOnNextCall(g2);
138assertTrue(typeof g2() == "object");
139assertTrue(typeof g2(42) == "object");
140
141// Test calls of aliased eval.
142function outer_eval_receiver() {
143  var eval = function() { return this; }
144  function inner_strict() {
145    "use strict";
146    assertEquals('object', typeof eval());
147  }
148  inner_strict();
149}
150outer_eval_receiver();
151
152function outer_eval_conversion3(eval, expected) {
153  function inner_strict() {
154    "use strict";
155    var x = eval("this");
156    assertEquals(expected, typeof x);
157  }
158  inner_strict();
159}
160
161function strict_return_this() { "use strict"; return this; }
162function return_this() { return this; }
163function strict_eval(s) { "use strict"; return eval(s); }
164function non_strict_eval(s) { return eval(s); }
165
166outer_eval_conversion3(strict_return_this, 'undefined');
167outer_eval_conversion3(return_this, 'object');
168outer_eval_conversion3(strict_eval, 'undefined');
169outer_eval_conversion3(non_strict_eval, 'object');
170
171outer_eval_conversion3(eval, 'undefined');
172
173function test_constant_function() {
174  var o = { f: function() { "use strict"; return this; } };
175  this.__proto__ = o;
176  for (var i = 0; i < 10; i++) assertEquals(void 0, f());
177}
178test_constant_function();
179
180function test_field() {
181  var o = { };
182  o.f = function() {};
183  o.f = function() { "use strict"; return this; };
184  this.__proto__ = o;
185  for (var i = 0; i < 10; i++) assertEquals(void 0, f());
186}
187test_field();
188