4 * Establish some immutable descriptor Shapes with our preferred defaults.
5 * We want normally-behaving properties unless told otherwise.
7 function defaultShape(proto
, ...objs
) {
8 const newObject
= Object
.create(proto
);
9 Object
.assign(newObject
, ...objs
);
13 const defaultDataDescriptor
= defaultShape(null, {
20 const defaultAccessorDescriptor
= defaultShape(null, {
28 * Create a new descriptor which inherits our preferred defaults.
29 * @param {Object} defaultDescriptor
30 * @param {...any} objs
33 function descriptorFromDefault(defaultDescriptor
, ...objs
) {
34 const newObject
= Object
.create(defaultDataDescriptor
);
35 Object
.assign(newObject
, ...objs
);
36 return Object
.assign(Object
.create(defaultDescriptor
), ...objs
);
40 * Defer calling initializer to set value for name until name is read.
42 * @param {String} name
43 * @param {() => {*}} initializer
44 * @param {Object=} descriptor
45 * @param {Boolean} descriptor.configurable
46 * @param {Boolean} descriptor.enumerable
47 * @param {Boolean} descriptor.writable
49 function lazy(obj
, name
, initializer
, descriptor
) {
50 if (typeof initializer
!== 'function') {
51 throw new TypeError('initialize is not callable');
54 // Establish the descriptor for the eventually-initialized property.
55 const finalDescriptor
= descriptorFromDefault(defaultDataDescriptor
, descriptor
);
57 // The descriptor defining the interim accessor property.
58 const lazyDescriptor
= descriptorFromDefault(defaultAccessorDescriptor
, {
59 // The accessor replaces itself with the value returned by invoking the initializer.
61 finalDescriptor
.value
= initializer
.apply(obj
);
62 Object
.defineProperty(obj
, name
, finalDescriptor
);
63 return finalDescriptor
.value
;
66 // An explicit set overrides the lazy descriptor with a default data property.
67 set: function (value
) {
68 Object
.defineProperty(obj
, name
, descriptorFromDefault(defaultDataDescriptor
, {
73 configurable: true, // Ensure we can replace ourself.
74 enumerable: finalDescriptor
.enumerable
, // Use requested visibility.
77 Object
.defineProperty(obj
, name
, lazyDescriptor
);