1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

[CS2] Remove unnecessary utility helper functions (#4526)

* Uncomment module test that was waiting for classes to be supported

* Rely on native indexOf

* Replace `bind` helper with native `bind` (no shortcut necessary)

* Update output

* Update modules class tests

* Remove helper for prototype extends

* Update docs to reflect removed extends operator

* Add shortcut for splice, like we have for slice
This commit is contained in:
Geoffrey Booth 2017-04-25 07:10:42 -07:00 committed by GitHub
parent 7e35c2c3da
commit 07ae1edb44
12 changed files with 70 additions and 96 deletions

View file

@ -1,6 +1,6 @@
## Prototypal Inheritance
In addition to supporting ES2015 classes, CoffeeScript provides a few shortcuts for working with prototypes. The `extends` operator can be used to create an inheritance chain between any pair of constructor functions, and `::` gives you quick access to an objects prototype:
In addition to supporting ES2015 classes, CoffeeScript provides a shortcut for working with prototypes. The `::` operator gives you quick access to an objects prototype:
```
codeFor('prototypes', '"one_two".dasherize()')

View file

@ -1,7 +1,7 @@
// Generated by CoffeeScript 2.0.0-beta1
(function() {
var CoffeeScript, compile, runScripts,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
indexOf = [].indexOf;
CoffeeScript = require('./coffeescript');

View file

@ -1,7 +1,7 @@
// Generated by CoffeeScript 2.0.0-beta1
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
indexOf = [].indexOf;
fs = require('fs');

View file

@ -783,8 +783,6 @@
return new Assign($1, $4, $2);
}), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', function() {
return new Assign($1, $4, $2);
}), o('SimpleAssignable EXTENDS Expression', function() {
return new Extends($1, $3);
})
]
};

View file

@ -1,7 +1,7 @@
// Generated by CoffeeScript 2.0.0-beta1
(function() {
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, repeat, starts, throwSyntaxError,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
indexOf = [].indexOf;
({Rewriter, INVERSES} = require('./rewriter'));

View file

@ -1,7 +1,8 @@
// Generated by CoffeeScript 2.0.0-beta1
(function() {
var Access, Arr, Assign, AwaitReturn, Base, Block, BooleanLiteral, Call, Class, Code, CodeFragment, Comment, ExecutableClassBody, Existence, Expansion, ExportAllDeclaration, ExportDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, ExportSpecifierList, Extends, For, HoistTarget, IdentifierLiteral, If, ImportClause, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, ImportSpecifierList, In, Index, InfinityLiteral, JS_FORBIDDEN, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, ModuleDeclaration, ModuleSpecifier, ModuleSpecifierList, NEGATE, NO, NaNLiteral, NullLiteral, NumberLiteral, Obj, Op, Param, Parens, PassthroughLiteral, PropertyName, Range, RegexLiteral, RegexWithInterpolations, Return, SIMPLENUM, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, Super, SuperCall, Switch, TAB, THIS, TaggedTemplateCall, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, isLiteralArguments, isLiteralThis, isUnassignable, locationDataToString, merge, multident, shouldCacheOrIsAssignable, some, starts, throwSyntaxError, unfoldSoak, utility,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
splice = [].splice,
indexOf = [].indexOf,
slice = [].slice;
Error.stackTraceLimit = 2e308;
@ -241,7 +242,7 @@
for (i = k = 0, len2 = children.length; k < len2; i = ++k) {
child = children[i];
if (match(child)) {
[].splice.apply(children, [i, i - i + 1].concat(ref2 = replacement(child, this))), ref2;
splice.apply(children, [i, i - i + 1].concat(ref2 = replacement(child, this))), ref2;
return true;
} else {
if (child.replaceInContext(match, replacement)) {
@ -341,7 +342,7 @@
for (i = j = fragments.length - 1; j >= 0; i = j += -1) {
fragment = fragments[i];
if (fragment.fragments) {
[].splice.apply(fragments, [i, i - i + 1].concat(ref1 = this.expand(fragment.fragments))), ref1;
splice.apply(fragments, [i, i - i + 1].concat(ref1 = this.expand(fragment.fragments))), ref1;
}
}
return fragments;
@ -1830,7 +1831,7 @@
end++;
}
pushSlice();
[].splice.apply(expressions, [i, i - i + 1].concat(exprs)), exprs;
splice.apply(expressions, [i, i - i + 1].concat(exprs)), exprs;
i += exprs.length;
} else {
if (initializerExpression = this.addInitializerExpression(expression)) {
@ -1942,7 +1943,7 @@
for (j = ref1.length - 1; j >= 0; j += -1) {
name = ref1[j];
name = new Value(new ThisLiteral, [name]).compile(o);
results.push(new Literal(`${name} = ${utility('bind', o)}(${name}, this)`));
results.push(new Literal(`${name} = ${name}.bind(this)`));
}
return results;
}).call(this);
@ -2629,7 +2630,7 @@
to = "9e9";
}
[valDef, valRef] = this.value.cache(o, LEVEL_LIST);
answer = [].concat(this.makeCode(`[].splice.apply(${name}, [${fromDecl}, ${to}].concat(`), valDef, this.makeCode(")), "), valRef);
answer = [].concat(this.makeCode(`${utility('splice', o)}.apply(${name}, [${fromDecl}, ${to}].concat(`), valDef, this.makeCode(")), "), valRef);
if (o.level > LEVEL_TOP) {
return this.wrapInParentheses(answer);
} else {
@ -4180,23 +4181,20 @@
})();
UTILITIES = {
extend: function(o) {
return `function(child, parent) { for (var key in parent) { if (${utility('hasProp', o)}.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); return child; }`;
},
bind: function() {
return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
},
indexOf: function() {
return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }";
},
modulo: function() {
return "function(a, b) { return (+a % (b = +b) + b) % b; }";
return 'function(a, b) { return (+a % (b = +b) + b) % b; }';
},
hasProp: function() {
return '{}.hasOwnProperty';
},
indexOf: function() {
return '[].indexOf';
},
slice: function() {
return '[].slice';
},
splice: function() {
return '[].splice';
}
};

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
// Generated by CoffeeScript 2.0.0-beta1
(function() {
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, rite,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
indexOf = [].indexOf;
generate = function(tag, value, origin) {
var tok;

View file

@ -1,7 +1,7 @@
// Generated by CoffeeScript 2.0.0-beta1
(function() {
var Scope,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
indexOf = [].indexOf;
exports.Scope = Scope = class Scope {
constructor(parent, expressions, method, referencedVars) {

View file

@ -699,7 +699,6 @@ grammar =
INDENT Expression OUTDENT', -> new Assign $1, $4, $2
o 'SimpleAssignable COMPOUND_ASSIGN TERMINATOR
Expression', -> new Assign $1, $4, $2
o 'SimpleAssignable EXTENDS Expression', -> new Extends $1, $3
]

View file

@ -1427,7 +1427,7 @@ exports.Class = class Class extends Base
proxyBoundMethods: (o) ->
@ctor.thisAssignments = for name in @boundMethods by -1
name = new Value(new ThisLiteral, [ name ]).compile o
new Literal "#{name} = #{utility 'bind', o}(#{name}, this)"
new Literal "#{name} = #{name}.bind(this)"
null
@ -1873,7 +1873,7 @@ exports.Assign = class Assign extends Base
if not expandedIdx and obj instanceof Splat
name = obj.name.unwrap().value
obj = obj.unwrap()
val = "#{olen} <= #{vvarText}.length ? #{ utility 'slice', o }.call(#{vvarText}, #{i}"
val = "#{olen} <= #{vvarText}.length ? #{utility 'slice', o}.call(#{vvarText}, #{i}"
rest = olen - i - 1
if rest isnt 0
ivar = o.scope.freeVariable 'i', single: true
@ -1972,7 +1972,7 @@ exports.Assign = class Assign extends Base
else
to = "9e9"
[valDef, valRef] = @value.cache o, LEVEL_LIST
answer = [].concat @makeCode("[].splice.apply(#{name}, [#{fromDecl}, #{to}].concat("), valDef, @makeCode(")), "), valRef
answer = [].concat @makeCode("#{utility 'splice', o}.apply(#{name}, [#{fromDecl}, #{to}].concat("), valDef, @makeCode(")), "), valRef
if o.level > LEVEL_TOP then @wrapInParentheses answer else answer
eachName: (iterator) ->
@ -3109,49 +3109,13 @@ exports.If = class If extends Base
# ---------
UTILITIES =
# Correctly set up a prototype chain for inheritance, including a reference
# to the superclass for `super()` calls, and copies of any static properties.
extend: (o) -> "
function(child, parent) {
for (var key in parent) {
if (#{utility 'hasProp', o}.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
return child;
}
"
# Create a function bound to the current value of "this".
bind: -> '
function(fn, me){
return function(){
return fn.apply(me, arguments);
};
}
'
# Discover if an item is in an array.
indexOf: -> "
[].indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (i in this && this[i] === item) return i;
}
return -1;
}
"
modulo: -> """
function(a, b) { return (+a % (b = +b) + b) % b; }
"""
modulo: -> 'function(a, b) { return (+a % (b = +b) + b) % b; }'
# Shortcuts to speed up the lookup time for native functions.
hasProp: -> '{}.hasOwnProperty'
indexOf: -> '[].indexOf'
slice : -> '[].slice'
splice : -> '[].splice'
# Levels indicate a node's position in the AST. Useful for knowing if
# parens are necessary or superfluous.

View file

@ -433,47 +433,65 @@ test "export default predefined function", ->
export default foo;"""
eq toJS(input), output
# Uncomment this test once ES2015+ `class` support is added
test "export default class", ->
input = """
export default class foo extends bar
baz: ->
console.log 'hello, world!'"""
output = """
var foo;
# test "export default class", ->
# input = """
# export default class foo extends bar
# baz: ->
# console.log 'hello, world!'"""
# output = """
# export default class foo extends bar {
# baz: function {
# return console.log('hello, world!');
# }
# }"""
# eq toJS(input), output
export default foo = class foo extends bar {
baz() {
return console.log('hello, world!');
}
};"""
eq toJS(input), output
# Very limited tests for now, testing that `export class foo` either compiles
# identically (ES2015+) or at least into some function, leaving the specifics
# vague in case the CoffeeScript `class` interpretation changes
test "export class", ->
input = """
export class foo
baz: ->
console.log 'hello, world!'"""
output = toJS input
ok /^export (var foo = class foo|var foo = \(function)/.test toJS input
output = """
export var foo = class foo {
baz() {
return console.log('hello, world!');
}
};"""
eq toJS(input), output
test "export class that extends", ->
input = """
export class foo extends bar
baz: ->
console.log 'hello, world!'"""
output = toJS input
ok /export var foo = class foo/.test(output) and \
not /var foo(;|,)/.test output
output = """
export var foo = class foo extends bar {
baz() {
return console.log('hello, world!');
}
};"""
eq toJS(input), output
test "export default class that extends", ->
input = """
export default class foo extends bar
baz: ->
console.log 'hello, world!'"""
ok /export default foo = class foo/.test toJS input
output = """
var foo;
export default foo = class foo extends bar {
baz() {
return console.log('hello, world!');
}
};"""
eq toJS(input), output
test "export default named member, within an object", ->
input = "export { foo as default, bar }"