Revision: 7561
Author: [email protected]
Date: Fri Apr 8 07:30:10 2011
Log: Strict mode fixes.
- mutual inlining strict and non-strict functions in crankshaft.
- assignment to undefined variable with eval in scope.
- propagation of strict mode through lazy compilation.
BUG=
TEST=test/mjsunit/strict-mode.js test/mjsunit/strict-mode-opt.js
Review URL: http://codereview.chromium.org/6814012
http://code.google.com/p/v8/source/detail?r=7561
Added:
/branches/bleeding_edge/test/mjsunit/strict-mode-opt.js
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/ast.h
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.h
/branches/bleeding_edge/test/mjsunit/strict-mode.js
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/strict-mode-opt.js Fri Apr 8
07:30:10 2011
@@ -0,0 +1,98 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+var global = 0;
+var MAX = 1000000;
+
+// Attempt to inline strcit in non-strict.
+
+function strictToBeInlined(n) {
+ "use strict";
+ global = "strict";
+ if (n == MAX) { undefined_variable_strict = "value"; }
+}
+
+function nonstrictCallStrict(n) {
+ strictToBeInlined(n);
+}
+
+(function testInlineStrictInNonStrict() {
+ for (var i = 0; i <= MAX; i ++) {
+ try {
+ nonstrictCallStrict(i);
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ assertEquals(MAX, i);
+ return;
+ }
+ }
+ fail("ReferenceError after MAX iterations", "no exception");
+})();
+
+// Attempt to inline non-strict in strict.
+
+function nonstrictToBeInlined(n) {
+ global = "nonstrict";
+ if (n == MAX) { undefined_variable_nonstrict = "The nonstrict value"; }
+}
+
+function strictCallNonStrict(n) {
+ "use strict";
+ nonstrictToBeInlined(n);
+}
+
+(function testInlineNonStrictInStrict() {
+ for (var i = 0; i <= MAX; i ++) {
+ try {
+ strictCallNonStrict(i);
+ } catch (e) {
+ fail("no exception", "exception");
+ }
+ }
+ assertEquals("The nonstrict value", undefined_variable_nonstrict);
+})();
+
+// Optimize strict function.
+
+function strictAssignToUndefined(n) {
+ "use strict";
+ global = "strict";
+ if (n == MAX) { undefined_variable_strict_2 = "value"; }
+}
+
+(function testOptimizeStrictAssignToUndefined() {
+ for (var i = 0; i <= MAX; i ++) {
+ try {
+ strictAssignToUndefined(i);
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ assertEquals(MAX, i);
+ return;
+ }
+ }
+ fail("ReferenceError after MAX iterations", "no exception");
+})();
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Mon Apr 4 08:03:34 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Fri Apr 8 07:30:10 2011
@@ -1309,6 +1309,7 @@
LOperand* global_object() { return InputAt(0); }
Handle<Object> name() const { return hydrogen()->name(); }
LOperand* value() { return InputAt(1); }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -1639,6 +1640,7 @@
LOperand* object() { return inputs_[0]; }
LOperand* value() { return inputs_[1]; }
Handle<Object> name() const { return hydrogen()->name(); }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -1678,6 +1680,7 @@
LOperand* object() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0,
3, 0> {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Apr 7
08:01:20 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Apr 8
07:30:10 2011
@@ -2242,7 +2242,9 @@
ASSERT(ToRegister(instr->value()).is(r0));
__ mov(r2, Operand(instr->name()));
- Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize();
+ Handle<Code> ic = instr->strict_mode()
+ ? isolate()->builtins()->StoreIC_Initialize_Strict()
+ : isolate()->builtins()->StoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
}
@@ -3134,7 +3136,7 @@
// Name is always in r2.
__ mov(r2, Operand(instr->name()));
- Handle<Code> ic = info_->is_strict_mode()
+ Handle<Code> ic = instr->strict_mode()
? isolate()->builtins()->StoreIC_Initialize_Strict()
: isolate()->builtins()->StoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
@@ -3222,7 +3224,7 @@
ASSERT(ToRegister(instr->key()).is(r1));
ASSERT(ToRegister(instr->value()).is(r0));
- Handle<Code> ic = info_->is_strict_mode()
+ Handle<Code> ic = instr->strict_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
=======================================
--- /branches/bleeding_edge/src/ast.h Thu Apr 7 07:45:34 2011
+++ /branches/bleeding_edge/src/ast.h Fri Apr 8 07:30:10 2011
@@ -1728,7 +1728,6 @@
int start_position_;
int end_position_;
bool is_expression_;
- bool strict_mode_;
int function_token_position_;
Handle<String> inferred_name_;
bool pretenure_;
=======================================
--- /branches/bleeding_edge/src/compiler.cc Fri Apr 8 04:25:19 2011
+++ /branches/bleeding_edge/src/compiler.cc Fri Apr 8 07:30:10 2011
@@ -603,6 +603,12 @@
// rest of the function into account to avoid overlap with the lazy
// parsing statistics.
HistogramTimerScope timer(isolate->counters()->compile_lazy());
+
+ // After parsing we know function's strict mode. Remember it.
+ if (info->function()->strict_mode()) {
+ shared->set_strict_mode(true);
+ info->MarkAsStrictMode();
+ }
// Compile the code.
if (!MakeCode(info)) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Apr 7 23:54:50
2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Fri Apr 8 07:30:10
2011
@@ -2910,8 +2910,10 @@
HStoreGlobalGeneric(HValue* context,
HValue* global_object,
Handle<Object> name,
- HValue* value)
- : name_(name) {
+ HValue* value,
+ bool strict_mode)
+ : name_(name),
+ strict_mode_(strict_mode) {
SetOperandAt(0, context);
SetOperandAt(1, global_object);
SetOperandAt(2, value);
@@ -2923,6 +2925,7 @@
HValue* global_object() { return OperandAt(1); }
Handle<Object> name() const { return name_; }
HValue* value() { return OperandAt(2); }
+ bool strict_mode() { return strict_mode_; }
virtual void PrintDataTo(StringStream* stream);
@@ -2934,6 +2937,7 @@
private:
Handle<Object> name_;
+ bool strict_mode_;
};
@@ -3265,8 +3269,10 @@
HStoreNamedGeneric(HValue* context,
HValue* object,
Handle<String> name,
- HValue* value)
- : name_(name) {
+ HValue* value,
+ bool strict_mode)
+ : name_(name),
+ strict_mode_(strict_mode) {
SetOperandAt(0, object);
SetOperandAt(1, value);
SetOperandAt(2, context);
@@ -3277,6 +3283,7 @@
HValue* value() { return OperandAt(1); }
HValue* context() { return OperandAt(2); }
Handle<String> name() { return name_; }
+ bool strict_mode() { return strict_mode_; }
virtual void PrintDataTo(StringStream* stream);
@@ -3288,6 +3295,7 @@
private:
Handle<String> name_;
+ bool strict_mode_;
};
@@ -3365,7 +3373,9 @@
HStoreKeyedGeneric(HValue* context,
HValue* object,
HValue* key,
- HValue* value) {
+ HValue* value,
+ bool strict_mode)
+ : strict_mode_(strict_mode) {
SetOperandAt(0, object);
SetOperandAt(1, key);
SetOperandAt(2, value);
@@ -3377,6 +3387,7 @@
HValue* key() { return OperandAt(1); }
HValue* value() { return OperandAt(2); }
HValue* context() { return OperandAt(3); }
+ bool strict_mode() { return strict_mode_; }
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
@@ -3385,6 +3396,9 @@
virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
+
+ private:
+ bool strict_mode_;
};
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Thu Apr 7 07:45:34 2011
+++ /branches/bleeding_edge/src/hydrogen.cc Fri Apr 8 07:30:10 2011
@@ -2981,7 +2981,12 @@
HValue* value = Pop();
Handle<String> name = Handle<String>::cast(key->handle());
HStoreNamedGeneric* store =
- new(zone()) HStoreNamedGeneric(context, literal, name,
value);
+ new(zone()) HStoreNamedGeneric(
+ context,
+ literal,
+ name,
+ value,
+ function_strict_mode());
AddInstruction(store);
AddSimulate(key->id());
} else {
@@ -3122,7 +3127,12 @@
HValue* value) {
HContext* context = new(zone()) HContext;
AddInstruction(context);
- return new(zone()) HStoreNamedGeneric(context, object, name, value);
+ return new(zone()) HStoreNamedGeneric(
+ context,
+ object,
+ name,
+ value,
+ function_strict_mode());
}
@@ -3300,7 +3310,8 @@
new(zone()) HStoreGlobalGeneric(context,
global_object,
var->name(),
- value);
+ value,
+ function_strict_mode());
instr->set_position(position);
AddInstruction(instr);
ASSERT(instr->HasSideEffects());
@@ -3628,7 +3639,12 @@
HValue* value) {
HContext* context = new(zone()) HContext;
AddInstruction(context);
- return new(zone()) HStoreKeyedGeneric(context, object, key, value);
+ return new(zone()) HStoreKeyedGeneric(
+ context,
+ object,
+ key,
+ value,
+ function_strict_mode());
}
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Thu Apr 7 02:51:25 2011
+++ /branches/bleeding_edge/src/hydrogen.h Fri Apr 8 07:30:10 2011
@@ -709,6 +709,9 @@
void ClearInlinedTestContext() {
function_state()->ClearInlinedTestContext();
}
+ bool function_strict_mode() {
+ return function_state()->compilation_info()->is_strict_mode();
+ }
// Generators for inline runtime functions.
#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Apr 7
06:32:45 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Apr 8
07:30:10 2011
@@ -2108,7 +2108,9 @@
ASSERT(ToRegister(instr->value()).is(eax));
__ mov(ecx, instr->name());
- Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize();
+ Handle<Code> ic = instr->strict_mode()
+ ? isolate()->builtins()->StoreIC_Initialize_Strict()
+ : isolate()->builtins()->StoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr, CONTEXT_ADJUSTED);
}
@@ -2997,7 +2999,7 @@
ASSERT(ToRegister(instr->value()).is(eax));
__ mov(ecx, instr->name());
- Handle<Code> ic = info_->is_strict_mode()
+ Handle<Code> ic = instr->strict_mode()
? isolate()->builtins()->StoreIC_Initialize_Strict()
: isolate()->builtins()->StoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
@@ -3097,7 +3099,7 @@
ASSERT(ToRegister(instr->key()).is(ecx));
ASSERT(ToRegister(instr->value()).is(eax));
- Handle<Code> ic = info_->is_strict_mode()
+ Handle<Code> ic = instr->strict_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Mon Apr 4 08:03:34 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Fri Apr 8 07:30:10 2011
@@ -1346,6 +1346,7 @@
LOperand* global_object() { return InputAt(1); }
Handle<Object> name() const { return hydrogen()->name(); }
LOperand* value() { return InputAt(2); }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -1694,6 +1695,7 @@
LOperand* object() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
Handle<Object> name() const { return hydrogen()->name(); }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -1755,6 +1757,7 @@
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+ DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
virtual void PrintDataTo(StringStream* stream);
@@ -1762,6 +1765,7 @@
LOperand* object() { return inputs_[1]; }
LOperand* key() { return inputs_[2]; }
LOperand* value() { return inputs_[3]; }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed Apr 6 10:54:39 2011
+++ /branches/bleeding_edge/src/runtime.cc Fri Apr 8 07:30:10 2011
@@ -7820,8 +7820,17 @@
// The property exists in the extension context.
context_ext = Handle<JSObject>::cast(holder);
} else {
- // The property was not found. It needs to be stored in the global
context.
+ // The property was not found.
ASSERT(attributes == ABSENT);
+
+ if (strict_mode == kStrictMode) {
+ // Throw in strict mode (assignment to undefined variable).
+ Handle<Object> error =
+ isolate->factory()->NewReferenceError(
+ "not_defined", HandleVector(&name, 1));
+ return isolate->Throw(*error);
+ }
+ // In non-strict mode, the property is stored in the global context.
attributes = NONE;
context_ext = Handle<JSObject>(isolate->context()->global());
}
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Apr 7
06:32:45 2011
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Apr 8
07:30:10 2011
@@ -2115,7 +2115,9 @@
ASSERT(ToRegister(instr->value()).is(rax));
__ Move(rcx, instr->name());
- Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize();
+ Handle<Code> ic = instr->strict_mode()
+ ? isolate()->builtins()->StoreIC_Initialize_Strict()
+ : isolate()->builtins()->StoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
}
@@ -2979,7 +2981,7 @@
ASSERT(ToRegister(instr->value()).is(rax));
__ Move(rcx, instr->hydrogen()->name());
- Handle<Code> ic = info_->is_strict_mode()
+ Handle<Code> ic = instr->strict_mode()
? isolate()->builtins()->StoreIC_Initialize_Strict()
: isolate()->builtins()->StoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
@@ -3075,7 +3077,7 @@
ASSERT(ToRegister(instr->key()).is(rcx));
ASSERT(ToRegister(instr->value()).is(rax));
- Handle<Code> ic = info_->is_strict_mode()
+ Handle<Code> ic = instr->strict_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Mon Apr 4 08:03:34 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.h Fri Apr 8 07:30:10 2011
@@ -1295,6 +1295,7 @@
LOperand* global_object() { return InputAt(0); }
Handle<Object> name() const { return hydrogen()->name(); }
LOperand* value() { return InputAt(1); }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -1616,6 +1617,7 @@
LOperand* object() { return inputs_[0]; }
LOperand* value() { return inputs_[1]; }
Handle<Object> name() const { return hydrogen()->name(); }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -1671,12 +1673,14 @@
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+ DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
virtual void PrintDataTo(StringStream* stream);
LOperand* object() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
+ bool strict_mode() { return hydrogen()->strict_mode(); }
};
=======================================
--- /branches/bleeding_edge/test/mjsunit/strict-mode.js Sun Mar 27 23:11:08
2011
+++ /branches/bleeding_edge/test/mjsunit/strict-mode.js Fri Apr 8 07:30:10
2011
@@ -387,10 +387,9 @@
testFutureReservedWord(future_reserved_words[i]);
}
-function testAssignToUndefined(should_throw) {
- "use strict";
+function testAssignToUndefined(test, should_throw) {
try {
- possibly_undefined_variable_for_strict_mode_test = "should throw?";
+ test();
} catch (e) {
assertTrue(should_throw, "strict mode");
assertInstanceof(e, ReferenceError, "strict mode");
@@ -399,33 +398,78 @@
assertFalse(should_throw, "strict mode");
}
-testAssignToUndefined(true);
-testAssignToUndefined(true);
-testAssignToUndefined(true);
+function repeat(n, f) {
+ for (var i = 0; i < n; i ++) { f(); }
+}
+
+function assignToUndefined() {
+ "use strict";
+ possibly_undefined_variable_for_strict_mode_test = "should throw?";
+}
+
+testAssignToUndefined(assignToUndefined, true);
+testAssignToUndefined(assignToUndefined, true);
+testAssignToUndefined(assignToUndefined, true);
possibly_undefined_variable_for_strict_mode_test = "value";
-testAssignToUndefined(false);
-testAssignToUndefined(false);
-testAssignToUndefined(false);
+testAssignToUndefined(assignToUndefined, false);
+testAssignToUndefined(assignToUndefined, false);
+testAssignToUndefined(assignToUndefined, false);
delete possibly_undefined_variable_for_strict_mode_test;
-testAssignToUndefined(true);
-testAssignToUndefined(true);
-testAssignToUndefined(true);
-
-function repeat(n, f) {
- for (var i = 0; i < n; i ++) { f(); }
-}
-
-repeat(10, function() { testAssignToUndefined(true); });
+testAssignToUndefined(assignToUndefined, true);
+testAssignToUndefined(assignToUndefined, true);
+testAssignToUndefined(assignToUndefined, true);
+
+repeat(10, function() { testAssignToUndefined(assignToUndefined, true); });
possibly_undefined_variable_for_strict_mode_test = "value";
-repeat(10, function() { testAssignToUndefined(false); });
+repeat(10, function() { testAssignToUndefined(assignToUndefined, false);
});
delete possibly_undefined_variable_for_strict_mode_test;
-repeat(10, function() { testAssignToUndefined(true); });
+repeat(10, function() { testAssignToUndefined(assignToUndefined, true); });
possibly_undefined_variable_for_strict_mode_test = undefined;
-repeat(10, function() { testAssignToUndefined(false); });
+repeat(10, function() { testAssignToUndefined(assignToUndefined, false);
});
+
+function assignToUndefinedWithEval() {
+ "use strict";
+ possibly_undefined_variable_for_strict_mode_test_with_eval = "should
throw?";
+ eval("");
+}
+
+testAssignToUndefined(assignToUndefinedWithEval, true);
+testAssignToUndefined(assignToUndefinedWithEval, true);
+testAssignToUndefined(assignToUndefinedWithEval, true);
+
+possibly_undefined_variable_for_strict_mode_test_with_eval = "value";
+
+testAssignToUndefined(assignToUndefinedWithEval, false);
+testAssignToUndefined(assignToUndefinedWithEval, false);
+testAssignToUndefined(assignToUndefinedWithEval, false);
+
+delete possibly_undefined_variable_for_strict_mode_test_with_eval;
+
+testAssignToUndefined(assignToUndefinedWithEval, true);
+testAssignToUndefined(assignToUndefinedWithEval, true);
+testAssignToUndefined(assignToUndefinedWithEval, true);
+
+repeat(10, function() {
+ testAssignToUndefined(assignToUndefinedWithEval, true);
+ });
+possibly_undefined_variable_for_strict_mode_test_with_eval = "value";
+repeat(10, function() {
+ testAssignToUndefined(assignToUndefinedWithEval, false);
+ });
+delete possibly_undefined_variable_for_strict_mode_test_with_eval;
+repeat(10, function() {
+ testAssignToUndefined(assignToUndefinedWithEval, true);
+ });
+possibly_undefined_variable_for_strict_mode_test_with_eval = undefined;
+repeat(10, function() {
+ testAssignToUndefined(assignToUndefinedWithEval, false);
+ });
+
+
(function testDeleteNonConfigurable() {
function delete_property(o) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev