Huh, pretty major site-killing bug to go not only noticed or repaired, but 
no work-around listed either...

Should I move my bug report to elm-core since mine has substantially more 
information about how and where it is happening?


On Wednesday, August 3, 2016 at 3:46:26 PM UTC-6, Nick H wrote:
>
> This is a known issue with subscription swapping (see here 
> <https://github.com/elm-lang/html/issues/58>, here 
> <https://github.com/elm-lang/elm-compiler/issues/1426>, here 
> <https://github.com/elm-lang/core/issues/612>, and here 
> <https://github.com/elm-lang/core/issues/628>).
>
>
> On Wed, Aug 3, 2016 at 1:04 PM, OvermindDL1 <[email protected] 
> <javascript:>> wrote:
>
>> And found a workaround, but a really nasty horrible workaround.
>>
>> I had code kind of like this:
>> ```elm
>> subscriptions model =
>>       Sub.batch
>>           [ if List.isEmpty model.onNextFrame then
>>               Sub.none
>>             else
>>               AnimationFrame.times HelpersMsg_Frame
>>           ]
>> ```
>> I changed it to always be subscribed instead of turning off and on as I 
>> need it (I really really badly do not want to always be ticking, but ugh...)
>>
>> Thus definitely seems like a bug somewhere, probably in AnimationFrame (I 
>> reported a bug to https://github.com/elm-lang/animation-frame/issues/7 
>> so lets see what happens).
>>
>> And now brain-fried...
>>
>>
>> On Wednesday, August 3, 2016 at 1:53:35 PM UTC-6, OvermindDL1 wrote:
>>>
>>> The message that contains the one that gets wiped is `id: 38` as stated 
>>> before, it is a "_Task_andThen" with a `task` of what will become `id: 
>>> 39`.
>>>
>>> When `id: 38` gets processed it enqueues `id: 39`, at this time the 
>>> `cancel` key on the task that becomes Process `id: 39` is null, but 
>>> walking back up the parent stack of `id: 38` shows it calls the 
>>> `callback` on `id: 4` while creating the cancel key in the `step` 
>>> function when `if (ctor === '_Task_nativeBinding') {`.
>>>
>>> Traced through the entire `id: 38` path, it ends up creating `id: 39` 
>>> when it calls Native_AnimationFrame native callback on `rAF`, which then 
>>> ends up calling the callback given to `requestAnimationFrame`, which then 
>>> calls `callback(_elm_lang$core$Native_Scheduler.succeed(timeNow));`, which 
>>> then calls "_Task_succeed" to be called on `id: 38`, which then calls 
>>> the callback on its 'stack' key, which ends up calling `sendToSelf` with 
>>> the animation frame time value, and `id: 38` gets called *more* times 
>>> on the work loop because it ended up getting queued up a few times earlier, 
>>> but these next ones do not do anything of importance since its stack is 
>>> null (it early breaks).  Process `id: 4` appears to get fed the message 
>>> to queue up the task for the animationframe callback.
>>>
>>> When `id: 39` does work and there is no exception in a run it is filled 
>>> with the animation frame callback succeed task and then message.
>>>
>>> When `id: 39` does not work, I.E. root is null during the 'work' call, 
>>> root is not null and is assigned an object when `id: 39` is initially 
>>> created, and that object is a "_Task_andThen" that will do a 
>>> "_Task_nativeBinding" to the animation frame "callback' function.
>>>
>>> It gets cleared *during* the `step` of `id: 4`, which involves a 
>>> "_Task_succeed", that then calls the callback on the stack, which is a 
>>> "_Task_andThen", which then immediately gets called in the step loop again 
>>> (did not exit as it was via the internal loop), which then process as a 
>>> "_Task_andThen" this time, which then bumps on a "_Task_succeed", which 
>>> calls the list 'Cons' operator (empty list and a tuple0) and gives the 
>>> result back as a "_Task_succeed", which then gets called via the `id: 4` 
>>> loop to get wrapped up in a 'Just', sent to the animation frame native code 
>>> that then packages up the time information into another "_Task_succeed", 
>>> which then loops again and passes that value into the main application 
>>> spawnLoop `loop` function and stuffs things into a ready to handle 
>>> onMessage, then `id: 4` loops again to handle the "_Task_andThen" that 
>>> the `loop` put into it just now, which then stuffs the loop callback back 
>>> onto itself and loops again to handle the "_Task_receive" for the onMessage 
>>> callbacks (the `id: 4` process at this point has 3 things in its 
>>> mailbox), the first message is the animationframe callback, which ends up 
>>> calling down to `_elm_lang$animation_frame$AnimationFrame$onEffects` of 
>>> which is passed in is a subscription object that holds `id: 39` (whoo 
>>> found it!  ow...), which stuffs our `id: 39` object into a return 
>>> object on the `request._0` key, which all gets bundled into a 
>>> "_Task_succeed", and processed via the loop for `id: 4` and passing 
>>> that to the main `loop` callback again that stuffs a "_Task_receive" onto `
>>> id: 4` (the elm compiler could really optimize a *LOT* of this, maybe 
>>> translate elm to llvm, optimize it, then translate to javascript as a 
>>> start, like holy heck..., hmm webassembly is not a bad idea for elm at 
>>> all...), so then `id: 4` handles the "_Task_andThen" which then puts on 
>>> then handles the "_Task_receive", then it pops the second of the originally 
>>> 3 messages on `id: 4` and gives it to the callback that then calls 
>>> onMessage with the animationframe time stuff again, which calls back into 
>>> `_elm_lang$animation_frame$AnimationFrame$onEffects` again and OhHeyLook `
>>> id: 39` Again (>.>), which stuffs it into the `request._0` key again on 
>>> the return object so we loop around `id: 4` a couple more times again 
>>> while a "_Task_receive" shuffles to the top yet again (really, elm 
>>> compiler, optimization, maybe llvm to output to both javascript and 
>>> webassembly for options...), and we receive the last message on the mailbox 
>>> which is all the same stuff through 
>>> `_elm_lang$animation_frame$AnimationFrame$onEffects` yet again except this 
>>> last time instead of returning a "_Task_succeed" it instead goes down the 
>>> other path where a `kill` function is called's callback for a native 
>>> binding within the process of `id: 39` (Oh hey there it is again!), 
>>> which is then pushed on to be called so yet again `id: 4` gets looped 
>>> around again to handle a "_Task_andThen" that then handles the prior 
>>> "_Task_nativeBinding" that builds the cancel function on the root via the 
>>> callback function on that same root (which is the prior `kill` returned 
>>> callback function that was on `id: 39`), this function does:
>>> ```javascript
>>> function kill(process) {
>>> return nativeBinding(function (callback) {
>>> var root = process.root;
>>> if (root.ctor === '_Task_nativeBinding' && root.cancel) {
>>> root.cancel();
>>> }
>>>
>>> process.root = null;
>>>
>>> callback(succeed(_elm_lang$core$Native_Utils.Tuple0));
>>> });
>>> }
>>> ```
>>> Where 'process' is the process with `id: 39`, so you see here the 
>>> `function (callback)` function that was passed into a nativeBinding 
>>> function (that returned the nativeBinding task message that is 'now' being 
>>> processed) is being called, so first it does `var root = process.root`, so 
>>> far so good, it then calls `root.cancel` if `root.ctor === 
>>> '_Task_nativeBinding'`, which it is not (it is a "_Task_andThen"), so it 
>>> skips that `if` entirely and continues on down to `process.root = null`, 
>>> and *BOOM* there `id: 39` was just corrupted, so when `id: 39` is run 
>>> through later then its root being null causes it to die when it is trying 
>>> to figure out what to do.
>>>
>>> So yes, this is a bug, probably in AnimationFrame (maybe in core, I 
>>> don't know).
>>>
>>> And this hurts...  How do I work around this bug for the time being 
>>> until it is fixed?
>>>
>>>
>>> On Wednesday, August 3, 2016 at 12:28:47 PM UTC-6, OvermindDL1 wrote:
>>>>
>>>> Sometime between when `id: 39` and `id: 40` is created during 
>>>> `rawSpawn` the `root` key in the object goes null.  Still trying to find 
>>>> what code is wiping it...
>>>>
>>>>
>>>> On Wednesday, August 3, 2016 at 12:21:18 PM UTC-6, OvermindDL1 wrote:
>>>>>
>>>>> The task object with `id: 39` does not have a null `root` at the time 
>>>>> it is put into workQueue.  At the time it is put into the workQueue it 
>>>>> is: 
>>>>>  {callback : function(b), ctor: "_Task_andThen", task: {callback: 
>>>>> function(callback), cancel: function(), ctor: "_Task_nativeBinding"}}
>>>>>
>>>>> The root.task.callback function seems to have one interesting closure 
>>>>> that has a key/value of `navStart:1470247637381`, and there is 
>>>>> another link in the cancel to the process with `id: 38` so it appears 
>>>>> to be a continuation of that one.  I am not sure of the internal 
>>>>> structure 
>>>>> of Elm so I am not sure what Native Binding it is called, and I use no 
>>>>> Native Bindings in my project (only what comes with Elm core libraries is 
>>>>> what exists here at all).
>>>>>
>>>>> A little further digging and I am seeing 
>>>>> `_elm_lang$animation_frame$Native_AnimationFrame` in the stack, further 
>>>>> digging makes it seem (although I am unsure) that the 
>>>>> `root.task.callback` 
>>>>> is the same function as defined at:  
>>>>> https://github.com/elm-lang/animation-frame/blob/master/src/Native/AnimationFrame.js#L13
>>>>>
>>>>> I am not yet seeing how the `root` key on this "_Process" object is 
>>>>> getting cleared yet before it has a chance to be processed, still 
>>>>> tracing...
>>>>>
>>>>>
>>>>> On Wednesday, August 3, 2016 at 11:59:23 AM UTC-6, OvermindDL1 wrote:
>>>>>>
>>>>>> Debugged into it and caught the exception at the point to get the 
>>>>>> stack values:
>>>>>> ```javascript
>>>>>> numSteps = 403
>>>>>> process = Object {ctor: "_Process", id: 39, root: null, stack: null, 
>>>>>> mailbox: Array[0]}
>>>>>> ```
>>>>>> So root is null, why would it be trying to access a null value 
>>>>>> without checking if null?
>>>>>>
>>>>>> Any ideas how to work around this in this project so I can at least 
>>>>>> keep working in chrome?
>>>>>>
>>>>>>
>>>>>> On Wednesday, August 3, 2016 at 11:52:36 AM UTC-6, OvermindDL1 wrote:
>>>>>>>
>>>>>>> I keep getting this exception thrown from inside Elm, so far only 
>>>>>>> from Chrome Version 51.0.2704.103 m
>>>>>>> ```
>>>>>>> elm.js:2417  Uncaught TypeError: Cannot read property 'ctor' of null
>>>>>>> ```
>>>>>>>
>>>>>>> Where that line and the surrounding context is purely Elm generated 
>>>>>>> code, and is:
>>>>>>> ```javascript
>>>>>>> // STEP PROCESSES  // Line 2411
>>>>>>>
>>>>>>> function step(numSteps, process)
>>>>>>> {
>>>>>>> while (numSteps < MAX_STEPS)
>>>>>>> {
>>>>>>> var ctor = process.root.ctor;  // Line 2417 -- This is the error: 
>>>>>>>  Uncaught TypeError: Cannot read property 'ctor' of null
>>>>>>>
>>>>>>> if (ctor === '_Task_succeed')
>>>>>>> {
>>>>>>> while (process.stack && process.stack.ctor === '_Task_onError')
>>>>>>> {
>>>>>>> process.stack = process.stack.rest;
>>>>>>> }
>>>>>>> if (process.stack === null)
>>>>>>> ```
>>>>>>>
>>>>>>> The same javascript seems to run fine in firefox, IE, and edge, this 
>>>>>>> only seems to happen in Chrome and only 'sometimes'.  It seems to 
>>>>>>> happen 
>>>>>>> pretty quickly during loading and if it does not happen at the start 
>>>>>>> then 
>>>>>>> it does not seem to happen.  I've not been able to find code to whittle 
>>>>>>> down that lets my app still do anything while still causing this error.
>>>>>>>
>>>>>>> The 'step' function is being called from the 'work' function of (and 
>>>>>>> with context):
>>>>>>> ```
>>>>>>> javascript
>>>>>>>
>>>>>>> // WORK QUEUE
>>>>>>>
>>>>>>> var working = false;
>>>>>>> var workQueue = [];
>>>>>>>
>>>>>>> function enqueue(process) {
>>>>>>> workQueue.push(process);
>>>>>>>
>>>>>>> if (!working) {
>>>>>>> setTimeout(work, 0);
>>>>>>> working = true;
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> function work() {
>>>>>>> var numSteps = 0;
>>>>>>> var process;
>>>>>>> while (numSteps < MAX_STEPS && (process = workQueue.shift())) {
>>>>>>> numSteps = step(numSteps, process); // This is the place in the 
>>>>>>> callstack before step
>>>>>>> }
>>>>>>> if (!process) {
>>>>>>> working = false;
>>>>>>> return;
>>>>>>> }
>>>>>>> setTimeout(work, 0);
>>>>>>> }
>>>>>>> ```
>>>>>>>
>>>>>>> Chrome is not reporting anything in the stack below `work` so this 
>>>>>>> appears to be during the setTimeout callback set a few lines prior to 
>>>>>>> work 
>>>>>>> that calls work.
>>>>>>>
>>>>>>> Any thoughts as to the cause?
>>>>>>>
>>>>>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Elm Discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to [email protected] <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to