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.
161 lines
4.9 KiB
161 lines
4.9 KiB
/*
|
|
* A lighweight function can be used as a setter/getter but it will be
|
|
* coerced to an ordinary function by Object.defineProperty() and
|
|
* Object.defineProperties().
|
|
*
|
|
* For the most part this is transparent, but when the property descriptor
|
|
* is read back, the 'set' and 'get' properties will be ordinary functions
|
|
* and will not match the original values.
|
|
*/
|
|
|
|
/*---
|
|
{
|
|
"custom": true
|
|
}
|
|
---*/
|
|
|
|
function isLightFunc(x) {
|
|
return Duktape.info(x)[0] == 9; // tag
|
|
}
|
|
|
|
/*===
|
|
Object.defineProperty
|
|
pd_in
|
|
typeof get: function
|
|
isLightFunc get: true
|
|
typeof set: function
|
|
isLightFunc set: true
|
|
get(=Math.min)(9,-3,11,4): -3
|
|
set(=Math.max)(9,-3,11,4): 11
|
|
pd_out
|
|
typeof get: function
|
|
isLightFunc get: false
|
|
typeof set: function
|
|
isLightFunc set: false
|
|
get(=Math.min)(9,-3,11,4): -3
|
|
set(=Math.max)(9,-3,11,4): 11
|
|
pd_in.get == pd_out.get: false
|
|
pd_in.get === pd_out.get: false
|
|
pd_in.set == pd_out.set: false
|
|
pd_in.set === pd_out.set: false
|
|
Object.defineProperties
|
|
pd_in
|
|
typeof get: function
|
|
isLightFunc get: true
|
|
typeof set: function
|
|
isLightFunc set: true
|
|
get(=Math.min)(9,-3,11,4): -3
|
|
set(=Math.max)(9,-3,11,4): 11
|
|
pd_out
|
|
typeof get: function
|
|
isLightFunc get: false
|
|
typeof set: function
|
|
isLightFunc set: false
|
|
get(=Math.min)(9,-3,11,4): -3
|
|
set(=Math.max)(9,-3,11,4): 11
|
|
pd_in.get == pd_out.get: false
|
|
pd_in.get === pd_out.get: false
|
|
pd_in.set == pd_out.set: false
|
|
pd_in.set === pd_out.set: false
|
|
===*/
|
|
|
|
function lightfuncAsAccessorTest() {
|
|
/*
|
|
* Accessor (setter/getter) properties are stored in the internal
|
|
* property table as a pair of duk_hobject pointers. On 32-bit
|
|
* platforms the property value slot is 8 bytes which fits either
|
|
* one duk_tval or two duk_hobject pointers. There is no space for
|
|
* lightfunc flags in the property slot, and increasing the slot
|
|
* size for accessors would be a bad trade-off.
|
|
*
|
|
* The current solution is to coerce a lightfunc into a full function
|
|
* when a user tries to use the lightfunc as a getter/setter. This
|
|
* works transparently for the most part. However, when the property
|
|
* descriptor is read back, the setter/getter is not a lightfunc and
|
|
* doesn't match the original argument.
|
|
*/
|
|
|
|
var obj;
|
|
var pd_in, pd_out;
|
|
|
|
obj = {};
|
|
pd_in = {
|
|
get: Math.min,
|
|
set: Math.max,
|
|
enumerable: true,
|
|
configurable: true
|
|
};
|
|
|
|
print('Object.defineProperty');
|
|
|
|
print('pd_in');
|
|
print('typeof get:', typeof pd_in.get);
|
|
print('isLightFunc get:', isLightFunc(pd_in.get));
|
|
print('typeof set:', typeof pd_in.set);
|
|
print('isLightFunc set:', isLightFunc(pd_in.set));
|
|
print('get(=Math.min)(9,-3,11,4):', pd_in.get(9, -3, 11, 4));
|
|
print('set(=Math.max)(9,-3,11,4):', pd_in.set(9, -3, 11, 4));
|
|
|
|
Object.defineProperty(obj, 'prop', pd_in);
|
|
pd_out = Object.getOwnPropertyDescriptor(obj, 'prop');
|
|
|
|
print('pd_out');
|
|
print('typeof get:', typeof pd_out.get);
|
|
print('isLightFunc get:', isLightFunc(pd_out.get));
|
|
print('typeof set:', typeof pd_out.set);
|
|
print('isLightFunc set:', isLightFunc(pd_out.set));
|
|
print('get(=Math.min)(9,-3,11,4):', pd_out.get(9, -3, 11, 4));
|
|
print('set(=Math.max)(9,-3,11,4):', pd_out.set(9, -3, 11, 4));
|
|
|
|
// Never compares true: lightweight and normal functions never compare
|
|
// as equal.
|
|
print('pd_in.get == pd_out.get:', pd_in.get == pd_out.get);
|
|
print('pd_in.get === pd_out.get:', pd_in.get === pd_out.get);
|
|
print('pd_in.set == pd_out.set:', pd_in.set == pd_out.set);
|
|
print('pd_in.set === pd_out.set:', pd_in.set === pd_out.set);
|
|
|
|
/*
|
|
* Same test for Object.defineProperties() which has a different
|
|
* internal code path.
|
|
*/
|
|
|
|
obj = {};
|
|
pd_in = {
|
|
get: Math.min,
|
|
set: Math.max,
|
|
enumerable: true,
|
|
configurable: true
|
|
};
|
|
|
|
print('Object.defineProperties');
|
|
|
|
print('pd_in');
|
|
print('typeof get:', typeof pd_in.get);
|
|
print('isLightFunc get:', isLightFunc(pd_in.get));
|
|
print('typeof set:', typeof pd_in.set);
|
|
print('isLightFunc set:', isLightFunc(pd_in.set));
|
|
print('get(=Math.min)(9,-3,11,4):', pd_in.get(9, -3, 11, 4));
|
|
print('set(=Math.max)(9,-3,11,4):', pd_in.set(9, -3, 11, 4));
|
|
|
|
Object.defineProperties(obj, { prop: pd_in });
|
|
pd_out = Object.getOwnPropertyDescriptor(obj, 'prop');
|
|
|
|
print('pd_out');
|
|
print('typeof get:', typeof pd_out.get);
|
|
print('isLightFunc get:', isLightFunc(pd_out.get));
|
|
print('typeof set:', typeof pd_out.set);
|
|
print('isLightFunc set:', isLightFunc(pd_out.set));
|
|
print('get(=Math.min)(9,-3,11,4):', pd_out.get(9, -3, 11, 4));
|
|
print('set(=Math.max)(9,-3,11,4):', pd_out.set(9, -3, 11, 4));
|
|
|
|
print('pd_in.get == pd_out.get:', pd_in.get == pd_out.get);
|
|
print('pd_in.get === pd_out.get:', pd_in.get === pd_out.get);
|
|
print('pd_in.set == pd_out.set:', pd_in.set == pd_out.set);
|
|
print('pd_in.set === pd_out.set:', pd_in.set === pd_out.set);
|
|
}
|
|
|
|
try {
|
|
lightfuncAsAccessorTest();
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|