Breeze error: Illegal construction - use 'or&#

2019-03-10 11:53发布

问题:

I met this Breeze error

[Illegal construction - use 'or' to combine checks]

on Chrome when loading the edit page of an entity. When I refresh the page, the error message no longer appears. This error happens randomly, irregularly on my site. I could not reproduce it using a specified scenario, just met it by random.

I see this error message inside Breeze code

if (curContext.prevContext === null) {
    curContext.prevContext = context;
    // just update the prevContext but don't change the curContext.
    return that;
} else if (context.prevContext === null) {
    context.prevContext = that._context;
} else {
    throw new Error("Illegal construction - use 'or' to combine checks");
}

Could you please tell me: based on above block of code, in which cases this error is thrown?

Thanks a lot.

回答1:

We're kind of stumped because no one can pin down when this happens.

Would you all do us a favor and modify your breeze.debug.js to capture more information about the state of affairs when it throws?

Maybe you can add this:

} else {
     console.log("** Aaargh! 'curContext.prevContext': " + curContext.prevContext +
                " 'context.prevContext': " + context.prevContext);
     throw new Error("Illegal construction - use 'or' to combine checks");
}

Grasping at straws. All info helps.

Update 26 Feb 2014

AHA! Thank you @steve, @matthias, and others!

As I privately suspected, something, somewhere, has decide to set prevContext to undeclared instead of null. I was going to recommend that we switch to "==" anyway ... which would handle both cases. Falsiness is good enough IMO. We'll get back to you when we do it (assuming no one inside the Breeze team objects to applying a fix that we can't test).

Update 27 Feb 2014

I'm running my DocCode tests with breeze.min.js in Chrome v33 and they all pass. Frustrating. Jay will run his tests with breeze.min.js in Chrome v33 too ... and we will see if any of them fail for him. I am not hopeful.

I get the expected behavior for sensible (including illegal) variations of parm (undefined, null, true, false, a string) on the line from getEntityType that @Matthias mentioned

assertParam(parm, "okIfNotFound").isBoolean().isOptional().check(false);

My static analysis of the code (who trusts that?) tells me that the first comparison operator must remain === whereas the comparison operator in the second clause can be either == or ===. The code author worked hard to make sure that the left operand was never undefined in practice; my static analysis shows that it could become undefined ... although I am unable to arrange the world so that it happens. Maybe a failure of imagination.

My static analysis of the minified code says it is correct although my minified version is different from yours, perhaps because mine is minified against an evolving copy of breeze.debug.js (somewhere closer to what v.1.4.9 will be).

// Reformatted w/ spaces and new lines for readability. 
// Observe that the minifier reversed the direction of the second null test!
// That is smart and does no harm
// I can assure you the pre-minified code is the same as what you folks are reporting.
function m(a,b) {
    if(a._context){
          for(var c=a._context; null!=c.prevContext;) c=c.prevContext;
          if(null === c.prevContext) return c.prevContext=b, a;
          if(null !== b.prevContext)
               throw new Error("Illegal construction - use 'or' to combine checks");
          b.prevContext=a._context
    }
    return n(a,b)
}

Under these trying circumstances, unless we can find a failing test, we'll make a leap of faith, slaughter a chicken, rattle some bones, and change the code to this:

if (curContext.prevContext === null) {
    curContext.prevContext = context;
    // just update the prevContext but don't change the curContext.
    return that;
} else if (context.prevContext == null) {  // CHANGED TO "if null or undefined"
    context.prevContext = that._context;
} else {
    throw new Error("Illegal construction - use 'or' to combine checks");
}

If you can make the time, please try this in your apps and confirm that all is well.

We're shipping v.1.4.9 tomorrow (28 Feb) so please try this pronto!



回答2:

My team has been having this problem too. It started happening about a month ago, but has really increased in frequency over the past 1-2 weeks. Possibly the recent chrome release to blame.

Here is what I know, all commentary relative to breeze 1.4.1:

-The behavior is intermittent, and seemingly occurs at random. To me, this indicates a timing issue.

-The primary browser generating this error is chrome. We also support firefox and IE and have no concrete evidence that any browser but chrome is throwing this error. Perhaps the recent release of chrome has a different performance profile that exacerbates a pre-existing issue (again, timing?)

-For us, turning off bundling and minification seems to eliminate the problem. I don't believe there is an issue with our minified code (Microsoft Web Optimizations) as everything works on other browsers regardless. This to me again indicates a timing issue.

-Finally, I was just able to reproduce it in my dev environment with the chrome developer tools open. Using a q promise stack, and painfully navigating the minified code I was able to narrow it down to this: At my app start, I call fetchMetadata. Within the fetchMetadata success handler, I make a call to metadataStore.getEntityType('some_entity') and it is within this breeze method that the error is being generated in my scenario. Something with the metadata store isn't consistently initialized or setup at this early stage in the pages app lifecycle.

EDIT: From the comments, this appears to be a chrome 33 bug where null !== null at random times. For unknown reasons, the minifying of the breeze.debug.js file seems to be related (most/all reports of the problem are happening on a minified version of breeze). For me, changing the following code in breeze.debug.js:

} else if (context.prevContext === null) {
    context.prevContext = that._context;
} else {
    throw new Error("Illegal construction - use 'or' to combine checks");
}

to:

} else if (context.prevContext == null) {
    context.prevContext = that._context;
} else {
    throw new Error("Illegal construction - use 'or' to combine checks");
}

(change === to == on first line) seems to have resolved the issue as a workaround. All other aspects of breeze are working fine for me after this change.

One other thing I have noticed is that the minified version of the function has an argument with the same name of the function (t). This still doesn't explain the results of the "Aaarg" test.

   function t(n, t) {
        if (n._context) {
            for (var i = n._context; i.prevContext != null; )
                i = i.prevContext;
            if (i.prevContext === null)
                return i.prevContext = t, n;
            if (t.prevContext == null)
                t.prevContext = n._context;
            else
                throw new Error("Illegal construction - use 'or' to combine checks");
        }
        return b(n, t)
    }


回答3:

This started occurring when Chrome updated to version 33. It did not happen in Chrome 32. I downgraded Breeze from version 1.4.8 to version 1.4.7, and this fixed the problem made the problem happen less often.

(The only breaking change listed in the changelog is that contains queries must be escaped in version 1.4.7. So do a word = word.replace(/'/g, "''"); before doing .where("yourColumn", "contains", word))

Edit:

Nope, changing to 1.4.7 did NOT fix this, it just made the problem occur much less often.



回答4:

Ok, we just released Breeze 1.4.9 with Mathias999us's suggested fix. Please let us know whether this fixes the issue ... or not. Thanks Mathias ;)



回答5:

Looking at the code, Breeze is expecting either 'curContext.prevContext' or 'context.prevContext' to be 'null'. One of them has to be 'null' in this check.

The error is thrown when both curContext.prevContext and context.prevContext already are set to a value.



回答6:

For our application, switching to the non-minified (debug) version of breeze 1.4.8 eliminated the error. I cannot say with confidence that this will fix the problem for everyone since I don't know the root cause of the problem or how minification causes the error. Maybe the error can still happen with the non-minified version, but it doesn't in our application.

FWIW: Based on our experience and what I've read from others, the error is characterized in that it:

  • only occurs in the latest version of Chrome (33) -- windows and mac!
  • does not always happen.
  • seems to have a timing aspect. For us it only happens in first few breeze queries after starting the application -- although not necessarily the first query.
  • occurs for every query after the first query that fails.