Change global const handling to silently ignore redeclarations
and make window.{Infinity,NaN,undefined} read-only as per ES5 BUG=89490 TEST=mjsunit/const-redecl.js, mjsunit/undeletable-functions.js, es5conform, sputnik Review URL: http://codereview.chromium.org/7811015 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9299 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c7d2903fae
commit
fcc2e65aad
160
src/runtime.cc
160
src/runtime.cc
@ -1211,46 +1211,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
||||
LookupResult lookup;
|
||||
global->Lookup(*name, &lookup);
|
||||
if (lookup.IsProperty()) {
|
||||
// Determine if the property is local by comparing the holder
|
||||
// against the global object. The information will be used to
|
||||
// avoid throwing re-declaration errors when declaring
|
||||
// variables or constants that exist in the prototype chain.
|
||||
bool is_local = (*global == lookup.holder());
|
||||
// Get the property attributes and determine if the property is
|
||||
// read-only.
|
||||
PropertyAttributes attributes = global->GetPropertyAttribute(*name);
|
||||
bool is_read_only = (attributes & READ_ONLY) != 0;
|
||||
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.
|
||||
// We found an existing property. Unless it was an interceptor
|
||||
// that claims the property is absent, skip this declaration.
|
||||
if (lookup.type() != INTERCEPTOR) {
|
||||
continue;
|
||||
}
|
||||
PropertyAttributes attributes = global->GetPropertyAttribute(*name);
|
||||
if (attributes != ABSENT) {
|
||||
continue;
|
||||
}
|
||||
// Fall-through and introduce the absent property by using
|
||||
// SetProperty.
|
||||
}
|
||||
} else {
|
||||
is_function_declaration = true;
|
||||
@ -1267,20 +1238,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
||||
LookupResult 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
|
||||
// 13, page 71, the property must be read-only and
|
||||
// non-deletable. However, neither SpiderMonkey nor KJS creates the
|
||||
@ -1465,64 +1422,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
|
||||
// to assign to the property.
|
||||
// Note that objects can have hidden prototypes, so we need to traverse
|
||||
// the whole chain of hidden prototypes to do a 'local' lookup.
|
||||
JSObject* real_holder = global;
|
||||
Object* object = global;
|
||||
LookupResult lookup;
|
||||
while (true) {
|
||||
real_holder->LocalLookup(*name, &lookup);
|
||||
if (lookup.IsProperty()) {
|
||||
// Determine if this is a redeclaration of something read-only.
|
||||
if (lookup.IsReadOnly()) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Determine if this is a redeclaration of an intercepted read-only
|
||||
// property and figure out if the property exists at all.
|
||||
bool found = true;
|
||||
PropertyType type = lookup.type();
|
||||
if (type == INTERCEPTOR) {
|
||||
HandleScope handle_scope(isolate);
|
||||
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);
|
||||
while (object->IsJSObject() &&
|
||||
JSObject::cast(object)->map()->is_hidden_prototype()) {
|
||||
JSObject* raw_holder = JSObject::cast(object);
|
||||
raw_holder->LocalLookup(*name, &lookup);
|
||||
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
|
||||
HandleScope handle_scope(isolate);
|
||||
Handle<JSObject> holder(raw_holder);
|
||||
PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
|
||||
// Update the raw pointer in case it's changed due to GC.
|
||||
raw_holder = *holder;
|
||||
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
|
||||
// Found an interceptor that's not read only.
|
||||
if (assign) {
|
||||
return raw_holder->SetProperty(
|
||||
&lookup, *name, args[2], attributes, strict_mode);
|
||||
} else {
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
}
|
||||
|
||||
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* proto = real_holder->GetPrototype();
|
||||
if (!proto->IsJSObject())
|
||||
break;
|
||||
|
||||
if (!JSObject::cast(proto)->map()->is_hidden_prototype())
|
||||
break;
|
||||
|
||||
real_holder = JSObject::cast(proto);
|
||||
object = raw_holder->GetPrototype();
|
||||
}
|
||||
|
||||
// Reload global in case the loop above performed a GC.
|
||||
global = isolate->context()->global();
|
||||
if (assign) {
|
||||
return global->SetProperty(*name, args[2], attributes, strict_mode);
|
||||
@ -1560,25 +1485,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
|
||||
attributes);
|
||||
}
|
||||
|
||||
// Determine if this is a redeclaration of something not
|
||||
// read-only. In case the result is hidden behind an interceptor we
|
||||
// need to ask it for the property attributes.
|
||||
if (!lookup.IsReadOnly()) {
|
||||
if (lookup.type() != INTERCEPTOR) {
|
||||
return ThrowRedeclarationError(isolate, "var", name);
|
||||
}
|
||||
|
||||
PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
|
||||
|
||||
// Throw re-declaration error if the intercepted property is present
|
||||
// but not read-only.
|
||||
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
|
||||
return ThrowRedeclarationError(isolate, "var", name);
|
||||
}
|
||||
|
||||
// Restore global object from context (in case of GC) and continue
|
||||
// with setting the value because the property is either absent or
|
||||
// read-only. We also have to do redo the lookup.
|
||||
// with setting the value.
|
||||
HandleScope handle_scope(isolate);
|
||||
Handle<GlobalObject> global(isolate->context()->global());
|
||||
|
||||
@ -1595,19 +1504,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
|
||||
return *value;
|
||||
}
|
||||
|
||||
// Set the value, but only we're assigning the initial value to a
|
||||
// Set the value, but only if we're assigning the initial value to a
|
||||
// constant. For now, we determine this by checking if the
|
||||
// current value is the hole.
|
||||
// Strict mode handling not needed (const disallowed in strict mode).
|
||||
// Strict mode handling not needed (const is disallowed in strict mode).
|
||||
PropertyType type = lookup.type();
|
||||
if (type == FIELD) {
|
||||
FixedArray* properties = global->properties();
|
||||
int index = lookup.GetFieldIndex();
|
||||
if (properties->get(index)->IsTheHole()) {
|
||||
if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
|
||||
properties->set(index, *value);
|
||||
}
|
||||
} else if (type == NORMAL) {
|
||||
if (global->GetNormalizedProperty(&lookup)->IsTheHole()) {
|
||||
if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
|
||||
!lookup.IsReadOnly()) {
|
||||
global->SetNormalizedProperty(&lookup, *value);
|
||||
}
|
||||
} else {
|
||||
|
@ -193,13 +193,14 @@ function GlobalEval(x) {
|
||||
function SetUpGlobal() {
|
||||
%CheckIsBootstrapping();
|
||||
// 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.
|
||||
%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.
|
||||
%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.
|
||||
InstallFunctions(global, DONT_ENUM, $Array(
|
||||
|
@ -232,7 +232,7 @@ TEST(Unknown) {
|
||||
context.Check("const x; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ TEST(Unknown) {
|
||||
context.Check("const x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
|
||||
}
|
||||
}
|
||||
@ -285,18 +285,18 @@ TEST(Present) {
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("const x; x",
|
||||
0,
|
||||
0,
|
||||
1, // access
|
||||
1, // initialization
|
||||
1, // (re-)declaration
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("const x = 0; x",
|
||||
0,
|
||||
0,
|
||||
1, // access
|
||||
1, // initialization
|
||||
1, // (re-)declaration
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +341,7 @@ TEST(Absent) {
|
||||
context.Check("const x; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initializetion
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
@ -349,7 +349,7 @@ TEST(Absent) {
|
||||
context.Check("const x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
|
||||
}
|
||||
|
||||
@ -429,18 +429,20 @@ TEST(Appearing) {
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("const x; x",
|
||||
0,
|
||||
1, // declaration
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("const x = 0; x",
|
||||
0,
|
||||
1, // declaration
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
// Result is undefined because declaration succeeded but
|
||||
// initialization to 0 failed (due to context behavior).
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,9 +498,9 @@ TEST(Reappearing) {
|
||||
{ ReappearingPropertyContext context;
|
||||
context.Check("const x; var x = 0",
|
||||
0,
|
||||
2, // var declaration + const initialization
|
||||
4, // 2 x declaration + 2 x initialization
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
3, // const declaration+initialization, var initialization
|
||||
3, // 2 x declaration + var initialization
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
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
|
||||
# non-property in the test.
|
||||
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) {
|
||||
var msg = s;
|
||||
if (opt_e) { e = opt_e; msg += "; " + opt_e; }
|
||||
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 + "'");
|
||||
}
|
||||
|
||||
@ -218,3 +219,62 @@ TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x");
|
||||
// Test that const inside with behaves correctly.
|
||||
TestAll(87, "with ({x:42}) { const x = 87; }", "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 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Check that dynamically introducing conflicting consts/vars
|
||||
// leads to exceptions.
|
||||
// is silently ignored (and does not lead to exceptions).
|
||||
|
||||
var caught = 0;
|
||||
|
||||
@ -46,12 +46,12 @@ eval("var c");
|
||||
try { eval("const c"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
|
||||
assertTrue(typeof c == 'undefined');
|
||||
try { eval("const c = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
|
||||
assertTrue(typeof c == 'undefined');
|
||||
assertEquals(1, c);
|
||||
|
||||
eval("var d = 0");
|
||||
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); }
|
||||
assertEquals(0, d);
|
||||
assertEquals(1, d);
|
||||
|
||||
assertEquals(8, caught);
|
||||
assertEquals(0, caught);
|
||||
|
@ -49,7 +49,7 @@ try {
|
||||
exception = true;
|
||||
assertTrue(/TypeError/.test(e));
|
||||
}
|
||||
assertTrue(exception);
|
||||
assertFalse(exception);
|
||||
|
||||
exception = false;
|
||||
try {
|
||||
|
@ -25,17 +25,16 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Make sure that a const definition always
|
||||
// conflicts with a defined setter. This avoid
|
||||
// trying to pass 'the hole' to the setter.
|
||||
// Make sure that a const definition does not try
|
||||
// to pass 'the hole' to a defined setter.
|
||||
|
||||
this.__defineSetter__('x', function(value) { assertTrue(false); });
|
||||
this.__defineSetter__('x', function(value) { assertTrue(value === 1); });
|
||||
|
||||
var caught = false;
|
||||
try {
|
||||
eval('const x');
|
||||
eval('const x = 1');
|
||||
} catch(e) {
|
||||
assertTrue(e instanceof TypeError);
|
||||
caught = true;
|
||||
}
|
||||
assertTrue(caught);
|
||||
assertFalse(caught);
|
||||
|
@ -76,6 +76,8 @@ array = [
|
||||
"execScript"];
|
||||
CheckEcmaSemantics(this, array, "Global");
|
||||
CheckReadOnlyAttr(this, "Infinity");
|
||||
CheckReadOnlyAttr(this, "NaN");
|
||||
CheckReadOnlyAttr(this, "undefined");
|
||||
|
||||
array = ["exec", "test", "toString", "compile"];
|
||||
CheckEcmaSemantics(RegExp.prototype, array, "RegExp prototype");
|
||||
@ -189,7 +191,7 @@ function CheckReadOnlyAttr(type, prop) {
|
||||
assertFalse(deleted, "delete operator returned true: " + prop);
|
||||
assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop);
|
||||
type[prop] = "foo";
|
||||
assertEquals("foo", type[prop], "overwritable: " + prop);
|
||||
assertEquals(old, type[prop], "overwritable: " + prop);
|
||||
}
|
||||
|
||||
print("OK");
|
||||
|
@ -176,6 +176,14 @@ S15.5.4.13_A1_T3: FAIL_OK
|
||||
S15.5.4.14_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 #####################
|
||||
|
||||
# These tests take a looong time to run in debug mode.
|
||||
|
Loading…
Reference in New Issue
Block a user