mirror of https://github.com/svaarala/duktape.git
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.
178 lines
5.0 KiB
178 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');
|
|
|
|
|