Skip to content

Add a check for undefined val for parseColor #190

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

kasimir-dka
Copy link

Fixes issue #189

@domenic
Copy link
Member

domenic commented Apr 8, 2025

Can you explain why you are passing undefined to this function in the first place?

@kasimir-dka
Copy link
Author

Can you explain why you are passing undefined to this function in the first place?

I'm not - Stencil JS is. When running test for web components built with Stencil that line under some circumstances causes undefined to be set as a color value, and then CSSStyle tries to parse that as a color and uses asamuzakjp/css-color to resoleve the value as color, and that in turn throws, causing unwanted output in the terminal.

After looking both cssColor and Stencil, I feel cssStlyle is the right place to fix this.

@asamuzaK
Copy link
Contributor

asamuzaK commented Apr 10, 2025

It's probably wrong to treat undefined the same as an empty string or null.

See the test case below.

Note that when undefined is specified, nothing is done and the previous value continues to be used.
On the other hand, an empty string or null resets the style.

So the right approach might be to add a try-catch around resolveColor(), like:

  try {
    var res = resolveColor(val, {
      format: 'specifiedValue',
    });
    if (res) {
      return res;
    }
  } catch (e) {
    // Return the previous value somehow
  }
  return undefined;

But I'm not sure if we are caching values somewhere.

Test case:

<!DOCTYPE html>
<html>
<style>
.div {
  background-color: red;
  width: 50%;
  height: 3rem;
}
</style>
<div id="div" class="div"></div>
<script>
const declaration = document.styleSheets[0].cssRules[0].style;
let declarationValue = declaration.getPropertyValue('background-color');
console.log(`
declarationValue: ${declarationValue}
`);
declaration.setProperty('background-color', 'green');
declarationValue = declaration.getPropertyValue('background-color');
console.log(`
declaration.setProperty('background-color', 'green');
declarationValue: ${declarationValue}
`);
declaration.setProperty('background-color', undefined);
declarationValue = declaration.getPropertyValue('background-color');
console.log(`
declaration.setProperty('background-color', undefined);
declarationValue: ${declarationValue}
`);

const div = document.getElementById('div');
let propertyValue = getComputedStyle(div).getPropertyValue('background-color');
let stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
default value:
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}, is empty string: ${stylePropertyValue === ''}
`);

div.style.setProperty('background-color', 'blue');
propertyValue = getComputedStyle(div).getPropertyValue('background-color');
stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
div.style.setProperty('background-color', 'blue');
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}
`);

div.style.setProperty('background-color', undefined);
propertyValue = getComputedStyle(div).getPropertyValue('background-color');
stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
div.style.setProperty('background-color', undefined);
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}
`);

div.style.setProperty('background-color', '');
propertyValue = getComputedStyle(div).getPropertyValue('background-color');
stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
div.style.setProperty('background-color', '');
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}, is empty string: ${stylePropertyValue === ''}
`);

div.style.backgroundColor = 'rebeccapurple';
propertyValue = getComputedStyle(div).getPropertyValue('background-color');
stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
div.style.backgroundColor = 'rebeccapurple';
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}
`);

div.style.backgroundColor = undefined;
propertyValue = getComputedStyle(div).getPropertyValue('background-color');
stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
div.style.backgroundColor = undefined;
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}
`);

div.style.backgroundColor = null;
propertyValue = getComputedStyle(div).getPropertyValue('background-color');
stylePropertyValue = div.style.getPropertyValue('background-color');
console.log(`
div.style.backgroundColor = null;
propertyValue: ${propertyValue}
stylePropertyValue: ${stylePropertyValue}, is empty string: ${stylePropertyValue === ''}
`);
</script>
</html>

Results in browser:

declarationValue: red

declaration.setProperty('background-color', 'green');
declarationValue: green

declaration.setProperty('background-color', undefined);
declarationValue: green

default value:
propertyValue: rgb(0, 128, 0)
stylePropertyValue: , is empty string: true

div.style.setProperty('background-color', 'blue');
propertyValue: rgb(0, 0, 255)
stylePropertyValue: blue

div.style.setProperty('background-color', undefined);
propertyValue: rgb(0, 0, 255)
stylePropertyValue: blue

div.style.setProperty('background-color', '');
propertyValue: rgb(0, 128, 0)
stylePropertyValue: , is empty string: true

div.style.backgroundColor = 'rebeccapurple';
propertyValue: rgb(102, 51, 153)
stylePropertyValue: rebeccapurple

div.style.backgroundColor = undefined;
propertyValue: rgb(102, 51, 153)
stylePropertyValue: rebeccapurple

div.style.backgroundColor = null;
propertyValue: rgb(0, 128, 0)
stylePropertyValue: , is empty string: true

@asamuzaK
Copy link
Contributor

I've looked into it a bit deeper and it seems there's nothing wrong with returning undefined early.
Forget my previous comment.
Sorry for a noise.

@domenic
Copy link
Member

domenic commented Apr 20, 2025

I guess I am not excited to merge this until we can get a test in the upstream jsdom repository that this solves.

I also wonder if this is just one instance of #129.

@asamuzaK
Copy link
Contributor

Re #129
I'm having difficulty following what the reporter of #129 is trying to say.
In particular, it's unclear whether the results written in the comments are expected values ​​or actual values.

@asamuzaK
Copy link
Contributor

Test summary: #196 (comment)

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.

4 participants