Monkey patching constructors in builtin class hierarchies?

Logan Smyth loganfsmyth at gmail.com
Tue Oct 24 17:32:14 UTC 2017


Given that these are constructors that you don't own, adding your own
properties to them seems like an overall ugly approach to me. Why not store
your data separately in a WeakMap and rather than injecting properties onto
existing objects? Then you can initialize the stored data on first access
of the data you want.

On Tue, Oct 24, 2017 at 10:25 AM, /#!/JoePea <joe at trusktr.io> wrote:

> Well, I know I can set accessors on a prototype easily, but what I
> mean is, I need each instance of an `Element` to have exactly one
> instance of something right after construction during the same
> synchronous operation.
>
> For example, if we have an application with a bunch of pre-existing
> Elements that do not extend from any classes of mine, I'd like for the
> all to have `foo` properties, so that I can do this:
>
> ```js
> const el = new SomeCustomElementThatWasDefinedCreatedByMe
> console.log(el.foo) // it exists and is specific to the instance, not
> a prototype property
>
> // or
>
> const div = document.createElement('div')
> console.log(div.foo) // it exists and is specific to the instance, not
> a prototype property
> ```
>
> Can this be done?
> /#!/JoePea
>
>
> On Tue, Oct 24, 2017 at 10:19 AM, /#!/JoePea <joe at trusktr.io> wrote:
> >> This feels like a problem similar to https://esdiscuss.org/topic/
> block-scoped-prototype-extensions
> >
> > @Boris, even if it were scoped, how do we monkey patch a
> > *constructor*? By the way, for some reason your link to
> > `https://esdiscuss.org/topic/block-scoped-prototype-extensions` posted
> > as `https://esdiscuss.org/topic/block` which is 404. If you can edit
> > it it would help others not to stumble on a broken link.
> >
> >> if that would be possible, then everyone could just monkey patch
> Object, right?
> >
> > But everyone can monkey patch the entire class already, aside from the
> > constructor, by modifying the prototype. Obviously if someone returns
> > something new from the constructor they might break everything, but it
> > will be completely obvious and people then won't do that. The same
> > applies with methods and properties, it is super easy to break entire
> > applications monkey patching methods.
> >
> > ---
> >
> > So suppose I want to "polyfill" a concept. For example, I want all
> > elements to have a new "foo" accessor after they've been constructed.
> > Or for example, suppose `HTMLElement.prototype.style` and
> > `SVGElement.prototype.style` didn't exist yet. How would I patch those
> > in?
> > /#!/JoePea
> >
> >
> > On Tue, Oct 24, 2017 at 10:07 AM, Michał Wadas <michalwadas at gmail.com>
> wrote:
> >> AFAIR DOM classes are not extensible by any means.
> >>
> >>
> >>
> >> On 24 Oct 2017 6:51 pm, "/#!/JoePea" <joe at trusktr.io> wrote:
> >>>
> >>> Is it possible to monkey-patch an intermediate constructor of a
> built-in
> >>> subclass?
> >>>
> >>> For example, suppose I want all `Element` instances in a web app to
> have
> >>> new instance properties, is there a way to monkey-patch the Element
> >>> constructor so that when I make a custom element by extending a
> subclass of
> >>> `Element` that the new logic will fire?
> >>>
> >>> For example:
> >>>
> >>> ```js
> >>> // monkey-patch the Element constructor somehow so that it logs
> "patched
> >>> in Element".
> >>>
> >>> // then
> >>> class FooBar extends HTMLElement {}
> >>> customElement.define('foo-bar', FooBar)
> >>> new FooBar // "patched in Element"
> >>> ```
> >>>
> >>> I tried
> >>>
> >>> ```js
> >>> const OldElement = window.Element
> >>>
> >>> window.Element = function Element() {
> >>>   const _this = new OldElement
> >>>   console.log("patched in Element")
> >>>   return _this
> >>> }
> >>>
> >>> window.Element.prototype = OldElement.prototype
> >>> window.Element.prototype.constructor = window.Element
> >>>
> >>> class FooBar extends HTMLElement {}
> >>> customElements.define('f-b', FooBar)
> >>> new FooBar // does not log "patched in Element"
> >>> ```
> >>>
> >>> But when I make a new custom element, constructing it seems to use the
> old
> >>> Element constructor, as if a non-global reference to the original
> >>> constructor is kept inside a module so that modifying the global
> wouldn't
> >>> have any effect.
> >>>
> >>> Is there a way to monkey patch a constructor in the middle of a
> built-in
> >>> prototype chain or to otherwise inject construction logic to base
> classes of
> >>> existing class hierarchies?
> >>>
> >>>
> >>> /#!/JoePea
> >>>
> >>> _______________________________________________
> >>> es-discuss mailing list
> >>> es-discuss at mozilla.org
> >>> https://mail.mozilla.org/listinfo/es-discuss
> >>>
> >>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171024/ee5c09b1/attachment.html>


More information about the es-discuss mailing list