{"action":"created","issue":{"url":"https://api.github.com/repos/js2coffee/js2coffee/issues/301","labels_url":"https://api.github.com/repos/js2coffee/js2coffee/issues/301/labels{/name}","comments_url":"https://api.github.com/repos/js2coffee/js2coffee/issues/301/comments","events_url":"https://api.github.com/repos/js2coffee/js2coffee/issues/301/events","html_url":"https://github.com/js2coffee/js2coffee/issues/301","id":37253276,"number":301,"title":"Be very careful with == undefined","user":{"login":"nickretallack","id":13291,"avatar_url":"https://avatars.githubusercontent.com/u/13291?v=3","gravatar_id":"","url":"https://api.github.com/users/nickretallack","html_url":"https://github.com/nickretallack","followers_url":"https://api.github.com/users/nickretallack/followers","following_url":"https://api.github.com/users/nickretallack/following{/other_user}","gists_url":"https://api.github.com/users/nickretallack/gists{/gist_id}","starred_url":"https://api.github.com/users/nickretallack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nickretallack/subscriptions","organizations_url":"https://api.github.com/users/nickretallack/orgs","repos_url":"https://api.github.com/users/nickretallack/repos","events_url":"https://api.github.com/users/nickretallack/events{/privacy}","received_events_url":"https://api.github.com/users/nickretallack/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":20,"created_at":"2014-07-07T09:39:50Z","updated_at":"2015-01-28T15:26:00Z","closed_at":"2014-08-22T21:21:53Z","body":"I just got a terrible bug due this subtle thing being lost in translation.  I put the file [realtime-client-utils.js](https://developers.google.com/drive/realtime/realtime-quickstart#step_2_set_up_the_sample) through js2coffee.  The place where it gets screwed up is getOption:\r\n\r\n```javascript\r\nrtclient.getOption = function(options, key, defaultValue) {\r\n  var value = options[key] == undefined ? defaultValue : options[key];\r\n  if (value == undefined) {\r\n    console.error(key + ' should be present in the options.');\r\n  }\r\n  console.log(value);\r\n  return value;\r\n}\r\n```\r\n\r\njs2coffee converts this to:\r\n\r\n```coffeescript\r\nrtclient.getOption = (options, key, defaultValue) ->\r\n  value = (if options[key] is `undefined` then defaultValue else options[key])\r\n  console.error key + \" should be present in the options.\"  if value is `undefined`\r\n  console.log value\r\n  value\r\n```\r\n\r\nAnd then the coffeescript compiler turns that into:\r\n\r\n```javascript\r\nrtclient.getOption = function(options, key, defaultValue) {\r\n  var value;\r\n  value = (options[key] === undefined ? defaultValue : options[key]);\r\n  if (value === undefined) {\r\n    console.error(key + \" should be present in the options.\");\r\n  }\r\n  console.log(value);\r\n  return value;\r\n};\r\n```\r\n\r\nNote that `==` has become `===`.  Now if you pass in `options` with a `key` whose value is `null`, like it is for several of the options in the example `index.html`, you won't get the default value like you normally would have, since `null !== undefined`.\r\n\r\nTo fix this problem, I think js2coffee should look for weak comparisons with undefined and output the existential operator `?` instead of the `is` operator.  For example, here's what js2coffee should have generated:\r\n\r\n```coffeescript\r\nrtclient.getOption = (options, key, defaultValue) ->\r\n  value = (if not options[key]? then defaultValue else options[key])\r\n  console.error key + \" should be present in the options.\" if not value?\r\n  console.log value\r\n  value\r\n```\r\n\r\nThis would compile into:\r\n\r\n```javascript\r\n  rtclient.getOption = function(options, key, defaultValue) {\r\n    var value;\r\n    value = (options[key] == null ? defaultValue : options[key]);\r\n    if (value == null) {\r\n      console.error(key + \" should be present in the options.\");\r\n    }\r\n    console.log(value);\r\n    return value;\r\n  };\r\n```\r\n\r\n...which is functionally equivalent to the original code.\r\n"},"comment":{"url":"https://api.github.com/repos/js2coffee/js2coffee/issues/comments/71852783","html_url":"https://github.com/js2coffee/js2coffee/issues/301#issuecomment-71852783","issue_url":"https://api.github.com/repos/js2coffee/js2coffee/issues/301","id":71852783,"user":{"login":"michaelficarra","id":218840,"avatar_url":"https://avatars.githubusercontent.com/u/218840?v=3","gravatar_id":"","url":"https://api.github.com/users/michaelficarra","html_url":"https://github.com/michaelficarra","followers_url":"https://api.github.com/users/michaelficarra/followers","following_url":"https://api.github.com/users/michaelficarra/following{/other_user}","gists_url":"https://api.github.com/users/michaelficarra/gists{/gist_id}","starred_url":"https://api.github.com/users/michaelficarra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaelficarra/subscriptions","organizations_url":"https://api.github.com/users/michaelficarra/orgs","repos_url":"https://api.github.com/users/michaelficarra/repos","events_url":"https://api.github.com/users/michaelficarra/events{/privacy}","received_events_url":"https://api.github.com/users/michaelficarra/received_events","type":"User","site_admin":false},"created_at":"2015-01-28T15:26:00Z","updated_at":"2015-01-28T15:26:00Z","body":"Looks like your demo uncovered a [scoping bug](http://js2.coffee/#try:%28function%20camelize%20%28str%29%20%7B%0A%20%20return%20str.replace%28%2F%5Bs_-%5D%2B%28%5Ba-zA-Z%5D%29%2Fg%2C%0A%20%20%20%20function%20%28_%2C%20l%29%20%7B%0A%20%20%20%20%20%20return%20l.toUpperCase%28%29%0A%20%20%20%20%7D%29%3B%0A%7D%29%20%3D%3D%20%28function%20alsocamelize%28%29%20%7B%0A%20%20return%20alert%28true%2C%202%29%3B%0A%7D%29)."}}