DataTableNode: Added support for fields without CUI. prefix.

--- src/elements/DataTable/DataTableNode.coffee
+++ src/elements/DataTable/DataTableNode.coffee
@@ -38,7 +38,11 @@
 		for f in @__dataTable.getFieldList()
 			fopts = f.getOpts()
 			fopts.undo_support = false
-			_f = new CUI[f.getElementClass()](fopts)
+			if CUI[f.getElementClass()]
+				_f = new CUI[f.getElementClass()](fopts)
+			else
+				_f = new window[f.getElementClass()](fopts)
+
 			_f.setForm(@)
 			_f.setData(@__data)
 			if f.hasData()


Fix scaled image bounding box

Fix scaled image bounding box

--- src/core/shapes.coffee
+++ src/core/shapes.coffee
@@ -122,7 +122,8 @@
     @y = args.y or 0
     @scale = args.scale or 1
     @image = args.image or null
-  getBoundingRect: -> {@x, @y, width: @image.width, height: @image.height, @scale}
+  getBoundingRect: ->
+    {@x, @y, width: @image.width * @scale, height: @image.height * @scale}
   toJSON: -> {@x, @y, imageSrc: @image.src, imageObject: @image, @scale}
   fromJSON: (data) ->
     img = null


Remove some old documentation

Remove some old documentation

--- app/assets/javascripts/embeditor/adapters/embedly.js.coffee
+++ app/assets/javascripts/embeditor/adapters/embedly.js.coffee
@@ -1,8 +1,3 @@
-# This doesn't inherit from Adapters.Oembed because the Embedly plugin
-# handles most of that stuff on its own.
-#
-# Note that the Wrapper element is actually made by the Embedly jQuery plugin,
-# not this one.
 class Embeditor.Adapters.Embedly extends Embeditor.Adapters.Oembed
     className: "Embedly"


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/core_object.coffee
+++ src/core_object.coffee
@@ -157,7 +157,7 @@
             I.included_modules.push moduleName
             self.extend Module(I, self)
         else
-          warn "Unable to discover name for module:"
+          warn "Unable to discover name for module: ", Module
           self.extend Module(I, self)

       return self


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/core_object.coffee
+++ src/core_object.coffee
@@ -144,10 +144,10 @@
     include: (modules...) ->
       for Module in modules
         if Module.isString?()
-          moduleName =
+          moduleName = Module
           Module = Module.constantize()
-
         else
+

         self.extend Module(I, self)


Revert "Revert "Update translations.coffee""

This reverts commit 34eac281c63bdb67b0a2217166a09809aee9a5df.

--- addon/locales/zh-tw/translations.coffee
+++ addon/locales/zh-tw/translations.coffee
@@ -11,7 +11,7 @@
   "language": "繁體中文"
   "loading": "正在加載..."
   "loading_timeout": "需時太久了！點擊可以重新加載"
-  "goodcity.hk" : "GoodCity.HK"
+  "goodcity.hk" : "好人好市.HK"
   "skip_intro" : "跳過簡介"
   "next" : "下一步"
   "prev" : "上一步"
@@ -47,14 +47,14 @@
   "thank_you": "多謝"
   "go_to_top": "回到頁面頂端"
   "input_length_error_message" : "InputWithCounter doesn\'t work without a maxlength attribute'"
-  "loading_timeout_error": "Loading view timeout reached.時限而過"
+  "loading_timeout_error": "讀取時限已過"
   "items_text": "項目"
   "version": "版本"
   "crossroads_foundation": "十字路會"

   "menu":
     "terms": "使用條款"
-    "policy": "個人私隱政策"
+    "policy": "私隱政策"
     "version_short": "版本"

   "day":
@@ -118,7 +118,7 @@
     "unread" : "({{unreadCount}}) 條未讀信息"
     "owner" : "你"
     "today_with_time": "今天, {{time}}"
-    "chat_note": "與審查員討論此項物資"
+    "chat_note": "與審查員討論這項物資狀況"

   "notifications":
     "view": "查看"
@@ -185,8 +185,8 @@
     "missing": "{{name}} 將此物的狀況改為'失蹤'"

   "offer_log":
-    "donor_called": "{{name}} 曾來電"
-    "call_accepted": "{{name}} 接聽來電"
+    "donor_called": "{{name}} 曾經來電"
+    "call_accepted": "{{name}} 接通電話"

   "edit_images":
     "upload": "選擇圖片"
@@ -203,8 +203,8 @@
     "image_uploading": "圖片上載中"
     "remove_image": "移除圖片"
     "cancel_item": "取消項目"
-    "cannot_provide_photo": "沒有照片提供"
-    "last_image_with_item": "此項物資只有一張圖片"
+    "cannot_provide_photo": "未能提供照片"
+    "last_image_with_item": "此為這項物資的唯一圖片"
     "cancelling_item_will_cancel_offer" : "刪除最後一項物品即會刪除此捐獻及已預約的運輸。"

   "plan_delivery":
@@ -304,7 +304,7 @@
   "drop-off":
     "select_schedule": "選擇時間"
     "expect_delivery": "物資大約何時到達？"
-    "find_crossroads": "在Google地圖上尋找十字路會位置"
+    "find_crossroads": "在Google地圖上尋找十字路會"
     "open_new_tab": "將在新視窗打開"
     "arrive_on_time": "煩請於我們的辦公時間內到達，以確保我們能順利接收您的物資。"
     "book_schedule": "預約時間"
@@ -314,10 +314,10 @@
         "show_more": "更多"

   "offer":
-    "disable": "暫停"
-    "closed_by": "{{lastName}} {{firstName}} 封存"
-    "cancelled_by": "{{lastName}} {{firstName}} 取消"
-    "received_by": "{{lastName}} {{firstName}} 接收"
+    "disable": "關閉"
+    "closed_by": "由 {{lastName}} {{firstName}} 關閉"
+    "cancelled_by": "由 {{lastName}} {{firstName}} 取消"
+    "received_by": "由 {{lastName}} {{firstName}} 接收"

   # Components
   "upload-images":
@@ -398,67 +398,67 @@
     "last_updated": "本聲明最後更新日期為2014年8月。"

   "terms":
-    "title": "條款及細則"
-    "info": "GoodCity.hk is part of the Crossroads Foundation network. By using the GoodCity.hk website http://www.goodcity.hk (\"GoodCity Website\") you are agreeing to be bound by these terms of use between you and the Crossroads Foundation and its affiliates (\"Crossroads\", \"us\", \"we\" and \"our\")."
+    "title": "使用條款及細則"
+    "info": "好人好市.hk為十字路會聯網的一部分。使用好人好市.hk網頁http://www.goodcity.hk (\"好人好市網站\")，即表示閣下同意閣下與十字路會及其旗下所屬部門 (\"十字路會\", \"我們\" and \"我們的\")之間的使用條款。"

     "agreement":
-      "title": "Your Agreement"
-      "terms_of_use": "You agree to use the GoodCity Website in accordance with these terms of use."
-      "use_authority": "You agree to use the GoodCity Website only for your personal use. If you are using the GoodCity Website on behalf of a company, partnership, association, government or other organisation, you represent and warrant that you are authorised to do so and that you are authorised to bind your organisation to these terms of use."
-      "lawful_use": "You agree to use the GoodCity Website only for lawful purposes."
-      "security": "You agree not to take any action that might compromise the security of the GoodCity Website, render the GoodCity Website inaccessible to others or otherwise cause damage to the GoodCity Website or its content."
-      "access_attempt": "You agree not to attempt to access any parts of the GoodCity Website that are not intended for you;"
-      "website_rights": "You agree not to use the GoodCity Website in any manner that might interfere with the rights of third parties."
+      "title": "閣下的同意書"
+      "terms_of_use": "閣下同意跟從下列使用條款使用好人好市網站。"
+      "use_authority": "閣下同意僅以個人身份使用好人好市網站。假如閣下代表公司、合作夥伴、聯會、政府或其他機構使用好人好市網頁，閣下必須代表並保證已經得到貴機構之授權，並代表其遵從下列使用條款。"
+      "lawful_use": "閣下同意僅為合法目的使用好人好市網站。"
+      "security": "閣下同意不會採取任何可能損害好人好市網站保安之手段，導致他人無法讀取好人好市網站及其內容，並/或對之造成損害。"
+      "access_attempt": "閣下同意不會企圖讀取好人好市網站上，任何不對閣下開放的內容；"
+      "website_rights": "閣下同意不會以任何可能損害第三方權益的方式使用好人好市網站。"
     "changes":
-      "title": "Changes to these Terms of Use"
-      "info": "We may from time to time issue, revise or add specific instructions, policies and terms applicable to your use of the GoodCity Website and these instructions, policies and terms form part of these terms of use. Please read the GoodCity Website terms of use carefully and come back to review them from time to time. By continuing to use the GoodCity Website after any amendment to the terms of use you are agreeing to these terms of use as amended."
-      "contact_us": "If you have any questions about the GoodCity Website terms of use, please contact us at"
+      "title": "使用條款的更改"
+      "info": "我們或會間中發布、修正或增加有關閣下使用好人好市網站的特定指引、政策及條款，而這些指引、政策及條款為使用條款的一部份。請細閱好人好市網站上的使用條款，並間中重閱。使用條款經過修正後繼續使用好人好市網站，即表示閣下同意經改正後的條款。"
+      "contact_us": "如閣下對好人好市網站上的使用條款有任何疑問，請與我們聯絡"
     "account":
-      "title": "Account Details"
-      "info": "Your GoodCity account name remains our property and we can reclaim and reuse the account name once your account is terminated or deactivated for whatever reason by either you or us. You are responsible for safeguarding any passwords used to access your account and the GoodCity Website. You will promptly notify us at privacy@crossroads.org.hk if you believe that your password or account has been compromised."
+      "title": "帳戶資料"
+      "info": "閣下的帳戶名稱為我們的資產。不論任何原因或肇事者，一旦閣下的帳戶終止使用或遭暫停，我們能夠收回該帳戶名稱，並重新使用。閣下有責任保障登入帳戶及好人好市網站的密碼。假如閣下認為密碼或帳戶遭入侵，必須儘快電郵至privacy@crossroads.org.hk通知我們。"
     "privacy":
-      "title": "Privacy Policy"
-      "info": "Your privacy is very important to us. We have prepared a Personal Information Collection Statement (PICS) which outlines our policies and practices with respect to the personal data you may be asked to provide when registering to receive items through GoodCity.HK."
-      "pics": "The PICS is available to view"
-      "privacy_link": "The full Crossroads privacy policy is available to view"
-      "use": "These policies are incorporated into and form part of these GoodCity Website terms of use."
-      "here": "here"
+      "title": "私隱政策"
+      "info": "我們十分重視閣下的私隱。當閣下登記，經由好人好市接收物資時，我們或回查詢閣下的個人資料，我們已經準備收集個人資料聲名（PICS），詳列我們有關個人資料的私隱政策及執行細節。"
+      "pics": "閣下可以隨時翻閱PICS"
+      "privacy_link": "十字路會完整的私隱政策亦可供查詢"
+      "use": "這些政策為好人好市網站使用條款的一部分。"
+      "here": "這裏"
     "intellectual":
-      "title": "Intellectual Property"
-      "info": "All intellectual property rights in the GoodCity Website (including any future updates, upgrades and new versions) and any connected or related applications, systems and services shall continue to belong to us and our licensors. You have no right to use our intellectual property rights except to the extent expressly permitted by us. In particular, you have no right to use our trade marks or product names, logos, domain names or other distinctive brand features without our prior written consent."
-      "grant": "We grant you a personal, non-exclusive, non-sublicensable, non-transferrable, royalty-free and revocable licence to use the GoodCity Website only in accordance with these terms of use."
-      "unauthorised_access": "You may not copy, modify, reverse engineer or extract any information, source codes or underlying HTML from the GoodCity Website or any connected or related applications, systems or services, except to the extent that we may not prohibit you from doing so under applicable law or you have our prior written consent to do so. You will not use the GoodCity Website in conjunction with any application or other technology that attempts to do any of the foregoing or which otherwise causes the GoodCity Website to operate in an unauthorised manner."
+      "title": "知識產權"
+      "info": "好人好市網站包含的一切知識產權（包括將來一切的資料更新、系統更新及新版本）及任何相聯或相關的程式、系統及服務將一直屬於我們及我們的發牌人。除了在得到我們明確授權外，閣下並無權利使用我們的知識產權。特別指出，如事前未得到我們的書面同意，閣下並無權使用我們的商標或產品名稱，標誌，網域名稱或其他明顯的品牌細節。"
+      "grant": "僅在合乎使用條款的情況下，我們給予閣下使用好人好市網站的使用權利，該使用權利供閣下個人，但不限於閣下一人使用，授權不得二次授權，不得轉讓，並不需專利費用，我們保留撤回的權利。"
+      "unauthorised_access": "除了在現行法例導致我們或不會禁止閣下，或閣下事前得到書面同意的情況下，閣下不能從好人好市網站或任何相聯或相關程式、系統或服務中複製、更改、進行逆向工程或提取任何資料，程式源代碼或基礎HTML。在使用好人好市網站時，閣下不能同時使用任何可能導致或嘗試引致上列或其他令好人好市網站以未經授權的方式運行的程式或其他技術。"

     "content":
-      "title": "Your Content"
-      "info": "When you submit, upload, transmit or display any photographs, data, information, media or other content in connection with your use of the GoodCity Website (“Your Content”), you understand and agree that:"
-      "responsible": "You will continue to own and be responsible for Your Content."
-      "no_sell": "We will not sell Your Content to any third party."
-      "privacy_policy": "Our use of Your Content will be subject to our Privacy Policy."
-      "right_to_use": "You are giving us and our affiliate companies the right to use Your Content (with no fees or charges payable by us to you) to provide our services and for the purposes of promoting, developing and trying to improve our services, including new services that we may provide in the future."
-      "share": "We may share Your Content with third parties that we work with to help provide, promote, develop and improve our services, but these third parties (other than our affiliate companies) will not make any separate use of Your Content for their own purposes (i.e. for any purposes that are not related to our services) and"
-      "suggestions": "Any comments or suggestions you may provide regarding the GoodCity Website are entirely voluntary and we will be free to use such comments and suggestions in our discretion without any obligation to you."
+      "title": "閣下的內容"
+      "info": "當閣下使用好人好市網站時提交、上載、傳輸或展示任何照片、數據、資料、媒介或其他內容（閣下的內容），即表示閣下明白並同意："
+      "responsible": "閣下將繼續擁有閣下的內容，並對其負責。""
+      "no_sell": "我們不會將閣下的內容銷售給第三方。"
+      "privacy_policy": "我們將跟隨我們的私隱政策使用閣下的內容。"
+      "right_to_use": "閣下給予我們及與我們相關的公司使用閣下的內容的權利（我們不須向閣下支付任何費用），用以提供我們的服務，並進行宣傳、發展和改善我們的服務的目的，包括我們於將來新增的服務。"
+      "share": "我們或會向與我們合作的第三方分享閣下的內容，以提供、宣傳、發展及改善我們的服務，但該第三方（非與我們相關的公司）將不會以私人目的單獨使用閣下的內容（意指任何與我們的服務無關的目的），並且"
+      "suggestions": "閣下提供任何有關好人好事網站的意見或建議均屬自願性質，我們將能夠免費使用，而不須向閣下進行任何義務。"
     "warranty":
-      "title": "Warranty and Disclaimer"
-      "info": "We warrant that we will provide the GoodCity Website and the services relating to it using reasonable care and skill. However, apart from this warranty, we make no representation or warranty and give no undertaking in relation to our services, our software or any content submitted, transmitted or displayed by our services, including any representation, warranty or undertaking that the GoodCity Website or any software, content or information provided to you by it will be secure or error-free or that the GoodCity Website will be compatible with your device or any software operating on it or fit for a particular purpose. The GoodCity Website is provided on an “as is” and “as available” basis."
+      "title": "擔保及免責聲明"
+      "info": "我們保證為好人好市網站及其相關服務提供合理保養及技術。然而，除此擔保外，對於我們的服務、軟件或任何已提交、傳輸或展示的內容，我們並不表示或擔保以及承諾會完全安全或不出錯、或好人好市會和閣下使用的裝置或任何安裝在裝置上的軟件兼容，這包括我們服務中，任何在好人好市網站或其他任何軟件、內容或資料中的顯示、擔保或承諾。好人好市網站僅提供現有、可用的版本。"
     "liability":
-      "title": "Liability"
-      "info": "The total aggregate liability of us and our affiliated companies in connection with the GoodCity Website, arising out of any circumstances, shall be limited to USD100."
-      "exclude": "Nothing in these terms of use shall limit or exclude any liability for any loss arising from death or personal injury caused by negligence, for fraudulent misrepresentation or for any other liability, to the extent that any such liability cannot be limited or excluded by law."
-      "indemnify_us": "You agree to indemnify us and hold us harmless against any liability or loss incurred by us arising in connection with your breach of these terms of use."
+      "title": "責任"
+      "info": "無論因為任何情況，好人好市網站及與其相關的公司的整體責任僅限至總計100美元。"
+      "exclude": "使用條款中沒有任何情況可免除任何由疏忽導致的死亡或人身傷害所造成的一切損失，欺詐誤導或任何其他責任均不能受限於或免除法律責任。"
+      "indemnify_us": "假如閣下違反任何使用條款，即閣下同意對我們作出賠償，並不能追究我們因此而造成的任何責任或損失。"

     "policy_to_children":
-      "title": "Our Policy Towards Children"
-      "info": "The GoodCity Website is not intended for use by children. Unfortunately, we cannot always determine the age of users to our site. Please do not use the GoodCity Website if you are under 18 years of age."
+      "title": "對兒童政策"
+      "info": "好人好市網站的使用對象並不包括兒童。然而，我們並無法完全斷定使用者的年齡。假如閣下的年齡為18歲或以下，請勿使用好人好市網站。"

     "general":
-      "title": "General"
-      "info": "These GoodCity Website terms of use are the entire agreement between you and us in relation to the GoodCity Website. You agree that you will have no claim against us for any statement which is not explicitly set out in these terms of use. No delay in enforcing any provision of these terms of use shall be construed to be a waiver of any rights under that provision. Any rights and obligations under these terms of use which by their nature should survive, including but not limited to any obligations in relation to the liability of the respective parties, will remain in effect after termination or expiration of these terms of use."
-      "hk_law": "These terms of use and any dispute or claim arising out of or in connection with them shall be governed by the laws of the Hong Kong Special Administrative Region. All legal proceedings arising out or in connection with these terms of use shall be non-exclusively brought in the courts of the Hong Kong Special Administrative Region."
-      "language": "Where there is any inconsistency between the English and any other language versions of these terms of use, the English language version will prevail."
+      "title": "一般"
+      "info": "這些好人好市網站使用條款完全是閣下和我們之間有關好人好市網站的合約。閣下同意不會就任何並未在這些使用條款中明確列明的條例向我們追究。如使用條款的實施有所延誤，不能將之視為放棄規定下的任何權利。根據其原意，在使用條款遭終止或過期前，使用條款中的任何權利及義務均有效並應得以保存，包括但不限於任何對相關方面責任的義務。"
+      "hk_law": "使用條款及與其相關或衍生的任何紛爭或索償均受香港特別行政區法律的監管。使用條款衍生出的或相關的任何法律程序皆由，並不限於香港特別行政區法院處理。"
+      "language": "如使用條款的英文版本與其他語言版本有出入，皆以英文版本為凖。"

     "contact":
-      "title": "Contact Us"
-      "info": "If you have any questions or concerns regarding the GoodCity Website or these terms of use please contact us at"
+      "title": "聯絡我們"
+      "info": "假如閣下對好人好市網站或這些使用條款有任何問題或疑問，請聯絡我們"

 `export default I18nTranslationsZhTw`


More preprocessor pragmas

More preprocessor pragmas

--- src/haskell.coffee
+++ src/haskell.coffee
@@ -511,7 +511,7 @@
       begin: /\{-#/
       end: /#-\}/
       patterns: [
-          match: /\b(LANGUAGE|UNPACK|INLINE|OPTIONS_GHC)(?!')\b/
+          match: /\b(LANGUAGE|OPTIONS_GHC|INCLUDE|WARNING|DEPRECATED|INLINE|NOINLINE|ANN|LINE|RULES|SPECIALIZE|UNPACK|SOURCE)(?!')\b/
           name: 'keyword.other.preprocessor.haskell'
       ]
     function_type_declaration:


:art: :memo: Add a comment about a probably confusing case

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -224,6 +224,10 @@
     if isPartialMatch
       bindingRemainderContainsOnlyKeyups = false unless bindingKeystroke.startsWith('^')

+  # Bindings that match the beginning of the user's keystrokes are not a match.
+  # e.g. This is not a match. It would have been a match on the previous keystroke:
+  # bindingKeystrokes = ['ctrl-tab', '^tab']
+  # userKeystrokes    = ['ctrl-tab', '^tab', '^ctrl']
   return false if userKeystrokeIndex < userKeystrokes.length - 1

   if isPartialMatch and bindingRemainderContainsOnlyKeyups


s/unknown identifier/undeclared identifier/ in exception message

--- lib/compiler.coffee
+++ lib/compiler.coffee
@@ -426,7 +426,7 @@
                         gname = prop.value

                 if not hasOwn.call @ejs_globals, gname
-                        throw new ReferenceError "unknown identifier `#{gname}' at line #{prop.loc.start.line}"
+                        throw new ReferenceError "undeclared identifier `#{gname}' at line #{prop.loc.start.line}"

                 c = @getAtom gname

@@ -438,7 +438,7 @@
                 gname = prop.name

                 if not hasOwn.call @ejs_globals, gname
-                        throw new ReferenceError "unknown identifier `#{gname}' at line #{prop.loc.start.line}"
+                        throw new ReferenceError "undeclared identifier `#{gname}' at line #{prop.loc.start.line}"

                 if @options.frozen_global
                         return ir.createLoad @ejs_globals[prop.name], "load-#{gname}"
@@ -914,7 +914,7 @@
                 else if is_intrinsic(lhs, "%getGlobal")
                         gname = lhs.arguments[0].name
                         if not hasOwn.call @ejs_globals, gname
-                                throw new ReferenceError "unknown identifier `#{gname}' at line #{lhs.loc.start.line}"
+                                throw new ReferenceError "undeclared identifier `#{gname}' at line #{lhs.loc.start.line}"

                         @createCall @ejs_runtime.global_setprop, [@getAtom(gname), rhvalue], "globalpropstore_#{lhs.arguments[0].name}"
                 else
@@ -1796,7 +1796,7 @@
                 gname = exp.arguments[0].name

                 if not hasOwn.call @ejs_globals, gname
-                        throw new ReferenceError "unknown identifier `#{gname}' at line #{exp.loc.start.line}"
+                        throw new ReferenceError "undeclared identifier `#{gname}' at line #{exp.loc.start.line}"

                 if @options.frozen_global
                         throw new SyntaxError "cannot set global property '#{exp.arguments[0].name}' when using --frozen-global"


Added Model attribute type "date"

Added Model attribute type "date"

--- lib/ST/Model.coffee
+++ lib/ST/Model.coffee
@@ -312,21 +312,10 @@
           test: (test) -> test == value
         }
     }
-
-  @classMethod 'string', (name, defaultValue) ->
-    @attribute name, 'string', defaultValue
-
-  @classMethod 'integer', (name, defaultValue) ->
-    @attribute name, 'integer', defaultValue
-
-  @classMethod 'float', (name, defaultValue) ->
-    @attribute name, 'float', defaultValue
-
-  @classMethod 'boolean', (name, defaultValue) ->
-    @attribute name, 'boolean', defaultValue
-
-  @classMethod 'datetime', (name, defaultValue) ->
-    @attribute name, 'datetime', defaultValue
+
+  for dataType in 'string integer float boolean date datetime'.split(' ')
+    @classMethod dataType, (name, defaultValue) ->
+      @attribute name, dataType, defaultValue

   @classMethod 'belongsTo', (name, assocModel, options={}) ->
     @attribute "#{name}Uuid"


Fix missing param in call to ::installModule

Signed-off-by: Michelle Tilley <19f7a7eb6786def4c39d6d86c40af5dbc6589663@github.com>

--- src/install.coffee
+++ src/install.coffee
@@ -89,7 +89,7 @@
       else
         callback("#{stdout}\n#{stderr}")

-  installModule: (options, pack, modulePath, destination=@atomPackagesDirectory, callback) ->
+  installModule: (options, pack, modulePath, destination, callback) ->
     installArgs = ['--globalconfig', config.getGlobalConfigPath(), '--userconfig', config.getUserConfigPath(), 'install']
     installArgs.push(modulePath)
     installArgs.push("--target=#{@electronVersion}")
@@ -344,7 +344,7 @@
           commands.push (packagePath, callback) =>
             @installNode (error) -> callback(error, packagePath)
         commands.push (packagePath, callback) =>
-          @installModule(options, pack, packagePath, callback)
+          @installModule(options, pack, packagePath, @atomPackagesDirectory, callback)

         async.waterfall commands, (error) =>
           unless installGlobally


Don't recalculate dimensions on stylesheet changes for detached editors

--- src/editor-view.coffee
+++ src/editor-view.coffee
@@ -884,6 +884,8 @@
     @setHeightInLines()

   recalculateDimensions: ->
+    return unless @attached
+
     oldCharWidth = @charWidth
     oldLineHeight = @lineHeight


Update devunity.coffee

Update devunity.coffee

--- lib/devunity.coffee
+++ lib/devunity.coffee
@@ -62,7 +62,7 @@
       @div 'This is your current session details',class:'sendchattext'
       @div 'Session on web',class:'sendchattext'
       @subview 'sessionurl', new TextEditorView(mini: true)
-      @a 'Open in browser', class:'floatright', href: 'http://devunity.com/c/'+codekey,target:"_blank"
+      @a 'Open in browser', class:'floatright', href: 'https://devunity.com/c/'+codekey,target:"_blank"
       @hr
       @div 'Session key',class:'sendchattext'
       @subview 'sessionkey', new TextEditorView(mini: true)
@@ -83,7 +83,7 @@

   show: (codekey) ->
     @sessionkey.setText(codekey)
-    @sessionurl.setText('http://www.devunity.com/c/'+codekey);
+    @sessionurl.setText('https://devunity.com/c/'+codekey);
     @removepanel = atom.workspace.addModalPanel(item:this)
     @sessionkey.focus()

@@ -183,8 +183,8 @@
         class: 'colabdetailsrow'
         =>
           @div '[x] Stop',id: 'stopCollab', class: 'stopcollab pull-right'
-          @div id: 'openvideo', class:'openvideo pull-right',=>
-            @iframe src: 'https://appear.in/devunity_'+@codekey, class:'videoiframe'
+          #@div id: 'openvideo', class:'openvideo pull-right',=>
+          #  @iframe src: 'https://appear.in/devunity_'+@codekey, class:'videoiframe'
           @div '[C] Send chat',id: 'openchat', class:'openchattext pull-right'
           @div '[D] Details',id: 'details', class: 'details pull-right'
           @div id: 'readonly', class: 'readonly pull-right', =>
@@ -196,7 +196,7 @@
             @span 'un',style:'color:#ef4423'
             @span 'ity}'
           @div class: 'pull-left', style:'padding-left:5px;padding-right:5px',=>
-            @a '/ '+@codekey, href: 'http://devunity.com/c/'+@codekey,target:"_blank"
+            @a '/ '+@codekey, href: 'https://devunity.com/c/'+@codekey,target:"_blank"

   show: ->
     statusbar = new StatusBarManager()
@@ -236,7 +236,7 @@
     #Grab a playlist ID and save it.

     $.ajax
-      url:'http://devunity.com/playlist/new',
+      url:'https://devunity.com/playlist/new',
       type:'GET'
       dataType:'json'
       crossDomain: true
@@ -254,7 +254,7 @@
       language = @getLanguage()

       $.ajax
-        url:'http://devunity.com/c/new/'+atom.config.get('devunity.apikey')
+        url:'https://devunity.com/c/new/'+atom.config.get('devunity.apikey')
         type:'POST'
         data:{'code':code,'language':language}
         dataType:'json'
@@ -390,59 +390,59 @@
     comment = ''
     switch fileextension
       when 'py'
-        comment +='\n# Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n# Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='# To end collaboration click Packages > Devunity > stop\n'

       when 'php'
-        comment += '\n// Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment += '\n// Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='// To end collaboration click Packages > Devunity > stop\n'

       when 'html'
-        comment +='\n<!-- Collaboration url: http://devunity.com/c/'+codekey+'-->\n'
+        comment +='\n<!-- Collaboration url: https://devunity.com/c/'+codekey+'-->\n'
         comment +='<!-- To end collaboration click Packages > Devunity > stop\n'

       when 'js'
-        comment +='\n// Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n// Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='// To end collaboration click Packages > Devunity > stop\n'

       when 'javascript'
-        comment +='\n// Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n// Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='// To end collaboration click Packages > Devunity > stop\n'

       when 'coffee'
-        comment +='\n# Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n# Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='# To end collaboration click Packages > Devunity > stop\n'

       when 'c'
-        comment +='\n/* Collaboration url: http://devunity.com/c/'+codekey+' */\n'
+        comment +='\n/* Collaboration url: https://devunity.com/c/'+codekey+' */\n'
         comment +='/* To end collaboration click Packages > Devunity > stop */\n'

       when 'css'
-        comment +='\n/* Collaboration url: http://devunity.com/c/'+codekey+' */\n'
+        comment +='\n/* Collaboration url: https://devunity.com/c/'+codekey+' */\n'
         comment +='/* To end collaboration click Packages > Devunity > stop */\n'

       when 'h'
-        comment +='\n/* Collaboration url: http://devunity.com/c/'+codekey+' */\n'
+        comment +='\n/* Collaboration url: https://devunity.com/c/'+codekey+' */\n'
         comment +='/* To end collaboration click Packages > Devunity > stop */\n'

       when 'jsp'
-        comment +='\n/* Collaboration url: http://devunity.com/c/'+codekey+' */\n'
+        comment +='\n/* Collaboration url: https://devunity.com/c/'+codekey+' */\n'
         comment +='/* To end collaboration click Packages > Devunity > stop */\n'

       when 'txt'
-        comment +='\n# Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n# Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='# To end collaboration click Packages > Devunity > stop */\n'

       when 'pl'
-        comment +='\n# Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n# Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='# To end collaboration click Packages > Devunity > stop\n'

       when 'rc'
-        comment +='\n# Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n# Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='# To end collaboration click Packages > Devunity > stop\n'

       else # default, could also just omit condition or 'if True'
-        comment +='\n# Collaboration url: http://devunity.com/c/'+codekey+'\n'
+        comment +='\n# Collaboration url: https://devunity.com/c/'+codekey+'\n'
         comment +='# To end collaboration click Packages > Devunity > stop\n'
     return comment


engine data module

engine data module

--- src/engine_data.coffee
+++ src/engine_data.coffee
@@ -7,7 +7,7 @@
 @param {Object} I Instance variables
 @param {Object} self Reference to the engine
 ###
-Engine.Data = (I, self) ->
+Engine.Data = (I={}, self) ->
   Object.reverseMerge I,
     data: {}


remove unused import

remove unused import

--- lib/atom-butterfly.coffee
+++ lib/atom-butterfly.coffee
@@ -1,8 +1,3 @@
-rimraf = require 'rimraf'
-fs = require 'fs-plus'
-path = require 'path'
-mkdirp = require 'mkdirp'
-
 remote = require 'remote'
 dialog = remote.require 'dialog'

@@ -62,12 +57,6 @@
         pv.destroy()
         atom.open {pathsToOpen: [destPath]}

-  cmdRunOnServer: ->
-    @runOnServerView = new RunOnServerView()
-    @runOnServerView.attach()
-    @runOnServerView.on 'createServer', (event, rootPath, destPath, httpPort, pushState)=>
-      @debugServer.start(rootPath, destPath, httpPort, pushState)
-
   cmdInstall: ->

     pv = new ProgressView(this)
@@ -80,3 +69,9 @@
       pv.setProgress(progress)
     .on 'finish', ->
       pv.destroy()
+
+  cmdRunOnServer: ->
+    @runOnServerView = new RunOnServerView()
+    @runOnServerView.attach()
+    @runOnServerView.on 'createServer', (event, rootPath, destPath, httpPort, pushState)=>
+      @debugServer.start(rootPath, destPath, httpPort, pushState)


Handle missing/error when deleting avatar from cache

--- lib/atom-io-client.coffee
+++ lib/atom-io-client.coffee
@@ -153,8 +153,9 @@
           writeStream = fs.createWriteStream imagePath
           writeStream.on 'finish', -> callback(null, imagePath)
           writeStream.on 'error', (error) ->
-            writeStream.end()
-            fs.unlinkSync imagePath
+            writeStream.close()
+            try
+              fs.unlinkSync imagePath if fs.existsSync imagePath
             callback(error)
           request(requestObject).pipe(writeStream)


Don't ask request to do JSON parsing for us

--- lib/atom-io-client.coffee
+++ lib/atom-io-client.coffee
@@ -69,19 +69,23 @@
     options = {
       url: "#{@baseURL}#{path}"
       headers: {'User-Agent': navigator.userAgent}
-      json: true
       gzip: true
     }

     request options, (err, res, body) =>
       return callback(err) if err

-      delete body.versions
-      cached =
-        data: body
-        createdOn: Date.now()
-      localStorage.setItem(@cacheKeyForPath(path), JSON.stringify(cached))
-      callback(err, cached.data)
+      try
+        body = JSON.parse(body)
+        delete body.versions
+
+        cached =
+          data: body
+          createdOn: Date.now()
+        localStorage.setItem(@cacheKeyForPath(path), JSON.stringify(cached))
+        callback(err, cached.data)
+      catch error
+        callback(error)

   cacheKeyForPath: (path) ->
     "settings-view:#{path}"
@@ -199,24 +203,25 @@
       url: "#{@baseURL}packages/search"
       headers: {'User-Agent': navigator.userAgent}
       qs: qs
-      json: true
       gzip: true
     }

     new Promise (resolve, reject) ->
       request options, (err, res, body) ->
-        # Interestingly, request does not treat failure to parse JSON as an error
-        # and returns the raw HTML instead as a string.
-        # Therefore, make sure the body has been successfully parsed before
-        # trying to filter package results.
-        if err or typeof body isnt 'object'
+        if err
           error = new Error("Searching for \u201C#{query}\u201D failed.")
-          error.stderr = err?.message ? "Please try again later."
+          error.stderr = err.message
           reject error
         else
-          resolve(
-            body.filter (pkg) -> pkg.releases?.latest?
-                .map ({readme, metadata, downloads, stargazers_count}) ->
-                  Object.assign metadata, {readme, downloads, stargazers_count}
-                .sort (a, b) -> b.downloads - a.downloads
-          )
+          try
+            body = JSON.parse(body)
+            resolve(
+              body.filter (pkg) -> pkg.releases?.latest?
+                  .map ({readme, metadata, downloads, stargazers_count}) ->
+                    Object.assign metadata, {readme, downloads, stargazers_count}
+                  .sort (a, b) -> b.downloads - a.downloads
+            )
+          catch e
+            error = new Error("Searching for \u201C#{query}\u201D failed.")
+            error.stderr = e.message + '\n' + body
+            reject error


Remove old package skeleton.

Remove old package skeleton.

--- lib/atom-repl-view.coffee
+++ lib/atom-repl-view.coffee
@@ -1,26 +0,0 @@
-module.exports =
-class AtomReplView
-  constructor: (serializedState) ->
-    # Create root element
-    @element = document.createElement('div')
-    @element.classList.add('atom-repl')
-
-    # Create message element
-    message = document.createElement('div')
-    message.textContent = "The AtomRepl package is Alive! It's ALIVE!"
-    message.classList.add('message')
-    @element.appendChild(message)
-
-    # @editor = currentPaneItem
-    # @editorView = atom.views.getView(@editor)
-    # @buffer = @editor.getBuffer()
-
-  # Returns an object that can be retrieved when package is activated
-  serialize: ->
-
-  # Tear down any state and detach
-  destroy: ->
-    @element.remove()
-
-  getElement: ->
-    @element


Update grammars.coffee

Update grammars.coffee

--- lib/grammars.coffee
+++ lib/grammars.coffee
@@ -792,7 +792,7 @@
       args: (context) -> ['SQL requires setting \'Script: Run Options\' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information.']
     "File Based":
       command: "echo"
-      args: (context) -> ['SQL requires setting \'Script: Run Options\' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information.']
+      args: (context) -> ['SQL requires setting \'Script: Run Options\' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information.']

   "SQL (PostgreSQL)":
     "Selection Based":


Can now change tab type and tabWidth

Can now change tab type and tabWidth

--- lib/class-complete.coffee
+++ lib/class-complete.coffee
@@ -1,7 +1,7 @@

 module.exports =
+
     activate: ->
-        # atom.workspaceView.command "class-complete:complete", => @complete()
         atom.commands.add "atom-workspace",
             "class-complete:complete": => @complete()

@@ -11,6 +11,16 @@
         cursor = editor.cursors[0]
         text = editor.getSelections()[0].getText()

+        @tabString = "\t";
+        tabLength = atom.config.get("editor.tabLength")
+        if atom.config.get("editor.tabType") == "soft" or atom.config.get("editor.tabType") == "auto"
+            @tabString = ""
+            i = 0
+            while i < 4
+                i++
+                @tabString += " "
+
+
         # Parse classdef to find out what needs to be generated
         classdef = module.exports.parseClassdef(text)

@@ -27,8 +37,8 @@
             # If classdef extends another class, add appropriate code
             if classdef.extends
                 buffer += "\n"
-                buffer += "\t#{classdef.name}.prototype = Object.create(#{classdef.extends}.prototype);\n"
-                buffer += "\t#{classdef.name}.prototype.constructor = #{classdef.name};\n"
+                buffer += "#{@tabString}#{classdef.name}.prototype = Object.create(#{classdef.extends}.prototype);\n"
+                buffer += "#{@tabString}#{classdef.name}.prototype.constructor = #{classdef.name};\n"

             if classdef.methods.length > 0
                 for method in [0..classdef.methods.length - 1]
@@ -39,7 +49,7 @@
                     buffer += module.exports.indent(module.exports.generateMethod(classdef.name, method.name, method.parameters, method.type), 1)

             buffer += "\n"
-            buffer += "\treturn #{classdef.name};"
+            buffer += "#{@tabString}return #{classdef.name};"
             buffer += "\n}());"

         else if classdef.type == "require"
@@ -190,10 +200,10 @@

                 if param.type
                     checks = true
-                    buffer += "\tif (typeof #{param.name} !== \"#{param.type}\") throw new Error(\"Parameter '#{param.name}' expects to be type '#{param.type}'\");\n"
+                    buffer += "#{@tabString}if (typeof #{param.name} !== \"#{param.type}\") throw new Error(\"Parameter '#{param.name}' expects to be type '#{param.type}'\");\n"
                 if param.instance
                     checks = true
-                    buffer += "\tif (!(#{param.name} instanceof #{param.instance})) throw new Error(\"Parameter '#{param.name}' expects to be instance of '#{param.instance}'\");\n"
+                    buffer += "#{@tabString}if (!(#{param.name} instanceof #{param.instance})) throw new Error(\"Parameter '#{param.name}' expects to be instance of '#{param.instance}'\");\n"

         if parameters.length > 0 && members
@@ -201,13 +211,13 @@
             for param in [0..parameters.length - 1]
                 param = parameters[param]
                 if param.member
-                    buffer += "\tthis.#{param.name} = #{param.name};\n"
+                    buffer += "#{@tabString}this.#{param.name} = #{param.name};\n"

         if body.after
             buffer += "\n" if checks || members
             buffer += "#{module.exports.indent(body.after, 1)}"

-        buffer += "};"
+        buffer += "}"

         return buffer

@@ -216,7 +226,7 @@
         lines = text.split(/\n|\r\n/)

         prefix = ""
-        prefix += "\t" for i in [0..indent - 1]
+        prefix += "#{@tabString}" for i in [0..indent - 1]

         for line in lines
             buffer += prefix + line + "\n"


Dump error in CommandRunner.getEnv

Dump error in CommandRunner.getEnv

--- lib/command-runner.coffee
+++ lib/command-runner.coffee
@@ -66,6 +66,7 @@
   @getEnv: (callback) ->
     if @_cachedEnv == undefined
       @fetchEnvOfLoginShell (error, env) =>
+        console.log(error.stack) if error?
         env ?= {}
         @_cachedEnv = @mergePathEnvs(env, process.env)
         @_cachedEnv['HOME'] = process.env.HOME


make async_map a private method

make async_map a private method


Add logging for debug

Add logging for debug

--- src/app/app.coffee
+++ src/app/app.coffee
@@ -50,6 +50,9 @@

   @info("Rubic/%s %s", @version, window?.navigator.userAgent)

+  # Object disclosure for debugging
+  @log("Application: %o", App)
+
   ###*
   @static
   @method


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/flickerable.coffee
+++ src/flickerable.coffee
@@ -48,7 +48,7 @@
   @param {Number} [frequency=3] The number of frames in between opacity changes
   @param {Number} [alpha=0.5] The alpha value to flicker to
   ###
-  flicker: (duration = 30, frequency = 3, alpha = 0.5) ->
+  flicker: ({duration = 30, frequency = 3, alpha = 0.5}) ->
     I.flickerDuration = duration
     I.flickerFrequency = frequency
     I.flickerAlpha = alpha


fix comparisons now that %EjsValueType is {i64} instead of just i64.  also, visit all arguments before emitting the stores to our scratch area, or else we might clobber earlier args

--- lib/compiler.coffee
+++ lib/compiler.coffee
@@ -313,74 +313,39 @@
                 rv

         loadBoolEjsValue: (n) ->
+                name = if n then "true" else "false"
+                bool_alloca = @createAlloca @currentFunction, types.EjsValue, "#{name}_alloca"
+                alloca_as_int64 = ir.createBitCast bool_alloca, types.int64.pointerTo(), "alloca_as_pointer"
                 if @options.target_pointer_size is 64
-                        name = if n then "true" else "false"
-                        bool_alloca = @createAlloca @currentFunction, types.EjsValue, "#{name}_alloca"
-                        alloca_as_int64 = ir.createBitCast bool_alloca, types.int64.pointerTo(), "alloca_as_pointer"
                         ir.createStore consts.int64_lowhi(0xfff98000, if n then 0x00000001 else 0x000000000), alloca_as_int64
-                        ir.createLoad bool_alloca, "#{name}_load"
-                else
-                        # fixme verify this
-                        bool_alloca = @createAlloca @currentFunction, types.EjsValue, "bool_alloca"
-                        alloca_as_int64 = ir.createBitCast bool_alloca, types.int64.pointerTo(), "alloca_as_pointer"
+                else
                         ir.createStore consts.int64_lowhi(0xffffff83, if n then 0x00000001 else 0x00000000), alloca_as_int64
-                        ir.createLoad bool_alloca, "bool_load"
+                ir.createLoad bool_alloca, "#{name}_load"

         loadDoubleEjsValue: (n) ->
-                if @opencode_intrinsics.numberNew
-                        c = llvm.ConstantFP.getDouble n
-                        num_alloca = @createAlloca @currentFunction, types.EjsValue, "num_alloca"
-                        alloca_as_double = ir.createBitCast num_alloca, types.double.pointerTo(), "alloca_as_pointer"
-                        ir.createStore c, alloca_as_double
-                        return ir.createLoad num_alloca, "numload"
-                else
-                        literal_key = "num-" + n
-                        if @currentFunction.literalAllocas[literal_key]
-                                num_alloca = @currentFunction.literalAllocas[literal_key]
-                        else
-                                # only create 1 instance of num literals used in a function, and allocate them in the entry block
-                                @doInsideBBlock @currentFunction.entry_bb, =>
-                                        num_alloca = ir.createAlloca types.EjsValue, "num-alloca-#{n}"
-                                        c = llvm.ConstantFP.getDouble n
-                                        val = @createCall @ejs_runtime.number_new, [c], "numconst-#{n}", !@ejs_runtime.number_new.doesNotThrow
-                                        ir.createStore val, num_alloca
-                                        @currentFunction.literalAllocas[literal_key] = num_alloca
-                        numload = @createLoad num_alloca, "%num_alloca"
-                        numload.literal = n
-                        debug.log -> "numload = #{numload}"
-                        return numload
+                c = llvm.ConstantFP.getDouble n
+                num_alloca = @createAlloca @currentFunction, types.EjsValue, "num_alloca"
+                alloca_as_double = ir.createBitCast num_alloca, types.double.pointerTo(), "alloca_as_pointer"
+                ir.createStore c, alloca_as_double
+                ir.createLoad num_alloca, "numload"

         loadNullEjsValue: ->
+                null_alloca = @createAlloca @currentFunction, types.EjsValue, "null_alloca"
+                alloca_as_int64 = ir.createBitCast null_alloca, types.int64.pointerTo(), "alloca_as_pointer"
                 if @options.target_pointer_size is 64
-                        @currentAllocas.null = @createAlloca @currentFunction, types.EjsValue, "null_alloca" unless @currentAllocas.null?
-                        alloca_as_int64 = ir.createBitCast @currentAllocas.null, types.int64.pointerTo(), "alloca_as_pointer"
                         ir.createStore consts.int64_lowhi(0xfffb8000, 0x00000000), alloca_as_int64
-                        ir.createLoad @currentAllocas.null, "nullload"
-                else
-                        ###
-                        # fixme verify this
-                        @currentAllocas.num = @createAlloca @currentFunction, types.EjsValue, "num_alloca" unless @currentAllocas.num?
-                        alloca_as_int64 = ir.createBitCast @currentAllocas.num, types.int64.pointerTo(), "alloca_as_pointer"
+                else # 32 bit
                         ir.createStore consts.int64_lowhi(0xffffff87, 0x00000000), alloca_as_int64
-                        ir.createLoad @currentAllocas.num, "numload"
-                        ###
-                        return ir.createLoad @ejs_runtime['null'], "null_load"
+                ir.createLoad null_alloca, "nullload"

         loadUndefinedEjsValue: ->
+                undef_alloca = @createAlloca @currentFunction, types.EjsValue, "undef_alloca"
+                alloca_as_int64 = ir.createBitCast undef_alloca, types.int64.pointerTo(), "alloca_as_pointer"
                 if @options.target_pointer_size is 64
-                        @currentAllocas.undef = @createAlloca @currentFunction, types.EjsValue, "undef_alloca" unless @currentAllocas.undef?
-                        alloca_as_int64 = ir.createBitCast @currentAllocas.undef, types.int64.pointerTo(), "alloca_as_pointer"
                         ir.createStore consts.int64_lowhi(0xfff90000, 0x00000000), alloca_as_int64
-                        ir.createLoad @currentAllocas.undef, "undefload"
-                else
-                        ###
-                        # fixme verify this
-                        @currentAllocas.num = @createAlloca @currentFunction, types.EjsValue, "num_alloca" unless @currentAllocas.num?
-                        alloca_as_int64 = ir.createBitCast @currentAllocas.num, types.int64.pointerTo(), "alloca_as_pointer"
+                else # 32 bit
                         ir.createStore consts.int64_lowhi(0xffffff82, 0x00000000), alloca_as_int64
-                        ir.createLoad @currentAllocas.num, "numload"
-                        ###
-                        return ir.createLoad @ejs_runtime['undefined'], "undefined_load"
+                ir.createLoad undef_alloca, "undefload"

         storeGlobal: (prop, value) ->
                 # we store obj.prop, prop is an id
@@ -566,7 +531,7 @@
                                 discTest = @createCall eqop, [discr, test], "test", !eqop.doesNotThrow

                                 if discTest._ejs_returns_ejsval_bool
-                                        disc_cmp = @createEjsValueCmpEQ discTest, @loadBoolEjsValue(false)
+                                        disc_cmp = @createEjsValueCmpEq discTest, @loadBoolEjsValue(false)
                                 else
                                         disc_truthy = @createCall @ejs_runtime.truthy, [discTest], "disc_truthy"
                                         disc_cmp = ir.createICmpEq disc_truthy, consts.false(), "disccmpresult"
@@ -605,7 +570,7 @@
         visitContinue: (n) ->
                 return ExitableScope.scopeStack.exitFore n.label?.name

-        createEjsValueCmpEQ: (x, y) ->
+        createEjsvalCmpEq: (x, y) ->
                 x_alloc = @createAlloca @currentFunction, types.EjsValue, "x_alloca"
                 ir.createStore x, x_alloc
                 x_ptr = ir.createBitCast x_alloc, types.int64.pointerTo(), "x_ptr"
@@ -621,7 +586,7 @@
         generateCondBr: (exp, then_bb, else_bb) ->
                 exp_value = @visit exp
                 if exp_value._ejs_returns_ejsval_bool
-                        cmp = @createEjsValueCmpEQ exp_value, (@loadBoolEjsValue false), "cmpresult"
+                        cmp = @createEjsvalCmpEq exp_value, (@loadBoolEjsValue false), "cmpresult"
                 else
                         cond_truthy = @createCall @ejs_runtime.truthy, [exp_value], "cond_truthy"
                         cmp = ir.createICmpEq cond_truthy, consts.false(), "cmpresult"
@@ -936,7 +901,6 @@
                 #debug.log -> "param #{param.llvm_type} #{param.name}" for param in n.formal_params

                 @currentFunction = ir_func
-                @currentAllocas = {}

                 # Create a new basic block to start insertion into.
                 entry_bb = new llvm.BasicBlock "entry", ir_func
@@ -988,7 +952,7 @@
                 body_bb = new llvm.BasicBlock "body", ir_func
                 ir.setInsertPoint body_bb

-                @createCall @ejs_runtime.log, [consts.string(ir, "entering #{n.ir_name}")], ""
+                #@createCall @ejs_runtime.log, [consts.string(ir, "entering #{n.ir_name}")], ""

                 if n.toplevel?
                         ir.createCall @literalInitializationFunction, [], ""
@@ -1005,14 +969,14 @@
                                 else_bb  = new llvm.BasicBlock "arg_else", insertFunc
                                 merge_bb = new llvm.BasicBlock "arg_merge", insertFunc

-                                cmp = ir.createICmpSGt load_argc, (consts.int32 i), "argcmpresult"
+                                cmp = ir.createICmpSGt load_argc, consts.int32(i), "argcmpresult"
                                 ir.createCondBr cmp, then_bb, else_bb

                                 ir.setInsertPoint then_bb
                                 # in the then branch, the argument was
                                 # provided, pull the value out of the
                                 # args array
-                                arg_ptr = ir.createGetElementPointer args_load, [(consts.int32 i)], "arg#{i}_ptr"
+                                arg_ptr = ir.createGetElementPointer args_load, [consts.int32(i)], "arg#{i}_ptr"
                                 arg = @createLoad arg_ptr, "arg#{i}_load"
                                 store = ir.createStore arg, allocas[first_formal_index+i]
                                 ir.createBr merge_bb
@@ -1023,7 +987,7 @@
                                 # default value, evaluate that here
                                 # and store it in the alloca.
                                 if n.defaults[i]?
-                                        arg_ptr = ir.createGetElementPointer args_load, [(consts.int32 i)], "arg#{i}_ptr"
+                                        arg_ptr = ir.createGetElementPointer args_load, [consts.int32(i)], "arg#{i}_ptr"
                                         arg = @visit n.defaults[i], "arg#{i}_default_value"
                                         ir.createStore arg, allocas[first_formal_index+i]
                                 ir.createBr merge_bb
@@ -1039,14 +1003,14 @@

                         load_argc = @createLoad @currentFunction.topScope.get("%argc"), "argc_load"

-                        cmp = ir.createICmpSGt load_argc, (consts.int32 n.formal_params.length), "argcmpresult"
+                        cmp = ir.createICmpSGt load_argc, consts.int32(n.formal_params.length), "argcmpresult"
                         ir.createCondBr cmp, has_rest_bb, no_rest_bb

                         ir.setInsertPoint has_rest_bb
                         # we have > args than are declared, shove the rest into the rest parameter
                         load_args = @createLoad @currentFunction.topScope.get("%args"), "args_load"
-                        gep = ir.createInBoundsGetElementPointer load_args, [(consts.int32 n.formal_params.length)], "rest_arg_gep"
-                        load_argc = ir.createNswSub load_argc, (consts.int32 n.formal_params.length)
+                        gep = ir.createInBoundsGetElementPointer load_args, [consts.int32(n.formal_params.length)], "rest_arg_gep"
+                        load_argc = ir.createNswSub load_argc, consts.int32(n.formal_params.length)
                         rest_value = @createCall @ejs_runtime.array_new_copy, [load_argc, gep], "argstmp", !@ejs_runtime.array_new_copy.doesNotThrow
                         ir.createStore rest_value, rest_alloca
                         ir.createBr rest_merge_bb
@@ -1078,7 +1042,6 @@
                 ir.createBr body_bb

                 @currentFunction = null
-                @currentAllocas = {}

                 ir.setInsertPoint insertBlock

@@ -1110,7 +1073,7 @@
                 else if n.operator is "!"
                         arg_value =  @visitOrNull n.argument
                         if @opencode_intrinsics.unaryNot and @options.target_pointer_size is 64 and arg_value._ejs_returns_ejsval_bool
-                                cmp = ir.createICmpEq arg_value, @loadBoolEjsValue(true), "cmpresult"
+                                cmp = @createEjsvalCmpEq arg_value, @loadBoolEjsValue(true), "cmpresult"
                                 rv = ir.createSelect cmp, @loadBoolEjsValue(false), @loadBoolEjsValue(true), "sel"
                                 rv._ejs_returns_ejsval_bool = true
                                 rv
@@ -1137,7 +1100,7 @@
                 right_visited = @visit n.right

                 if @options.record_types
-                        @createCall @ejs_runtime.record_binop, [(consts.int32 @genRecordId()), (consts.string ir, n.operator), left_visited, right_visited], ""
+                        @createCall @ejs_runtime.record_binop, [consts.int32(@genRecordId()), consts.string(ir, n.operator), left_visited, right_visited], ""

                 # call the actual runtime binaryop method
                 rv = @createCall callee, [left_visited, right_visited], "result_#{n.operator}", !callee.doesNotThrow
@@ -1203,11 +1166,13 @@
                         argv.push consts.int32 args.length    # %argc

                         if args.length > 0
+                                visited = (@visitOrNull(a) for a in args)
+
                                 args.forEach (a,i) =>
-                                        gep = ir.createGetElementPointer @currentFunction.scratch_area, [(consts.int32 0), (consts.int64 i)], "arg_gep_#{i}"
-                                        store = ir.createStore @visitOrNull(args[i]), gep, "argv[#{i}]-store"
-
-                                argsCast = ir.createGetElementPointer @currentFunction.scratch_area, [(consts.int32 0), (consts.int64 0)], "call_args_load"
+                                        gep = ir.createGetElementPointer @currentFunction.scratch_area, [consts.int32(0), consts.int64(i)], "arg_gep_#{i}"
+                                        store = ir.createStore visited[i], gep, "argv[#{i}]-store"
+
+                                argsCast = ir.createGetElementPointer @currentFunction.scratch_area, [consts.int32(0), consts.int64(0)], "call_args_load"

                                 argv.push argsCast
                         else
@@ -1237,11 +1202,13 @@
                 argv.push consts.int32 args.length                                  # %argc

                 if args.length > 0
-                        argv.forEach (a,i) =>
-                                gep = ir.createGetElementPointer @currentFunction.scratch_area, [(consts.int32 0), (consts.int64 i)], "arg_gep_#{i}"
-                                store = ir.createStore @visitOrNull(args[i]), gep, "argv[#{i}]-store"
-
-                        argsCast = ir.createGetElementPointer @currentFunction.scratch_area, [(consts.int32 0), (consts.int64 0)], "call_args_load"
+                        visited = (@visitOrNull(a) for a in args)
+
+                        visited.forEach (a,i) =>
+                                gep = ir.createGetElementPointer @currentFunction.scratch_area, [consts.int32(0), consts.int64(i)], "arg_gep_#{i}"
+                                store = ir.createStore visited[i], gep, "argv[#{i}]-store"
+
+                        argsCast = ir.createGetElementPointer @currentFunction.scratch_area, [consts.int32(0), consts.int64(0)], "call_args_load"

                         argv.push argsCast
                 else
@@ -1277,7 +1244,7 @@

         visitThisExpression: (n) ->
                 debug.log "visitThisExpression"
-                @createLoad (@findIdentifierInScope "%this"), "load_this"
+                @createLoad @findIdentifierInScope("%this"), "load_this"

         visitIdentifier: (n) ->
                 debug.log -> "identifier #{n.name}"
@@ -1326,7 +1293,7 @@
                         val = @visit property.value
                         key = if property.key.type is _Identifier then @getAtom property.key.name else @visit property.key

-                        @createCall @ejs_runtime.object_define_value_prop, [obj, key, val, consts.int32 0x77], "define_value_prop_#{property.key}"
+                        @createCall @ejs_runtime.object_define_value_prop, [obj, key, val, consts.int32 0x77], "define_value_prop_#{property.key.name}"
                 obj

         visitArrayExpression: (n) ->
@@ -1375,15 +1342,15 @@
                 arg0 = strname
                 arg1 = val
                 arg2 = primstr
-                arg3 = ir.createInBoundsGetElementPointer ucs2, [(consts.int32 0), (consts.int32 0)], "ucs2"
-
-                ir.createCall @ejs_runtime.init_string_literal, [arg0, arg1, arg2, arg3, consts.int32 len], ""
+                arg3 = ir.createInBoundsGetElementPointer ucs2, [consts.int32(0), consts.int32(0)], "ucs2"
+
+                ir.createCall @ejs_runtime.init_string_literal, [arg0, arg1, arg2, arg3, consts.int32(len)], ""
                 ir.setInsertPoint saved_insert_point

         getAtom: (str) ->
                 # check if it's an atom (a runtime library constant) first of all
                 if hasOwn.call @ejs_atoms, str
-                        return @createLoad @ejs_atoms[str], "%str_atom_load"
+                        return @createLoad @ejs_atoms[str], "#{str}_atom_load"

                 # XXX we need to prepend the 'atom-' here because str could be === '__proto__' which fouls up our lookup.
                 #     this can be fixed when we support ES6 Maps (@module_atoms would be a map).
@@ -1567,19 +1534,19 @@
                                         @doInsideBBlock return_tramp, =>

                                                 if @finallyStack.length > 0
-                                                        ir.createStore (consts.int32 ExitableScope.REASON_RETURN), @currentFunction.cleanup_reason
+                                                        ir.createStore consts.int32(ExitableScope.REASON_RETURN), @currentFunction.cleanup_reason
                                                         ir.createBr @finallyStack[0]
                                                 else
                                                         @createRet @createLoad @currentFunction.returnValueAlloca, "rv"

                                 switch_stmt = ir.createSwitch cleanup_reason, merge_block, scope.destinations.length + 1
                                 if @currentFunction.returnValueAlloca?
-                                        switch_stmt.addCase (consts.int32 ExitableScope.REASON_RETURN), return_tramp
+                                        switch_stmt.addCase consts.int32(ExitableScope.REASON_RETURN), return_tramp

                                 falloff_tramp = new llvm.BasicBlock "falloff_tramp", insertFunc
                                 @doInsideBBlock falloff_tramp, =>
                                         ir.createBr merge_block
-                                switch_stmt.addCase (consts.int32 TryExitableScope.REASON_FALLOFF_TRY), falloff_tramp
+                                switch_stmt.addCase consts.int32(TryExitableScope.REASON_FALLOFF_TRY), falloff_tramp

                                 for s in [0...scope.destinations.length]
                                         dest_tramp = new llvm.BasicBlock "dest_tramp", insertFunc
@@ -1646,9 +1613,7 @@
         # this method assumes it's called in an opencoded context
         emitEjsvalTo: (val, type, prefix) ->
                 if @options.target_pointer_size is 64
-                        #  %1 = and i64 %val, 140737488355327
-                        #  %2 = inttoptr i64 %1 to %struct._EJSObject*
-                        payload = ir.createAnd val, (consts.int64_lowhi 0x7fff, 0xffffffff), "#{prefix}_payload"
+                        payload = @createEjsvalAnd val, consts.int64_lowhi(0x7fff, 0xffffffff), "#{prefix}_payload"
                         ir.createIntToPtr payload, type, "#{prefix}_load"
                 else
                         throw new Error "emitEjsvalTo not implemented for this case"
@@ -1659,19 +1624,19 @@
                 if @options.target_pointer_size is 64
                         # %1 = getelementptr inbounds %struct._EJSObject* %obj, i64 0, i32 1
                         # %specops_load = load %struct.EJSSpecOps** %1, align 8, !tbaa !0
-                        specops_slot = ir.createInBoundsGetElementPointer obj, [(consts.int64 0), (consts.int32 1)], "specops_slot"
+                        specops_slot = ir.createInBoundsGetElementPointer obj, [consts.int64(0), consts.int32(1)], "specops_slot"
                         ir.createLoad specops_slot, "specops_load"
                 else
                         throw new Error "emitLoadSpecops not implemented for this case"

         emitThrowNativeError: (errorCode, errorMessage) ->
-                @createCall @ejs_runtime.throw_nativeerror_utf8, [(consts.int32 errorCode), (consts.string ir, errorMessage)], "", true
+                @createCall @ejs_runtime.throw_nativeerror_utf8, [consts.int32(errorCode), consts.string(ir, errorMessage)], "", true
                 ir.createUnreachable()

         # this method assumes it's called in an opencoded context
         emitLoadEjsFunctionIsBound: (closure) ->
                 if @options.target_pointer_size is 64
-                        bound_slot_gep = ir.createInBoundsGetElementPointer closure, [(consts.int64 1), (consts.int32 2)], "bound_slot_gep"
+                        bound_slot_gep = ir.createInBoundsGetElementPointer closure, [consts.int64(1), consts.int32(2)], "bound_slot_gep"
                         bound_slot = ir.createBitCast bound_slot_gep, types.int32.pointerTo(), "bound_slot"
                         ir.createLoad bound_slot, "bound_load"
                 else
@@ -1680,7 +1645,7 @@
         # this method assumes it's called in an opencoded context
         emitLoadEjsFunctionClosureFunc: (closure) ->
                 if @options.target_pointer_size is 64
-                        func_slot_gep = ir.createInBoundsGetElementPointer closure, [consts.int64 1], "func_slot_gep"
+                        func_slot_gep = ir.createInBoundsGetElementPointer closure, [consts.int64(1)], "func_slot_gep"
                         func_slot = ir.createBitCast func_slot_gep, types.EjsClosureFunc.pointerTo(), "func_slot"
                         ir.createLoad func_slot, "func_load"
                 else
@@ -1689,7 +1654,7 @@
         # this method assumes it's called in an opencoded context
         emitLoadEjsFunctionClosureEnv: (closure) ->
                 if @options.target_pointer_size is 64
-                        env_slot_gep = ir.createInBoundsGetElementPointer closure, [(consts.int64 1),(consts.int32 1)], "env_slot_gep"
+                        env_slot_gep = ir.createInBoundsGetElementPointer closure, [consts.int64(1), consts.int32(1)], "env_slot_gep"
                         env_slot = ir.createBitCast env_slot_gep, types.EjsValue.pointerTo(), "env_slot"
                         ir.createLoad env_slot, "env_load"
                 else
@@ -1713,7 +1678,7 @@
                         invoke_merge_bb = new llvm.BasicBlock "invoke_merge_bb", insertFunc

                         candidate = argv[0]
-                        cmp = ir.createICmpUGt candidate, (consts.int64_lowhi 0xfffbffff, 0xffffffff), "cmpresult"
+                        cmp = @createEjsvalICmpUGt candidate, consts.int64_lowhi(0xfffbffff, 0xffffffff), "cmpresult"
                         ir.createCondBr cmp, candidate_is_object_bb, object_isnt_function_bb

                         @doInsideBBlock object_isnt_function_bb, =>
@@ -1739,7 +1704,7 @@

                                         load_isbound = @emitLoadEjsFunctionIsBound closure

-                                        cmp = ir.createICmpEq load_isbound, (consts.int32 0), "notbound?"
+                                        cmp = ir.createICmpEq load_isbound, consts.int32(0), "notbound?"
                                         ir.createCondBr cmp, direct_invoke_bb, runtime_invoke_bb

                                         @doInsideBBlock runtime_invoke_bb, =>
@@ -1766,16 +1731,16 @@
                 # otherwise we return argv[0]

                 if opencode and @options.target_pointer_size is 64
-                        cmp = ir.createICmpUGt call_result, (consts.int64_lowhi 0xfffbffff, 0xffffffff), "cmpresult"
+                        cmp = @createEjsvalICmpUGt call_result, consts.int64_lowhi(0xfffbffff, 0xffffffff), "cmpresult"
                 else
                         call_result_is_object = @createCall @ejs_runtime.typeof_is_object, [call_result], "call_result_is_object", false
                         if call_result_is_object._ejs_returns_ejsval_bool
-                                cmp = @createEjsValueCmpEQ call_result_is_object, (@loadBoolEjsValue true), "cmpresult"
+                                cmp = @createEjsvalCmpEq call_result_is_object, (@loadBoolEjsValue true), "cmpresult"
                         else
                                 cond_truthy = @createCall @ejs_runtime.truthy, [call_result_is_object], "cond_truthy"
                                 cmp = ir.createICmpEq cond_truthy, consts.true(), "cmpresult"
-
-                return ir.createSelect cmp, call_result, argv[2], "sel"
+
+                return ir.createSelect cmp, call_result, argv[@abi.this_param_index], "sel"

         handleMakeClosure: (exp, opencode) ->
@@ -1822,19 +1787,33 @@

                 if opencode and @options.target_pointer_size is 64
                         envp = @emitEjsvalTo env, types.EjsClosureEnv.pointerTo(), "closureenv"
-                        ir.createInBoundsGetElementPointer envp, [(consts.int64 0), (consts.int32 2), (consts.int64 slotnum), (consts.int32 0)], "slot_ref"
-                else
-                        @createCall @ejs_runtime.get_env_slot_ref, [env, (consts.int32 slotnum)], "slot_ref_tmp", false
+                        ir.createInBoundsGetElementPointer envp, [consts.int64(0), consts.int32(2), consts.int64(slotnum)], "slot_ref"
+                else
+                        @createCall @ejs_runtime.get_env_slot_ref, [env, consts.int32(slotnum)], "slot_ref_tmp", false

         createEjsBoolSelect: (val) ->
                 rv = ir.createSelect val, @loadBoolEjsValue(true), @loadBoolEjsValue(false), "sel"
                 rv._ejs_returns_ejsval_bool = true
                 rv
-
+
+        getEjsvalBits: (arg) ->
+                bits_alloc = @createAlloca @currentFunction, types.EjsValue, "bits_alloca"
+                ir.createStore arg, bits_alloc
+                bits_ptr = ir.createBitCast bits_alloc, types.int64.pointerTo(), "bits_ptr"
+                ir.createLoad bits_ptr, "bits_load"
+
+        createEjsvalICmpUGt: (arg, i64_const, name) -> ir.createICmpUGt @getEjsvalBits(arg), i64_const, name
+
+        createEjsvalICmpULt: (arg, i64_const, name) -> ir.createICmpULt @getEjsvalBits(arg), i64_const, name
+
+        createEjsvalICmpEq: (arg, i64_const, name) ->  ir.createICmpEq @getEjsvalBits(arg), i64_const, name
+
+        createEjsvalAnd: (arg, i64_const, name) ->     ir.createAnd @getEjsvalBits(arg), i64_const, name
+
         handleTypeofIsObject: (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        @createEjsBoolSelect ir.createICmpUGt arg, consts.int64_lowhi(0xfffbffff, 0xffffffff), "cmpresult"
+                        @createEjsBoolSelect @createEjsvalICmpUGt arg, consts.int64_lowhi(0xfffbffff, 0xffffffff), "cmpresult"
                 else
                         @createCall @ejs_runtime.typeof_is_object, [arg], "is_object", false

@@ -1850,8 +1829,8 @@
                         is_object_bb = new llvm.BasicBlock "typeof_function_is_object", insertFunc
                         success_bb   = new llvm.BasicBlock "typeof_function_true",      insertFunc
                         merge_bb     = new llvm.BasicBlock "typeof_function_merge",     insertFunc
-
-                        cmp = ir.createICmpUGt arg, (consts.int64_lowhi 0xfffbffff, 0xffffffff), "cmpresult"
+
+                        cmp = @createEjsvalICmpUGt arg, consts.int64_lowhi(0xfffbffff, 0xffffffff), "cmpresult"
                         ir.createCondBr cmp, is_object_bb, failure_bb

                         @doInsideBBlock is_object_bb, =>
@@ -1889,7 +1868,7 @@
                         success_bb   = new llvm.BasicBlock "typeof_symbol_true",      insertFunc
                         merge_bb     = new llvm.BasicBlock "typeof_symbol_merge",     insertFunc

-                        cmp = ir.createICmpUGt arg, (consts.int64_lowhi 0xfffbffff, 0xffffffff), "cmpresult"
+                        cmp = @createEjsvalICmpUGt arg, consts.int64_lowhi(0xfffbffff, 0xffffffff), "cmpresult"
                         ir.createCondBr cmp, is_object_bb, failure_bb

                         @doInsideBBlock is_object_bb, =>
@@ -1917,7 +1896,7 @@
         handleTypeofIsString: (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        mask = ir.createAnd arg, consts.int64_lowhi(0xffff8000, 0x00000000), "mask.i"
+                        mask = @createEjsvalAnd arg, consts.int64_lowhi(0xffff8000, 0x00000000), "mask.i"
                         @createEjsBoolSelect ir.createICmpEq mask, consts.int64_lowhi(0xfffa8000, 0x00000000), "cmpresult"
                 else
                         @createCall @ejs_runtime.typeof_is_string, [arg], "is_string", false
@@ -1925,37 +1904,37 @@
         handleTypeofIsNumber:    (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        @createEjsBoolSelect ir.createICmpULt arg, consts.int64_lowhi(0xfff80001, 0x00000000), "cmpresult"
+                        @createEjsBoolSelect @createEjsvalICmpULt arg, consts.int64_lowhi(0xfff80001, 0x00000000), "cmpresult"
                 else
                         @createCall @ejs_runtime.typeof_is_number,    [arg], "is_number", false

         handleTypeofIsBoolean:   (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        mask = ir.createAnd arg, consts.int64_lowhi(0xffff8000, 0x00000000), "mask.i"
-                        @createEjsBoolSelect ir.createICmpEq mask, consts.int64_lowhi(0xfff98000, 0x00000000), "cmpresult"
+                        mask = @createEjsvalAnd arg, consts.int64_lowhi(0xffff8000, 0x00000000), "mask.i"
+                        @createEjsBoolSelect @createEjsvalICmpEq mask, consts.int64_lowhi(0xfff98000, 0x00000000), "cmpresult"
                 else
                         @createCall @ejs_runtime.typeof_is_boolean,   [arg], "is_boolean", false

         handleIsUndefined: (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        @createEjsBoolSelect ir.createICmpEq arg, consts.int64_lowhi(0xfff90000, 0x00000000), "cmpresult"
+                        @createEjsBoolSelect @createEjsvalICmpEq arg, consts.int64_lowhi(0xfff90000, 0x00000000), "cmpresult"
                 else
                         @createCall @ejs_runtime.typeof_is_undefined, [arg], "is_undefined", false

         handleIsNull: (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        @createEjsBoolSelect ir.createICmpEq arg, consts.int64_lowhi(0xfffb8000, 0x00000000), "cmpresult"
+                        @createEjsBoolSelect @createEjsvalICmpEq arg, consts.int64_lowhi(0xfffb8000, 0x00000000), "cmpresult"
                 else
                         @createCall @ejs_runtime.typeof_is_null,      [arg], "is_null", false

         handleIsNullOrUndefined: (exp, opencode) ->
                 arg = @visitOrNull exp.arguments[0]
                 if opencode and @options.target_pointer_size is 64
-                        cmp1 = ir.createICmpEq arg, consts.int64_lowhi(0xfff90000, 0x00000000), "cmpresult1"
-                        cmp2 = ir.createICmpEq arg, consts.int64_lowhi(0xffb80000, 0x00000000), "cmpresult2"
+                        cmp1 = @createEjsvalICmpEq arg, consts.int64_lowhi(0xfff90000, 0x00000000), "cmpresult1"
+                        cmp2 = @createEjsvalICmpEq arg, consts.int64_lowhi(0xffb80000, 0x00000000), "cmpresult2"
                         @createEjsBoolSelect ir.createOr cmp1, cmp2, "or"
                 else
                         @createCall @ejs_binops["=="],   [@loadNullEjsValue(), arg], "is_null_or_undefined", false
@@ -1982,7 +1961,7 @@
                 n.formal_params = n.params

                 n.params = ({ type: _Identifier, name: param.name, llvm_type: param.llvm_type } for param in @abi.ejs_params)
-                n.params[1].name = env_name
+                n.params[@abi.env_param_index].name = env_name

                 # create the llvm IR function using our platform calling convention
                 n.ir_func = types.takes_builtins @abi.createFunction @module, n.ir_name, @abi.ejs_return_type, (param.llvm_type for param in n.params)


Fix discussion link sometimes not scrolling to the discussion

--- resources/assets/lib/beatmap-discussions/main.coffee
+++ resources/assets/lib/beatmap-discussions/main.coffee
@@ -33,6 +33,7 @@
     @checkNewTimeoutDefault = 10000
     @checkNewTimeoutMax = 60000
     @cache = {}
+    @disposers = new Set
     @timeouts = {}
     @xhr = {}
     @state = JSON.parse(props.container.dataset.beatmapsetDiscussionState ? null)
@@ -75,7 +76,9 @@
     $(document).on "click.#{@eventId}", '.js-beatmap-discussion--jump', @jumpToClick
     $(document).on "turbolinks:before-cache.#{@eventId}", @saveStateToContainer

-    @jumpToDiscussionByHash() if !@restoredState
+    if !@restoredState
+      @disposers.add core.reactTurbolinks.runAfterPageLoad(@jumpToDiscussionByHash)
+
     @timeouts.checkNew = Timeout.set @checkNewTimeoutDefault, @checkNew

@@ -95,6 +98,7 @@

     Timeout.clear(timeout) for _name, timeout of @timeouts
     xhr?.abort() for _name, xhr of @xhr
+    @disposers.forEach (disposer) => disposer?()

   render: =>


Documentation

Documentation

--- src/bounded.coffee
+++ src/bounded.coffee
@@ -211,6 +211,7 @@

   @name center
   @methodOf Bounded#
+  @returns {Point} The middle of the calling object
   ###
   center: () ->
     self.position()


s-expression parsing

s-expression parsing

--- lib/agda/parser.coffee
+++ lib/agda/parser.coffee
@@ -46,31 +46,32 @@
       length = chunk.length
       chunk = chunk.substring index, length - 1

-    # split into list of tokens
-    tokens = chunk.split ' '

-
-
-    switch tokens[0]
-
-      when "agda2-status-action" then command =
-        type: STATUS_ACTION
-        status: tokens[1]
-
-      when "agda2-info-action" then command =
-        type: INFO_ACTION
-        header: tokens[1]
-        content: tokens[2]
-
-      when "agda2-goals-action" then command =
-        type: GOALS_ACTION
-        goals: tokens[1]
-
-      when "agda2-highlight-clear" then command =
-        type: HIGHLIGHT_CLEAR
-
-      else command = type: UNKNOWN
-
+    #
+    #
+    #
+    # switch tokens[0]
+    #
+    #   when "agda2-status-action" then command =
+    #     type: STATUS_ACTION
+    #     status: tokens[1]
+    #
+    #   when "agda2-info-action" then command =
+    #     type: INFO_ACTION
+    #     header: tokens[1]
+    #     content: tokens[2]
+    #
+    #   when "agda2-goals-action" then command =
+    #     type: GOALS_ACTION
+    #     goals: tokens[1]
+    #
+    #   when "agda2-highlight-clear" then command =
+    #     type: HIGHLIGHT_CLEAR
+    #
+    #   else
+    #     throw 'wtf is this command? ' + tokens
+    #     command = type: UNKNOWN
+    #

     @push chunk
     next()
@@ -79,53 +80,91 @@
 class Lexer extends Transform

   constructor: ->
+
     super
       objectMode: true

   _transform: (chunk, encoding, next) ->
+    [tokens, rest] = @takeList chunk
+    @push tokens
+    next()
+
+  head: (string) -> string.substr 0, 1
+  tail: (string) -> string.substr 1
+  take: (n, string) -> string.substr 0, n
+  drop: (n, string) -> string.substr n
+
+  # (a b "c" '(d r)) => [a, b, "c", [d, r]]
+  takeList: (string) ->
+
     tokens = []

-    # remove '('
-    chunk = chunk.substr 1
+    # drop "("
+    string = @tail string

-    takeString = ->
-      # end of the string
-      index = chunk.substr(1).indexOf '"'
-      # take the string, remove qoutes, and push it into tokens
-      tokens.push chunk.substr 1, index - 1
-      # drop chunk
-      chunk = chunk.substr index + 1
+    while string.length > 0
+      switch @head string
+        when ' '
+          string = @tail string
+          # console.log '[SPACE]', [string]
+        when '('
+          [token, string] = @takeList string
+          # console.log '[List]', [token, string]
+          tokens.push token, [string]
+        when ')'
+          string = @tail string
+        when '\''
+          [token, string] = @takeQuote string
+          # console.log '[Quote]', [token, string]
+          tokens.push token
+        when '"'
+          [token, string] = @takeString string
+          # console.log '[String]', [token, string]
+          tokens.push token
+        else
+          [token, string] = @takeAtom string
+          # console.log '[Atom]', [token, string]
+          tokens.push token

-    takeQuote = ->
-      # end of the string
-      index = chunk.substr(1).indexOf '"'
-      # take the string, remove qoutes, and push it into tokens
-      tokens.push chunk.substr 1, index - 1
-      # drop chunk
-      chunk = chunk.substr index + 1
+    # drop ")"
+    rest = @tail string
+    return [tokens, rest]

+  takeAtom: (string) ->

-    takeAtom = ->
-      # end of the atom
-      index = chunk.indexOf ' '
-      index = if index is -1 then chunk.length else index
+    indexI = string.indexOf ' '
+    indexP = string.indexOf ')'
+    indexE = string.length

-      # take the atom and push it into tokens
-      tokens.push chunk.substr 0, index
-      # drop chunk
-      chunk = chunk.substr index + 1
+    if indexI isnt -1
+      index = indexI
+    else if indexP isnt -1
+      index = indexP
+    else
+      index = indexE

+    token = @take index, string
+    rest = @drop index, string
+    return [token, rest]

+  takeQuote: (string) ->

-    takeAtom()
-    # takeString()
-    # takeString()
-    # takeString()
-    # takeAtom()
-    console.log chunk
+    # drop '
+    string = @tail string

-    @push tokens
-    next()
+    @takeList string
+
+  takeString: (string) ->
+
+    # drop "
+    string = @tail string
+
+    indexQ = string.indexOf '"'
+
+    token = @take indexQ, string
+    rest = @drop (indexQ + 1), string    # indexQ+1 to drop the closing "
+
+    return [token, rest]

 module.exports =


Add options to enable and disable plugins from loading by default for a user; added an option to list loaded plugins and their descriptions

--- src/command.coffee
+++ src/command.coffee
@@ -2,6 +2,7 @@
 The nesh command, which parses options and then drops the user
 into an interactive session.
 ###
+_ = require 'underscore'
 fs = require 'fs'
 nesh = require './nesh'

@@ -10,9 +11,15 @@
     .options 'c',
         describe: 'Load CoffeeScript; shortcut for -l coffee'
         boolean: true
+    .options 'disable',
+        describe: 'Disable plugin(s) for autoload'
+        string: true
     .options 'e',
         alias: 'eval'
         describe: 'Filename or string to eval in the REPL context'
+        string: true
+    .options 'enable',
+        describe: 'Enable plugin(s) for autoload'
         string: true
     .options 'h',
         alias: 'help'
@@ -29,6 +36,9 @@
         alias: 'prompt'
         describe: 'Set prompt string'
         string: true
+    .options 'plugins',
+        describe: 'List auto-loaded plugins'
+        boolean: true
     .options 'v',
         alias: 'version'
         describe: 'Show version and exit'
@@ -58,6 +68,33 @@
 if argv.verbose
     nesh.log.level = nesh.log.DEBUG

+nesh.config.load()
+
+if argv.enable
+    enabled = argv.enable.split ','
+
+    config = nesh.config.get()
+    config.plugins ?= []
+    config.plugins = _(config.plugins.concat enabled).uniq()
+    config.pluginsExclude ?= []
+    config.pluginsExclude = _(config.pluginsExclude).reject (item) -> item in enabled
+
+    nesh.config.save()
+
+if argv.disable
+    disabled = argv.disable.split ','
+
+    config = nesh.config.get()
+    config.plugins ?= []
+    config.plugins = _(config.plugins).reject (item) -> item in disabled
+    config.pluginsExclude ?= []
+    config.pluginsExclude = _(config.pluginsExclude.concat disabled).uniq()
+
+    nesh.config.save()
+
+if argv.enable or argv.disable
+    return
+
 if argv.c
     argv.lang = 'coffee'

@@ -80,7 +117,13 @@
         nesh.log.debug 'Compiling eval data'
         opts.evalData = nesh.compile opts.evalData

-nesh.config.load()
+nesh.init true, (err) ->
+    return nesh.log.error err if err

-nesh.start opts, (err) ->
-    console.error err.toString().red if err
+    if argv.plugins
+        for plugin in nesh.plugins
+            nesh.log.info "#{plugin.name}: #{plugin.description}"
+        return
+
+    nesh.start opts, (err) ->
+        nesh.log.error err if err


Feature: add support for .js and .ini contexts as suggested in #4.

--- src/context.coffee
+++ src/context.coffee
@@ -2,7 +2,7 @@
 fs.path = require 'path'
 async = require 'async'
 _ = require 'underscore'
-yaml = require 'js-yaml'
+confert = require 'confert'
 utils = require './utils'
 {unwrap} = utils.string

@@ -24,19 +24,6 @@
                 namespace = fs.path.basename filename, extension

         {filename, namespace}
-
-readData = (path) ->
-    resolvedPath = fs.path.resolve path
-    fs.readFileSync resolvedPath, encoding: 'utf8'
-
-parseData = (raw, extension) ->
-    switch extension
-        when '.json'
-            JSON.parse raw
-        when '.yml', '.yaml'
-            yaml.safeLoad raw
-        else
-            throw new Error "Context files need to be JSON or YAML."

 # REFACTOR: this function can use a more rigorous rethink
 merge = (sources...) ->
@@ -79,8 +66,7 @@
     for path in paths
         {filename, namespace} = path
         extension = fs.path.extname filename
-        raw = readData filename
-        path.data = parseData raw, extension
+        path.data = confert fs.path.resolve filename

     merge paths...


ConfirmEmail: Member listing lazy load corrections

--- client/Dashboard/views/groupsmemberpermissionsview.coffee
+++ client/Dashboard/views/groupsmemberpermissionsview.coffee
@@ -23,12 +23,11 @@
       unless @listController.scrollView.hasScrollBars()
         @continueLoadingTeasers()

-    @refresh()
-
     @on 'SearchInputChanged', (value)=>
       @_searchValue = value
       if value isnt ""
-        @timestamp = new Date 0
+        @timestamp = new Date
+        @skip = 0
         @listController.removeAllItems()
         @fetchSomeMembers()
       else @refresh()
@@ -50,11 +49,12 @@
   fetchSomeMembers:(selector={})->
     @listController.showLazyLoader no
     options =
-      limit : 20
+      limit : 30
       sort  : { timestamp: -1 }
     # return
     if @_searchValue
       {JAccount} = KD.remote.api
+      options = {limit : 30, skip: @skip}
       JAccount.byRelevance @_searchValue, options, (err, members)=> @populateMembers err, members
     else
       @getData().fetchMembers selector, options, (err, members)=> @populateMembers err, members
@@ -62,6 +62,9 @@
   populateMembers:(err, members)->
     return warn err if err
     @listController.hideLazyLoader()
+    @skip += members.length
+    @timestamp = new Date members.last.timestamp_
+
     if members.length > 0
       ids = (member._id for member in members)
       @getData().fetchUserRoles ids, (err, userRoles)=>
@@ -87,17 +90,18 @@
           list.getOptions().userStatus ?= []
           list.getOptions().userStatus = _.extend(list.getOptions().userStatus, userStatusHash)
           @listController.instantiateListItems members
-          @timestamp = new Date members.last.timestamp_
-          @emit 'teasersLoaded' if members.length is 20
+          if members.length < 30
+            @continueLoadingTeasers()

   refresh:->
     @listController.removeAllItems()
-    @timestamp = new Date 0
+    @timestamp = new Date
+    @skip = 0
     @fetchRoles()
     @fetchSomeMembers()

   continueLoadingTeasers:->
-    @listController.showLazyLoader()
+    @listController.showLazyLoader no
     @fetchSomeMembers {timestamp: $lt: @timestamp.getTime()}

   memberRolesChange:(view, member, roles)->


在 summary 更新时更新 version

在 summary 更新时更新 version

--- lib/gulpfile.coffee
+++ lib/gulpfile.coffee
@@ -15,7 +15,6 @@
 dist = '_book'
 book = 'book'
 tpl = 'tpl'
-version = Date.now().toString(36)
 cwd = process.cwd()

 gulp.task('default', ['server'])
@@ -102,7 +101,7 @@
         console.error(e, e)
         summary = {}

-      summary.v = version
+      summary.v = Date.now().toString(36)
       summary.title = cwd.split(path.sep).pop()
       JSON.stringify(summary)
     ))


cleanup

cleanup

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -75,32 +75,32 @@
     {@mutationManager, @occurrenceManager, @persistentSelection} = @vimState

     @initialize()
-
-    @onDidSetOperatorModifier (options) =>
-      if options.wise?
-        @wise = options.wise
-
-      if options.occurrence?
-        @setOccurrence(options.occurrence)
-        if @isOccurrence()
-          # Reset existing preset-occurrence. e.g. `c o p`, `d o f`
-          @occurrenceManager.resetPatterns()
-          @addOccurrencePattern()
-
+    @onDidSetOperatorModifier(@setModifier.bind(this))
     @target = selectionTarget if selectionTarget = @getSelectionTarget()

-    if _.isString(@target)
-      @setTarget(@new(@target))
-
-    # When preset-occurrence was exists, auto enable occurrence-wise
-    if @acceptPresetOccurrence and @occurrenceManager.hasPatterns()
+    @setTarget(@new(@target)) if _.isString(@target)
+
+    # When preset-occurrence was exists, operate on occurrence-wise
+    if @acceptPresetOccurrence and @occurrenceManager.hasMarkers()
       @setOccurrence(true)
+
     if @isOccurrence()
       @addOccurrencePattern() unless @occurrenceManager.hasMarkers()

     if @acceptPersistentSelection
       @subscribe @onDidDeactivateMode ({mode}) =>
         @occurrenceManager.resetPatterns() if mode is 'operator-pending'
+
+  setModifier: (options) ->
+    if options.wise?
+      @wise = options.wise
+
+    if options.occurrence?
+      @setOccurrence(options.occurrence)
+      if @isOccurrence()
+        # Reset existing preset-occurrence. e.g. `c o p`, `d o f`
+        @occurrenceManager.resetPatterns()
+        @addOccurrencePattern()

   getSelectionTarget: ->
     # In visual-mode and target was not pre-set, operate on selected area.


Init package as a fork of language-ruby

Init package as a fork of language-ruby

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -2,12 +2,12 @@
 path = require 'path'

 module.exports =
-  selector: '.source.ruby'
-  disableForSelector: '.source.ruby .comment'
+  selector: '.source.rubymotion'
+  disableForSelector: '.source.rubymotion .comment'

   getSuggestions: ({editor, bufferPosition, scopeDescriptor, prefix}) ->
     completions = []
-
+
     if isCompletingInheritedClass = @isCompletingInheritedClass({scopeDescriptor})
       completions = completions.concat(@getClassCompletions({prefix}))


Use activatedManually: false detail to not auto-accept option if only one

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -30,7 +30,7 @@
     setTimeout(@triggerAutocomplete.bind(this, editor), 1) if suggestion.type is 'attribute'

   triggerAutocomplete: (editor) ->
-    atom.commands.dispatch(atom.views.getView(editor), 'autocomplete-plus:activate')
+    atom.commands.dispatch(atom.views.getView(editor), 'autocomplete-plus:activate', activatedManually: false)

   isTagStartWithNoPrefix: ({prefix, scopeDescriptor}) ->
     scopes = scopeDescriptor.getScopesArray()


expectation fixes and new "hold" chain

expectation fixes and new "hold" chain

--- lib/expectation.coffee
+++ lib/expectation.coffee
@@ -32,8 +32,8 @@

   @addProperty: (name, getter) -> super(name, @promisify(getter, name))

-  @promisify: (fn, name = null) -> ->
-    task = @resolveFlags().then => Q.promised(fn)
+  @promisify: (fn, name = null) -> (args...) ->
+    task = @resolveFlags().then => Q.promised(fn).apply(this, args)
     barrierContext.pushTask(task, "expectation #{name}")

     this
@@ -47,6 +47,8 @@
       this

   resolveFlags: ->
+    return Q(null) if @flag("hold")
+
     flags = _.keys(@__flags || {})
     promises = _.map flags, (flag) =>
       Q(@__flags[flag]).then (value) =>
@@ -56,8 +58,9 @@

 Expectation.addMethod "reject", (args...) ->
   fn = @flag("object")
+  p = if _.isFunction(fn) then fn() else fn

-  promise = fn()
+  promise = p
     .then(-> ->)
     .catch((err) -> -> throw err)
     .then (resolvedFn) => @flag("object", resolvedFn).throw(args...)
@@ -66,4 +69,9 @@

   this

+Assertion.addProperty.call Expectation, "hold", ->
+  @__flags.hold = true
+
+  this
+
 assertions("Assertion": Expectation, utils)


Use eachSeries to load snippets so we don't exhaust file descriptors

--- lib/snippets.coffee
+++ lib/snippets.coffee
@@ -50,7 +50,7 @@
         done()

     fs.readdir snippetsDirPath, (err, paths) ->
-      async.each(paths, loadSnippetFile, done)
+      async.eachSeries(paths, loadSnippetFile, done)

   loadTextMateSnippets: (path, done) ->
     snippetsDirPath = fsUtils.join(path, 'Snippets')
@@ -89,7 +89,7 @@
       if err
         console.warn err
         return done()
-      async.each(paths, loadSnippetFile, done)
+      async.eachSeries(paths, loadSnippetFile, done)

   translateTextmateSnippet: ({ scope, name, content, tabTrigger }) ->
     scope = TextMatePackage.cssSelectorFromScopeSelector(scope) if scope


Avoid mutating the ClassData!

Avoid mutating the ClassData!

--- src/methods.coffee
+++ src/methods.coffee
@@ -121,9 +121,12 @@
       i = -1
       param_type_objs = []
       k = 0
-      handlers = @code?.exception_handlers ? []
-      # HotSpot seems to do this
-      handlers.unshift catch_type: 'Ljava/lang/Throwable;' if handlers.length > 0
+      if @code?.exception_handlers? and @code.exception_handlers.length > 0
+        # HotSpot seems to do this
+        handlers = [catch_type: 'Ljava/lang/Throwable;']
+        Array::push.apply handlers, @code.exception_handlers
+      else
+        handlers = []

       fetch_catch_type = =>
         if k < handlers.length


mr note fixes and show method used insteadof removing the kdhiddentab

--- client/app/MainApp/maincontroller/mainviewcontroller.coffee
+++ client/app/MainApp/maincontroller/mainviewcontroller.coffee
@@ -34,9 +34,11 @@
     cdController.emit "ContentDisplaysShouldBeHidden"
     {mainTabView}   = mainView

+    # temp fix
+    # until fixing the original issue w/ the dnd this should be kept here
     if pane
     then @setViewState pane.getOptions()
-    else mainTabView.getActivePane().unsetClass "kdhiddentab"
+    else mainTabView.getActivePane().show()

     {title} = app.getOption('navItem')


access store to read ota token

access store to read ota token

--- client/home/lib/utilities/components/kdcli/container.coffee
+++ client/home/lib/utilities/components/kdcli/container.coffee
@@ -1,40 +1,28 @@
-_               = require 'lodash'
-kd              = require 'kd'
-React           = require 'kd-react'
-globals         = require 'globals'
-whoami          = require 'app/util/whoami'
-Tracker         = require 'app/util/tracker'
+kd = require 'kd'
+React = require 'kd-react'
+globals = require 'globals'
+whoami = require 'app/util/whoami'
+Tracker = require 'app/util/tracker'
 copyToClipboard = require 'app/util/copyToClipboard'
-View            = require './view'
-KodingKontrol   = require 'app/kite/kodingkontrol'
-
+View  = require './view'
+TeamFlux = require 'app/flux/teams'
+KDReactorMixin = require 'app/flux/base/reactormixin'

 module.exports = class KDCliContainer extends React.Component
+
+  getDataBindings: ->
+
+    return {
+      otaToken: TeamFlux.getters.otaToken
+    }
+

   constructor: (props) ->

     super props

     @state=
-      key : ''
-      cmd : ''
-
-
-  componentWillMount: ->
-
-    whoami().fetchOtaToken (err, token) =>
-
-      key = if globals.os is 'mac' then '⌘ + C' else 'Ctrl + C'
-      cmd = if err
-        "Failed to generate your command, click to try again!"
-      else
-        if globals.config.environment in ['dev', 'default', 'sandbox']
-          "export KONTROLURL=#{KodingKontrol.getKontrolUrl()}; curl -sL https://sandbox.kodi.ng/c/d/kd | bash -s #{token}"
-        else "curl -sL https://kodi.ng/c/p/kd | bash -s #{token}"
-
-      @setState
-        key : key
-        cmd : cmd
+      key : if globals.os is 'mac' then '⌘ + C' else 'Ctrl + C'

   onCMDClick: ->
@@ -50,5 +38,8 @@
     <View
       ref='view'
       copyKey={@state.key}
-      cmd={@state.cmd}
+      cmd={@state.otaToken}
       onCMDClick={@bound 'onCMDClick'} />
+
+KDCliContainer.include [KDReactorMixin]
+


Workspace: Fixed panel button callbacks.

--- client/landing/app/CommonViews/workspace/panel/panel.coffee
+++ client/landing/app/CommonViews/workspace/panel/panel.coffee
@@ -30,9 +30,10 @@
       partial   : """#{title}"""

   createHeaderButtons: ->
-    for buttonOptions in @getOptions().buttons
+    @getOptions().buttons.forEach (buttonOptions) =>
       buttonView = new KDButtonView
         title    : buttonOptions.title
+        cssClass : buttonOptions.cssClass
         callback : =>
           buttonOptions.callback @, @getDelegate()