@webqit/observer 2.0.7 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/actors.js CHANGED
@@ -1,176 +1,180 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _from as _arrFrom } from '@webqit/util/arr/index.js';
6
- import { _isClass, _isFunction, _isTypeObject, _getType } from '@webqit/util/js/index.js';
7
- import { set, deleteProperty, has, get, ownKeys, defineProperty, getOwnPropertyDescriptor } from "./main.js";
8
- import { apply, construct, getPrototypeOf, setPrototypeOf, isExtensible, preventExtensions } from "./main.js";
9
- import { _ } from './util.js';
10
-
11
- /* ---------------ACCESSORIZE METHODS--------------- */
12
-
13
- /**
14
- * Accessorizes props.
15
- *
16
- * @param Array|Object target
17
- * @param String|Array props
18
- * @param Object params
19
- *
20
- * @return Array
21
- */
22
- export function accessorize( target, props, params = {} ) {
23
- target = resolveTarget( target );
24
- const accessorizedProps = _( target, 'accessorizedProps' );
25
- // ---------
26
- function getDescriptorDeep( prop ) {
27
- let descriptor, proto = target;
28
- while ( !descriptor && ( proto = Object.getPrototypeOf( proto ) ) ) {
29
- descriptor = Object.getOwnPropertyDescriptor( proto, prop );
30
- }
31
- return descriptor
32
- ? { proto, descriptor }
33
- : { descriptor: { value: undefined } };
34
- }
35
- // ---------
36
- function accessorizeProp( prop ) {
37
- if ( accessorizedProps.has( prop ) ) return true;
38
- // ------------------
39
- // Current Descriptor Record
40
- const currentDescriptorRecord = getDescriptorDeep( prop );
41
- currentDescriptorRecord.getValue = function() {
42
- return 'get' in this.descriptor ? this.descriptor.get() : this.descriptor.value;
43
- };
44
- currentDescriptorRecord.setValue = function( value ) {
45
- return 'set' in this.descriptor ? this.descriptor.set( value ) : ( this.descriptor.value = value )
46
- };
47
- currentDescriptorRecord.intact = function() {
48
- const currentDescriptor = Object.getOwnPropertyDescriptor( target, prop );
49
- return currentDescriptor.get === accessorization.get
50
- && currentDescriptor.set === accessorization.set
51
- && accessorizedProps.get( prop ) === this;
52
- };
53
- currentDescriptorRecord.restore = function() {
54
- if ( !this.intact() ) return false;
55
- if ( this.proto !== target ) { delete target[ prop ]; }
56
- else { Object.defineProperty( target, prop, this.descriptor ); }
57
- accessorizedProps.delete( prop );
58
- return true;
59
- };
60
- accessorizedProps.set( prop, currentDescriptorRecord );
61
- // ------------------
62
- // enumerable, configurable
63
- const { enumerable = true, configurable = true } = currentDescriptorRecord.descriptor;
64
- const accessorization = { enumerable, configurable };
65
- // set, get
66
- if ( [ 'value', 'set' ].some( x => x in currentDescriptorRecord.descriptor ) ) {
67
- accessorization.set = function ( value ) { return set( this, prop, value, params ); };
68
- }
69
- if ( [ 'value', 'get' ].some( x => x in currentDescriptorRecord.descriptor ) ) {
70
- accessorization.get = function () { return get( this, prop, params ); };
71
- }
72
- try {
73
- Object.defineProperty( target, prop, accessorization );
74
- return true;
75
- } catch( e ) {
76
- accessorizedProps.delete( prop );
77
- return false;
78
- }
79
- }
80
- const _props = Array.isArray( props ) ? props : (
81
- props === undefined ? Object.keys( target ) : [ props ]
82
- );
83
- const statuses = _props.map( accessorizeProp );
84
- return props === undefined || Array.isArray( props )
85
- ? statuses
86
- : statuses[ 0 ];
87
- }
88
-
89
- /**
90
- * Unaccessorizes previously accessorized props.
91
- *
92
- * @param Array|Object target
93
- * @param String|Array props
94
- * @param Object params
95
- *
96
- * @return Array
97
- */
98
- export function unaccessorize( target, props, params = {} ) {
99
- target = resolveTarget( target );
100
- const accessorizedProps = _( target, 'accessorizedProps' );
101
- function unaccessorizeProp( prop ) {
102
- if ( !accessorizedProps.has( prop ) ) return true;
103
- return accessorizedProps.get( prop ).restore();
104
- }
105
- const _props = Array.isArray( props ) ? props : (
106
- props === undefined ? Object.keys( target ) : [ props ]
107
- );
108
- const statuses = _props.map( unaccessorizeProp );
109
- return props === undefined || Array.isArray( props )
110
- ? statuses
111
- : statuses[ 0 ];
112
- }
113
-
114
- /* ---------------PROXY METHODS--------------- */
115
-
116
- /**
117
- * Returns an object as a proxy and binds all instance methods
118
- * to the proxy instead of the object itself.
119
- *
120
- * @param Array|Object target
121
- * @param Object params
122
- *
123
- * @return Proxy
124
- */
125
- export function proxy( target, params = {} ) {
126
- target = resolveTarget( target );
127
- const proxy = new Proxy( target, {
128
- apply: ( target, thisArgument, argumentsList ) => apply( target, thisArgument, argumentsList, params ),
129
- construct: ( target, argumentsList, newTarget = null ) => construct( target, argumentsList, newTarget, params ),
130
- defineProperty: ( target, propertyKey, attributes ) => defineProperty( target, propertyKey, attributes, params ),
131
- deleteProperty: ( target, propertyKey ) => deleteProperty( target, propertyKey, params ),
132
- get: ( target, propertyKey, receiver = null ) => {
133
- const val = get( target, propertyKey, { ...params, receiver } );
134
- if ( params.proxyAutoBinding !== false && _isFunction( val ) && !_isClass( val )) {
135
- return val.bind( proxy );
136
- }
137
- return val;
138
- },
139
- getOwnPropertyDescriptor: ( target, propertyKey ) => getOwnPropertyDescriptor( target, propertyKey, params ),
140
- getPrototypeOf: target => getPrototypeOf( target, params ),
141
- has: ( target, propertyKey ) => has( target, propertyKey, params ),
142
- isExtensible: target => isExtensible( target, params ),
143
- ownKeys: target => ownKeys( target, params ),
144
- preventExtensions: target => preventExtensions( target, params ),
145
- set: ( target, propertyKey, value, receiver = null ) => set( target, propertyKey, value, { ...params, receiver } ),
146
- setPrototypeOf: ( target, prototype ) => setPrototypeOf( target, prototype, params ),
147
- });
148
- _( proxy ).set( proxy, target );
149
- return proxy;
150
- }
151
-
152
- /**
153
- * Returns the original object earlier proxied by proxy().
154
- *
155
- * @param Proxy|Any target
156
- *
157
- * @return Any
158
- */
159
- export function unproxy( target ) {
160
- // Proxy targets are mapped to their own instances internally
161
- return _( target ).get( target ) || target;
162
- }
163
-
164
- /* ---------------HELPERS--------------- */
165
-
166
- /**
167
- * Ensures target object is an object or array.
168
- *
169
- * @param Array|Object target
170
- *
171
- * @return Array|Object
172
- */
173
- function resolveTarget( target ) {
174
- if ( !target || !_isTypeObject( target ) ) throw new Error('Target must be of type object!');
175
- return unproxy( target );
176
- }
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import { _from as _arrFrom } from '@webqit/util/arr/index.js';
6
+ import { _isClass, _isFunction, _isTypeObject, _getType } from '@webqit/util/js/index.js';
7
+ import { set, deleteProperty, has, get, ownKeys, defineProperty, getOwnPropertyDescriptor } from "./main.js";
8
+ import { batch, apply, construct, getPrototypeOf, setPrototypeOf, isExtensible, preventExtensions } from "./main.js";
9
+ import { _ } from './util.js';
10
+
11
+ /* ---------------ACCESSORIZE METHODS--------------- */
12
+
13
+ /**
14
+ * Accessorizes props.
15
+ *
16
+ * @param Array|Object target
17
+ * @param String|Array props
18
+ * @param Object params
19
+ *
20
+ * @return Array
21
+ */
22
+ export function accessorize( target, props, params = {} ) {
23
+ target = resolveTarget( target );
24
+ const accessorizedProps = _( target, 'accessorizedProps' );
25
+ // ---------
26
+ function getDescriptorDeep( prop ) {
27
+ let descriptor, proto = target;
28
+ do {
29
+ descriptor = Object.getOwnPropertyDescriptor( proto, prop );
30
+ } while ( !descriptor && ( proto = Object.getPrototypeOf( proto ) ) );
31
+ return descriptor
32
+ ? { proto, descriptor }
33
+ : { descriptor: { value: undefined, configurable: true, enumerable: true, writable: true } };
34
+ }
35
+ // ---------
36
+ function accessorizeProp( prop ) {
37
+ if ( accessorizedProps.has( prop + '' ) ) return true;
38
+ // ------------------
39
+ // Current Descriptor Record
40
+ const currentDescriptorRecord = getDescriptorDeep( prop );
41
+ currentDescriptorRecord.getValue = function() {
42
+ return this.descriptor.get ? this.descriptor.get() : this.descriptor.value;
43
+ };
44
+ currentDescriptorRecord.setValue = function( value ) {
45
+ this.dirty = true;
46
+ return this.descriptor.set ? this.descriptor.set( value ) !== false : ( this.descriptor.value = value, true );
47
+ };
48
+ currentDescriptorRecord.intact = function() {
49
+ const currentDescriptor = Object.getOwnPropertyDescriptor( target, prop );
50
+ return currentDescriptor?.get === accessorization.get
51
+ && currentDescriptor?.set === accessorization.set
52
+ && accessorizedProps.get( prop + '' ) === this;
53
+ };
54
+ currentDescriptorRecord.restore = function() {
55
+ if ( !this.intact() ) return false;
56
+ if ( ( this.proto && this.proto !== target ) || ( !this.proto && !this.dirty ) ) { delete target[ prop ]; }
57
+ else { Object.defineProperty( target, prop, this.descriptor ); }
58
+ accessorizedProps.delete( prop + '' );
59
+ return true;
60
+ };
61
+ accessorizedProps.set( prop + '', currentDescriptorRecord );
62
+ // ------------------
63
+ // enumerable, configurable
64
+ const { enumerable = true } = currentDescriptorRecord.descriptor;
65
+ const accessorization = { enumerable, configurable: true };
66
+ // set, get
67
+ if ( ( 'value' in currentDescriptorRecord.descriptor ) || currentDescriptorRecord.descriptor.set ) {
68
+ accessorization.set = function ( value ) { return set( this, prop, value, params ); };
69
+ }
70
+ if ( ( 'value' in currentDescriptorRecord.descriptor ) || currentDescriptorRecord.descriptor.get ) {
71
+ accessorization.get = function () { return get( this, prop, params ); };
72
+ }
73
+ try {
74
+ Object.defineProperty( target, prop, accessorization );
75
+ return true;
76
+ } catch( e ) {
77
+ accessorizedProps.delete( prop + '' );
78
+ return false;
79
+ }
80
+ }
81
+ const _props = Array.isArray( props ) ? props : (
82
+ props === undefined ? Object.keys( target ) : [ props ]
83
+ );
84
+ const statuses = _props.map( accessorizeProp );
85
+ return props === undefined || Array.isArray( props )
86
+ ? statuses
87
+ : statuses[ 0 ];
88
+ }
89
+
90
+ /**
91
+ * Unaccessorizes previously accessorized props.
92
+ *
93
+ * @param Array|Object target
94
+ * @param String|Array props
95
+ * @param Object params
96
+ *
97
+ * @return Array
98
+ */
99
+ export function unaccessorize( target, props, params = {} ) {
100
+ target = resolveTarget( target );
101
+ const accessorizedProps = _( target, 'accessorizedProps' );
102
+ function unaccessorizeProp( prop ) {
103
+ if ( !accessorizedProps.has( prop + '' ) ) return true;
104
+ return accessorizedProps.get( prop + '' ).restore();
105
+ }
106
+ const _props = Array.isArray( props ) ? props : (
107
+ props === undefined ? Object.keys( target ) : [ props ]
108
+ );
109
+ const statuses = _props.map( unaccessorizeProp );
110
+ return props === undefined || Array.isArray( props )
111
+ ? statuses
112
+ : statuses[ 0 ];
113
+ }
114
+
115
+ /* ---------------PROXY METHODS--------------- */
116
+
117
+ /**
118
+ * Returns an object as a proxy and binds all instance methods
119
+ * to the proxy instead of the object itself.
120
+ *
121
+ * @param Array|Object target
122
+ * @param Object params
123
+ *
124
+ * @return Proxy
125
+ */
126
+ export function proxy( target, params = {} ) {
127
+ target = resolveTarget( target );
128
+ const proxy = new Proxy( target, {
129
+ apply: ( target, thisArgument, argumentsList ) => apply( target, thisArgument, argumentsList, params ),
130
+ construct: ( target, argumentsList, newTarget = null ) => construct( target, argumentsList, newTarget, params ),
131
+ defineProperty: ( target, propertyKey, attributes ) => defineProperty( target, propertyKey, attributes, params ),
132
+ deleteProperty: ( target, propertyKey ) => deleteProperty( target, propertyKey, params ),
133
+ get: ( target, propertyKey, receiver = null ) => {
134
+ const val = get( target, propertyKey, { ...params, receiver } );
135
+ if ( params.proxyAutoBinding !== false && _isFunction( val ) && !_isClass( val )) {
136
+ return function( ...args ) {
137
+ const _this = this || proxy;
138
+ return batch( _this, () => val.call( _this, ...args ) );
139
+ }
140
+ }
141
+ return val;
142
+ },
143
+ getOwnPropertyDescriptor: ( target, propertyKey ) => getOwnPropertyDescriptor( target, propertyKey, params ),
144
+ getPrototypeOf: target => getPrototypeOf( target, params ),
145
+ has: ( target, propertyKey ) => has( target, propertyKey, params ),
146
+ isExtensible: target => isExtensible( target, params ),
147
+ ownKeys: target => ownKeys( target, params ),
148
+ preventExtensions: target => preventExtensions( target, params ),
149
+ set: ( target, propertyKey, value, receiver = null ) => set( target, propertyKey, value, { ...params, receiver } ),
150
+ setPrototypeOf: ( target, prototype ) => setPrototypeOf( target, prototype, params ),
151
+ });
152
+ _( proxy ).set( proxy, target );
153
+ return proxy;
154
+ }
155
+
156
+ /**
157
+ * Returns the original object earlier proxied by proxy().
158
+ *
159
+ * @param Proxy|Any target
160
+ *
161
+ * @return Any
162
+ */
163
+ export function unproxy( target ) {
164
+ // Proxy targets are mapped to their own instances internally
165
+ return _( target ).get( target ) || target;
166
+ }
167
+
168
+ /* ---------------HELPERS--------------- */
169
+
170
+ /**
171
+ * Ensures target object is an object or array.
172
+ *
173
+ * @param Array|Object target
174
+ *
175
+ * @return Array|Object
176
+ */
177
+ function resolveTarget( target ) {
178
+ if ( !target || !_isTypeObject( target ) ) throw new Error('Target must be of type object!');
179
+ return unproxy( target );
180
+ }
@@ -1,23 +1,23 @@
1
-
2
- /**
3
- * ---------------------------
4
- * The Descriptor class
5
- * ---------------------------
6
- */
7
-
8
- export default class Descriptor {
9
-
10
- /**
11
- * Initializes the instance.
12
- *
13
- * @param array|object target
14
- * @param object dfn
15
- *
16
- * @return void
17
- */
18
- constructor( target, dfn ) {
19
- this.target = target;
20
- if ( !( dfn.type ) ) throw new Error( 'Descriptor type must be given in definition!' );
21
- Object.assign( this, dfn );
22
- }
1
+
2
+ /**
3
+ * ---------------------------
4
+ * The Descriptor class
5
+ * ---------------------------
6
+ */
7
+
8
+ export default class Descriptor {
9
+
10
+ /**
11
+ * Initializes the instance.
12
+ *
13
+ * @param array|object target
14
+ * @param object dfn
15
+ *
16
+ * @return void
17
+ */
18
+ constructor( target, dfn ) {
19
+ this.target = target;
20
+ if ( !( dfn.type ) ) throw new Error( 'Descriptor type must be given in definition!' );
21
+ Object.assign( this, dfn );
22
+ }
23
23
  }
@@ -1,57 +1,61 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _from as _arrFrom } from '@webqit/util/arr/index.js';
6
- import Registration from './Registration.js';
7
-
8
- /**
9
- * ---------------------------
10
- * The ListenerRegistration class
11
- * ---------------------------
12
- */
13
-
14
- export default class ListenerRegistration extends Registration {
15
-
16
- /**
17
- * @constructor
18
- */
19
- constructor() {
20
- super( ...arguments );
21
- Object.defineProperty( this, 'abortController', { value: new AbortController } );
22
- Object.defineProperty( this, 'signal', { value: this.abortController.signal } );
23
- }
24
-
25
- /**
26
- * De-registers the instance.
27
- *
28
- * @return Void
29
- */
30
- remove() {
31
- this.abortController.abort();
32
- super.remove();
33
- }
34
-
35
- /**
36
- * Calls the observer's handler function
37
- * on matching with the event's fields.
38
- *
39
- * @param Array events
40
- *
41
- * @return Any
42
- */
43
- fire( events ) {
44
- let matches = events, filter = this.filter;
45
- if ( filter !== Infinity && ( filter = _arrFrom( filter ) ) ) {
46
- matches = events.filter( event => filter.includes( event.key ) );
47
- }
48
- if ( this.params.diff ) {
49
- matches = matches.filter( event => event.type !== 'set' || event.value !== event.oldValue );
50
- }
51
- if ( matches.length ) {
52
- return this.filter === Infinity || Array.isArray( this.filter )
53
- ? this.handler( matches, this )
54
- : this.handler( matches[ 0 ], this );
55
- }
56
- }
57
- }
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import { _from as _arrFrom } from '@webqit/util/arr/index.js';
6
+ import Registration from './Registration.js';
7
+
8
+ /**
9
+ * ---------------------------
10
+ * The ListenerRegistration class
11
+ * ---------------------------
12
+ */
13
+
14
+ export default class ListenerRegistration extends Registration {
15
+
16
+ /**
17
+ * @constructor
18
+ */
19
+ constructor() {
20
+ super( ...arguments );
21
+ Object.defineProperty( this, 'abortController', { value: new AbortController } );
22
+ Object.defineProperty( this, 'signal', { value: this.abortController.signal } );
23
+ }
24
+
25
+ /**
26
+ * De-registers the instance.
27
+ *
28
+ * @return Void
29
+ */
30
+ remove() {
31
+ this.abortController.abort();
32
+ super.remove();
33
+ }
34
+
35
+ /**
36
+ * Calls the observer's handler function
37
+ * on matching with the event's fields.
38
+ *
39
+ * @param Array events
40
+ *
41
+ * @return Any
42
+ */
43
+ fire( events ) {
44
+ if ( this.handler.firing ) return;
45
+ let matches = events, filter = this.filter;
46
+ if ( filter !== Infinity && ( filter = _arrFrom( filter ) ) ) {
47
+ matches = events.filter( event => filter.includes( event.key ) );
48
+ }
49
+ if ( this.params.diff ) {
50
+ matches = matches.filter( event => event.type !== 'set' || event.value !== event.oldValue );
51
+ }
52
+ if ( matches.length ) {
53
+ this.handler.firing = true;
54
+ const ret = this.filter === Infinity || Array.isArray( this.filter )
55
+ ? this.handler( matches, this )
56
+ : this.handler( matches[ 0 ], this );
57
+ this.handler.firing = false;
58
+ return ret;
59
+ }
60
+ }
61
+ }