Breeze error: Illegal construction - use 'or' to combine checks - javascript

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.

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)
}

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!

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.

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 ;)

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.

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.

Related

ESLint for Guard Clauses

Is there an ESLint rule to detect if the code can be detected when it's not using guard clauses?
This is related to this post- https://elliotekj.com/2016/12/02/guard-clauses-in-javascript/
for example, this should HAVE a warning:
function doSomething(obj) {
if(obj) {
console.log('I did something');
}
return null;
}
This should have NO warning
function doSomething(obj) {
if(!obj) {
return null;
}
console.log('I did something');
}
I would prefer the latter. Please don't comment on the 'opinionated' aspect of this question. I just want to know if there is an ESLint specific rule or something similar that I can work with.
Or is ESLint even the right tool to detect/correct this kind of code style enforcement?
Thank you.
PS. I did do some research and did not found any rules that related to this my specific need on ESLint Rules. Now, I'm just a newcomer JS developer and would like to know if I miss anything that I should have checked before I go any deeper into writing my own rule.
There is no ESLint rule that will catch that (up to v5.8.0). You provided the source yourself :)
I'm all in for guard clauses but I don't think this is a feature coming anytime soon because it's very context dependent and difficult to correctly identify it on all cases.
A sidenote from looking at your snippet, if you want to follow ESLint best practices, you should be returning a undefined/void instead of null in cases you don't expect a value to be returned (check https://eslint.org/docs/rules/consistent-return#require-return-statements-to-either-always-or-never-specify-values-consistent-return)

CreateJS - Type not recognized error thrown during sound registration

I am trying to load sounds through the SoundJS sound registration, and getting the following error:
createjs.js:15 Uncaught Error: Type not recognized.
I figure that the soundjs library is having issues either locating my files or having trouble with the file extensions, but I am using .ogg, which is inline with all the examples I've seen.
Here is my code:
createjs.Sound.alternateExtensions = ["mp3", "ogg"];
createjs.Sound.on("fileload", function(event) {
console.log(event);
}, this);
for (var i = 0; i < soundManifest.length; i++) {
soundManifest[i].loaded = false;
console.log("loading " + soundManifest[i].src);
createjs.Sound.registerSound(soundManifest[i].src, soundManifest[i].id)
}
soundManifest is an array of objects with a source item giving the path to the .ogg files, and an id. I've double and triple checked the path names, so pretty sure that's not it. Any ideas? I am developing on Chrome.
Thanks for posting a github link. It was helpful. Fortunately, I have a super simple answer for you.
Rename the "Object" class you made in Main.js, and you should be good to go.
-- The long answer --
I tossed a breakpoint the error that is thrown, and it showed that when SoundJS tries to create a LoadItem, it fails. This is because it should be treating the LoadItem it receives as an Object, but the line below is failing:
} else if (value instanceof Object && value.src) {
// This code should be executed
}
At first I thought there was a bug in SoundJS that we had somehow missed in the last 2 years, but closer inspection showed that object prototypes in your application are messed up. If you open any browser window, and hit the console, this will return true:
({}) instanceof Object
// true
However while running your app, it returns false.
The issue became clear when I removed all your other classes other than CreateJS and main, and then tried this:
new Object();
// Throws an error that includes info about "Victor"
In main.js, you are defining an "Object" class, which extends a CreateJS Shape. It is global because there is no method closure around the code, so it overwrites the global Object class/prototype.
The reason I included this explanation, is because I couldn't figure out what was going on until I had my steps to show that prototypes were broken in the app mostly written out before the reason dawned on me. I thought it might be of some interest :)

How to locate bug from clients view for a syntaxerror

I have webpage that uses various libraries and some personal javascript code. I've tested it on my machine and it works.
When I pushed it to production a user informed my that the page was broken. After looking at their console log I see that my page is now throwing a syntaxerror on a generic function that seems to be fine. I can't reproduce it on my machine but it happens on theirs.
I'm assuming its either a different os issue or a x-browser version issue (I'm using Win-8, Chrome they are using Mac, Chrome). I could see how a function would break and it would spit out an error saying it couldn't execute function of undefined. What would be my next step in trying to identify what could be the cause?
The syntaxerror is "Unexpected token ("
Is there some php I can inject into the page to get more info about this error?
var objBillManager = {
...
objBillTableManager:{
...
GetsBillsStatus(bPayed){
if(bPayed == "1"){
return "Payed";
} else {
return "Not Payed";
}
},
...
},
...
}
Without seeing more, it's hard to know what's going on. As someone else mentioned, firebug is a pretty good debugger.
One thing I noticed: your GetsBillsStatus was not defined as a function. It should look like this:
GetsBillsStatus: function(bPayed){
if(bPayed == "1") {
return "Payed";
} else {
return "Not Payed";
}
}
Maybe that's the issue?

How should I mark a method as "obsolete" in JS?

I am refactoring a rather large JS file that contains many unrelated methods into something that will regroup the methods together according to their usage, and renaming some of them as needed (to prevent misleading names).
However, most of the web pages that actually use this code are spread across different code branches, preventing me from doing a simple find&replace. I could do it in all the different branches, but that requires doing maintenance in 30+ branches at the same time, or probably forgetting to perform the renaming once the change is merged in the other branches (by me or other team members).
If this was C#, I could just mark the method with [Obsolete] and it would flag the necessary changes as needed, so I am looking for something somewhat equivalent. I will still provide functionality with the old interface for a while by just redirecting the calls to the new methods, but I'd like to "force" people to switch to the new interface as they work on the pages for other reasons.
Is there any other way to do something similar, besides adding a debugger;
statement and a verbose comment to every method so that it breaks when developing but not in production?
There are a couple of things you can do in a transition period.
Add the #deprecated JSDoc flag.
Add a console warning message that indicates that the function is deprecated.
A sample:
/**
* #deprecated Since version 1.0. Will be deleted in version 3.0. Use bar instead.
*/
function foo() {
console.warn("Calling deprecated function!");
bar();
}
Here's what we've found for Visual Studio 2013 : http://msdn.microsoft.com/en-us/library/vstudio/dn387587.aspx
It's not tested yet as we haven't made the switch, but it looks promising.
In the meantime, I am inserting a flag at page load depending on context such as :
<%
#if DEBUG
Response.Write("<script type=\"text/javascript\"> Flags.Debug = true; </script>");
#endif
%>
and then I call a method that throws an error if the flag is true, or redirect to the new call if it is in release configuration.
function obsolete(oldFunc, newFunc) {
const wrapper = function() {
console.warn(`WARNING! Obsolete function called. Function ${oldFunc.name} has been deprecated, please use the new ${newFunc.name} function instead!`)
newFunc.apply(this, arguments)
}
wrapper.prototype = newFunc.prototype
return wrapper
}

Have you had problems with Dojo 1.7.1 in Internet Explorer 7/8?

I have been working on upgrading an application from dojo 1.4.3 to 1.7.1. Everything is working great in Firefox/Chrome/Safari, but IE7 and IE8 are both failing. The first failure appears to be coming from the code in dojo/ready around line 40.
try{
f();
}
// FIXME: signal the error via require.on
finally{
onLoadRecursiveGuard = 0;
}
Has anyone else noticed problems with this? Is there a work around? Dojo claims it should work in IE 6 - 9, but I have seen other comments that suggest the try/finally will break in IE without the catch. Is this true? Thanks for any insight into this problem ahead of time!
I had this problem and it was because safeMixin was called throughout my code without checking the arguments passed in. safeMixin is 'supposed' to have a valid object passed in as an argument.
This can happen up if you 'new' an object with an empty constructor and then pass the args directly into safeMixin. There are other cases as well.
Here is a bug report.
I had same problem when using JsonRest:
var jr = new JsonRest(); // cause exception
var jr = new JsonRest({}); // it works

Categories