Why isn't my simple object converting to an Immutable.Map() with Immutable.fromJS({}) - immutable.js

Why isn't my simple object converting to an Immutable.Map() with Immutable.fromJS({})
Here it is with Map() - works as expected
> var mymap = Immutable.Map({test:0})
undefined
> mymap
Map { "test": 0 }
Here it is with .fromJS() - does not work as I expect
> var mymap = Immutable.fromJS({test: 0});
undefined
> mymap
{ test: 0 }
> mymap.set('test', 1)
TypeError: mymap.set is not a function
at repl:1:7
at sigintHandlersWrap (vm.js:32:31)
at sigintHandlersWrap (vm.js:96:12)
at ContextifyScript.Script.runInContext (vm.js:31:12)
at REPLServer.defaultEval (repl.js:308:29)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
at REPLServer.<anonymous> (repl.js:489:10)
at emitOne (events.js:101:20)
at REPLServer.emit (events.js:188:7)
> mymap
{ test: 0 }
> typeof mymap
'object'
Using
Node.js 6.3.0
Immutable.js 3.8.1
Update 8/18/16:
#oluckyman pointed out in a comment that this happens in the console. And as the question shows, that is where I'm seeing it too. I haven't yet tested to see if it happens when running in a node file, but the results from the console don't inspire confidence.

Are you sure you are importing them fine? It should work well.
I just tested and they seem to be working fine. Here is the link to my jsbin

Related

Cannot read property 'environment' of null - ionic native google maps

When running my ionic project with ionic serve -c
Everytime, I get an this error :
ERROR TypeError: Cannot read property 'environment' of null
at Function.Environment.setEnv (index.js:1980)
at HomePage.webpackJsonp.194.HomePage.loadMap (home.ts:98)
at HomePage.webpackJsonp.194.HomePage.ionViewDidLoad (home.ts:45)
at ViewController._lifecycle (view-controller.js:486)
at ViewController._didLoad (view-controller.js:369)
at NavControllerBase._didLoad (nav-controller-base.js:768)
at t.invoke (polyfills.js:3)
at Object.onInvoke (core.js:4760)
at t.invoke (polyfills.js:3)
at r.run (polyfills.js:3)
There is the loadMap method :
loadMap() {
Environment.setEnv({
'API_KEY_FOR_BROWSER_DEBUG' : '',
'API_KEY_FOR_BROWSER_RELEASE' : ''
})
this.geoLocation.getCurrentPosition().then((resp) => {
this.latitude = resp.coords.latitude;
this.longitude = resp.coords.longitude;
console.log(this.latitude);
console.log(this.longitude);
let CurrentPosition : LatLng = new LatLng(this.latitude,this.longitude);
let CameraPosition : CameraPosition<ILatLng> = {
target : CurrentPosition,
zoom : 18
};
this.addMarker();
this.map.moveCamera(CameraPosition);
}).catch((error) => {
console.log('Error getting location', error);
});
this.map = GoogleMaps.create('map_canvas');
}
I don't understand. I only launch my component after the device.isReady() is fired, so it should not be a lifecycle problem.
Do you have any idea as to where does this come from?
Thank you!
EDIT : When using the ionic cordova run browser -l command, the map is loaded without error the first time then on some refresh of the webpage, the error appears again, without me changing anything to the code...
I had the same problem I found the solution on this thread https://stackoverflow.com/a/52681481/6560704
You need to build your platforms to create that 'environment' variable, by using CLI for example :
ionic cordova build browser -l
Hope this will help
Problem solved !
It was in fact a lifecycle problem. I was attributing the HomePage to the rootPage in app.components.ts before the device was ready.

Loading Aurelia breaks Google API

I have created a reproduction of this bug here (ugly use of Aurelia but to prove the point): https://jberggren.github.io/GoogleAureliaBugReproduce/
If I load Google API and try to list my files in Google Drive my code derived from Googles quickstart works fine. If I use the same code after loading Aurelia I get a script error from gapi stating
Uncaught Error: arrayForEach was called with a non array value
at Object._.Sa (cb=gapi.loaded_0:382)
at Object._.eb (cb=gapi.loaded_0:402)
at MF (cb=gapi.loaded_0:723)
at Object.HF (cb=gapi.loaded_0:722)
at Object.list (cb=gapi.loaded_0:40)
at listFiles (index.js:86)
...
When debugging it seems to be some sort of array check (Chroms says 'native code') that failes after Aurelia is loaded. In my search for an answer I found two other people with the same problem but no solution (Aurelia gitter question, SO Question). Don't know if to report this to the Aurelia team, Google or where the actual problem lays.
Help me SO, you are my only hope.
This is not a perfect solution but works.
aurelia-binding
https://github.com/aurelia/binding/blob/master/src/array-observation.js
Aurelia overrides Array.prototype.* for some reasons.
gapi (especially spreadsheets)
Gapi lib checks to make sure that is it native code or not.
// example
const r = /\[native code\]/
r.test(Array.prototype.push)
conclusion
So, we have to monkey patching.
gapi.load('client:auth2', async () => {
await gapi.client.init({
clientId: CLIENT_ID,
discoveryDocs: ['https://sheets.googleapis.com/$discovery/rest?version=v4'],
scope: 'https://www.googleapis.com/auth/spreadsheets',
});
// monkey patch
const originTest = RegExp.prototype.test;
RegExp.prototype.test = function test(v) {
if (typeof v === 'function' && v.toString().includes('__array_observer__.addChangeRecord')) {
return true;
}
return originTest.apply(this, arguments);
};
});

How to capture $compile or $digest error? (AngularJS directive with templateUrl)

I'm writing a unit test of an AngularJS 1.x directive.
If I use "template" it works.
If I use "templateUrl" it does not work (the directive element remains the same original HTML instead of being "compiled").
This is how I create the directive element to test in Jasmine:
function createDirectiveElement() {
scope = $rootScope.$new();
var elementHtml = '<my-directive>my directive</my-directive>';
var element = $compile(elementHtml)(scope);
scope.$digest();
if (element[0].tagName == "my-directive".toUpperCase()) throw Error("Directive is not compiled");
return element;
};
(this does not actually work, see Update for real code)
I'm using this workaround to use the $httpBackend from ngMockE2E (instead of the one in ngMock). In the browser developer "network" tab I don't see any request to the template file. It seems to work because I solved the error "Object # has no method 'passThrough'".
I know that the call to the template is done asynchronously using the $httpBackend (this means $compile exit before the template is really applied).
My question is:
obviously $compile is not doing what I expect. How can I trap this error?
If I use a wrong address in the templateUrl I don't receive any error.
How can I found the problem happened when I called $compile(directive) or scope.$digest() ?
Thanks,
Alex
[Solution]
As suggested by #Corvusoft I inject $exceptionHandler and I check for errors after every test.
In the end this is the only code I have added:
afterEach(inject(function ($exceptionHandler) {
if ($exceptionHandler.errors.length > 0)
throw $exceptionHandler.errors;
}));
Now I can clearly see the errors occurred in the Jasmine test result (instead of search for them in the console), example:
Error: Unexpected request: GET /api/category/list
No more request expected,Error: Unexpected request: GET /api/category/list
No more request expected thrown
And, most important, my tests does not pass in case there are some errors.
[Update to show real example case]
Actually the real code to make templateUrl work use asynchronous beforeEach ("done") and a timeout to wait the end of compile/digest.
My directive use some prividers/services and the template contains other directives which in turn use their templateUrl and make calls to some APIs in the link function().
This is the current (working) test code:
// workaround to have .passThrough() in $httpBackend
beforeEach(angular.mock.http.init); // set $httpBackend to use the ngMockE2E to have the .passThrough()
afterEach(angular.mock.http.reset); // restore the $httpBackend to use ngMock
beforeEach(inject(function (_$compile_, _$rootScope_, _$http_, $httpBackend, $templateCache, $injector) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$http = _$http_;
$httpBackend.whenGET(/\/Scripts of my app\/Angular\/*/).passThrough();
$httpBackend.whenGET(/\/api\/*/).passThrough(); // comment out this to see the errors in Jasmine
}));
afterEach(inject(function ($exceptionHandler) {
if ($exceptionHandler.errors.length > 0)
throw $exceptionHandler.errors;
}));
beforeEach(function(done) {
createDirectiveElementAsync(function (_element_) {
element = _element_;
scope = element.isolateScope();
done();
});
});
function createDirectiveElementAsync(callback) {
var scope = $rootScope.$new();
var elementHtml = '<my-directive>directive</my-directive>';
var element = $compile(elementHtml)(scope);
scope.$digest();
// I haven't found an "event" to know when the compile/digest end
setTimeout(function () {
if (element.tagName == "my-directive".toUpperCase()) throw Error("Directive is not compiled");
callback(element);
}, 0.05*1000); // HACK: change it accordingly to your system/code
};
it("is compiled", function () {
expect(element).toBeDefined();
expect(element.tagName).not.toEqual("my-directive".toUpperCase());
});
I hope this example helps someone else.
$exceptionHandler
Any uncaught exception in AngularJS expressions is delegated to this
service. The default implementation simply delegates to $log.error
which logs it into the browser console.
In unit tests, if angular-mocks.js is loaded, this service is overridden by mock $exceptionHandler which aids in testing.
angular.
module('exceptionOverwrite', []).
factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) {
return function myExceptionHandler(exception, cause) {
logErrorsToBackend(exception, cause);
$log.warn(exception, cause);
};
}]);

JSON.parse(dt) doesn't work at all, give all the errors it can imagine

I have this code at server side (nodejs):
socket.on('data', function(dt){
var rdata = dt;
var msg = JSON.parse(rdata);
broadcast(msg);
});
Also I tried this way: var msg = JSON.parse(dt);
dt gets either:
{"chat":"hey","nickname":"nick_name"} OR
'{"chat":"hey","nickname":"nick_name"}'
Also I have this at the client side (AS3), tried both:
var msg = JSON.stringify({nickname: nname.text, chat: input_txt.text}); OR
var msg = "'" + JSON.stringify({nickname: nname.text, chat: input_txt.text}) + "'";
That is what console gives:
undefined:1
{"chat":"hey","nickname":"nick_name"}
^
SyntaxError: Unexpected token
DEBUG: Program node app exited with code 8
Also in some other situations, it gives all kinds of messages.
Just have no idea what is going on.
BTW, also tried JSONStream, still doesn't work.
What kind of socket exactly are you using? If you are using a websocket you might have already received an object as a response (I think most frameworks do so). If you are using plain net.socket you might be receiving a buffer or the data in chunks and not all at once. This seems like an appropriate fix for that situation:
var buffer;
socket.setEncoding('utf8');
socket.on('data', function(data) {
buffer += data;
});
socket.on('end', function() {
var object = JSON.parse(buffer);
});
Unexpected token at the end of data string, is some ghost symbol that is not a white space. trim() doesn't work, so to substring the last symbor works. This is AS3 symbol, so we have to keep it. First you save this symbol in the new variable. the you erase this symbol from the line. After that you can parse the string. work with it.
undefined:1
{"chat":"hey","nickname":"nick_name"}
^
SyntaxError: Unexpected token
DEBUG: Program node app exited with code 8
When you finish working with it, stringify the object, then add ghost symbol to the end and send over the socket. Without this symbol AS3 will not parse the data.
I don't know why is that, but that works for me.

Ace editor - Uncaught TypeError: Cannot read property 'clientX' of undefined

Im using ace editor and mootools.
I have just updated my mootools to version 1.4.5 and when i click/drag on the editor i get js exception:
Uncaught TypeError: Cannot read property 'clientX' of undefined
Please help... Thanks
Instead of removing the bind method always I think I found a workaround. It seems that only a couple of Mootools builds have this issue. So I use this code to fix them:
if (this.MooTools.build=='ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0') {
delete Function.prototype.bind;
Function.implement({
/*<!ES5-bind>*/
bind: function(that){
var self = this,
args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
F = function(){};
var bound = function(){
var context = that, length = arguments.length;
if (this instanceof bound){
F.prototype = self.prototype;
context = new F;
}
var result = (!args && !length)
? self.call(context)
: self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
return context == that ? result : context;
};
return bound;
},
/*</!ES5-bind>*/
});
}
The benefit is that I can fix it for each build separately. The drawback is clearly to have mootools code shipped with my own code. But currently I see no other option and since I code for Joomla I'm pretty sure that there is a limited number of mootools versions in use.
i solve it for my situation!
i've delete some lines from mootools.js:
1) bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype;
g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;}
2) delete Function.prototype.bind;
(i don't need mouse binding in mootools so it's revelation for me!)
This is a very strange error. During debugging I didn't get the error. But as soon as I removed the breakpoint it appeared again. I finally solved the issue by adding the latest version of mootools 1.4.5 to joomla. The error was immediately gone.