diff --git a/tests/ecmascript/test-dev-ondemand-constructor-prototype-defineproperty.js b/tests/ecmascript/test-dev-ondemand-constructor-prototype-defineproperty.js new file mode 100644 index 0000000000..da3d6f5694 --- /dev/null +++ b/tests/ecmascript/test-dev-ondemand-constructor-prototype-defineproperty.js @@ -0,0 +1,66 @@ +/*--- +{ + "custom": true +} +---*/ + +/*=== +- Object.defineProperty() and .prototype +TypeError +number 321 +number 123 +TypeError +done +===*/ + +// Because the .prototype is intended to be writable, but configurable or +// enumerable, Object.defineProperty() should not allow modification of +// any attributes except: (1) to disable writable, (2) to update the value. +print('- Object.defineProperty() and .prototype'); +try { + // This must fail because the (actually non-existent) .prototype is + // not configurable. + var X = function () {}; + Object.defineProperty(X, 'prototype', { enumerable: true }); + print('never here'); +} catch (e) { + print(e.name); +} +try { + // This must succeed because the .prototype is writable. + var X = function () {}; + Object.defineProperty(X, 'prototype', { value: 321 }); + print(typeof X.prototype, X.prototype); +} catch (e) { + print(e); +} +try { + // Defining all attributes which are compatible with the virtualized + // existing ones -> must succeed. + var X = function () {}; + Object.defineProperty(X, 'prototype', { + value: 123, + writable: true, + enumerable: false, + configurable: false + }); + print(typeof X.prototype, X.prototype); +} catch (e) { + print(e); +} +try { + // Defining all attributes which are incompatible with the virtualized + // existing ones -> must fail. + var X = function () {}; + Object.defineProperty(X, 'prototype', { + value: 123, + writable: true, + enumerable: true, // incompatible + configurable: false + }); + print('never here'); +} catch (e) { + print(e.name); +} + +print('done'); diff --git a/tests/ecmascript/test-dev-ondemand-constructor-prototype-getownpropertydescriptor.js b/tests/ecmascript/test-dev-ondemand-constructor-prototype-getownpropertydescriptor.js new file mode 100644 index 0000000000..3427f8338d --- /dev/null +++ b/tests/ecmascript/test-dev-ondemand-constructor-prototype-getownpropertydescriptor.js @@ -0,0 +1,26 @@ +/*--- +{ + "custom": true +} +---*/ + +/*=== +- Object.getOwnPropertyDescriptor() spawns .prototype +object +object +true +false +false +done +===*/ + +print('- Object.getOwnPropertyDescriptor() spawns .prototype'); +var X = function () {}; +var pd = Object.getOwnPropertyDescriptor(X, 'prototype'); +print(typeof pd); +print(typeof pd.value); +print(pd.writable); +print(pd.enumerable); +print(pd.configurable); + +print('done'); diff --git a/tests/ecmascript/test-dev-ondemand-constructor-prototype-misc.js b/tests/ecmascript/test-dev-ondemand-constructor-prototype-misc.js new file mode 100644 index 0000000000..a63a9bcd1c --- /dev/null +++ b/tests/ecmascript/test-dev-ondemand-constructor-prototype-misc.js @@ -0,0 +1,23 @@ +/*--- +{ + "custom": true +} +---*/ + +print('- non-constructable built-ins have no .prototype'); +var X = Math.cos; +print('prototype' in X); +print(X.prototype); +print('prototype' in X); + +print('- non-constructable functions like object getter/setters have no .prototype'); +var tmp = { + get X() {}, +}; +X = Object.getOwnPropertyDescriptor(tmp, 'X').get; +print(typeof X); +print('prototype' in X); +print(X.prototype); +print('prototype' in X); + +print('done'); diff --git a/tests/ecmascript/test-dev-ondemand-constructor-prototype-refcount-finalize.js b/tests/ecmascript/test-dev-ondemand-constructor-prototype-refcount-finalize.js new file mode 100644 index 0000000000..ddf7a85328 --- /dev/null +++ b/tests/ecmascript/test-dev-ondemand-constructor-prototype-refcount-finalize.js @@ -0,0 +1,72 @@ +/*--- +{ + "custom": true +} +---*/ + +function FX() { + print('finalize X'); +} +function FY() { + print('finalize Y'); +} + +print('- prototype in func'); +var f = function () {}; +print('prototype' in f); +Duktape.gc(); Duktape.gc(); + +print('- own property names'); +var f = function () {}; +print(Object.getOwnPropertyNames(f).join(',')); +f.prototype.foo = 'bar'; +print(Object.getOwnPropertyNames(f).join(',')); +Duktape.gc(); Duktape.gc(); + +print('- refcount finalization, anonymous function'); +var X = function () {}; +Duktape.fin(X, FX); +print('setting X to null'); +X = null; +print('X set to null'); +Duktape.gc(); Duktape.gc(); + +print('- refcount finalization, named function'); +var X = function foo() {}; +Duktape.fin(X, FX); +print('setting X to null'); +X = null; +print('X set to null'); +Duktape.gc(); Duktape.gc(); + +print('- refcount finalization, anonymous inner function, reference not kept'); +var X = function () { + var Y = function () {}; + Duktape.fin(Y, FY); + Y = null; +}; +Duktape.fin(X, FX); +print('call X'); +X(); +print('setting X to null'); +X = null; +print('X set to null'); +Duktape.gc(); Duktape.gc(); + +print('- refcount finalization, anonymous inner function, reference kept'); +var X = function () { + var Y = function () {}; + Duktape.fin(Y, FY); + // At this point the anonymous inner function points to the outer scope, + // which holds a reference back to the function via 'Y', so cannot + // collect via refcounting. +}; +Duktape.fin(X, FX); +print('call X'); +X(); +print('setting X to null'); +X = null; +print('X set to null'); +Duktape.gc(); Duktape.gc(); + +print('done');