Skip to content
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

Add a lang IDL Attribute to CanvasTextDrawingStyles, and clarify "direction" on same #10873

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
186 changes: 144 additions & 42 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -65349,13 +65349,21 @@ callback <dfn callback>BlobCallback</dfn> = undefined (<span>Blob</span>? blob);
and <code data-x="attr-canvas-height">height</code> content attributes of this
<code>canvas</code> element.</p></li>

<li><p>Set the <span data-x="offscreencanvas-placeholder">placeholder <code>canvas</code>
element</span> of <var>offscreenCanvas</var> to a weak reference to this <code>canvas</code>
element.</p></li>
<li><p>Set the <var>offscreenCanvas</var>'s <span
data-x="offscreencanvas-placeholder">placeholder <code>canvas</code> element</span> of <var>
offscreenCanvas</var> to a weak reference to this <code>canvas</code> element.</p></li>

<li><p>Set this <code>canvas</code> element's <span data-x="concept-canvas-context-mode">context
mode</span> to <span data-x="concept-canvas-placeholder">placeholder</span>.</p></li>

<li><p>Set the <var>offscreenCanvas</var>'s <span
data-x="offscreencanvas-inherited-lang">inherited language</span> to the <span
data-x="language">language</span> of this <code>canvas</code> element.</p></li>

<li><p>Set the <var>offscreenCanvas</var>'s <span
data-x="offscreencanvas-inherited-direction">inherited direction</span> to the <span
data-x="the directionality">directionality</span> of this <code>canvas</code> element.</p></li>

<li><p>Return <var>offscreenCanvas</var>.</p></li>
</ol>

Expand Down Expand Up @@ -65566,6 +65574,7 @@ interface mixin <dfn interface>CanvasPathDrawingStyles</dfn> {

interface mixin <dfn interface>CanvasTextDrawingStyles</dfn> {
// text
attribute DOMString <span data-x="dom-context-2d-lang">lang</span>; // (default: "inherit")
attribute DOMString <span data-x="dom-context-2d-font">font</span>; // (default 10px sans-serif)
attribute <span>CanvasTextAlign</span> <span data-x="dom-context-2d-textAlign">textAlign</span>; // (default: "start")
attribute <span>CanvasTextBaseline</span> <span data-x="dom-context-2d-textBaseline">textBaseline</span>; // (default: "alphabetic")
Expand Down Expand Up @@ -66039,6 +66048,7 @@ context.fillRect(100,0,50,50); // only this square remains</code></pre>
data-x="dom-context-2d-shadowOffsetX">shadowOffsetX</code>, <code
data-x="dom-context-2d-shadowOffsetY">shadowOffsetY</code>, <code
data-x="dom-context-2d-shadowBlur">shadowBlur</code>, <code
data-x="dom-context-2d-lang">lang</code>, <code
data-x="dom-context-2d-font">font</code>, <code
data-x="dom-context-2d-textAlign">textAlign</code>, <code
data-x="dom-context-2d-textBaseline">textBaseline</code>, <code
Expand Down Expand Up @@ -66530,13 +66540,27 @@ transform. ack Shaun Morris. -->
<h6>Text styles</h6>

<dl class="domintro">
<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-lang">lang</span> [ = <var>value</var> ]</code></dt>
<dt><code data-x=""><var>styles</var>.<span data-x="dom-context-2d-lang">lang</span> [ = <var>value</var> ]</code></dt>
<dd>
<p>Returns the current language setting.</p>

<p>Can be set, to change the language used when resolving fonts. The syntax and valid values
schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved
are the same as those for the <span data-x="attr-lang">lang</span> element attribute, or the
value "<code data-x="dom-context-2d-direction-inherit">inherit</code>" which is described
below.</p>
Copy link
Member

Choose a reason for hiding this comment

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

Nit: The /dev/ version of the specs won't have the "below" section, only this note; not sure it's great referencing it that way.
Though I must admit I'm not sure why things like the text-preparation-algo are in the /dev/ version, certainly some cleaning is required around there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Almost every attribute in this block uses "The possible values are and their meanings are given below." I don't think there's anything to be done without a big refactoring but I will use the same phrasing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is an issue with almost every attribute in this section. They use "The possible values and their meanings are given below." Fixing that would be another PR but I'll try to use the same text for lang.

Copy link
Member

Choose a reason for hiding this comment

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

Well, turns out that these actually are part of the /dev/ version: https://html.spec.whatwg.org/dev/canvas.html#dom-context-2d-direction-inherit.

But there is also some stuff in there that I doubt should have been exposed, like the whole text-preparation-algo, so this indeed might require a new separate PR to clean this up. I think you can ignore for now. The best would probably have been a single sentence description of the behavior, but given its complexity I'm not sure it's doable.

Copy link
Member

Choose a reason for hiding this comment

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

Though, the "inherit" link here is wrong, it links to direction's "inherit" value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, all of lang's "inherit" link to the direction one. I'll fix that.


<p>The default is "<code data-x="dom-context-2d-direction-inherit">inherit</code>".</p>
</dd>

<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-font">font</span> [ = <var>value</var> ]</code></dt>
<dt><code data-x=""><var>styles</var>.<span data-x="dom-context-2d-font">font</span> [ = <var>value</var> ]</code></dt>
<dd>
<p>Returns the current font settings.</p>

<p>Can be set, to change the font. The syntax is the same as for the CSS <span>'font'</span>
property; values that cannot be parsed as CSS font values are ignored.</p>
property; values that cannot be parsed as CSS font values are ignored. The default is "10px
sans-serif".</p>

<p>Relative keywords and lengths are computed relative to the font of the <code>canvas</code>
element.</p>
Expand Down Expand Up @@ -66708,15 +66732,54 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
Notice that the font is only loaded inside the worker, and not in the document context.</p>
</div>

<p>Objects that implement the <code>CanvasTextDrawingStyles</code> interface have a <dfn attribute
for="CanvasTextDrawingStyles"><code data-x="dom-context-2d-lang">lang</code></dfn> attribute
that controls localization of the font. It is used to set the internal <dfn
data-x="concept-CanvasTextDrawingStyles-font-language">font language</dfn> used when setting the
schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved
<code data-x="dom-context-2d-font">font</code> attribute.</p>

<p>The <code data-x="dom-context-2d-lang">lang</code> getter steps are to return the current
value.</p>

<p>The <code data-x="dom-context-2d-lang">lang</code> setter steps are:</p>

<ol>
<li><p>Change the current value to the new value.</p></li>
<li><p>If the value is "<code data-x="dom-context-2d-direction-inherit">inherit</code>", then</p>
<ol>
<li><p>If <var>object</var>'s <span>font style source object</span> is a <code>canvas</code>
element, then set the <span data-x="concept-CanvasTextDrawingStyles-font-language">font
language</span> to the element's <span data-x="language">language</span>.</p></li>
Copy link
Member

Choose a reason for hiding this comment

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

To be clear, this doesn't work like direction for "inherit".

If we have something like,

canvasElement.lang = "en";
canvasElement.dir = "ltr";
context.lang = "inherit";
context.direction = "inherit";
canvasElement.lang = "ar";
canvasElement.dir = "rtl";
context.fillText(str, x, y);

The direction used to render the text will be rtl, as determined in the text preparation algorithm, but the font language will be "en"and not "ar", because it's directly set during this setter step.

So, as currently written, for DOM canvases, lang actually has an inherit-only-at-setting behavior while direction has a true inherit behavior.
(I think the behavior for OffscreenCanvas is now stable though).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In Chrome, at least, the font is re-created before use when any properties that affect the font are changed (letter spacing, font-stretch, font-kerning etc.). The same will happen for language so in your example the behavior will match direction. I'm leveraging the fact that the font section says you must consider the language whenever you set the font, whenever you do update the font.

But yes, the spec does not say anything about this explicitly. The only reference I can find to updating the font is "Font family names must be interpreted in the context of the font style source when the font is to be used". We would need to add something broadening this notion of "when the font is used" and then mention it with all of the font-affecting properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Chrome, and I suspect all browsers, currently update the font when any font-affecting properties change (such as letter-spacing, font-kerning, etc). It's not in the spec in any way and I don't want to try to add it now, though I could if folks insist. A change in language should update the font.

There are test like this, for instance, where the font should reflect the value set after the font, and all browsers pass.
ctx.font = '100px serif';
ctx.fontKerning = "none";

Though there do not seem to be explicit dynamic update tests for these properties. I am in the process of adding them for direction and will add for lang too.

Copy link
Member

Choose a reason for hiding this comment

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

It's not in the spec in any way

Yes, it's in the text-preparation-algorithm (step 5 for these). Every time new text is drawn to the context, or measureText() is called, this will be computed again (for the specs, impl. can obviously optimize this).

So, given this one and the related review comments, I think I see where is the misunderstanding.

You don't want to handle anything in the lang getter and setter, instead you want it to act just like direction:

The lang IDL attribute, on getting, must return the current value. On setting, the current value must be changed to the new value. When the object implementing the CanvasTextDrawingStyles interface is created, the lang attribute must initially have the value "inherit".

And then, you create a new determine the font language1 algo, which would take the CanvasTextDrawingStyles as parameter (and maybe its lang attribute value separately, editors will tell better than me). This algorithm will return either the explicit language, either the font style source object's internal inherited language, or its font language in case it's a <canvas>.
Then, in the text-preparation-algorithm you create a new local variable and set it to the result of running the determine the font language algorithm with target and use it where it's needed. At a first glance I'd say the easiest path would be to set the inline-box's font-language-override CSS property in the step 5, just like it's done for the other attributes, but maybe this property doesn't match entirely with what we want in a way I can't foresee. In this case we'd need a new concept to pass the content language to the CSS inline box.

Footnotes

  1. I let you bike shed the name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. I get your point and matching what I have for direction would make sense. Part of what confused me is that there's a mismatch between the spec and how Chromium at least implements it, because many of the CSS properties in Step 5 of the text preparation algorithm are actually part of step 3, getting the current font.

The problem we run into is that there is no CSS property for language (the override takes the wrong kind of value), but I suppose we can refer to and link to the discussion of the Content Language in CSS.

I'll get another version ready ASAP.

Copy link
Member

@Kaiido Kaiido Feb 5, 2025

Choose a reason for hiding this comment

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

Part of what confused me is that there's a mismatch between the spec and how Chromium at least implements it, because many of the CSS properties in Step 5 of the text preparation algorithm are actually part of step 3, getting the current font.

I see, font in step 3 is not an actual font as in an open-type thing that could be used. It's a string that is used later as the value for the CSS font shorthand, in the step 5, second row of the table. The actual font selection is done in CSS land.

the override takes the wrong kind of value

Right... that's unfortunate. Handwavely setting content-language in prose might work though?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the latest version I say that the canvas language is used as the CSS content language with a I linked to the CSS Fonts descriptive block on font localization in which the content language is used, but your link is better.


<li><p>Otherwise, <var>object</var>'s <span>font style source object</span> is an
<code>OffscreenCanvas</code> object. Set the <span
data-x="concept-CanvasTextDrawingStyles-font-language">
font language</span> to the <code>OffscreenCanvas</code>'s internal
<span data-x="offscreencanvas-inherited-lang">inherited language</span>.</p></li>
</ol>
</li>
<li><p>Otherwise, the <span data-x="concept-CanvasTextDrawingStyles-font-language">font
language</span> is the value, with the semantics of the global <code
data-x="attr-lang">lang</code> attribute.</p></li>
</ol>

<p>When the object implementing the <code>CanvasTextDrawingStyles</code> interface is created,
the <code data-x="dom-context-2d-lang">lang</code> attribute must initially have the value
"<code data-x="dom-context-2d-direction-inherit">inherit</code>" and the
<span data-x="concept-CanvasTextDrawingStyles-font-language">font language</span> must be set as
above.</p>

<p>The <dfn attribute for="CanvasTextDrawingStyles"><code
data-x="dom-context-2d-font">font</code></dfn> IDL attribute, on setting, must be <span
data-x="parse something according to a CSS grammar">parsed as a CSS &lt;'font'> value</span> (but
without supporting property-independent style sheet syntax like 'inherit'), and the resulting font
must be assigned to the context, with the <span>'line-height'</span> component forced to 'normal',
with the <span>'font-size'</span> component converted to <span data-x="'px'">CSS pixels</span>,
and with system fonts being computed to explicit values. If the new value is syntactically
incorrect (including using property-independent style sheet syntax like 'inherit' or 'initial'),
then it must be ignored, without assigning a new font value. <ref>CSS</ref></p>
must be assigned to the context, with the <span
data-x="concept-CanvasTextDrawingStyles-font-language">font language</span> as determined above,
Copy link
Member

Choose a reason for hiding this comment

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

"above" where? Here we're supposed to already have a value for this font language internal value.
Should the lang setter steps be ran again? With what value? To what effect?

Also, is this occurrence of "font language" supposed to link to another concept, maybe in CSS, like for the following line-height and font-size components of the font shorthand? Currently it's quite unclear how this font language is being used.
CSS has a font-language-override property should it use this? Or maybe it's enough to reference the "content language" even though they don't export this term yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed it to be explicit as "with the font language as determined by the lang setter steps".

The font selection code in each browser has the notion of the "locale" or "language". It goes through to harfbuzz in Chrome and Core Text in Safari. That's what this is intended to refer to. I'm not sure how to be more specific without referring to an explicit software package. I'll see if there's any way to make it clearer, such as using Core Text's phrasing "Language specifier string to select a font for a particular localization."

Copy link
Member

Choose a reason for hiding this comment

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

with the <span>'line-height'</span> component forced to 'normal', with the
<span>'font-size'</span> component converted to <span data-x="'px'">CSS pixels</span>, and with
system fonts being computed to explicit values. If the new value is syntactically incorrect
(including using property-independent style sheet syntax like 'inherit' or 'initial'), then it
must be ignored, without assigning a new font value.<ref>CSS</ref></p>

<p>Font family names must be interpreted in the context of the <span>font style source
object</span> when the font is to be used; any fonts embedded using <code
Expand Down Expand Up @@ -66914,16 +66977,30 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>

<dd><p>Treat input to the <span>text preparation algorithm</span> as right-to-left text.</p></dd>

<!--
<dt><dfn><code data-x="dom-context-2d-direction-auto">auto</code></dfn>
<dt><dfn enum-value for="CanvasDirection"><code data-x="dom-context-2d-direction-inherit">inherit</code></dfn>

<dd><p>Determine the direction from the input to the <span>text preparation algorithm</span>.</p></dd>
-->
<dd><p>Use the following process to determine the value for the
<dfn for="CanvasDirection"><code data-x="dom-context-2d-inherited-direction">inherited direction</code></dfn> referred to in the <span>text preparation algorithm</span></p>

<dt><dfn enum-value for="CanvasDirection"><code data-x="dom-context-2d-direction-inherit">inherit</code></dfn>
<ol>
<li><p>If <var>object</var>'s <span>font style source object</span> is a <code>canvas</code>
element:</p>
<ol>
<li><p>If the element has a <span>computed value</span> for
<span>'direction'</span> use that as the <span data-x="dom-context-2d-inherited-direction">inherited direction</span>.</p></li>

<dd><p>Default to the directionality of the <code>canvas</code> element or <code>Document</code>
as appropriate.</p></dd>
<li><p>Otherwise, use the <span data-x="the directionality">directionality</span>
of the element as the <span data-x="dom-context-2d-inherited-direction">inherited direction</span>.</p></li>
</ol>

<li><p>Otherwise, <var>object</var>'s <span>font style source object</span> is an
<code>OffscreenCanvas</code> object. Set the <span
data-x="dom-context-2d-inherited-direction">inherited direction</span> to the
<code>OffscreenCanvas</code>'s internal <span
data-x="offscreencanvas-inherited-direction">inherited
direction</span>.</p></li>
</ol>
</dd>
</dl>

<p>The <code data-x="dom-context-2d-fontKerning">fontKerning</code> attribute's allowed keywords
Expand Down Expand Up @@ -67047,32 +67124,11 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
data-x="dom-context-2d-direction-rtl">rtl</code>"</dt>
<dd>Let <var>direction</var> be '<span data-x="concept-rtl">rtl</span>'.</dd>

<!--
<dt>If the <var>target</var> object's <code
data-x="dom-context-2d-direction">direction</code> attribute has the value "<code
data-x="dom-context-2d-direction-auto">auto</code>"</dt>
<dd>
Find the first character in <var>text</var> of bidirectional character type L, AL, or
R, if any. If such a character is found and it is of bidirectional character type AL or R,
then let <var>direction</var> be '<span data-x="concept-rtl">rtl</span>'; otherwise,
let <var>direction</var> be '<span data-x="concept-rtl">rtl</span>'. <ref>BIDI</ref>
</dd>
-->

<dt>If the <var>target</var> object's <span>font style source object</span> is an
element</dt>

<dd>Let <var>direction</var> be <span>the directionality</span> of the <var>target</var> object's <span>font style source object</span>.</dd>

<dt>If the <var>target</var> object's <span>font style source object</span> is a
<code>Document</code> with a non-null <span>document element</span></dt>

<dd>Let <var>direction</var> be <span>the directionality</span> of the <var>target</var>
object's <span>font style source object</span>'s <span>document element</span>.</dd>

<dt>Otherwise</dt>

<dd>Let <var>direction</var> be '<span data-x="concept-ltr">ltr</span>'.</dd>
data-x="dom-context-2d-direction-inherit">inherit</code>"</dt>
<dd>Let <var>direction</var> be the <var>target</var>'s <span
data-x="dom-context-2d-inherited-direction">inherited direction</span>.</dd>
</dl>
</li>

Expand Down Expand Up @@ -71282,6 +71338,11 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
data-x="dom-OffscreenCanvas-height">height</code> attributes of the <code>OffscreenCanvas</code>
object. Initially, all the bitmap's pixels are <span>transparent black</span>.</p>

<p>An <code>OffscreenCanvas</code> object has an internal <dfn
data-x="offscreencanvas-inherited-lang">inherited language</dfn> and <dfn
data-x="offscreencanvas-inherited-direction">inherited direction</dfn> set when
the <code>OffscreenCanvas</code> is created.</p>

<p>An <code>OffscreenCanvas</code> object can have a rendering context bound to it. Initially,
it does not have a bound rendering context. To keep track of whether it has a rendering context
or not, and what kind of rendering context it is, an <code>OffscreenCanvas</code> object also
Expand All @@ -71302,9 +71363,37 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
array of <span>transparent black</span> pixels of the dimensions specified by <var>width</var> and
<var>height</var>; and its <code data-x="dom-OffscreenCanvas-width">width</code> and <code
data-x="dom-OffscreenCanvas-height">height</code> attributes initialized to <var>width</var> and
<var>height</var> respectively.</p>
<var>height</var> respectively. The <span data-x="offscreencanvas-inherited-lang">inherited
language</span> and <span data-x="offscreencanvas-inherited-direction">inherited direction</span>
internal values must be set as follows:</p>

<hr>
<ol>
<li><p>Let <var>global</var> be the <code>OffscreenCanvas</code>'s <span>relevant global
object</span>.</p></li>
<li><p>If <var>global</var> is a <code>Window</code> object:</p>
<ol>
<li><p>Let <var>Document</var> be the <var>global</var>'s
<span data-x="concept-document-window">associated <code>Document</code></span>.</p></li>

<li><p>Set the <code>OffscreenCanvas</code>'s <span
data-x="offscreencanvas-inherited-lang">inherited language</span> to the
<var>Document</var>'s <span data-x="language">language</span>.</p></li>

<li><p>Set the <code>OffscreenCanvas</code>'s <span
data-x="offscreencanvas-inherited-direction">inherited direction</span>
to the <var>Document</var>'s <span data-x="the directionality">directionality</span>.</p></li>
</ol>
</li>
<li><p>Otherwise:</p>
<ol>
<li><p>Set the <span data-x="offscreencanvas-inherited-lang">inherited language</span>
to explicitly unknown.</p></li>

<li><p>Set the <span data-x="offscreencanvas-inherited-direction">inherited direction</span>
to "ltr".</p></li>
</ol>
</li>
</ol>

<p><code>OffscreenCanvas</code> objects are <span data-x="transferable
objects">transferable</span>. Their <span>transfer steps</span>, given <var>value</var> and
Expand All @@ -71321,11 +71410,18 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
<li><p>Let <var>width</var> and <var>height</var> be the dimensions of <var>value</var>'s <span
data-x="offscreencanvas-bitmap">bitmap</span>.</p></li>

<li><p>Let <var>language</var> and <var>direction</var> be the values of <var>value</var>'s
<span data-x="offscreencanvas-inherited-lang">inherited language</span> and
<span data-x="offscreencanvas-inherited-direction">inherited direction</span>.</p></li>

<li><p>Unset <var>value</var>'s <span data-x="offscreencanvas-bitmap">bitmap</span>.</p></li>

<li><p>Set <var>dataHolder</var>.[[Width]] to <var>width</var> and
<var>dataHolder</var>.[[Height]] to <var>height</var>.</p></li>

<li><p>Set <var>dataHolder</var>.[[Language]] to <var>language</var> and
<var>dataHolder</var>.[[Direction]] to <var>direction</var>.</p></li>

<li><p>Set <var>dataHolder</var>.[[PlaceholderCanvas]] to be a weak reference to
<var>value</var>'s <span data-x="offscreencanvas-placeholder">placeholder <code>canvas</code>
element</span>, if <var>value</var> has one, or null if it does not.</p></li>
Expand All @@ -71339,6 +71435,11 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
rectangular array of <span>transparent black</span> pixels with width given by
<var>dataHolder</var>.[[Width]] and height given by <var>dataHolder</var>.[[Height]].</p></li>

<li><p>Set <var>value</var>'s <span data-x="offscreencanvas-inherited-lang">inherited
language</span> to <var>dataHolder</var>.[[Language]] and <span
data-x="offscreencanvas-inherited-direction">inherited direction</span> to
<var>dataHolder</var>.[[Direction]].</p></li>

<li><p>If <var>dataHolder</var>.[[PlaceholderCanvas]] is not null, set <var>value</var>'s <span
data-x="offscreencanvas-placeholder">placeholder <code>canvas</code> element</span> to
<var>dataHolder</var>.[[PlaceholderCanvas]] (while maintaining the weak reference
Expand Down Expand Up @@ -147039,6 +147140,7 @@ INSERT INTERFACES HERE
Ştefan Vargyas,
Stefan Weiss,
Steffen Meschkat,
Stephen Chenney,
Stephen Ma,
Stephen Stewart,
Stephen White,
Expand Down