Skip to content

Some fixes to the updated code#65

Closed
DmitrySharabin wants to merge 2 commits intoclass-mixinsfrom
some-fixes
Closed

Some fixes to the updated code#65
DmitrySharabin wants to merge 2 commits intoclass-mixinsfrom
some-fixes

Conversation

@DmitrySharabin
Copy link
Member

No description provided.


delegate({
properties: this[formAssociated].properties,
delegate.call(Class, {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside delegate(), we use this in the getters we define, so we need Class as a context.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should fix delegate then, that’s a utility method, not a static method

};

if (sourceDescriptor.writable || sourceDescriptor.set) {
if (sourceDescriptor?.writable || sourceDescriptor?.set) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some sourceDescriptors can be undefined, e.g., the ones that are not in ElementInternals.prototype (e.g., type).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We delegate type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's one of the default properties:

Image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er, that's not a real property (yet). No idea why it's there.

Comment on lines +95 to +96
let descriptor = conflictPolicy.canMerge(prop) ? getMergeDescriptor(targetDescriptor, sourceDescriptor) : sourceDescriptor;
Object.defineProperty(target, prop, descriptor);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, if we don't skip or throw or if prop is not in target, we should merge, so this code should be outside if.

Comment on lines +71 to +74
for (let prop of [
...Object.keys(sourceDescriptors),
...Object.getOwnPropertySymbols(sourceDescriptors),
]) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, we miss symbols.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getOwnPropertyDescriptors should return symbols too (unlike getOwnPropertyNames)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, but for…in doesn't iterate over them

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, true, for .. in skips symbols. Reflect.ownKeys() should give you all of them.


function getMergeDescriptor (targetDescriptor, sourceDescriptor) {
if (!canMerge(targetDescriptor, sourceDescriptor)) {
if (!targetDescriptor || !canMerge(targetDescriptor, sourceDescriptor)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't throw on undefined targetDescriptior.

let Super = Object.getPrototypeOf(this);

if (Super[self]) {
if (!Super[self]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this based on the comment? Because the logic seems right to me

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not only on the comment. Without the change, the global styles defined on a super will not be handled. For example, if we define a color element, the global styles defined on the parent ColorElement class are ignored. But I might miss some nuances of the main idea of the refactored code, though. 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that if a class doesn't have [self] then it doesn't have this mixin, and any globalStyles properties it may have are incidental. Does ColorElement have this property?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, now I got it. So, to make the GlobalStyles mixin work, a class should import the self symbol from global.js and add a static property [self] with any (?) value (I added static [self] = self). Is that correct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, applying the mixin should add it automatically.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this isn't happening. I'll take a closer look

let config = this.constructor[formAssociated] ?? this.constructor.formAssociated;
let { like, role, valueProp, changeEvent } = config;
let internals = this[internals] || this.attachInternals();
this[internals] ??= this.attachInternals();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should already be done inside attachInternals, is it not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This covers cases where this.attachInternals was already called before [constructed]() is executed, e.g., in a class constructor (like we do in ColorElement).

Copy link
Contributor

@LeaVerou LeaVerou Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has nothing to do with [constructed]. We override attachInternals() in L44. Since mixins are applied before instances are constructed, that should work.


static [onApply] () {
let config = this[formAssociated] || this.formAssociated;
static [onApply] (Class) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? This is a static method, so this should resolve to the class anyway

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found the "real" issue—we called it incorrectly: we should've passed Class as a context, not a parameter. Fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did you fix it? I see this PR is closed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here (you've already moved my change to your PR):
image

LeaVerou added a commit that referenced this pull request Nov 24, 2025
Co-Authored-By: Dmitry Sharabin <dmitrysharabin@gmail.com>
@DmitrySharabin DmitrySharabin deleted the some-fixes branch November 24, 2025 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants