mirror of
https://github.com/chartjs/Chart.js.git
synced 2024-10-06 12:19:08 +02:00
Add support for common object methods to Proxies (#8452)
This commit is contained in:
parent
ba99c4185c
commit
5411be10a0
@ -15,19 +15,46 @@ export function _createResolver(scopes, prefixes = ['']) {
|
||||
override: (scope) => _createResolver([scope].concat(scopes), prefixes),
|
||||
};
|
||||
return new Proxy(cache, {
|
||||
/**
|
||||
* A trap for getting property values.
|
||||
*/
|
||||
get(target, prop) {
|
||||
return _cached(target, prop,
|
||||
() => _resolveWithPrefixes(prop, prefixes, scopes));
|
||||
},
|
||||
|
||||
ownKeys(target) {
|
||||
return getKeysFromAllScopes(target);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for Object.getOwnPropertyDescriptor.
|
||||
* Also used by Object.hasOwnProperty.
|
||||
*/
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for Object.getPrototypeOf.
|
||||
*/
|
||||
getPrototypeOf() {
|
||||
return Reflect.getPrototypeOf(scopes[0]);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for the in operator.
|
||||
*/
|
||||
has(target, prop) {
|
||||
return getKeysFromAllScopes(target).includes(prop);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.
|
||||
*/
|
||||
ownKeys(target) {
|
||||
return getKeysFromAllScopes(target);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for setting property values.
|
||||
*/
|
||||
set(target, prop, value) {
|
||||
scopes[0][prop] = value;
|
||||
return delete target[prop];
|
||||
@ -54,19 +81,46 @@ export function _attachContext(proxy, context, subProxy) {
|
||||
override: (scope) => _attachContext(proxy.override(scope), context, subProxy)
|
||||
};
|
||||
return new Proxy(cache, {
|
||||
/**
|
||||
* A trap for getting property values.
|
||||
*/
|
||||
get(target, prop, receiver) {
|
||||
return _cached(target, prop,
|
||||
() => _resolveWithContext(target, prop, receiver));
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for Object.getOwnPropertyDescriptor.
|
||||
* Also used by Object.hasOwnProperty.
|
||||
*/
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
return Reflect.getOwnPropertyDescriptor(proxy, prop);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for Object.getPrototypeOf.
|
||||
*/
|
||||
getPrototypeOf() {
|
||||
return Reflect.getPrototypeOf(proxy);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for the in operator.
|
||||
*/
|
||||
has(target, prop) {
|
||||
return Reflect.has(proxy, prop);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.
|
||||
*/
|
||||
ownKeys() {
|
||||
return Reflect.ownKeys(proxy);
|
||||
},
|
||||
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
return Reflect.getOwnPropertyDescriptor(proxy._scopes[0], prop);
|
||||
},
|
||||
|
||||
/**
|
||||
* A trap for setting property values.
|
||||
*/
|
||||
set(target, prop, value) {
|
||||
proxy[prop] = value;
|
||||
return delete target[prop];
|
||||
|
@ -88,6 +88,41 @@ describe('Chart.helpers.config', function() {
|
||||
option3: 'defaults3'
|
||||
});
|
||||
});
|
||||
|
||||
it('should support common object methods', function() {
|
||||
const defaults = {
|
||||
option1: 'defaults'
|
||||
};
|
||||
class Options {
|
||||
constructor() {
|
||||
this.option2 = 'options';
|
||||
}
|
||||
get getter() {
|
||||
return 'options getter';
|
||||
}
|
||||
}
|
||||
const options = new Options();
|
||||
|
||||
const resolver = _createResolver([options, defaults]);
|
||||
|
||||
expect(Object.prototype.hasOwnProperty.call(resolver, 'option2')).toBeTrue();
|
||||
|
||||
expect(Object.prototype.hasOwnProperty.call(resolver, 'option1')).toBeFalse();
|
||||
expect(Object.prototype.hasOwnProperty.call(resolver, 'getter')).toBeFalse();
|
||||
expect(Object.prototype.hasOwnProperty.call(resolver, 'nonexistent')).toBeFalse();
|
||||
|
||||
expect(Object.keys(resolver)).toEqual(['option2']);
|
||||
expect(Object.getOwnPropertyNames(resolver)).toEqual(['option2', 'option1']);
|
||||
|
||||
expect('option2' in resolver).toBeTrue();
|
||||
expect('option1' in resolver).toBeTrue();
|
||||
expect('getter' in resolver).toBeFalse();
|
||||
expect('nonexistent' in resolver).toBeFalse();
|
||||
|
||||
expect(resolver instanceof Options).toBeTrue();
|
||||
|
||||
expect(resolver.getter).toEqual('options getter');
|
||||
});
|
||||
});
|
||||
|
||||
describe('_attachContext', function() {
|
||||
@ -249,6 +284,41 @@ describe('Chart.helpers.config', function() {
|
||||
expect(opts.fn).toEqual(1);
|
||||
});
|
||||
|
||||
it('should support common object methods', function() {
|
||||
const defaults = {
|
||||
option1: 'defaults'
|
||||
};
|
||||
class Options {
|
||||
constructor() {
|
||||
this.option2 = () => 'options';
|
||||
}
|
||||
get getter() {
|
||||
return 'options getter';
|
||||
}
|
||||
}
|
||||
const options = new Options();
|
||||
const resolver = _createResolver([options, defaults]);
|
||||
const opts = _attachContext(resolver, {index: 1});
|
||||
|
||||
expect(Object.prototype.hasOwnProperty.call(opts, 'option2')).toBeTrue();
|
||||
|
||||
expect(Object.prototype.hasOwnProperty.call(opts, 'option1')).toBeFalse();
|
||||
expect(Object.prototype.hasOwnProperty.call(opts, 'getter')).toBeFalse();
|
||||
expect(Object.prototype.hasOwnProperty.call(opts, 'nonexistent')).toBeFalse();
|
||||
|
||||
expect(Object.keys(opts)).toEqual(['option2']);
|
||||
expect(Object.getOwnPropertyNames(opts)).toEqual(['option2', 'option1']);
|
||||
|
||||
expect('option2' in opts).toBeTrue();
|
||||
expect('option1' in opts).toBeTrue();
|
||||
expect('getter' in opts).toBeFalse();
|
||||
expect('nonexistent' in opts).toBeFalse();
|
||||
|
||||
expect(opts instanceof Options).toBeTrue();
|
||||
|
||||
expect(opts.getter).toEqual('options getter');
|
||||
});
|
||||
|
||||
describe('_indexable and _scriptable', function() {
|
||||
it('should default to true', function() {
|
||||
const options = {
|
||||
|
Loading…
Reference in New Issue
Block a user