handleMandatorySetter = function handleMandatorySetter(m, obj, keyName): void { let descriptor = lookupDescriptor(obj, keyName); let hasDescriptor = descriptor !== null; let possibleDesc = hasDescriptor && descriptor!.value; if (isDescriptor(possibleDesc)) { return; } let configurable = hasDescriptor ? descriptor!.configurable : true; let isWritable = hasDescriptor ? descriptor!.writable : true; let hasValue = hasDescriptor ? 'value' in descriptor! : true; // this x in Y deopts, so keeping it in this function is better; if (configurable && isWritable && hasValue && keyName in obj) { let desc = { configurable: true, set: MANDATORY_SETTER_FUNCTION(keyName), enumerable: propertyIsEnumerable(obj, keyName), get: (undefined as any) as (() => any | undefined | null), }; if (hasOwnProperty(obj, keyName)) { m.writeValues(keyName, obj[keyName]); desc.get = DEFAULT_GETTER_FUNCTION(keyName); } else { desc.get = INHERITING_GETTER_FUNCTION(keyName); } Object.defineProperty(obj, keyName, desc); } };
export function get(obj: object, keyName: string): any { assert( `Get must be called with two arguments; an object and a property key`, arguments.length === 2 ); assert( `Cannot call get with '${keyName}' on an undefined object.`, obj !== undefined && obj !== null ); assert( `The key provided to get must be a string or number, you passed ${keyName}`, typeof keyName === 'string' || (typeof keyName === 'number' && !isNaN(keyName)) ); assert( `'this' in paths is not supported`, typeof keyName !== 'string' || keyName.lastIndexOf('this.', 0) !== 0 ); let type = typeof obj; let isObject = type === 'object'; let isFunction = type === 'function'; let isObjectLike = isObject || isFunction; let descriptor; let value: any; if (isObjectLike) { if (EMBER_METAL_TRACKED_PROPERTIES) { let tracker = getCurrentTracker(); if (tracker) tracker.add(tagForProperty(obj, keyName)); } descriptor = descriptorFor(obj, keyName); if (descriptor !== undefined) { return descriptor.get(obj, keyName); } if (DEBUG && HAS_NATIVE_PROXY) { value = getPossibleMandatoryProxyValue(obj, keyName); } else { value = obj[keyName]; } if (PROPERTY_BASED_DESCRIPTORS && isDescriptor(value)) { deprecate( `[DEPRECATED] computed property '${keyName}' was not set on object '${toString( obj )}' via 'defineProperty'`, false, { id: '@ember/-internals/meta.descriptor-on-object', until: '3.5.0', url: 'https://emberjs.com/deprecations/v3.x#toc_use-defineProperty-to-define-computed-properties', } ); Object.defineProperty(obj, keyName, { configurable: true, enumerable: value.enumerable === false, get() { return value.get(this, keyName); }, }); meta(obj).writeDescriptors(keyName, value); value.setup(obj, keyName); return value.get(obj, keyName); } } else { value = obj[keyName]; } if (value === undefined) { if (isPath(keyName)) { return _getPath(obj, keyName); } if ( isObject && !(keyName in obj) && typeof (obj as MaybeHasUnknownProperty).unknownProperty === 'function' ) { return (obj as MaybeHasUnknownProperty).unknownProperty!(keyName); } } return value; }
export function set(obj: object, keyName: string, value: any, tolerant?: boolean): any | void { assert( `Set must be called with three or four arguments; an object, a property key, a value and tolerant true/false`, arguments.length === 3 || arguments.length === 4 ); assert( `Cannot call set with '${keyName}' on an undefined object.`, (obj && typeof obj === 'object') || typeof obj === 'function' ); assert( `The key provided to set must be a string or number, you passed ${keyName}`, typeof keyName === 'string' || (typeof keyName === 'number' && !isNaN(keyName)) ); assert( `'this' in paths is not supported`, typeof keyName !== 'string' || keyName.lastIndexOf('this.', 0) !== 0 ); if ((obj as ExtendedObject).isDestroyed) { assert( `calling set on destroyed object: ${toString(obj)}.${keyName} = ${toString(value)}`, tolerant ); return; } if (isPath(keyName)) { return setPath(obj, keyName, value, tolerant); } let possibleDesc = descriptorFor(obj, keyName); if (possibleDesc !== undefined) { /* computed property */ possibleDesc.set(obj, keyName, value); return value; } let currentValue: any; if (DEBUG && HAS_NATIVE_PROXY) { currentValue = getPossibleMandatoryProxyValue(obj, keyName); } else { currentValue = obj[keyName]; } if (PROPERTY_BASED_DESCRIPTORS && isDescriptor(currentValue)) { deprecate( `[DEPRECATED] computed property '${keyName}' was not set on object '${toString( obj )}' via 'defineProperty'`, false, { id: '@ember/-internals/meta.descriptor-on-object', until: '3.5.0', url: 'https://emberjs.com/deprecations/v3.x#toc_use-defineProperty-to-define-computed-properties', } ); let cv: Descriptor = currentValue; meta(obj).writeDescriptors(keyName, cv); cv.setup(obj, keyName); cv.set(obj, keyName, value); return value; } if ( currentValue === undefined && 'object' === typeof obj && !(keyName in obj) && typeof (obj as ExtendedObject).setUnknownProperty === 'function' ) { /* unknown property */ (obj as ExtendedObject).setUnknownProperty!(keyName, value); } else { let meta = peekMeta(obj); if (DEBUG) { setWithMandatorySetter<any, any>(meta, obj, keyName, value); } else { obj[keyName] = value; } if (currentValue !== value) { notifyPropertyChange(obj, keyName, meta); } } return value; }