<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Raphael Schweikert</title>
    <description>The latest articles on DEV Community by Raphael Schweikert (@sabberworm).</description>
    <link>https://dev.to/sabberworm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F94696%2F408adb8e-8984-4ca5-8ae5-9cd8d2c10cfc.png</url>
      <title>DEV Community: Raphael Schweikert</title>
      <link>https://dev.to/sabberworm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sabberworm"/>
    <language>en</language>
    <item>
      <title>The case of the non-stringifyable value</title>
      <dc:creator>Raphael Schweikert</dc:creator>
      <pubDate>Tue, 05 Sep 2023 15:24:40 +0000</pubDate>
      <link>https://dev.to/sabberworm/the-case-of-the-non-stringifyable-value-5bj3</link>
      <guid>https://dev.to/sabberworm/the-case-of-the-non-stringifyable-value-5bj3</guid>
      <description>&lt;p&gt;When I see someone calling &lt;code&gt;someVar.toString()&lt;/code&gt;, I usually advise them to use &lt;code&gt;String(someVar)&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt; instead, as it handles &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; cases gracefully (depending on the definition of gracefully, of course) instead of throwing&lt;sup id="fnref2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;For the longest time I was under the impression that calling &lt;code&gt;String(someVar)&lt;/code&gt; would never throw, for any value of &lt;code&gt;someVar&lt;/code&gt;. However, I was wrong. There are two cases where it also throws:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When passed an object whose &lt;code&gt;Symbol.toPrimitive&lt;/code&gt; exists but isn’t callable or calling it with &lt;code&gt;'string'&lt;/code&gt; as first argument returns a non-primitive or throws.&lt;/li&gt;
&lt;li&gt;When passed an object that doesn’t have a &lt;code&gt;Symbol.toPrimitive&lt;/code&gt; property and &lt;code&gt;toString&lt;/code&gt; or &lt;code&gt;valueOf&lt;/code&gt; each either don’t exist, aren’t callable, return a non-primitive, or throw.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most likely you’ll encounter the case where none of these methods are declared when handling an object that doesn’t have a prototype, e.g. if it was created using &lt;code&gt;Object.create(null)&lt;/code&gt;. In that case, my advice wouldn’t have been better or worse because both approaches throw.&lt;/p&gt;

&lt;p&gt;But we can also craft an object specifically to throw when passed to &lt;code&gt;String&lt;/code&gt; but not when calling &lt;code&gt;toString&lt;/code&gt; on it:&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const o = {
  [Symbol.toPrimitive]() {
    return {};
  },
};
console.log(o.toString());
console.log(String(o));

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;In this case, my initial advice would be completely wrong and &lt;code&gt;toString&lt;/code&gt; would have been the better option.&lt;/p&gt;

&lt;p&gt;Of course, we could also easily have crafted the opposite:&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const o = {
  [Symbol.toPrimitive]() {
    return "cool string";
  },
  toString: 42,
};
console.log(String(o));
console.log(o.toString());

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;I stand by the stance that &lt;code&gt;String(someVar)&lt;/code&gt; is usually the better approach in real-world scenarios (it also looks nicer) but I’ve come around to thinking that being explicit about &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; is better than being implicit so I always advice for having null checks anyway.&lt;/p&gt;

&lt;p&gt;Investigating this also helped me clear up another misconception. The &lt;code&gt;String&lt;/code&gt; construction (when used as a function) doesn’t just apply the abstract operation &lt;code&gt;ToString&lt;/code&gt; as defined by ECMAScript.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ToString&lt;/code&gt; is specified &lt;a href="https://tc39.es/ecma262/#sec-tostring"&gt;as follows&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--heTBFgD1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/liw6cksd408z8icfinqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--heTBFgD1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/liw6cksd408z8icfinqy.png" alt="ToString in ECMAScript 2024 Language Specification" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But I already knew that &lt;code&gt;String(Symbol('a'))&lt;/code&gt; doesn’t throw, so something else must be going on there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tc39.es/ecma262/#sec-string-constructor-string-value"&gt;The specification of &lt;code&gt;String(value)&lt;/code&gt;&lt;/a&gt; clarified things:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ROW99kKi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wa90w5vzunxc57xv7kfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ROW99kKi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wa90w5vzunxc57xv7kfj.png" alt="String(value)in ECMAScript 2024 Language Specification" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it, symbols are special-cased in &lt;code&gt;String(value)&lt;/code&gt;, they won’t ever throw!&lt;/p&gt;

&lt;p&gt;But symbols will throw when used in an untagged template string literal as there, the &lt;code&gt;ToString&lt;/code&gt; operation is used.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Or &lt;code&gt;${someVar}&lt;/code&gt; in a template string literal, which amounts to almost the same thing. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Technically, it’s not &lt;code&gt;toString&lt;/code&gt; that throws, it’s the property lookup on &lt;code&gt;someVar&lt;/code&gt; that throws. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>What to do about sub-pixel media-queries?</title>
      <dc:creator>Raphael Schweikert</dc:creator>
      <pubDate>Wed, 07 Jul 2021 17:35:21 +0000</pubDate>
      <link>https://dev.to/sabberworm/what-to-do-about-sub-pixel-media-queries-6ic</link>
      <guid>https://dev.to/sabberworm/what-to-do-about-sub-pixel-media-queries-6ic</guid>
      <description>&lt;p&gt;I came across an interesting conundrum today&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. I had zoomed into a webpage that uses both &lt;code&gt;max-width&lt;/code&gt; and &lt;code&gt;min-width&lt;/code&gt; media queries. I noticed that, while resizing the browser window, there was a brief moment where the layout was totally messed-up.&lt;/p&gt;

&lt;p&gt;Turns out I seem to be the last web developer using Firefox&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. And Firefox treats media queries much more literally than WebKit/Blink-based browsers.&lt;/p&gt;

&lt;p&gt;When zoomed in, the viewport can assume sub-pixel sizes. Say my window is 401px wide and zoom is set to 200%, the visual viewport width will be 200.5px wide.&lt;/p&gt;

&lt;p&gt;Assume the following CSS&lt;sup id="fnref3"&gt;3&lt;/sup&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#max200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;#min201&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;#max200&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;201px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;#min201&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While Safari and Chromium will round up the actual value of the visual viewport to 201 when matching against media queries, Firefox will happily try to match 200.5 pixels against the given queries and neither of them will match, which will result in Firefox displaying neither the &lt;code&gt;#max200&lt;/code&gt; nor the &lt;code&gt;#min201&lt;/code&gt; element&lt;sup id="fnref4"&gt;4&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;One could argue this is a bug in Firefox but it seems like the behaviour is simply &lt;a href="https://stackoverflow.com/a/34652275/11940"&gt;under-specified&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, how can this be solved? A simple workaround would be to use &lt;code&gt;@media screen and (max-width: 200.999px)&lt;/code&gt; for the first query but this will result in an overlap where both elements are shown on all browsers. It seems when parsing the media query, all browsers agree an rounding, treating &lt;code&gt;max-width: 200.999px&lt;/code&gt; the same as &lt;code&gt;max-width: 201px&lt;/code&gt;&lt;sup id="fnref5"&gt;5&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;What do you think would be the right course of action here and who’d need to take it? Should Firefox follow suit and take control over sub-pixel values away from devs? Should media-queries be extended with a &lt;code&gt;min-width-exclusive&lt;/code&gt; and &lt;code&gt;max-width-exclusive&lt;/code&gt; construct?&lt;/p&gt;

&lt;p&gt;Should web developers just live with this and hope no-one zooms and resizes their windows? Or should we restrict ourselves to only either use &lt;code&gt;min-width&lt;/code&gt; or &lt;code&gt;max-width&lt;/code&gt; queries but never mix them?&lt;/p&gt;

&lt;p&gt;Discuss!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;As with most interesting conundrums, it plays out mostly in the fringes; this one more literally than others. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;And, as it increasingly seems to me, one of the few who doesn’t just care about getting things to work but getting them to work on grounds of principle as opposed to accident. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Try it on &lt;a href="https://static.ra-phi.ch/demo/fractional-media-query.html"&gt;my test page&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;Interestingly, on 5x zoom level, Chrome also briefly hides both elements. I attribute this to rounding errors. Safari doesn’t but it also zooms to max 3x so maybe the rounding problems don’t manifest. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;Also, it would be ugly even if it worked, as it relies on the fact that browsers don’t have infinite zoom capability (and users don’t have infinite desires for zooming in). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>css</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
