-
Notifications
You must be signed in to change notification settings - Fork 405
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
refactor: hidden fields instead of internal fields #1478
Changes from all commits
2d75d7d
f2adc93
e52f953
0a80473
861a4c4
2968a25
e90b104
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 |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
* SPDX-License-Identifier: MIT | ||
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT | ||
*/ | ||
import { defineProperty, create, isUndefined } from './language'; | ||
import { create, defineProperty, isUndefined } from './language'; | ||
|
||
/** | ||
* In IE11, symbols are expensive. | ||
|
@@ -16,48 +16,32 @@ const hasNativeSymbolsSupport = Symbol('x').toString() === 'Symbol(x)'; | |
|
||
export function createFieldName(key: string): symbol { | ||
// @ts-ignore: using a string as a symbol for perf reasons | ||
return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-${key}$$`; | ||
return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-engine-${key}$$`; | ||
} | ||
|
||
const hiddenFieldsMap: WeakMap<any, Record<symbol, any>> = new WeakMap(); | ||
|
||
export function setHiddenField(o: any, fieldName: symbol, value: any) { | ||
let valuesByField = hiddenFieldsMap.get(o); | ||
if (isUndefined(valuesByField)) { | ||
valuesByField = create(null) as (Record<symbol, any>); | ||
hiddenFieldsMap.set(o, valuesByField); | ||
} | ||
valuesByField[fieldName] = value; | ||
} | ||
|
||
export function getHiddenField(o: any, fieldName: symbol) { | ||
const valuesByField = hiddenFieldsMap.get(o); | ||
if (!isUndefined(valuesByField)) { | ||
return valuesByField[fieldName]; | ||
} | ||
} | ||
|
||
export function setInternalField(o: object, fieldName: symbol, value: any) { | ||
// TODO: #1299 - use a weak map instead | ||
defineProperty(o, fieldName, { | ||
value, | ||
}); | ||
} | ||
|
||
export function getInternalField(o: object, fieldName: symbol): any { | ||
return o[fieldName]; | ||
} | ||
|
||
/** | ||
* Store fields that should be hidden from outside world | ||
* hiddenFieldsMap is a WeakMap. | ||
* It stores a hash of any given objects associative relationships. | ||
* The hash uses the fieldName as the key, the value represents the other end of the association. | ||
* | ||
* For example, if the association is | ||
* ViewModel | ||
* Component-A --------------> VM-1 | ||
* then, | ||
* hiddenFieldsMap : (Component-A, { Symbol(ViewModel) : VM-1 }) | ||
* | ||
*/ | ||
const hiddenFieldsMap: WeakMap<any, Record<symbol, any>> = new WeakMap(); | ||
export const setHiddenField = hasNativeSymbolsSupport | ||
? (o: any, fieldName: symbol, value: any): void => { | ||
let valuesByField = hiddenFieldsMap.get(o); | ||
if (isUndefined(valuesByField)) { | ||
valuesByField = create(null) as (Record<symbol, any>); | ||
hiddenFieldsMap.set(o, valuesByField); | ||
} | ||
valuesByField[fieldName] = value; | ||
} | ||
: setInternalField; // Fall back to symbol based approach in compat mode | ||
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. @ekashida #860 (comment) 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. Thanks. I didn't get the existing comment because it was actually falling back to the internal field approach (which was also based on symbols), which would fall back to the string-based approach. |
||
|
||
export const getHiddenField = hasNativeSymbolsSupport | ||
? (o: any, fieldName: symbol): any => { | ||
const valuesByField = hiddenFieldsMap.get(o); | ||
return !isUndefined(valuesByField) && valuesByField[fieldName]; | ||
} | ||
: getInternalField; // Fall back to symbol based approach in compat mode |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
* SPDX-License-Identifier: MIT | ||
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT | ||
*/ | ||
import { defineProperty } from './language'; | ||
import { create, isUndefined } from './language'; | ||
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. unrelated to this pr: The fields util is replicated in 3 submodules(engine, synthetic-shadow, node-reactions). Is it a good time to pull it out as a shared library or submodule? 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. yes, we have an issue for that |
||
|
||
/** | ||
* In IE11, symbols are expensive. | ||
|
@@ -16,16 +16,23 @@ const hasNativeSymbolsSupport = Symbol('x').toString() === 'Symbol(x)'; | |
|
||
export function createFieldName(key: string): symbol { | ||
// @ts-ignore: using a string as a symbol for perf reasons | ||
return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-${key}$$`; | ||
return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-synthetic-shadow-${key}$$`; | ||
} | ||
|
||
export function setInternalField(o: object, fieldName: symbol, value: any) { | ||
// TODO: #1299 - improve this to use a WeakMap | ||
defineProperty(o, fieldName, { | ||
value, | ||
}); | ||
const hiddenFieldsMap: WeakMap<any, Record<symbol, any>> = new WeakMap(); | ||
|
||
export function setHiddenField(o: any, fieldName: symbol, value: any) { | ||
let valuesByField = hiddenFieldsMap.get(o); | ||
if (isUndefined(valuesByField)) { | ||
valuesByField = create(null) as (Record<symbol, any>); | ||
hiddenFieldsMap.set(o, valuesByField); | ||
} | ||
valuesByField[fieldName] = value; | ||
} | ||
|
||
export function getInternalField(o: object, fieldName: symbol): any { | ||
return o[fieldName]; | ||
export function getHiddenField(o: any, fieldName: symbol) { | ||
const valuesByField = hiddenFieldsMap.get(o); | ||
if (!isUndefined(valuesByField)) { | ||
return valuesByField[fieldName]; | ||
} | ||
} |
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.
where is
getInternalField
used? I thought the idea was to remove that entirely.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.
Sorry, I mentioned above that it was in
vm.ts
but it was actually indef.ts
:I'm not sure why, but our perf tests blow up when we access the vm using
getHiddenField
here.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.
hmm, let me look at it.