Cannot read property 'replace' #102

Closed
nijikokun opened this Issue Jan 18, 2013 · 14 comments

Comments

Projects
None yet
3 participants

https://www.mashape.com/seatgeek/seatgeek

Uncaught TypeError: Cannot read property 'replace' of replacement
Line: 578

This will probably be replaced with another library today because of this, I'm not sure what exactly is causing it, my ideas hint toward the position of the current_level is wrongly given.

Owner

ccampbell commented Jan 18, 2013

Hey, sorry about this. It's hard for me to debug without any additional information though. I only see the minified one on your site which says line 21, but the entire javascript is on line 21.

Do you have a simple way to reproduce?

Owner

ccampbell commented Jan 18, 2013

Ahh I copied the page locally to test. Something is definitely up. It might have something to do with the initialization in Rainbow. I wrapped

return window.addEventListener('load', Rainbow.color, false);

with

setTimeout(function() {
    window.addEventListener('load', Rainbow.color, false);
}, 50);
return;

And I no longer see the error. I tried switching to use DOMContentLoaded, but that doesn't seem to make a difference. Looking into it more.

Owner

ccampbell commented Jan 18, 2013

Also when I remove all the other js except Rainbow from the page it works, and there are no errors.

Hmm... it happens on my local with the un-minified too, but that's nda stuff.. hence why I know the exact line

I'll see if I can replicate it with a simple test

Owner

ccampbell commented Jan 18, 2013

Is there any content being added to the page dynamically? I wonder if it is a race condition between the time rainbow runs the first time and when the content is added.

There are things added dynamically, curl examples which calls Rainbow.color again

Moved over to a JSFiddle example, and no errors so it is probably the race condition.

Owner

ccampbell commented Jan 18, 2013

I'm not sure that is it, but It definitely seems like some sort of race condition with the asynchronous processing. Still trying to figure it out. It is interesting that adding a small timeout to the initialization makes it work correctly.

Owner

ccampbell commented Jan 18, 2013

Can you try commenting out lines 270, 271 in api-profile.js to see if that fixes it.

if (typeof Rainbow !== 'undefined')
    Rainbow.color(Mashape.getFields);

I am hoping that is what is causing the problem

Yes, that is the problem actually. We need to call getFields after it has been ran, so we do it twice... so it is a race issue.

Check out prism.js they have a data-manual for this solution, but I feel that is a quick hack.

Owner

ccampbell commented Jan 18, 2013

Sweet, so there are a few ways to solve this. The simplest for me might be to add a Rainbow.ready callback that will be called when all the code that was present in the DOM has finished highlighting.

So that would let you change your code to

Rainbow.ready(function() {
    Rainbow.color(Mashape.getFields);
});

A more foolproof way would be to queue up all Rainbow.color calls so while rainbow is running it waits to execute any that are in the queue. That way you wouldn't have to change anything. I will take a stab and see how difficult that will be to implement.

As a temporary workaround you could add a timeout around that call or listen for Rainbow.onHighlight() until you get the last element on the page. I know those are ugly, but just ideas.

I was going to implement a ready, I like the queue idea lot more, it feels less hacky, maybe both actually.

grrowl commented Jun 12, 2014

+1 I'm also having this problem invoking Rainbow on many strings at once and waiting for callback, like this:

$('article.sourced').each(function (index) {
    var $this = $(this);
    Rainbow.color($this.html(), 'html', function (highlighted_code) {
        $this.append($('<pre>').html(highlighted_code));
  });
});

Errors with: Uncaught TypeError: Cannot read property 'replace' of undefined rainbow.js:557. Looks like the replace indexes get out of whack somehow. Replacing that code with the below solves it:

$('article.sourced').each(function (index) {
    var $this = $(this);
    setTimeout(function () {
        Rainbow.color($this.html(), 'html', function (highlighted_code) {
            $this.append($('<pre>').html(highlighted_code));
      });
    }, 250 * index);
});

So it appears the problem may be a shared closure somewhere, or static variable. Of course, the second method has the obvious drawback of being able to see the page generate these snippets.

For reference I'm highlighting HTML, there's 24 article.sourced elements on the page, and it seems to fail on "random" snippets (that is, it'll fail on a snippet consistently, but as I try to debug the error it will fail on a different snippet — which lead me to believe it was race-related)

grrowl commented Jun 12, 2014

Timeout offsets of >= 8ms work in my case, which leads to a max of about 2 callbacks per 16ms execution frame

Owner

ccampbell commented Jul 2, 2016

This should be resolved in version 2.0 (#196) since there is no longer a global state and the processing happens in webworkers.

ccampbell closed this Jul 2, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment