-
Notifications
You must be signed in to change notification settings - Fork 424
feat(engine): custom element registry pivots #2724
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
Conversation
|
Most of the Karma tests are passing; almost all of the failures now are due to I'm not sure how we plan to make |
|
OK, all Karma tests are passing now; it's just the server that's still busted. |
|
Server is fixed, but compat karma tests need to be fixed. |
7c4a7b9 to
476ca51
Compare
|
@caridy Local tests are passing, so it looks like your technique works. 🙂 My PR is still a bit rough, but overall this looks promising! Some downstream tests are failing, but it looks like it may just be Jest/JSDOM issues. |
|
/nucleus test |
| attributeChangedCallback(name: string, oldValue: any, newValue: any) { | ||
| attributeChangedCallback.call(this, name, oldValue, newValue); | ||
| } | ||
| static observedAttributes = observedAttributes; |
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.
this is one of the parts that worries me a little bit!
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.
@caridy For the sake of my fuzzy memory, what part of it worries you?
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 need to think more about it... but the fact that we now rely on observed attributes in the class that we produce, might introduce other issues with the inheritance path outside of LWC, and probably also conflict with authors list of attributes. I don't remember how observedAttributes from this record is constructed.
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 I'm not mistaken, we handle inheritance of observed attributes in base-bridge-element.ts:
lwc/packages/@lwc/engine-core/src/framework/base-bridge-element.ts
Lines 187 to 193 in 838035d
| // Specify attributes for which we want to reflect changes back to their corresponding | |
| // properties via attributeChangedCallback. | |
| defineProperty(HTMLBridgeElement, 'observedAttributes', { | |
| get() { | |
| return [...superObservedAttributes, ...keys(attributeToPropMap)]; | |
| }, | |
| }); |
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.
right, but beyond that, I don't know.
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.
The Karma tests are all passing currently. Is there a case you think isn't covered?
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.
yeah, I don't doubt that, but why was this change needed in the first place? If the custom element inherit the right thing... then you should be able to get the observedAttributes and others from there rather than rebuilding that yourself.
1339f84 to
b11b830
Compare
776139c to
c01ea64
Compare
| 'If this is a Jest environment, check your Jest/JSDOM configuration.' | ||
| ); | ||
| } | ||
| (nativeRegistry as any)[registryPatchedSymbol] = true; |
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 we don't add this check, then an error will be thrown eventually for "Illegal constructor." I saw this in two of our downstreams' Jest tests.
I considered wrapping this in a process.env.NODE_ENV condition, but what if a consumer loads two versions of the engine and one is minified? Better safe than sorry.
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.
this is one of the things that I want to discuss, this might actually be a red flag.
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.
Chatted with Caridy, the concerns are:
- If the patched registry doesn't work when applied twice, then this may limit our ability to have multiple versions of the framework running on top of the same registry. Ideally it should be resilient to being applied twice.
- Abstracting the Custom Element Infrastructure out of Core Package #2799 might allow us to get rid of the
UserCtorbeing passed in to thePivotCtor, we should explore that as well:
lwc/packages/@lwc/engine-dom/src/patches/global-registry.ts
Lines 59 to 60 in 5541855
| class PivotCtor extends NativeHTMLElement { | |
| constructor(UserCtor?: CustomElementConstructor) { |
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 news, it works with two copies of the engine when running in Karma. Looks like this is a Jest-only issue.
scripts/jest/root.config.js
Outdated
| global: { | ||
| branches: 80, | ||
| functions: 90, | ||
| functions: 85, |
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.
This is necessary because I added a Jest test to @lwc/engine-dom, and now Jest is complaining about the global-registry.ts file containing too much untested code. engine-dom is already well-tested elsewhere.
| { | ||
| "path": "packages/lwc/dist/engine-dom/umd/es2017/engine-dom.min.js", | ||
| "maxSize": "17.5KB", | ||
| "maxSize": "18KB", |
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.
The global-registry adds a decent chunk of code.
| const TestCustomElement = Test.CustomElementConstructor; | ||
|
|
||
| expect(typeof TestCustomElement).toBe('function'); | ||
| }); |
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.
Could not figure out why, but this started throwing in IE. Didn't seem worth investigating beyond that.
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.
It could be beneficial to throw an error when accessing CustomElementConstructor in an environment with no support for a native custom element eg. IE11.
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.
Aha, so you're saying that the fact that the behavior changed here is not a big deal? What if someone is using their own custom elements polyfill with CustomElementConstructor in IE11 though?
|
Blocked by #2855 |
86ae839 to
fc1d389
Compare
This reverts commit f3788c0.
ravijayaramappa
left a comment
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.
LGTM. Please wait for @caridy to +1 since he is most adept at the Custom Registry spec.
|
@ravijayaramappa We should move |
Yes. You can do it in this PR or a follow up. |
|
@ravijayaramappa No problem. Done: f0a3746 |
|
/nucleus ignore --reason "lwc-platform needs updating" |
|
Some feedback from discussion with @caridy: Currently when we call However, this may break a third-party component using this common pattern: if (!customElements.get('my-tag')) {
customElements.define('my-tag', ...)
}The above will break if LWC reserves However, it's worth acknowledging that even if we fix // LWC code
lwc.createElement('x-foo', ...)
// userland code
const elm = document.createElement('x-foo')
const PivotCtor = elm.constructor
new PivotCtor()So in a sense, we can't fully hide the This means we also need to fix the case where someone does: new PivotCtor(UserCtorThatWasNeverRegistered)^ This should be detectable, and we should probably throw an error in this case. |
|
@nolanlawson You probably have test cases for these, if not these should be add-ons to #3073 class Foo extends HTMLElement {}
customElements.define('x-foo', Foo);
const elm = document.createElement('x-foo');
console.log(elm instanceof Foo); // true
console.log(elm.constructor === Foo); // true |
|
@ravijayaramappa In the pivots implementation, those last two statements would be |
|
/nucleus test |
|
It's time to merge this... it's behind a flag, and we can fix remaining issues in follow-up PRs. Thanks to everyone who reviewed! |
Details
Fixes #2191
This is an attempt to rebase #2564 and get it working.
The main goal is to allow third-party custom elements to use tag names that are the same as tag names already reserved by LWC custom elements:
It also allows LWC custom elements to re-use the same tag name to refer to different components:
Does this pull request introduce a breaking change?
Does this pull request introduce an observable change?
Probably there is something observable about changing how we do custom element registry scoping, but I haven't thought it through yet.