-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cleanup Meta Descs #12852
Cleanup Meta Descs #12852
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,10 +96,7 @@ function giveDescriptorSuper(meta, key, property, values, descs, base) { | |
// If we didn't find the original descriptor in a parent mixin, find | ||
// it on the original object. | ||
if (!superProperty) { | ||
var possibleDesc = base[key]; | ||
var superDesc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined; | ||
|
||
superProperty = superDesc; | ||
superProperty = meta.peekDescs(key); | ||
} | ||
|
||
if (superProperty === undefined || !(superProperty instanceof ComputedProperty)) { | ||
|
@@ -235,7 +232,7 @@ function mergeMixins(mixins, m, descs, values, base, keys) { | |
currentMixin = mixins[i]; | ||
assert( | ||
`Expected hash or Mixin instance, got ${Object.prototype.toString.call(currentMixin)}`, | ||
typeof currentMixin === 'object' && currentMixin !== null && Object.prototype.toString.call(currentMixin) !== '[object Array]' | ||
typeof currentMixin === 'object' && currentMixin !== null && !Array.isArray(currentMixin) | ||
); | ||
|
||
props = mixinProperties(m, currentMixin); | ||
|
@@ -329,7 +326,7 @@ function followAlias(obj, desc, m, descs, values) { | |
if (descs[altKey] || values[altKey]) { | ||
value = values[altKey]; | ||
desc = descs[altKey]; | ||
} else if ((possibleDesc = obj[altKey]) && possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) { | ||
} else if (possibleDesc = m.peekDescs(altKey)) { | ||
desc = possibleDesc; | ||
value = undefined; | ||
} else { | ||
|
@@ -351,7 +348,8 @@ function updateObserversAndListeners(obj, key, observerOrListener, pathsKey, upd | |
} | ||
|
||
function replaceObserversAndListeners(obj, key, observerOrListener) { | ||
var prev = obj[key]; | ||
var desc = Object.getOwnPropertyDescriptor(obj, key); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can handle this more performently, but might require either extra branching or a re-think |
||
var prev = desc && desc.value; | ||
|
||
if ('function' === typeof prev) { | ||
updateObserversAndListeners(obj, key, prev, '__ember_observesBefore__', _removeBeforeObserver); | ||
|
@@ -386,6 +384,7 @@ function applyMixin(obj, mixins, partial) { | |
|
||
for (var i = 0, l = keys.length; i < l; i++) { | ||
key = keys[i]; | ||
|
||
if (key === 'constructor' || !values.hasOwnProperty(key)) { continue; } | ||
|
||
desc = descs[key]; | ||
|
@@ -400,7 +399,6 @@ function applyMixin(obj, mixins, partial) { | |
} | ||
|
||
if (desc === undefined && value === undefined) { continue; } | ||
|
||
replaceObserversAndListeners(obj, key, value); | ||
detectBinding(obj, key, value, m); | ||
defineProperty(obj, key, desc, value, m); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -112,40 +112,54 @@ export function INHERITING_GETTER_FUNCTION(name) { | |
@param {*} [data] something other than a descriptor, that will | ||
become the explicit value of this property. | ||
*/ | ||
export function defineProperty(obj, keyName, desc, data, meta) { | ||
var possibleDesc, existingDesc, watching, value; | ||
export function defineProperty(obj, keyName, desc, data/*, meta*/) { | ||
let meta = arguments[4] || metaFor(obj); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a meta may not exists here yet, we should be careful to not create on if it does not need to exist. |
||
let watchEntry = meta.peekWatching(keyName); | ||
let existingDesc = meta.peekDescs(keyName); | ||
|
||
if (!meta) { | ||
meta = metaFor(obj); | ||
} | ||
var watchEntry = meta.peekWatching(keyName); | ||
possibleDesc = obj[keyName]; | ||
existingDesc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined; | ||
|
||
watching = watchEntry !== undefined && watchEntry > 0; | ||
let watching = watchEntry !== undefined && watchEntry > 0; | ||
|
||
if (existingDesc) { | ||
existingDesc.teardown(obj, keyName); | ||
} | ||
|
||
let value; | ||
|
||
// is this instanceof needed? | ||
if (desc instanceof Descriptor) { | ||
value = desc; | ||
if (isEnabled('mandatory-setter')) { | ||
if (watching) { | ||
Object.defineProperty(obj, keyName, { | ||
configurable: true, | ||
enumerable: true, | ||
writable: true, | ||
value: value | ||
}); | ||
} else { | ||
meta.writeDescs(keyName, desc); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should likely extract this algo into |
||
|
||
Object.defineProperty(obj, keyName, { | ||
configurable: true, | ||
enumerable: true, | ||
get() { | ||
return metaFor(this).peekDescs(keyName).get(this, keyName); | ||
}, | ||
set(value) { | ||
// throw TypeError('Sorry this isnt supported "right now"'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. decide what we want to do here. (complex topic that will need more research) |
||
delete obj[keyName]; | ||
obj[keyName] = value; | ||
} | ||
} else { | ||
obj[keyName] = value; | ||
} | ||
}); | ||
|
||
// if (isEnabled('mandatory-setter')) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dealing with this will depend on the outcome of https://github.com/emberjs/ember.js/pull/12852/files#r50556996 |
||
// if (watching) { | ||
// Object.defineProperty(obj, keyName, { | ||
// configurable: true, | ||
// enumerable: true, | ||
// writable: true, | ||
// value: value | ||
// }); | ||
// } else { | ||
// obj[keyName] = value; | ||
// } | ||
// } else { | ||
// obj[keyName] = value; | ||
// } | ||
if (desc.setup) { desc.setup(obj, keyName); } | ||
} else { | ||
// add insert undefined subroutine, to do this more efficiently | ||
meta.writeDescs(keyName, false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need a more stable way to insert "no such member" at this level of the prototype. |
||
if (desc == null) { | ||
value = data; | ||
|
||
|
@@ -169,11 +183,13 @@ export function defineProperty(obj, keyName, desc, data, meta) { | |
obj[keyName] = data; | ||
} | ||
} else { | ||
obj[keyName] = data; | ||
Object.defineProperty(obj, keyName, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice if we could avoid this, but we do stop on CP's sometimes, which requires us to remove the existing descriptor. A likely approach is to check if this property has a desc or not, then decide defProp or not. (defProp tends to currently have much worse performance then a regular prop set) |
||
configurable: true, | ||
writable: true, | ||
value: data | ||
}); | ||
} | ||
} else { | ||
value = desc; | ||
|
||
// fallback to ES5 | ||
Object.defineProperty(obj, keyName, desc); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,26 +48,18 @@ export function get(obj, keyName) { | |
return obj; | ||
} | ||
|
||
var value = obj[keyName]; | ||
var desc = (value !== null && typeof value === 'object' && value.isDescriptor) ? value : undefined; | ||
var ret; | ||
|
||
if (desc === undefined && isPath(keyName)) { | ||
if (isPath(keyName)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. needs testing to be sure checking descs isn't cheaper then this. but keeping it simpler at first is likely better, but we should investigate further. |
||
return _getPath(obj, keyName); | ||
} | ||
|
||
if (desc) { | ||
return desc.get(obj, keyName); | ||
} else { | ||
ret = value; | ||
|
||
if (ret === undefined && | ||
'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) { | ||
return obj.unknownProperty(keyName); | ||
} | ||
let ret = obj[keyName]; | ||
|
||
return ret; | ||
if (ret === undefined && | ||
'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) { | ||
return obj.unknownProperty(keyName); | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
export function _getPath(root, path) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,23 +48,23 @@ export function set(obj, keyName, value, tolerant) { | |
assert(`The key provided to set must be a string, you passed ${keyName}`, typeof keyName === 'string'); | ||
assert(`'this' in paths is not supported`, !pathHasThis(keyName)); | ||
|
||
let meta, possibleDesc, desc; | ||
|
||
let meta, desc; | ||
if (obj) { | ||
meta = peekMeta(obj); | ||
possibleDesc = obj[keyName]; | ||
desc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined; | ||
desc = meta && meta.peekDescs(keyName); | ||
markObjectAsDirty(meta); | ||
} | ||
|
||
var isUnknown, currentValue; | ||
let isUnknown, currentValue; | ||
if (desc === undefined && isPath(keyName)) { | ||
return setPath(obj, keyName, value, tolerant); | ||
} | ||
|
||
assert(`calling set on destroyed object: ${toString(obj)}.${keyName} = ${toString(value)}`, | ||
!obj.isDestroyed); | ||
|
||
|
||
// soon this will be just obj[keyName] = value, as it shouldn be... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will depend on the outcome of https://github.com/emberjs/ember.js/pull/12852/files#r50556996 |
||
if (desc) { | ||
desc.set(obj, keyName, value); | ||
} else { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isDescriptor check isn't required