MIPS: port Remove in-loop tracking for call ICs.

port r9260 (af9cfd83).

Original commit message:
We passed this flag around in a lot of places and had differenc call
ICs based on it, but never did any real specialization based on its
value.

BUG=
TEST=

Review URL: http://codereview.chromium.org/7886028
Patch from Paul Lind <plind44@gmail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9269 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 40880d32
...@@ -2042,9 +2042,8 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ...@@ -2042,9 +2042,8 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
__ Call(ic, mode, expr->id()); __ Call(ic, mode, expr->id());
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
...@@ -2075,9 +2074,8 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, ...@@ -2075,9 +2074,8 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
__ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key.
__ Call(ic, RelocInfo::CODE_TARGET, expr->id()); __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
...@@ -2098,8 +2096,7 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { ...@@ -2098,8 +2096,7 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
} }
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; CallFunctionStub stub(arg_count, flags);
CallFunctionStub stub(arg_count, in_loop, flags);
__ CallStub(&stub); __ CallStub(&stub);
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
...@@ -2197,8 +2194,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -2197,8 +2194,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
} }
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT);
__ CallStub(&stub); __ CallStub(&stub);
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
...@@ -3574,9 +3570,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -3574,9 +3570,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
__ li(a2, Operand(expr->name())); __ li(a2, Operand(expr->name()));
RelocInfo::Mode mode = RelocInfo::CODE_TARGET; RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
NOT_IN_LOOP,
mode);
__ Call(ic, mode, expr->id()); __ Call(ic, mode, expr->id());
// Restore context register. // Restore context register.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
......
...@@ -395,7 +395,6 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, ...@@ -395,7 +395,6 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::ComputeFlags(kind, Code::Flags flags = Code::ComputeFlags(kind,
NOT_IN_LOOP,
MONOMORPHIC, MONOMORPHIC,
extra_ic_state, extra_ic_state,
NORMAL, NORMAL,
...@@ -732,9 +731,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { ...@@ -732,9 +731,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------------------------------- // -----------------------------------
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
NOT_IN_LOOP,
MONOMORPHIC);
Isolate::Current()->stub_cache()->GenerateProbe( Isolate::Current()->stub_cache()->GenerateProbe(
masm, flags, a0, a2, a3, t0, t1); masm, flags, a0, a2, a3, t0, t1);
...@@ -1395,10 +1392,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm, ...@@ -1395,10 +1392,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
// Get the receiver from the stack and probe the stub cache. // Get the receiver from the stack and probe the stub cache.
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, Code::Flags flags =
NOT_IN_LOOP, Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
MONOMORPHIC,
strict_mode);
Isolate::Current()->stub_cache()->GenerateProbe( Isolate::Current()->stub_cache()->GenerateProbe(
masm, flags, a1, a2, a3, t0, t1); masm, flags, a1, a2, a3, t0, t1);
......
...@@ -1211,46 +1211,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { ...@@ -1211,46 +1211,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
LookupResult lookup; LookupResult lookup;
global->Lookup(*name, &lookup); global->Lookup(*name, &lookup);
if (lookup.IsProperty()) { if (lookup.IsProperty()) {
// Determine if the property is local by comparing the holder // We found an existing property. Unless it was an interceptor
// against the global object. The information will be used to // that claims the property is absent, skip this declaration.
// avoid throwing re-declaration errors when declaring if (lookup.type() != INTERCEPTOR) {
// variables or constants that exist in the prototype chain. continue;
bool is_local = (*global == lookup.holder()); }
// Get the property attributes and determine if the property is
// read-only.
PropertyAttributes attributes = global->GetPropertyAttribute(*name); PropertyAttributes attributes = global->GetPropertyAttribute(*name);
bool is_read_only = (attributes & READ_ONLY) != 0; if (attributes != ABSENT) {
if (lookup.type() == INTERCEPTOR) {
// If the interceptor says the property is there, we
// just return undefined without overwriting the property.
// Otherwise, we continue to setting the property.
if (attributes != ABSENT) {
// Check if the existing property conflicts with regards to const.
if (is_local && (is_read_only || is_const_property)) {
const char* type = (is_read_only) ? "const" : "var";
return ThrowRedeclarationError(isolate, type, name);
};
// The property already exists without conflicting: Go to
// the next declaration.
continue;
}
// Fall-through and introduce the absent property by using
// SetProperty.
} else {
// For const properties, we treat a callback with this name
// even in the prototype as a conflicting declaration.
if (is_const_property && (lookup.type() == CALLBACKS)) {
return ThrowRedeclarationError(isolate, "const", name);
}
// Otherwise, we check for locally conflicting declarations.
if (is_local && (is_read_only || is_const_property)) {
const char* type = (is_read_only) ? "const" : "var";
return ThrowRedeclarationError(isolate, type, name);
}
// The property already exists without conflicting: Go to
// the next declaration.
continue; continue;
} }
// Fall-through and introduce the absent property by using
// SetProperty.
} }
} else { } else {
is_function_declaration = true; is_function_declaration = true;
...@@ -1267,20 +1238,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { ...@@ -1267,20 +1238,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
LookupResult lookup; LookupResult lookup;
global->LocalLookup(*name, &lookup); global->LocalLookup(*name, &lookup);
// There's a local property that we need to overwrite because
// we're either declaring a function or there's an interceptor
// that claims the property is absent.
//
// Check for conflicting re-declarations. We cannot have
// conflicting types in case of intercepted properties because
// they are absent.
if (lookup.IsProperty() &&
(lookup.type() != INTERCEPTOR) &&
(lookup.IsReadOnly() || is_const_property)) {
const char* type = (lookup.IsReadOnly()) ? "const" : "var";
return ThrowRedeclarationError(isolate, type, name);
}
// Compute the property attributes. According to ECMA-262, section // Compute the property attributes. According to ECMA-262, section
// 13, page 71, the property must be read-only and // 13, page 71, the property must be read-only and
// non-deletable. However, neither SpiderMonkey nor KJS creates the // non-deletable. However, neither SpiderMonkey nor KJS creates the
...@@ -1465,64 +1422,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { ...@@ -1465,64 +1422,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
// to assign to the property. // to assign to the property.
// Note that objects can have hidden prototypes, so we need to traverse // Note that objects can have hidden prototypes, so we need to traverse
// the whole chain of hidden prototypes to do a 'local' lookup. // the whole chain of hidden prototypes to do a 'local' lookup.
JSObject* real_holder = global; Object* object = global;
LookupResult lookup; LookupResult lookup;
while (true) { while (object->IsJSObject() &&
real_holder->LocalLookup(*name, &lookup); JSObject::cast(object)->map()->is_hidden_prototype()) {
if (lookup.IsProperty()) { JSObject* raw_holder = JSObject::cast(object);
// Determine if this is a redeclaration of something read-only. raw_holder->LocalLookup(*name, &lookup);
if (lookup.IsReadOnly()) { if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
// If we found readonly property on one of hidden prototypes, HandleScope handle_scope(isolate);
// just shadow it. Handle<JSObject> holder(raw_holder);
if (real_holder != isolate->context()->global()) break; PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
return ThrowRedeclarationError(isolate, "const", name); // Update the raw pointer in case it's changed due to GC.
} raw_holder = *holder;
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
// Determine if this is a redeclaration of an intercepted read-only // Found an interceptor that's not read only.
// property and figure out if the property exists at all. if (assign) {
bool found = true; return raw_holder->SetProperty(
PropertyType type = lookup.type(); &lookup, *name, args[2], attributes, strict_mode);
if (type == INTERCEPTOR) { } else {
HandleScope handle_scope(isolate); return isolate->heap()->undefined_value();
Handle<JSObject> holder(real_holder);
PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
real_holder = *holder;
if (intercepted == ABSENT) {
// The interceptor claims the property isn't there. We need to
// make sure to introduce it.
found = false;
} else if ((intercepted & READ_ONLY) != 0) {
// The property is present, but read-only. Since we're trying to
// overwrite it with a variable declaration we must throw a
// re-declaration error. However if we found readonly property
// on one of hidden prototypes, just shadow it.
if (real_holder != isolate->context()->global()) break;
return ThrowRedeclarationError(isolate, "const", name);
} }
} }
if (found && !assign) {
// The global property is there and we're not assigning any value
// to it. Just return.
return isolate->heap()->undefined_value();
}
// Assign the value (or undefined) to the property.
Object* value = (assign) ? args[2] : isolate->heap()->undefined_value();
return real_holder->SetProperty(
&lookup, *name, value, attributes, strict_mode);
} }
object = raw_holder->GetPrototype();
Object* proto = real_holder->GetPrototype();
if (!proto->IsJSObject())
break;
if (!JSObject::cast(proto)->map()->is_hidden_prototype())
break;
real_holder = JSObject::cast(proto);
} }
// Reload global in case the loop above performed a GC.
global = isolate->context()->global(); global = isolate->context()->global();
if (assign) { if (assign) {
return global->SetProperty(*name, args[2], attributes, strict_mode); return global->SetProperty(*name, args[2], attributes, strict_mode);
...@@ -1560,20 +1485,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { ...@@ -1560,20 +1485,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
attributes); attributes);
} }
// Determine if this is a redeclaration of something not // Determine if this is a re-initialization of something not
// read-only. In case the result is hidden behind an interceptor we // read-only. In case the result is hidden behind an interceptor we
// need to ask it for the property attributes. // need to ask it for the property attributes.
if (!lookup.IsReadOnly()) { if (!lookup.IsReadOnly() && lookup.type() == INTERCEPTOR) {
if (lookup.type() != INTERCEPTOR) {
return ThrowRedeclarationError(isolate, "var", name);
}
PropertyAttributes intercepted = global->GetPropertyAttribute(*name); PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
// Throw re-declaration error if the intercepted property is present // Ignore the re-initialization if the intercepted property is present
// but not read-only. // but not read-only.
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
return ThrowRedeclarationError(isolate, "var", name); return isolate->heap()->undefined_value();
} }
// Restore global object from context (in case of GC) and continue // Restore global object from context (in case of GC) and continue
...@@ -1603,11 +1524,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { ...@@ -1603,11 +1524,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
if (type == FIELD) { if (type == FIELD) {
FixedArray* properties = global->properties(); FixedArray* properties = global->properties();
int index = lookup.GetFieldIndex(); int index = lookup.GetFieldIndex();
if (properties->get(index)->IsTheHole()) { if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
properties->set(index, *value); properties->set(index, *value);
} }
} else if (type == NORMAL) { } else if (type == NORMAL) {
if (global->GetNormalizedProperty(&lookup)->IsTheHole()) { if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
!lookup.IsReadOnly()) {
global->SetNormalizedProperty(&lookup, *value); global->SetNormalizedProperty(&lookup, *value);
} }
} else { } else {
......
...@@ -193,13 +193,14 @@ function GlobalEval(x) { ...@@ -193,13 +193,14 @@ function GlobalEval(x) {
function SetUpGlobal() { function SetUpGlobal() {
%CheckIsBootstrapping(); %CheckIsBootstrapping();
// ECMA 262 - 15.1.1.1. // ECMA 262 - 15.1.1.1.
%SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE); %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
// ECMA-262 - 15.1.1.2. // ECMA-262 - 15.1.1.2.
%SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE); %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE | READ_ONLY);
// ECMA-262 - 15.1.1.3. // ECMA-262 - 15.1.1.3.
%SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE); %SetProperty(global, "undefined", void 0,
DONT_ENUM | DONT_DELETE | READ_ONLY);
// Set up non-enumerable function on the global object. // Set up non-enumerable function on the global object.
InstallFunctions(global, DONT_ENUM, $Array( InstallFunctions(global, DONT_ENUM, $Array(
......
...@@ -285,18 +285,18 @@ TEST(Present) { ...@@ -285,18 +285,18 @@ TEST(Present) {
{ PresentPropertyContext context; { PresentPropertyContext context;
context.Check("const x; x", context.Check("const x; x",
1, // access
0, 0,
0, 2, // (re-)declaration + initialization
1, // (re-)declaration EXPECT_EXCEPTION); // x is not defined!
EXPECT_EXCEPTION); // x has already been declared!
} }
{ PresentPropertyContext context; { PresentPropertyContext context;
context.Check("const x = 0; x", context.Check("const x = 0; x",
1, // access
0, 0,
0, 2, // (re-)declaration + initialization
1, // (re-)declaration EXPECT_EXCEPTION); // x is not defined!
EXPECT_EXCEPTION); // x has already been declared!
} }
} }
...@@ -429,18 +429,20 @@ TEST(Appearing) { ...@@ -429,18 +429,20 @@ TEST(Appearing) {
{ AppearingPropertyContext context; { AppearingPropertyContext context;
context.Check("const x; x", context.Check("const x; x",
0, 1, // access
1, // declaration 1, // declaration
2, // declaration + initialization 2, // declaration + initialization
EXPECT_EXCEPTION); // x has already been declared! EXPECT_RESULT, Undefined());
} }
{ AppearingPropertyContext context; { AppearingPropertyContext context;
context.Check("const x = 0; x", context.Check("const x = 0; x",
0, 1, // access
1, // declaration 1, // declaration
2, // declaration + initialization 2, // declaration + initialization
EXPECT_EXCEPTION); // x has already been declared! EXPECT_RESULT, Undefined());
// Result is undefined because declaration succeeded but
// initialization to 0 failed (due to context behavior).
} }
} }
...@@ -496,9 +498,9 @@ TEST(Reappearing) { ...@@ -496,9 +498,9 @@ TEST(Reappearing) {
{ ReappearingPropertyContext context; { ReappearingPropertyContext context;
context.Check("const x; var x = 0", context.Check("const x; var x = 0",
0, 0,
2, // var declaration + const initialization 3, // const declaration+initialization, var initialization
4, // 2 x declaration + 2 x initialization 4, // 2 x declaration + 2 x initialization
EXPECT_EXCEPTION); // x has already been declared! EXPECT_RESULT, Undefined());
} }
} }
......
...@@ -41,16 +41,6 @@ chapter10/10.4/10.4.2/10.4.2-2-c-1: FAIL_OK ...@@ -41,16 +41,6 @@ chapter10/10.4/10.4.2/10.4.2-2-c-1: FAIL_OK
# We are compatible with Safari and Firefox. # We are compatible with Safari and Firefox.
chapter11/11.1/11.1.5: UNIMPLEMENTED chapter11/11.1/11.1.5: UNIMPLEMENTED
# We do not have a global object called 'global' as required by tests.
chapter15/15.1: FAIL_OK
# NaN is writable. We are compatible with JSC.
chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-178: FAIL_OK
# Infinity is writable. We are compatible with JSC.
chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-179: FAIL_OK
# undefined is writable. We are compatible with JSC.
chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-180: FAIL_OK
# Our Function object has an "arguments" property which is used as a # Our Function object has an "arguments" property which is used as a
# non-property in the test. # non-property in the test.
chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-183: FAIL_OK chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-183: FAIL_OK
......
...@@ -98,7 +98,8 @@ function TestAll(expected,s,opt_e) { ...@@ -98,7 +98,8 @@ function TestAll(expected,s,opt_e) {
var msg = s; var msg = s;
if (opt_e) { e = opt_e; msg += "; " + opt_e; } if (opt_e) { e = opt_e; msg += "; " + opt_e; }
assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'"); assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'");
assertEquals(expected, TestGlobal(s,e), "global:'" + msg + "'"); // Redeclarations of global consts do not throw, they are silently ignored.
assertEquals(42, TestGlobal(s, 42), "global:'" + msg + "'");
assertEquals(expected, TestContext(s,e), "context:'" + msg + "'"); assertEquals(expected, TestContext(s,e), "context:'" + msg + "'");
} }
...@@ -218,3 +219,62 @@ TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x"); ...@@ -218,3 +219,62 @@ TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x");
// Test that const inside with behaves correctly. // Test that const inside with behaves correctly.
TestAll(87, "with ({x:42}) { const x = 87; }", "x"); TestAll(87, "with ({x:42}) { const x = 87; }", "x");
TestAll(undefined, "with ({x:42}) { const x; }", "x"); TestAll(undefined, "with ({x:42}) { const x; }", "x");
// Additional tests for how various combinations of re-declarations affect
// the values of the var/const in question.
try {
eval("var undefined;");
} catch (ex) {
assertUnreachable("undefined (1) has thrown");
}
var original_undef = undefined;
var undefined = 1; // Should be silently ignored.
assertEquals(original_undef, undefined, "undefined got overwritten");
undefined = original_undef;
var a; const a; const a = 1;
assertEquals(1, a, "a has wrong value");
a = 2;
assertEquals(2, a, "a should be writable");
var b = 1; const b = 2;
assertEquals(2, b, "b has wrong value");
var c = 1; const c = 2; const c = 3;
assertEquals(3, c, "c has wrong value");
const d = 1; const d = 2;
assertEquals(1, d, "d has wrong value");
const e = 1; var e = 2;
assertEquals(1, e, "e has wrong value");
const f = 1; const f;
assertEquals(1, f, "f has wrong value");
var g; const g = 1;
assertEquals(1, g, "g has wrong value");
g = 2;
assertEquals(2, g, "g should be writable");
const h; var h = 1;
assertEquals(undefined,h, "h has wrong value");
eval("Object.defineProperty(this, 'i', { writable: true });"
+ "const i = 7;"
+ "assertEquals(7, i, \"i has wrong value\");");
var global = this;
assertThrows(function() {
Object.defineProperty(global, 'j', { writable: true })
}, TypeError);
const j = 2; // This is what makes the function above throw, because the
// const declaration gets hoisted and makes the property non-configurable.
assertEquals(2, j, "j has wrong value");
var k = 1; const k;
// You could argue about the expected result here. For now, the winning
// argument is that "const k;" is equivalent to "const k = undefined;".
assertEquals(undefined, k, "k has wrong value");
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Check that dynamically introducing conflicting consts/vars // Check that dynamically introducing conflicting consts/vars
// leads to exceptions. // is silently ignored (and does not lead to exceptions).
var caught = 0; var caught = 0;
...@@ -46,12 +46,12 @@ eval("var c"); ...@@ -46,12 +46,12 @@ eval("var c");
try { eval("const c"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } try { eval("const c"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
assertTrue(typeof c == 'undefined'); assertTrue(typeof c == 'undefined');
try { eval("const c = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } try { eval("const c = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
assertTrue(typeof c == 'undefined'); assertEquals(1, c);
eval("var d = 0"); eval("var d = 0");
try { eval("const d"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } try { eval("const d"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
assertEquals(0, d); assertEquals(undefined, d);
try { eval("const d = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } try { eval("const d = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
assertEquals(0, d); assertEquals(1, d);
assertEquals(8, caught); assertEquals(0, caught);
...@@ -49,7 +49,7 @@ try { ...@@ -49,7 +49,7 @@ try {
exception = true; exception = true;
assertTrue(/TypeError/.test(e)); assertTrue(/TypeError/.test(e));
} }
assertTrue(exception); assertFalse(exception);
exception = false; exception = false;
try { try {
......
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Make sure that a const definition always // Make sure that a const definition does not try
// conflicts with a defined setter. This avoid // to pass 'the hole' to a defined setter.
// trying to pass 'the hole' to the setter.
this.__defineSetter__('x', function(value) { assertTrue(false); }); this.__defineSetter__('x', function(value) { assertTrue(false); });
...@@ -38,4 +37,4 @@ try { ...@@ -38,4 +37,4 @@ try {
assertTrue(e instanceof TypeError); assertTrue(e instanceof TypeError);
caught = true; caught = true;
} }
assertTrue(caught); assertFalse(caught);
...@@ -76,6 +76,8 @@ array = [ ...@@ -76,6 +76,8 @@ array = [
"execScript"]; "execScript"];
CheckEcmaSemantics(this, array, "Global"); CheckEcmaSemantics(this, array, "Global");
CheckReadOnlyAttr(this, "Infinity"); CheckReadOnlyAttr(this, "Infinity");
CheckReadOnlyAttr(this, "NaN");
CheckReadOnlyAttr(this, "undefined");
array = ["exec", "test", "toString", "compile"]; array = ["exec", "test", "toString", "compile"];
CheckEcmaSemantics(RegExp.prototype, array, "RegExp prototype"); CheckEcmaSemantics(RegExp.prototype, array, "RegExp prototype");
...@@ -189,7 +191,7 @@ function CheckReadOnlyAttr(type, prop) { ...@@ -189,7 +191,7 @@ function CheckReadOnlyAttr(type, prop) {
assertFalse(deleted, "delete operator returned true: " + prop); assertFalse(deleted, "delete operator returned true: " + prop);
assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop); assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop);
type[prop] = "foo"; type[prop] = "foo";
assertEquals("foo", type[prop], "overwritable: " + prop); assertEquals(old, type[prop], "overwritable: " + prop);
} }
print("OK"); print("OK");
...@@ -176,6 +176,14 @@ S15.5.4.13_A1_T3: FAIL_OK ...@@ -176,6 +176,14 @@ S15.5.4.13_A1_T3: FAIL_OK
S15.5.4.14_A1_T3: FAIL_OK S15.5.4.14_A1_T3: FAIL_OK
S15.5.4.15_A1_T3: FAIL_OK S15.5.4.15_A1_T3: FAIL_OK
# NaN, Infinity and undefined are read-only according to ES5.
S15.1.1.1_A2_T1: FAIL_OK # NaN
S15.1.1.1_A2_T2: FAIL_OK # NaN
S15.1.1.2_A2_T1: FAIL_OK # Infinity
# S15.1.1.2_A2_T2 would fail if it weren't bogus in r97. sputnik bug #45.
S15.1.1.3_A2_T1: FAIL_OK # undefined
S15.1.1.3_A2_T2: FAIL_OK # undefined
##################### SKIPPED TESTS ##################### ##################### SKIPPED TESTS #####################
# These tests take a looong time to run in debug mode. # These tests take a looong time to run in debug mode.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment