You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
5.0 KiB

/*
* E5.1 updated the algorithm in Section 10.5, declaration binding instantiation.
* Step 5.e is a new step (compared to E5) and restores compatibility to an E3
* idiom. See E5.1 Annex F.
*
* This testcase tests for the the updated E5.1 behavior for eval() calls.
* Eval creates configurable bindings.
*
* Tests for Program execution context are in individual separate files,
* because function declarations are "hoisted" to program entry. Thus,
* controlling test execution is a bit tricky. Program code creates
* non-configurable bindings.
*
* V8 does not pass these tests.
*/
/*
* Notes:
*
* - The new behavior only applies if a function is being re-declared in the
* global environment record. This is the case with:
*
* + Program code
* + Indirect eval
*
* - An existing property of the same name exists in the global object.
* Such a name can be:
*
* + Another function
* + Any other value (like a constant)
*
* - The existing property may have various attribute combinations, and may
* even be an accessor (set/get).
*
* - The purpose of step 5.e is to ensure that the resulting property is
* a plain data property, with [[Writable]] and [[Enumerable]] true;
* [[Configurable]] final value depends on execution context.
*
* + If configurable, the property is converted to a plain data property
* and [[Writable]] and [[Enumerable]] are set to true. [[Configurable]]
* is set based on whether configurable bindings are enabled.
*
* + If not configurable, the property must be a plain data property and
* have [[Writable]] and [[Enumerable]] set. If not, a TypeError occurs.
*
* - Note that re-declaring a global function automatically makes the property
* enumerable even if it earlier wasn't.
*/
function printProps(name) {
var indirectEval = eval;
var global = indirectEval('this;'); // indirect eval -> this = global object
var desc = Object.getOwnPropertyDescriptor(global, name);
if (desc.get || desc.set) {
// Note: typeof will invoke getter here
print(name + ': ' +
'typeof=' + typeof global[name] + ', ' +
'enumerable=' + desc.enumerable + ', ' +
'configurable=' + desc.configurable);
} else {
print(name + ': ' +
'typeof=' + typeof global[name] + ', ' +
'writable=' + desc.writable + ', ' +
'enumerable=' + desc.enumerable + ', ' +
'configurable=' + desc.configurable);
}
}
function defineProp(name, attrs) {
var indirectEval = eval;
var global = indirectEval('this;'); // indirect eval -> this = global object
Object.defineProperty(global, name, attrs);
}
/*===
RegExp: typeof=function, writable=true, enumerable=false, configurable=true
123
RegExp: typeof=function, writable=true, enumerable=true, configurable=true
===*/
/* Existing configurable data property.
*
* Note that the property should become enumerable (but does not in current
* V8).
*/
printProps('RegExp');
try {
eval("function RegExp() { return 123; }");
print(RegExp());
} catch (e) {
print(e.name);
}
printProps('RegExp');
/*===
NaN: typeof=number, writable=false, enumerable=false, configurable=false
TypeError
NaN: typeof=number, writable=false, enumerable=false, configurable=false
===*/
/* Existing non-configurable data property. */
printProps('NaN');
try {
// non-configurable and does not match requirements of step 5.e.iv -> TypeError */
eval("function NaN() { return 234; }");
print('never here');
} catch (e) {
print(e.name);
}
printProps('NaN');
/*===
getter
configurableAccessor: typeof=undefined, enumerable=false, configurable=true
345
configurableAccessor: typeof=function, writable=true, enumerable=true, configurable=true
===*/
/* Existing configurable accessor.
*
* Need to create ourselves.
*/
defineProp('configurableAccessor', {
get: function() { print('getter'); },
set: function(x) { print('setter'); },
enumerable: false,
configurable: true
})
// Note: printProps() will invoke getter here (but not below)
printProps('configurableAccessor');
try {
eval("function configurableAccessor() { return 345; }");
print(configurableAccessor());
} catch (e) {
print(e.name);
}
printProps('configurableAccessor');
/*===
getter
nonconfigurableAccessor: typeof=undefined, enumerable=false, configurable=false
TypeError
getter
nonconfigurableAccessor: typeof=undefined, enumerable=false, configurable=false
===*/
/* Existing non-configurable accessor. */
defineProp('nonconfigurableAccessor', {
get: function() { print('getter'); },
set: function(x) { print('setter'); },
enumerable: false,
configurable: false,
})
// Note: printProps() will invoke getter here and again below
printProps('nonconfigurableAccessor');
try {
eval("function nonconfigurableAccessor() { return 456; }");
} catch (e) {
print(e.name);
}
printProps('nonconfigurableAccessor');