mirror of https://github.com/svaarala/duktape.git
Sami Vaarala
12 years ago
4 changed files with 512 additions and 0 deletions
@ -0,0 +1,38 @@ |
|||
|
|||
/*--- |
|||
{ |
|||
"skip": true |
|||
} |
|||
---*/ |
|||
|
|||
/*=== |
|||
FIXME |
|||
===*/ |
|||
|
|||
print('object constructor as function'); |
|||
|
|||
function constructorAsFunctionTest() { |
|||
} |
|||
|
|||
try { |
|||
constructorAsFunctionTest(); |
|||
} catch (e) { |
|||
print(e.name); |
|||
} |
|||
|
|||
/*=== |
|||
FIXME |
|||
===*/ |
|||
|
|||
print('object constructor as constructor'); |
|||
|
|||
function constructorTest() { |
|||
} |
|||
|
|||
try { |
|||
constructorTest(); |
|||
} catch (e) { |
|||
print(e.name); |
|||
} |
|||
|
|||
|
@ -0,0 +1,125 @@ |
|||
|
|||
function dumpObject(o) { |
|||
print(typeof o, |
|||
Object.prototype.toString.call(o), |
|||
Object.getPrototypeOf(o) === Object.prototype, |
|||
Object.isExtensible(o)); |
|||
} |
|||
|
|||
/*=== |
|||
object constructor as function |
|||
object [object Object] true true |
|||
object [object Object] true true |
|||
object [object Object] true true |
|||
object [object Boolean] false true |
|||
object [object Boolean] false true |
|||
object [object Number] false true |
|||
object [object String] false true |
|||
object [object Array] false true |
|||
true |
|||
object [object Object] true true |
|||
true |
|||
function [object Function] false true |
|||
true |
|||
===*/ |
|||
|
|||
/* Object constructor called as a function. */ |
|||
|
|||
print('object constructor as function'); |
|||
|
|||
function constructorAsFunctionTest() { |
|||
var t1, t2; |
|||
|
|||
dumpObject(Object()); |
|||
dumpObject(Object(undefined)); |
|||
dumpObject(Object(null)); |
|||
dumpObject(Object(true)); |
|||
dumpObject(Object(false)); |
|||
dumpObject(Object(123.0)); |
|||
dumpObject(Object('foo')); |
|||
|
|||
// check that the same object comes back
|
|||
|
|||
t1 = []; |
|||
t2 = Object(t1); |
|||
dumpObject(t1); |
|||
print(t1 === t2); |
|||
|
|||
t1 = {}; |
|||
t2 = Object(t1); |
|||
dumpObject(t1); |
|||
print(t1 === t2); |
|||
|
|||
t1 = function() {}; |
|||
t2 = Object(t1); |
|||
dumpObject(t1); |
|||
print(t1 === t2); |
|||
} |
|||
|
|||
try { |
|||
constructorAsFunctionTest(); |
|||
} catch (e) { |
|||
print(e.name); |
|||
} |
|||
|
|||
/*=== |
|||
object constructor as constructor |
|||
object [object Object] true true |
|||
object [object Object] true true |
|||
object [object Object] true true |
|||
object [object Boolean] false true |
|||
object [object Boolean] false true |
|||
object [object Number] false true |
|||
object [object String] false true |
|||
object [object Array] false true |
|||
true |
|||
object [object Object] true true |
|||
true |
|||
function [object Function] false true |
|||
true |
|||
object [object Number] false true |
|||
===*/ |
|||
|
|||
/* Object constructor called as a constructor */ |
|||
|
|||
print('object constructor as constructor'); |
|||
|
|||
function constructorTest() { |
|||
var t1, t2; |
|||
|
|||
dumpObject(new Object()); |
|||
dumpObject(new Object(undefined)); |
|||
dumpObject(new Object(null)); |
|||
dumpObject(new Object(true)); |
|||
dumpObject(new Object(false)); |
|||
dumpObject(new Object(123.0)); |
|||
dumpObject(new Object('foo')); |
|||
|
|||
// check that the same object comes back
|
|||
|
|||
t1 = []; |
|||
t2 = new Object(t1); |
|||
dumpObject(t1); |
|||
print(t1 === t2); |
|||
|
|||
t1 = {}; |
|||
t2 = new Object(t1); |
|||
dumpObject(t1); |
|||
print(t1 === t2); |
|||
|
|||
t1 = function() {}; |
|||
t2 = new Object(t1); |
|||
dumpObject(t1); |
|||
print(t1 === t2); |
|||
|
|||
// arguments beyond first optional arg are ignored
|
|||
t2 = new Object(123, 'foo'); |
|||
dumpObject(t2); |
|||
} |
|||
|
|||
try { |
|||
constructorTest(); |
|||
} catch (e) { |
|||
print(e.name); |
|||
} |
|||
|
@ -0,0 +1,336 @@ |
|||
// FIXME: util
|
|||
function formatValue(v) { |
|||
if (typeof v === 'function') { |
|||
// avoid implementation dependent string formatting
|
|||
if (v.funcName) { |
|||
return '[function ' + v.funcName + ']'; |
|||
} else { |
|||
return Object.prototype.toString.call(v); |
|||
} |
|||
} |
|||
if (typeof v === 'number') { |
|||
if (v === 0) { |
|||
if (1/v === Number.NEGATIVE_INFINITY) { |
|||
// format negative zero specially to detect them in the output
|
|||
return '-0'; |
|||
} |
|||
} |
|||
} |
|||
return String(v); |
|||
} |
|||
|
|||
function getDesc(obj, prop) { |
|||
var pd; |
|||
|
|||
if (typeof obj !== 'object' || obj === null) { |
|||
return prop + ': non-object (' + Object.prototype.toString.call(obj) + ')'; |
|||
} |
|||
|
|||
pd = Object.getOwnPropertyDescriptor(obj, prop); |
|||
|
|||
if (pd === undefined) { |
|||
return prop + ': undefined'; |
|||
} |
|||
|
|||
return prop + ': ' + |
|||
'value=' + formatValue(pd.value) + |
|||
', writable=' + formatValue(pd.writable) + |
|||
', enumerable=' + formatValue(pd.enumerable) + |
|||
', configurable=' + formatValue(pd.configurable) + |
|||
', typeof(get)=' + formatValue(pd.get) + |
|||
', typeof(set)=' + formatValue(pd.set); |
|||
} |
|||
|
|||
function printDesc(obj, prop) { |
|||
print(getDesc(obj, prop)); |
|||
} |
|||
|
|||
/*=== |
|||
coercion |
|||
[object Undefined] [object Undefined] TypeError |
|||
[object Undefined] [object Object] TypeError |
|||
[object Null] [object Object] TypeError |
|||
[object Boolean] [object Object] TypeError |
|||
[object Boolean] [object Object] TypeError |
|||
[object Number] [object Object] TypeError |
|||
[object String] [object Object] TypeError |
|||
[object Array] [object Object] ok |
|||
[object Object] [object Object] ok |
|||
[object Object] [object Undefined] TypeError |
|||
[object Object] [object Undefined] TypeError |
|||
[object Object] [object Null] TypeError |
|||
[object Object] [object Boolean] ok |
|||
[object Object] [object Boolean] ok |
|||
[object Object] [object Number] ok |
|||
[object Object] [object String] ok |
|||
[object Object] [object Array] ok |
|||
[object Object] [object Object] ok |
|||
===*/ |
|||
|
|||
/* Test coercion of 'O' and 'Properties' arguments. */ |
|||
|
|||
print('coercion'); |
|||
|
|||
function coercionTest() { |
|||
function test(o, p, arg_count) { |
|||
var t; |
|||
|
|||
try { |
|||
if (arg_count === 0) { |
|||
t = Object.defineProperties(); |
|||
} else if (arg_count === 1) { |
|||
t = Object.defineProperties(o); |
|||
} else { |
|||
t = Object.defineProperties(o, p); |
|||
} |
|||
print(Object.prototype.toString.call(o), |
|||
Object.prototype.toString.call(p), 'ok'); |
|||
} catch (e) { |
|||
print(Object.prototype.toString.call(o), |
|||
Object.prototype.toString.call(p), e.name); |
|||
} |
|||
} |
|||
|
|||
// coercion of 'O'
|
|||
test(undefined, undefined, 0); |
|||
test(undefined, {}); |
|||
test(null, {}); |
|||
test(true, {}); |
|||
test(false, {}); |
|||
test(123, {}); |
|||
test('quux', {}); |
|||
test([1,2], {}); |
|||
test({ foo: 1, bar: 2 }, {}); |
|||
|
|||
// coercion of 'P'
|
|||
test({}, undefined, 1); |
|||
test({}, undefined); |
|||
test({}, null); |
|||
test({}, true); |
|||
test({}, false); |
|||
test({}, 123); |
|||
test({}, ''); // <-- careful to avoid TypeError from ToPropertyDescriptor()
|
|||
test({}, []); // (use empty string, array, object)
|
|||
test({}, {}); //
|
|||
|
|||
// coercion of 'O' and 'P'; 'O' is checked first -- how to test this?
|
|||
} |
|||
|
|||
try { |
|||
coercionTest(); |
|||
} catch (e) { |
|||
print(e); |
|||
} |
|||
|
|||
/*=== |
|||
proplist |
|||
prop1 |
|||
prop2 |
|||
proto-prop |
|||
proto-prop: undefined |
|||
nonenum-prop: undefined |
|||
prop1: value=prop1, writable=true, enumerable=true, configurable=true, typeof(get)=undefined, typeof(set)=undefined |
|||
prop2: value=prop2, writable=true, enumerable=true, configurable=true, typeof(get)=undefined, typeof(set)=undefined |
|||
prop1 |
|||
prop2 |
|||
===*/ |
|||
|
|||
/* Property list is created from own, enumerable properties of 'Properties' |
|||
* argument. |
|||
* |
|||
* This test expects enum order to match insertion order (but the testcase |
|||
* is not marked custom). |
|||
*/ |
|||
|
|||
print('proplist'); |
|||
|
|||
function propListTest() { |
|||
var proto = {}; |
|||
var props; |
|||
var obj; |
|||
var i; |
|||
|
|||
props = Object.create(proto); |
|||
|
|||
// enumerable, but not 'own property'
|
|||
Object.defineProperty(proto, 'proto-prop', { |
|||
value: { value: 'from-proto', writable: true, enumerable: true, configurable: true }, |
|||
writable: true, enumerable: true, configurable: true |
|||
}); |
|||
|
|||
// own property but not enumerable
|
|||
Object.defineProperty(props, 'nonenum-prop', { |
|||
value: { value: 'nonenum', writable: true, enumerable: true, configurable: true }, |
|||
writable: true, enumerable: false, configurable: true |
|||
}); |
|||
|
|||
// own property, enumerable -> will appear
|
|||
Object.defineProperty(props, 'prop1', { |
|||
value: { value: 'prop1', writable: true, enumerable: true, configurable: true }, |
|||
writable: true, enumerable: true, configurable: true |
|||
}); |
|||
Object.defineProperty(props, 'prop2', { |
|||
value: { value: 'prop2', writable: true, enumerable: true, configurable: true }, |
|||
writable: false, enumerable: true, configurable: false |
|||
}); |
|||
|
|||
// for-in will enumerate also inherited properties
|
|||
for (i in props) { |
|||
print(i); |
|||
} |
|||
|
|||
obj = {}; |
|||
Object.defineProperties(obj, props); |
|||
|
|||
printDesc(obj, 'proto-prop'); |
|||
printDesc(obj, 'nonenum-prop'); |
|||
printDesc(obj, 'prop1'); |
|||
printDesc(obj, 'prop2'); |
|||
|
|||
// prop1 and prop2 addition order should match order in 'props'
|
|||
for (i in obj) { |
|||
print(i); |
|||
} |
|||
} |
|||
|
|||
try { |
|||
propListTest(); |
|||
} catch (e) { |
|||
print(e); |
|||
} |
|||
|
|||
/*=== |
|||
topropdesc |
|||
foo: value=2, writable=true, enumerable=true, configurable=true, typeof(get)=undefined, typeof(set)=undefined |
|||
TypeError |
|||
foo: value=1, writable=true, enumerable=true, configurable=true, typeof(get)=undefined, typeof(set)=undefined |
|||
===*/ |
|||
|
|||
/* All ToPropertyDescriptor() coercions and checks happen before any object |
|||
* properties/attributes are changed. |
|||
*/ |
|||
|
|||
print('topropdesc'); |
|||
|
|||
function toPropDescTest() { |
|||
var obj; |
|||
|
|||
// base case: works
|
|||
obj = { foo: 1 }; |
|||
Object.defineProperties(obj, { |
|||
foo: { value: 2 } |
|||
}); |
|||
printDesc(obj, 'foo'); |
|||
|
|||
// invalid desc -> nothing is changed
|
|||
obj = { foo: 1 }; |
|||
try { |
|||
Object.defineProperties(obj, { |
|||
foo: { value: 3 }, // ok
|
|||
bar: { set: function(){}, value: 123 } // conflict
|
|||
}); |
|||
} catch (e) { |
|||
print(e.name); |
|||
} |
|||
printDesc(obj, 'foo'); |
|||
} |
|||
|
|||
try { |
|||
toPropDescTest(); |
|||
} catch (e) { |
|||
print(e); |
|||
} |
|||
|
|||
/*=== |
|||
multiple |
|||
foo: value=1, writable=true, enumerable=true, configurable=true, typeof(get)=undefined, typeof(set)=undefined |
|||
bar: value=2, writable=false, enumerable=true, configurable=false, typeof(get)=undefined, typeof(set)=undefined |
|||
foo |
|||
bar |
|||
TypeError |
|||
foo: value=1, writable=true, enumerable=true, configurable=true, typeof(get)=undefined, typeof(set)=undefined |
|||
bar: value=immutable, writable=false, enumerable=false, configurable=false, typeof(get)=undefined, typeof(set)=undefined |
|||
foo |
|||
===*/ |
|||
|
|||
/* Multiple changes in one go. Note that since 'Properties' is an Object, |
|||
* the same property cannot be edited twice in one defineProperties() call. |
|||
* |
|||
* Unlike the ToPropertyDescriptor() step, the first TypeError (or other |
|||
* error) causes defineProperties() to bail out. |
|||
*/ |
|||
|
|||
print('multiple'); |
|||
|
|||
function multiplePropsTest() { |
|||
var obj; |
|||
var i; |
|||
|
|||
// base case
|
|||
obj = {}; |
|||
Object.defineProperties(obj, { |
|||
foo: { value: 1, writable: true, enumerable: true, configurable: true }, |
|||
bar: { value: 2, writable: false, enumerable: true, configurable: false } |
|||
}); |
|||
printDesc(obj, 'foo'); |
|||
printDesc(obj, 'bar'); |
|||
for (i in obj) { |
|||
// demonstrate enum order
|
|||
print(i); |
|||
} |
|||
|
|||
// first edit bails out, so second one is not made
|
|||
obj = {}; |
|||
Object.defineProperty(obj, 'foo', { |
|||
value: 'configurable', writable: false, enumerable: false, configurable: true |
|||
}); |
|||
Object.defineProperty(obj, 'bar', { |
|||
value: 'immutable', writable: false, enumerable: false, configurable: false |
|||
}); |
|||
try { |
|||
Object.defineProperties(obj, { |
|||
foo: { value: 1, writable: true, enumerable: true, configurable: true }, |
|||
bar: { value: 2, writable: false, enumerable: true, configurable: false } |
|||
}); |
|||
} catch (e) { |
|||
print(e.name); |
|||
} |
|||
printDesc(obj, 'foo'); |
|||
printDesc(obj, 'bar'); |
|||
for (i in obj) { |
|||
// demonstrate enum order
|
|||
print(i); |
|||
} |
|||
} |
|||
|
|||
try { |
|||
multiplePropsTest(); |
|||
} catch (e) { |
|||
print(e); |
|||
} |
|||
|
|||
/*=== |
|||
return |
|||
true |
|||
===*/ |
|||
|
|||
/* Return value is 'O'. */ |
|||
|
|||
print('return'); |
|||
|
|||
function returnValueTest() { |
|||
var obj = {}; |
|||
var ret; |
|||
|
|||
ret = Object.defineProperties(obj, { |
|||
foo: { value: 1, writable: true, enumerable: true, configurable: true } |
|||
}); |
|||
print(ret === obj); |
|||
} |
|||
|
|||
try { |
|||
returnValueTest(); |
|||
} catch (e) { |
|||
print(e); |
|||
} |
|||
|
@ -0,0 +1,13 @@ |
|||
/*--- |
|||
{ |
|||
"skip": true |
|||
} |
|||
---*/ |
|||
|
|||
// FIXME: buffer, pointer, etc
|
|||
|
|||
/*=== |
|||
FIXME |
|||
===*/ |
|||
|
|||
|
Loading…
Reference in new issue