> On Jan 12, 2023, at 9:05 PM, Ryosuke Niwa via webkit-dev > <webkit-dev@lists.webkit.org> wrote: > > >> On Jan 12, 2023, at 8:37 PM, Darin Adler <da...@apple.com> wrote: >> >>> On Jan 12, 2023, at 9:35 PM, Ryosuke Niwa <rn...@apple.com> wrote: >>> >>> One alternative is to make bar() return RefPtr although that would be a bit >>> heavy handed in the case of trivial function calls like this: >>> document().frame()->ownerElement() >> >> I don’t quite follow. You just said that all arguments including this need >> to have RefPtr or something like it. > > Right. The caller should keep an object alive. > >> What makes it OK to call ownerElement without a RefPtr? What is a “trivial >> function” and how can we tell which functions are the trivial ones? > > We made an exception to “trivial functions” to allow chaining like the one > above possible. A trivial function is any inlined accessor of a member > variable the form: Document& document() { return m_document.get(); } or > Frame* frame() { return m_frame.get(); } > > Anything more complicated than that, or for any out-of-lined functions, we > should be storing “this” on a smart pointer type. > > > Here’s an example: > static void printNavigationErrorMessage(Frame& frame, const URL& activeURL, > const char* reason) > { > String message = "Unsafe JavaScript attempt to initiate navigation for > frame with URL '" + frame.document()->url().string() + "' from frame with URL > '" + activeURL.string() + "'. " + reason + "\n"; > > // FIXME: should we print to the console of the document performing the > navigation instead? > frame.document()->domWindow()->printErrorMessage(message); > } > > This function, under our rule, should be rewritten like this: > static void printNavigationErrorMessage(Frame& frame, const URL& activeURL, > const char* reason) > { > String message = "Unsafe JavaScript attempt to initiate navigation for > frame with URL '" + frame.document()->url().string() + "' from frame with URL > '" + activeURL.string() + "'. " + reason + "\n"; > > // FIXME: should we print to the console of the document performing the > navigation instead? > RefPtr { frame.document()->domWindow() }->printErrorMessage(message); > } > > Here, it’s okay to call document() without first storing “frame” in a smart > pointer because it is a function argument. By transitive property, the caller > of this function should be keeping the frame object alive. It’s okay to call > domWindow() because it’s a trivial accessor function of the form: > > DOMWindow* domWindow() const { return m_domWindow.get(); } > > But it’s not okay to call printErrorMessage without first storing DOMWindow > in a RefPtr because it’s a non-trivial function, and domWindow() was not an > argument to this function so there is no caller to guarantee the lifetime of > it. > > > Here’s another example: > int Element::clientLeft() > { > document().updateLayoutIgnorePendingStylesheets(); > > if (auto* renderer = renderBox()) { > auto clientLeft = LayoutUnit { roundToInt(renderer->clientLeft()) }; > return > convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(clientLeft, > *renderer).toDouble()); > } > return 0; > } > > This function should be rewritten to something like this assuming > RenderObject is updated to support CheckedPtr: > int Element::clientLeft() > { > Ref { document() }->updateLayoutIgnorePendingStylesheets(); > > if (CheckedPtr renderer = renderBox()) { > auto clientLeft = LayoutUnit { roundToInt(renderer->clientLeft()) }; > return > convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(clientLeft, > *renderer).toDouble()); > } > return 0; > } > > Here, we must store document() in Ref before calling > updateLayoutIgnorePendingStylesheets because > updateLayoutIgnorePendingStylesheets is a non-trivial function, and > document() is not one of the arguments. Similarly, we need to store > renderBox() in a smart pointer since clientLeft() is a non-trivial function. > But we don’t have to store “this” in Ref/RefPtr before calling > convertToNonSubpixelValue because “this” is an implicit function argument.
Oops, correction. convertToNonSubpixelValue is a static function which takes double & LegacyCSSOMElementMetricsRoundingStrategy so this is irrelevant there. - R. Niwa
_______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-dev