shama / on-load

On load/unload events for DOM elements using a MutationObserver
113 stars 19 forks source link

on-load doesn't work for strict mode callers #15

Open aknuds1 opened 8 years ago

aknuds1 commented 8 years ago

If the caller of on-load is in strict mode, a TypeError is caused in on-load/index.js: Function.caller used to retrieve strict caller.

kasperlewau commented 7 years ago

Yup, getting bit by this issue myself at the moment.

on-load is pulled in through my usage of nanocomponent inside a choo application.

Compiling it all up with browserify -g yo-yoify -g babelify results in:

Uncaught TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
    at VirtualList.onload [as _onload] (bundle.js:2256)
    at VirtualList.Nanocomponent.render (bundle.js:1541)
    at module.exports (bundle.js:3719)
    at module.exports (bundle.js:3942)
    at bundle.js:3871
    at bundle.js:530
    at emit (bundle.js:2030)
    at Function.<anonymous> (bundle.js:570)
    at redraw (bundle.js:1975)

Points to this line


Sure enough, I can get around this by not running yo-yoify & babelify as global transforms, but that pulls in more deps than I need (as per this yo-yoify issue) for the dist build.

moszeed commented 7 years ago

same here, tried to remove onload events in a choo app and replacing them with on-load module: so i did this:

    function view() {
        let $div = html`<div class="list-item">test</div>`;
            onload($div,
                function() { console.log('in'); },
                function() { console.log('out'); }
            );
        return $div;
    }

but have the same error, tried also following:

yoshuawuyts commented 7 years ago

Seems to be a bug in Babel; I don't know what they're doing and don't have the time to debug. Think it's best to file it with them

aknuds1 commented 7 years ago

@yoshuawuyts Care to elaborate how it's a bug in Babel? AFAICT, independently of Babel transformations, on-load accesses Function.caller, which is disallowed for strict mode functions. See this StackOverflow answer for example.

aknuds1 commented 7 years ago

@moszeed How is not using babel making a difference? Are you not declaring your code as being in strict mode, whereas babel does this automatically for you?

moszeed commented 7 years ago

@aknuds1 without babel i get the "access to strict mode caller function is censored" error in Firefox. I set "use strict" in every file.

aknuds1 commented 7 years ago

@moszeed So babel is not making any difference for you wrt. this bug? The way I understood your previous comment, the error disappears when you don't use it.

If babel does indeed not cause the error for you, it confirms my view that it's unrelated to babel.

aknuds1 commented 7 years ago

Does anyone have any suggestions for how to solve this bug? Should we simply remove the default option for the caller argument, which is to inspect Function.caller? It seems pretty clear to me at least that accessing Function.caller is a bad idea.

shama commented 7 years ago

I'd love to remove the Function.caller but currently I don't have another functioning way to uniquely identify a function in code. Some ideas could be using new Error() and parsing the stack trace or maybe there is another way I'm not familiar with?

FWIW, you can specify your own identifier (this is what yo-yoify does which makes Function.caller unnecessary in production):

const uniqueIdentifier = 1
onload(element, function load () {
  console.log('load')
}, function unload () {
  console.log('unload')
}, uniqueIdentifier)

The identifier is needed so when an element is updated, we know if it's the same portion of code that generated it, regardless of how the element or function looks (so similar ones dont collide).

bennlich commented 3 years ago

If this lib is about firing events when dom nodes are added/removed, why even listen to attribute mutations in the first place? I read through the code base but I don't understand the purpose of eachAttr.