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
feat(ivy): support object and array literals in render3 #21973
Conversation
You can preview 02b6bd8 at https://pr21973-02b6bd8.ngbuilds.io/. |
@@ -1832,6 +1832,221 @@ export function bind8( | |||
NO_CHANGE; | |||
} | |||
|
|||
/** |
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.
instructions.ts
is getting large as is. Can we move these into a separate file?
} | ||
|
||
/** Updates four expressions in an array literal if they have changed. */ | ||
function updateBinding4( |
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.
Building it up like this is clever. :-)
*/ | ||
export function memoize2(arr: any[], index1: number, exp1: any, index2: number, exp2: any): any[]| | ||
NO_CHANGE { | ||
return updateBinding2(arr, index1, exp1, index2, exp2) ? arr.slice() : NO_CHANGE; |
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.
I don't think this is right. If I am reading correctly you update the arr
and than you make a copy. But arr
is the prototype, which means that you are updating it for everyone. I think the correct behavior is to 1) determine if there are changes 2) clone the arr
and 3) assign the changes to the array.
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.
Discussed offline. For anyone curious: the current algorithm works because we are comparing bindings against themselves instead of against the array that is changing. But changing the const array that is generated by the compiler will cause headaches in the compiler code, so instead we will save a copy on TView.
const e0_literal = ['Nancy', null]; | ||
// /NORMATIVE | ||
|
||
expect(renderComp(MyApp)).toEqual(`<my-comp><p>Nancy</p><p>Bess</p></my-comp>`); |
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.
assert that e0_literal
has not been changed. (I believe that your code changes it which is incorrect.)
You can preview b4793f2 at https://pr21973-b4793f2.ngbuilds.io/. |
You can preview a16c5db at https://pr21973-a16c5db.ngbuilds.io/. |
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.
I think the same exact code with few minor changes should work for object literals as well as for arrays.
* @param exp Expression to set at index | ||
* @returns Whether or not there has been a change | ||
*/ | ||
function updateArrBinding(arr: any[], index: number, exp: any): boolean { |
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.
I think this can be updateBinding
since Array
and Object
will have the same exact code.
|
||
|
||
function getObjectCopy(index: number, arr: any[]): any[] { | ||
const tView = getTView(); |
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.
can you add assert that index
comes in the right order? so that we don't create a spares array.
const objectLiterals = tView.objectLiterals; | ||
return objectLiterals && index < objectLiterals.length ? | ||
objectLiterals[index] : | ||
(objectLiterals || (tView.objectLiterals = []))[index] = arr.slice(); |
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.
If you do something like Array.isArray(arr) ? arr.slice() : Object.create(Object, arr)
. it should work for both array and object. You may want to rename arr
=> obj
} | ||
|
||
|
||
function getObjectCopy(index: number, arr: any[]): any[] { |
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.
Can we call it getMutableBlueprint
?
You can preview b1ce536 at https://pr21973-b1ce536.ngbuilds.io/. |
} | ||
|
||
/** Updates two expressions in an object literal if they have changed. */ | ||
function updateBinding2(obj: any, key1: number, exp1: any, key2: number, exp2: any): boolean { |
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.
string | number
(multiples)
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.
Good catch. Can include in my follow-up here #22045
|
||
|
||
/** | ||
* Updates an expression in an object literal if the expression has changed. |
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.
object literal
should be object literal or array
* @param exp Expression to set at key | ||
* @returns A copy of the object or NO_CHANGE | ||
*/ | ||
export function objectLiteral1(objIndex: number, obj: any, key: string | number, exp: any): any { |
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.
objectLiteral is confusing wrt to array ?
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.
Since the instruction encompasses both, @mhevery and I discussed using "object" as the more general of the two.
* @param key1 | ||
* @param exp1 | ||
* @param key2 | ||
* @param exp2 |
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.
remove undocumented params ?
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Currently in render3, if you pass an array literal into a binding, it will be re-created every change detection run and its binding will be re-set every change detection run.
This PR adds a new set of
o1()...o8()
instructions that ensure the property is only set when one of the bound expressions in the array actually changes.This template:
currently generates this instruction:
will generate this instruction: