├── .gitignore ├── tests ├── fixtures │ ├── such-es2015 │ │ ├── input.js │ │ └── output.js │ ├── es6-module-syntax │ │ ├── input.js │ │ └── output.js │ ├── object-literal │ │ ├── input.js │ │ └── output.js │ ├── object-member │ │ ├── input.js │ │ └── output.js │ └── local-variable │ │ ├── input.js │ │ └── output.js ├── regex-test.js └── compiler-test.js ├── .travis.yml ├── package.json ├── .jshintrc ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /tests/fixtures/such-es2015/input.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | var { computed, get } = Ember; 4 | 5 | export default Ember.Component.extend({ 6 | // es6 syntax used here 7 | }); 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "4.0.0" # earliest supported release (see package.json) 5 | - "node" # latest stable node.js release 6 | script: npm test 7 | -------------------------------------------------------------------------------- /tests/fixtures/such-es2015/output.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | var { computed, get } = Ember; 4 | 5 | export default Ember.Component.extend({ 6 | // es6 syntax used here 7 | }); 8 | -------------------------------------------------------------------------------- /tests/fixtures/es6-module-syntax/input.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'foo', 3 | initializer: function(container, app) { 4 | return { 5 | default: 'something' 6 | }; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/fixtures/es6-module-syntax/output.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'foo', 3 | initializer: function(container, app) { 4 | return { 5 | 'default': 'something' 6 | }; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es3-safe-recast", 3 | "version": "3.0.0", 4 | "description": "esprima/recast es3 safe compile step", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "test": "mocha --reporter spec tests/**/*-test.js", 11 | "test:watch": "mocha --watch --reporter spec tests/**/*-test.js", 12 | "test:debug": "mocha debug --reporter spec tests/**/*-test.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/stefanpenner/es3-safe-recast.git" 17 | }, 18 | "author": "Stefan Penner", 19 | "license": "ISC", 20 | "dependencies": { 21 | "recast": "^0.13.0", 22 | "esprima": "^4.0.0" 23 | }, 24 | "devDependencies": { 25 | "mocha": "~1.18.2", 26 | "better-assert": "~1.0.0", 27 | "ast-equality": "^1.0.0" 28 | }, 29 | "engines": { 30 | "node": ">= 4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": { 3 | "console": true, 4 | "it": true, 5 | "describe": true, 6 | "beforeEach": true, 7 | "afterEach": true, 8 | "before": true, 9 | "after": true 10 | }, 11 | "proto": true, 12 | "strict": true, 13 | "indent": 2, 14 | "camelcase": true, 15 | "node" : true, 16 | "browser" : false, 17 | "boss" : true, 18 | "curly": true, 19 | "latedef": "nofunc", 20 | "debug": false, 21 | "devel": false, 22 | "eqeqeq": true, 23 | "evil": true, 24 | "forin": false, 25 | "immed": false, 26 | "laxbreak": false, 27 | "newcap": true, 28 | "noarg": true, 29 | "noempty": false, 30 | "quotmark": true, 31 | "nonew": false, 32 | "nomen": false, 33 | "onevar": false, 34 | "plusplus": false, 35 | "regexp": false, 36 | "undef": true, 37 | "unused": true, 38 | "sub": true, 39 | "trailing": true, 40 | "white": false, 41 | "eqnull": true, 42 | "esnext": true 43 | } 44 | -------------------------------------------------------------------------------- /tests/fixtures/object-literal/input.js: -------------------------------------------------------------------------------- 1 | var object = { 2 | break: null, 3 | case: null, 4 | catch: null, 5 | continue: null, 6 | default: null, 7 | delete: null, 8 | do: null, 9 | else: null, 10 | finally: null, 11 | for: null, 12 | function: null, 13 | if: null, 14 | in: null, 15 | instanceof: null, 16 | new: null, 17 | return: null, 18 | switch: null, 19 | this: null, 20 | throw: null, 21 | try: null, 22 | typeof: null, 23 | var: null, 24 | void: null, 25 | while: null, 26 | with: null, 27 | abstract: null, 28 | boolean: null, 29 | byte: null, 30 | char: null, 31 | class: null, 32 | const: null, 33 | debugger: null, 34 | double: null, 35 | enum: null, 36 | export: null, 37 | extends: null, 38 | final: null, 39 | float: null, 40 | goto: null, 41 | implements: null, 42 | import: null, 43 | int: null, 44 | interface: null, 45 | long: null, 46 | native: null, 47 | package: null, 48 | private: null, 49 | protected: null, 50 | public: null, 51 | short: null, 52 | static: null, 53 | super: null, 54 | synchronized: null, 55 | throws: null, 56 | transient: null, 57 | volatile: null, 58 | null: null, 59 | true: null, 60 | false: null, 61 | yield: null 62 | }; 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # es3-safe-recast [![Build Status](https://travis-ci.org/stefanpenner/es3-safe-recast.svg)](https://travis-ci.org/stefanpenner/es3-safe-recast) 2 | 3 | Recasts all [ECMAScript 3][1] reserved words to their safe alternatives. 4 | 5 | Optionally removes trailing commas in object and array literals (pass `{ trailingComma: true }` as the second argument to compile). 6 | 7 | 8 | ## helpers 9 | 10 | * [grunt-es3-safe-recast](https://github.com/phpro/grunt-es3-safe-recast) 11 | * [gulp-dereserve](https://www.npmjs.com/package/gulp-dereserve) 12 | * [broccoli-es3-safe-recast](broccoli-es3-safe-recast) 13 | 14 | ## Before 15 | 16 | ```js 17 | ajax('/asdf/1').catch(function(reason) { 18 | 19 | }).finally(function() { 20 | 21 | }); 22 | ``` 23 | 24 | ## After 25 | 26 | ```js 27 | ajax('/asdf/1')['catch'](function(reason) { 28 | 29 | })['finally'](function() { 30 | 31 | }); 32 | ``` 33 | 34 | ## Before 35 | 36 | ```js 37 | object = { 38 | catch: function() {}, 39 | finally: function() {}, 40 | default: function() {} 41 | }; 42 | ``` 43 | 44 | ## After 45 | 46 | ```js 47 | object = { 48 | 'catch': function() {}, 49 | 'finally': function() {}, 50 | 'default': function() {} 51 | }; 52 | ``` 53 | 54 | [1]: http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf 55 | -------------------------------------------------------------------------------- /tests/fixtures/object-literal/output.js: -------------------------------------------------------------------------------- 1 | var object = { 2 | "break": null, 3 | "case": null, 4 | "catch": null, 5 | "continue": null, 6 | "default": null, 7 | "delete": null, 8 | "do": null, 9 | "else": null, 10 | "finally": null, 11 | "for": null, 12 | "function": null, 13 | "if": null, 14 | "in": null, 15 | "instanceof": null, 16 | "new": null, 17 | "return": null, 18 | "switch": null, 19 | "this": null, 20 | "throw": null, 21 | "try": null, 22 | "typeof": null, 23 | "var": null, 24 | "void": null, 25 | "while": null, 26 | "with": null, 27 | "abstract": null, 28 | "boolean": null, 29 | "byte": null, 30 | "char": null, 31 | "class": null, 32 | "const": null, 33 | "debugger": null, 34 | "double": null, 35 | "enum": null, 36 | "export": null, 37 | "extends": null, 38 | "final": null, 39 | "float": null, 40 | "goto": null, 41 | "implements": null, 42 | "import": null, 43 | "int": null, 44 | "interface": null, 45 | "long": null, 46 | "native": null, 47 | "package": null, 48 | "private": null, 49 | "protected": null, 50 | "public": null, 51 | "short": null, 52 | "static": null, 53 | "super": null, 54 | "synchronized": null, 55 | "throws": null, 56 | "transient": null, 57 | "volatile": null, 58 | "null": null, 59 | "true": null, 60 | "false": null, 61 | "yield": null 62 | }; 63 | -------------------------------------------------------------------------------- /tests/fixtures/object-member/input.js: -------------------------------------------------------------------------------- 1 | object.break(function() { 2 | 3 | }).case(function() { 4 | 5 | }).catch(function() { 6 | 7 | }).continue(function() { 8 | 9 | }).default(function() { 10 | 11 | }).delete(function() { 12 | 13 | }).do(function() { 14 | 15 | }).else(function() { 16 | 17 | }).finally(function() { 18 | 19 | }).for(function() { 20 | 21 | }).function(function() { 22 | 23 | }).if(function() { 24 | 25 | }).in(function() { 26 | 27 | }).instanceof(function() { 28 | 29 | }).new(function() { 30 | 31 | }).return(function() { 32 | 33 | }).switch(function() { 34 | 35 | }).this(function() { 36 | 37 | }).throw(function() { 38 | 39 | }).try(function() { 40 | 41 | }).typeof(function() { 42 | 43 | }).var(function() { 44 | 45 | }).void(function() { 46 | 47 | }).while(function() { 48 | 49 | }).with(function() { 50 | 51 | }).abstract(function() { 52 | 53 | }).boolean(function() { 54 | 55 | }).byte(function() { 56 | 57 | }).char(function() { 58 | 59 | }).class(function() { 60 | 61 | }).const(function() { 62 | 63 | }).debugger(function() { 64 | 65 | }).double(function() { 66 | 67 | }).enum(function() { 68 | 69 | }).export(function() { 70 | 71 | }).extends(function() { 72 | 73 | }).final(function() { 74 | 75 | }).float(function() { 76 | 77 | }).goto(function() { 78 | 79 | }).implements(function() { 80 | 81 | }).import(function() { 82 | 83 | }).int(function() { 84 | 85 | }).interface(function() { 86 | 87 | }).long(function() { 88 | 89 | }).native(function() { 90 | 91 | }).package(function() { 92 | 93 | }).private(function() { 94 | 95 | }).protected(function() { 96 | 97 | }).public(function() { 98 | 99 | }).short(function() { 100 | 101 | }).static(function() { 102 | 103 | }).super(function() { 104 | 105 | }).synchronized(function() { 106 | 107 | }).throws(function() { 108 | 109 | }).transient(function() { 110 | 111 | }).volatile(function() { 112 | 113 | }).null(function() { 114 | 115 | }).true(function() { 116 | 117 | }).false(function() { 118 | 119 | }).yield(function() { 120 | 121 | }); 122 | -------------------------------------------------------------------------------- /tests/fixtures/object-member/output.js: -------------------------------------------------------------------------------- 1 | object["break"](function() { 2 | 3 | })["case"](function() { 4 | 5 | })["catch"](function() { 6 | 7 | })["continue"](function() { 8 | 9 | })["default"](function() { 10 | 11 | })["delete"](function() { 12 | 13 | })["do"](function() { 14 | 15 | })["else"](function() { 16 | 17 | })["finally"](function() { 18 | 19 | })["for"](function() { 20 | 21 | })["function"](function() { 22 | 23 | })["if"](function() { 24 | 25 | })["in"](function() { 26 | 27 | })["instanceof"](function() { 28 | 29 | })["new"](function() { 30 | 31 | })["return"](function() { 32 | 33 | })["switch"](function() { 34 | 35 | })["this"](function() { 36 | 37 | })["throw"](function() { 38 | 39 | })["try"](function() { 40 | 41 | })["typeof"](function() { 42 | 43 | })["var"](function() { 44 | 45 | })["void"](function() { 46 | 47 | })["while"](function() { 48 | 49 | })["with"](function() { 50 | 51 | })["abstract"](function() { 52 | 53 | })["boolean"](function() { 54 | 55 | })["byte"](function() { 56 | 57 | })["char"](function() { 58 | 59 | })["class"](function() { 60 | 61 | })["const"](function() { 62 | 63 | })["debugger"](function() { 64 | 65 | })["double"](function() { 66 | 67 | })["enum"](function() { 68 | 69 | })["export"](function() { 70 | 71 | })["extends"](function() { 72 | 73 | })["final"](function() { 74 | 75 | })["float"](function() { 76 | 77 | })["goto"](function() { 78 | 79 | })["implements"](function() { 80 | 81 | })["import"](function() { 82 | 83 | })["int"](function() { 84 | 85 | })["interface"](function() { 86 | 87 | })["long"](function() { 88 | 89 | })["native"](function() { 90 | 91 | })["package"](function() { 92 | 93 | })["private"](function() { 94 | 95 | })["protected"](function() { 96 | 97 | })["public"](function() { 98 | 99 | })["short"](function() { 100 | 101 | })["static"](function() { 102 | 103 | })["super"](function() { 104 | 105 | })["synchronized"](function() { 106 | 107 | })["throws"](function() { 108 | 109 | })["transient"](function() { 110 | 111 | })["volatile"](function() { 112 | 113 | })["null"](function() { 114 | 115 | })["true"](function() { 116 | 117 | })["false"](function() { 118 | 119 | })["yield"](function() { 120 | 121 | }); 122 | -------------------------------------------------------------------------------- /tests/regex-test.js: -------------------------------------------------------------------------------- 1 | var assert = require('better-assert'); 2 | var compiler = require('./../index'); 3 | var TEST_REGEX = compiler.TEST_REGEX; 4 | 5 | // For matching test cases 6 | function literalMatchSuite(literal) { 7 | describe(literal, function() { 8 | it('works with property syntax', function() { 9 | var sample = 'var something = { ' + literal + '\t\n :\n \'blah\' };'; 10 | 11 | assert(sample.match(TEST_REGEX)); 12 | }); 13 | 14 | it('works with member syntax', function() { 15 | var sample = 'object\n \t.\n\t ' + literal + '(function(){\n\n});'; 16 | 17 | assert(sample.match(TEST_REGEX)); 18 | }); 19 | 20 | it('does not match alone', function() { 21 | var sample = literal; 22 | 23 | assert(!sample.match(TEST_REGEX)); 24 | }); 25 | }); 26 | } 27 | 28 | // Keyword 29 | literalMatchSuite('break'); 30 | literalMatchSuite('case'); 31 | literalMatchSuite('catch'); 32 | literalMatchSuite('continue'); 33 | literalMatchSuite('default'); 34 | literalMatchSuite('delete'); 35 | literalMatchSuite('do'); 36 | literalMatchSuite('else'); 37 | literalMatchSuite('finally'); 38 | literalMatchSuite('for'); 39 | literalMatchSuite('function'); 40 | literalMatchSuite('if'); 41 | literalMatchSuite('in'); 42 | literalMatchSuite('instanceof'); 43 | literalMatchSuite('new'); 44 | literalMatchSuite('return'); 45 | literalMatchSuite('switch'); 46 | literalMatchSuite('this'); 47 | literalMatchSuite('throw'); 48 | literalMatchSuite('try'); 49 | literalMatchSuite('typeof'); 50 | literalMatchSuite('var'); 51 | literalMatchSuite('void'); 52 | literalMatchSuite('while'); 53 | literalMatchSuite('with'); 54 | 55 | // FutureReservedWords 56 | literalMatchSuite('abstract'); 57 | literalMatchSuite('boolean'); 58 | literalMatchSuite('byte'); 59 | literalMatchSuite('char'); 60 | literalMatchSuite('class'); 61 | literalMatchSuite('const'); 62 | literalMatchSuite('debugger'); 63 | literalMatchSuite('double'); 64 | literalMatchSuite('enum'); 65 | literalMatchSuite('export'); 66 | literalMatchSuite('extends'); 67 | literalMatchSuite('final'); 68 | literalMatchSuite('float'); 69 | literalMatchSuite('goto'); 70 | literalMatchSuite('implements'); 71 | literalMatchSuite('import'); 72 | literalMatchSuite('int'); 73 | literalMatchSuite('interface'); 74 | literalMatchSuite('long'); 75 | literalMatchSuite('native'); 76 | literalMatchSuite('package'); 77 | literalMatchSuite('private'); 78 | literalMatchSuite('protected'); 79 | literalMatchSuite('public'); 80 | literalMatchSuite('short'); 81 | literalMatchSuite('static'); 82 | literalMatchSuite('super'); 83 | literalMatchSuite('synchronized'); 84 | literalMatchSuite('throws'); 85 | literalMatchSuite('transient'); 86 | literalMatchSuite('volatile'); 87 | 88 | // NullLiteral 89 | literalMatchSuite('null'); 90 | 91 | // BooleanLiteral 92 | literalMatchSuite('true'); 93 | literalMatchSuite('false'); 94 | -------------------------------------------------------------------------------- /tests/fixtures/local-variable/input.js: -------------------------------------------------------------------------------- 1 | var Namespace = EmberObject.extend({ 2 | isNamespace: true, 3 | 4 | init: function() { 5 | Namespace.NAMESPACES.push(this); 6 | Namespace.PROCESSED = false; 7 | }, 8 | 9 | toString: function() { 10 | var name = get(this, 'name'); 11 | if (name) { return name; } 12 | 13 | findNamespaces(); 14 | return this[NAME_KEY]; 15 | }, 16 | 17 | nameClasses: function() { 18 | processNamespace([this.toString()], this, {}); 19 | }, 20 | 21 | destroy: function() { 22 | var namespaces = Namespace.NAMESPACES, 23 | toString = this.toString(); 24 | 25 | if (toString) { 26 | Ember.lookup[toString] = undefined; 27 | delete Namespace.NAMESPACES_BY_ID[toString]; 28 | } 29 | namespaces.splice(indexOf.call(namespaces, this), 1); 30 | this._super(); 31 | } 32 | }); 33 | 34 | Namespace.reopenClass({ 35 | NAMESPACES: [Ember], 36 | NAMESPACES_BY_ID: {}, 37 | PROCESSED: false, 38 | processAll: processAllNamespaces, 39 | byName: function(name) { 40 | if (!Ember.BOOTED) { 41 | processAllNamespaces(); 42 | } 43 | 44 | return NAMESPACES_BY_ID[name]; 45 | } 46 | }); 47 | 48 | var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID; 49 | 50 | var hasOwnProp = ({}).hasOwnProperty; 51 | 52 | function processNamespace(paths, root, seen) { 53 | var idx = paths.length; 54 | 55 | NAMESPACES_BY_ID[paths.join('.')] = root; 56 | 57 | // Loop over all of the keys in the namespace, looking for classes 58 | for(var key in root) { 59 | if (!hasOwnProp.call(root, key)) { continue; } 60 | var obj = root[key]; 61 | 62 | // If we are processing the `Ember` namespace, for example, the 63 | // `paths` will start with `["Ember"]`. Every iteration through 64 | // the loop will update the **second** element of this list with 65 | // the key, so processing `Ember.View` will make the Array 66 | // `['Ember', 'View']`. 67 | paths[idx] = key; 68 | 69 | // If we have found an unprocessed class 70 | if (obj && obj.toString === classToString) { 71 | // Replace the class' `toString` with the dot-separated path 72 | // and set its `NAME_KEY` 73 | obj.toString = makeToString(paths.join('.')); 74 | obj[NAME_KEY] = paths.join('.'); 75 | 76 | // Support nested namespaces 77 | } else if (obj && obj.isNamespace) { 78 | // Skip aliased namespaces 79 | if (seen[guidFor(obj)]) { continue; } 80 | seen[guidFor(obj)] = true; 81 | 82 | // Process the child namespace 83 | processNamespace(paths, obj, seen); 84 | } 85 | } 86 | 87 | paths.length = idx; // cut out last item 88 | } 89 | 90 | var STARTS_WITH_UPPERCASE = /^[A-Z]/; 91 | 92 | function findNamespaces() { 93 | var lookup = Ember.lookup, obj, isNamespace; 94 | 95 | if (Namespace.PROCESSED) { return; } 96 | 97 | for (var prop in lookup) { 98 | // Only process entities that start with uppercase A-Z 99 | if (!STARTS_WITH_UPPERCASE.test(prop)) { continue; } 100 | 101 | // Unfortunately, some versions of IE don't support window.hasOwnProperty 102 | if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; } 103 | 104 | // At times we are not allowed to access certain properties for security reasons. 105 | // There are also times where even if we can access them, we are not allowed to access their properties. 106 | try { 107 | obj = lookup[prop]; 108 | isNamespace = obj && obj.isNamespace; 109 | } catch (e) { 110 | continue; 111 | } 112 | 113 | if (isNamespace) { 114 | obj[NAME_KEY] = prop; 115 | } 116 | } 117 | } 118 | 119 | var NAME_KEY = Ember.NAME_KEY = GUID_KEY + '_name'; 120 | 121 | function superClassString(mixin) { 122 | var superclass = mixin.superclass; 123 | if (superclass) { 124 | if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; } 125 | else { return superClassString(superclass); } 126 | } else { 127 | return; 128 | } 129 | } 130 | 131 | function classToString() { 132 | if (!Ember.BOOTED && !this[NAME_KEY]) { 133 | processAllNamespaces(); 134 | } 135 | 136 | var ret; 137 | 138 | if (this[NAME_KEY]) { 139 | ret = this[NAME_KEY]; 140 | } else if (this._toString) { 141 | ret = this._toString; 142 | } else { 143 | var str = superClassString(this); 144 | if (str) { 145 | ret = "(subclass of " + str + ")"; 146 | } else { 147 | ret = "(unknown mixin)"; 148 | } 149 | this.toString = makeToString(ret); 150 | } 151 | 152 | return ret; 153 | } 154 | 155 | function processAllNamespaces() { 156 | var unprocessedNamespaces = !Namespace.PROCESSED, 157 | unprocessedMixins = Ember.anyUnprocessedMixins; 158 | 159 | if (unprocessedNamespaces) { 160 | findNamespaces(); 161 | Namespace.PROCESSED = true; 162 | } 163 | 164 | if (unprocessedNamespaces || unprocessedMixins) { 165 | var namespaces = Namespace.NAMESPACES, namespace; 166 | for (var i=0, l=namespaces.length; i= 0; i--) { 137 | var range = collectedDatas[i].range; 138 | var replaceString = collectedDatas[i].replaceString; 139 | source = source.slice(0, range[0]) + replaceString + source.slice(range[1]); 140 | } 141 | return source; 142 | } 143 | 144 | var TEST_REGEX = module.exports.TEST_REGEX = buildTestRegex(); 145 | module.exports.compile = function(source, options) { 146 | var ast, code; 147 | if (TEST_REGEX.test(source)) { 148 | ast = recast.parse(source); 149 | recast.visit(ast, visitor); 150 | code = recast.print(ast).code; 151 | } else { 152 | code = source; 153 | } 154 | if (options && options.trailingComma) { 155 | return removeTrailingComma(code); 156 | } 157 | return code; 158 | }; 159 | 160 | function buildTestRegex() { 161 | var literalsString = Object.keys(identifierToLiteral).join('|'); 162 | var memberString = '\\.\\s*(' + literalsString + ')'; 163 | var propertyString = '(' + literalsString + ')\\s*\\:'; 164 | var regexString = memberString + '|' + propertyString; 165 | return new RegExp(regexString, 'i'); 166 | } 167 | 168 | module.exports.visit = function(ast) { 169 | recast.visit(ast, visitor); 170 | 171 | return ast; 172 | }; 173 | -------------------------------------------------------------------------------- /tests/compiler-test.js: -------------------------------------------------------------------------------- 1 | var assert = require('better-assert'); 2 | var astEqual = require('ast-equality'); 3 | var readFileSync = require('fs').readFileSync; 4 | 5 | var compiler = require('./../index'); 6 | 7 | describe('object properties', function() { 8 | it('works', function() { 9 | var path = './tests/fixtures/object-literal'; 10 | var actual = compiler.compile(readFileSync(path + '/input.js')); 11 | var expected = readFileSync(path + '/output.js'); 12 | 13 | astEqual(actual, expected, 'expected input.js and output.js to match'); 14 | }); 15 | }); 16 | 17 | describe('parses es6-module-syntax without error', function() { 18 | it('works', function() { 19 | var path = './tests/fixtures/es6-module-syntax'; 20 | var actual = compiler.compile(readFileSync(path + '/input.js')); 21 | var expected = readFileSync(path + '/output.js'); 22 | 23 | // bring this back once we can output ES6 module syntax 24 | //astEqual(actual, expected, 'expected input.js and output.js to match'); 25 | }); 26 | }); 27 | 28 | describe('object member', function() { 29 | it('works', function() { 30 | var path = './tests/fixtures/object-member'; 31 | var actual = compiler.compile(readFileSync(path + '/input.js')); 32 | var expected = readFileSync(path + '/output.js'); 33 | 34 | astEqual(actual, expected, 'expected input.js and output.js to match'); 35 | }); 36 | }); 37 | 38 | describe('such-es2015', function() { 39 | it('works', function() { 40 | var path = './tests/fixtures/such-es2015'; 41 | var actual = compiler.compile(readFileSync(path + '/input.js')); 42 | var expected = readFileSync(path + '/output.js'); 43 | 44 | astEqual(actual, expected, 'expected input.js and output.js to match'); 45 | }); 46 | }); 47 | 48 | it('protected local variable scope test', function() { 49 | var path = './tests/fixtures/local-variable'; 50 | var actual = compiler.compile(readFileSync(path + '/input.js')); 51 | var expected = readFileSync(path + '/output.js'); 52 | 53 | astEqual(actual, expected, 'expected input.js and output.js to match'); 54 | }); 55 | 56 | it('should leave trailing commas in place when trailingComma option is not specified', function() { 57 | var expected = 'var object = {\n a:1, b:[1,2,],\n};' 58 | var actual = compiler.compile(expected); 59 | 60 | astEqual(actual, expected, "expected input and output to match."); 61 | }); 62 | 63 | it('should remove trailing commas in object/array literals when trailingComma option is specified', function() { 64 | var actual = compiler.compile('var object = {\n a:1, b:[1,2,],\n};', { trailingComma: true }); 65 | var expected = 'var object = {\n a:1, b:[1,2]\n};'; 66 | 67 | astEqual(actual, expected, "expected input and output to match"); 68 | }); 69 | 70 | function literalTestSuite(literal) { 71 | describe(literal, function() { 72 | it('works with literal syntax', function() { 73 | var actual = compiler.compile('var object = {\n' + literal + ': null,\n};'); 74 | var expected = 'var object = {\n"' + literal + '": null,\n};' 75 | 76 | astEqual(actual, expected, 'expected input.js and output.js to match'); 77 | }); 78 | 79 | it('works with literal syntax and set to remove trailing comma', function() { 80 | var actual = compiler.compile('var object = {\n' + literal + ': null,\n};', { trailingComma: true }); 81 | debugger; 82 | var expected = 'var object = {\n"' + literal + '": null\n};' 83 | 84 | astEqual(actual, expected, 'expected input.js and output.js to match'); 85 | }); 86 | 87 | it('works with member syntax', function() { 88 | var actual = compiler.compile('object.' + literal + '(function(){\n\n});'); 89 | var expected = 'object["' + literal + '"](function(){\n\n});'; 90 | 91 | astEqual(actual, expected, 'expected input.js and output.js to match'); 92 | }); 93 | }); 94 | } 95 | 96 | // Keyword 97 | literalTestSuite('break'); 98 | literalTestSuite('case'); 99 | literalTestSuite('catch'); 100 | literalTestSuite('continue'); 101 | literalTestSuite('default'); 102 | literalTestSuite('delete'); 103 | literalTestSuite('do'); 104 | literalTestSuite('else'); 105 | literalTestSuite('finally'); 106 | literalTestSuite('for'); 107 | literalTestSuite('function'); 108 | literalTestSuite('if'); 109 | literalTestSuite('in'); 110 | literalTestSuite('instanceof'); 111 | literalTestSuite('new'); 112 | literalTestSuite('return'); 113 | literalTestSuite('switch'); 114 | literalTestSuite('this'); 115 | literalTestSuite('throw'); 116 | literalTestSuite('try'); 117 | literalTestSuite('typeof'); 118 | literalTestSuite('var'); 119 | literalTestSuite('void'); 120 | literalTestSuite('while'); 121 | literalTestSuite('with'); 122 | 123 | // FutureReservedWords 124 | literalTestSuite('abstract'); 125 | literalTestSuite('boolean'); 126 | literalTestSuite('byte'); 127 | literalTestSuite('char'); 128 | literalTestSuite('class'); 129 | literalTestSuite('const'); 130 | literalTestSuite('debugger'); 131 | literalTestSuite('double'); 132 | literalTestSuite('enum'); 133 | literalTestSuite('export'); 134 | literalTestSuite('extends'); 135 | literalTestSuite('final'); 136 | literalTestSuite('float'); 137 | literalTestSuite('goto'); 138 | literalTestSuite('implements'); 139 | literalTestSuite('import'); 140 | literalTestSuite('int'); 141 | literalTestSuite('interface'); 142 | literalTestSuite('long'); 143 | literalTestSuite('native'); 144 | literalTestSuite('package'); 145 | literalTestSuite('private'); 146 | literalTestSuite('protected'); 147 | literalTestSuite('public'); 148 | literalTestSuite('short'); 149 | literalTestSuite('static'); 150 | literalTestSuite('super'); 151 | literalTestSuite('synchronized'); 152 | literalTestSuite('throws'); 153 | literalTestSuite('transient'); 154 | literalTestSuite('volatile'); 155 | 156 | // NullLiteral 157 | literalTestSuite('null'); 158 | 159 | // BooleanLiteral 160 | literalTestSuite('true'); 161 | literalTestSuite('false'); 162 | --------------------------------------------------------------------------------