Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Spread operator #9

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
557e531
spread operators in arrays
fdecampredon Mar 25, 2014
5d4165d
spread operator in call expression
fdecampredon Mar 25, 2014
eea0233
renaming
fdecampredon Mar 25, 2014
f624afa
spread in new expression
fdecampredon Mar 25, 2014
4f31127
cleaning and line break respect in new expression
fdecampredon Mar 25, 2014
a2491ef
replace spread template
fdecampredon Mar 25, 2014
366b3f4
comment with examples of how the spread operator works
fdecampredon Mar 25, 2014
b90ed59
todo comments syntax correction
fdecampredon Mar 25, 2014
7366326
externalize templates in a separate modules
fdecampredon Mar 26, 2014
7d7aeac
fix case of '(' and ')' in comments that was replaced
fdecampredon Mar 26, 2014
7828a12
Fix new expression with function that returns value
fdecampredon Mar 26, 2014
70bafa2
Revert templates extenalizing
fdecampredon Mar 27, 2014
ab7c4b4
reformat a little the code source output in tests
fdecampredon Mar 27, 2014
5d4d437
add runtimes inclusion logic
fdecampredon Mar 28, 2014
8615906
fix bad tests
fdecampredon Mar 28, 2014
0aa0ecb
replace spread element check by runtimes call
fdecampredon Mar 28, 2014
f15ee21
replace iife by runtimes call to executeNewExpression
fdecampredon Apr 1, 2014
1022d74
Merge branch 'spread-operator-with-runtime' into spread-operator
fdecampredon Apr 2, 2014
2f16f3d
remove loging
fdecampredon Apr 2, 2014
0e94da6
adding failing test case for array elements without spread operator
fdecampredon Apr 2, 2014
c941ee0
fix output code source too match the excepted transformation
fdecampredon Apr 2, 2014
d12fc1b
remove jshint comments in spread-operator-runtime
fdecampredon Apr 2, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 252 additions & 0 deletions visitors/__tests__/es6-spread-operator-visitors-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
/**
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @emails [email protected] [email protected]
*/

/*jshint evil:true, unused: false*/
/* global describe, beforeEach, expect, it*/



describe('es6-spread-operator-visitors', function() {
var fs = require('fs'), path = require('path'),
runtime = fs.readFileSync(path.join(__dirname, '..', 'es6-spread-operator-runtime.js'), 'utf-8');

var visitors,
transformFn;

beforeEach(function() {
visitors = require('../es6-spread-operator-visitors').visitorList;
transformFn = require('../../src/jstransform').transform;
});

function transform(code, options) {
return transformFn(visitors, code, options).code;
}

function expectTransform(code, result, options) {
expect(transform(code, options)).toEqual(result);
}

describe('runtime', function () {
it('should be included if the options \'includeSpreadRuntime \' is set to true ', function () {
expectTransform('', runtime, { includeSpreadRuntime: true });
});

it('should not be included otherwise', function () {
expectTransform('', '', {});
});
});


describe('within array', function () {
it('should create an array concatanation of each object in array, and each parameters ', function () {
expect(eval(transform('[1, 2, ...[3, 4]]', { includeSpreadRuntime: true }))).toEqual([1, 2, 3, 4]);
});

it('should works with only spread', function () {
expect(eval(transform('[...[1, 2]]', { includeSpreadRuntime: true }))).toEqual([1, 2]);
});

it('should throws an error if spread a non object ', function () {
expect(function () {
eval(transform('[1, 2, ...undefined]'));
}).toThrow();
});

it('should throws an error if passing a non array', function () {
expect(function () {
eval(transform('[1, 2, ...{ a: 5 }]'));
}).toThrow();
});

it('should accept anything that resolve to an array', function () {
expect(eval(transform('[1, 2, ...(function () { return [3, 4] })()]', { includeSpreadRuntime: true }))).toEqual([1, 2, 3, 4]);
});

it('it should not spread elements without spread operator', function () {
expect(eval(transform('[[1,2], ...[3, 4]]', { includeSpreadRuntime: true }))).toEqual([[1, 2], 3, 4]);
});

it('should ouput the following code source', function () {
expectTransform(
'[1, 2, ...[3, 4]]',
[
'Array.prototype.concat.call(',
'[1, 2], ____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([3, 4])',
')',
].join(''));
});


it('should keep lines break and comments', function () {
expectTransform(
['[1 /*mycomments*/, 2,',
'...[3,',
' 4]]'
].join('\n'),
[
'Array.prototype.concat.call([1 /*mycomments*/, 2],',
'____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([3,',
' 4]))'
].join('\n'));
});
});


describe('within call expression', function () {

function returnArgs () {
return Array.prototype.slice.call(arguments);
}


it('should pass spread array as parameters', function () {
expect(eval(transform('returnArgs(1, 2, ...[3, 4])', { includeSpreadRuntime: true }))).toEqual([1, 2, 3, 4]);
});

it('should ouput the following code source', function () {
expectTransform(
'returnArgs(1, 2, ...[3, 4])',
[
'returnArgs.apply(undefined, Array.prototype.concat.call(',
'[1, 2], ____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([3, 4])',
'))'
].join(''));
});


it('should keep lines break and comments', function () {
expectTransform(
[
'returnArgs /*comments*/(',
' 1, 2,',
' ...[3, 4]',
')'
].join('\n'),
[
'returnArgs.apply(undefined, /*comments*/Array.prototype.concat.call(',
' [1, 2],',
' ____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([3, 4])',
'))'
].join('\n'));
});

it('should keep intact comments with \'(\' && \')\' ', function () {
expectTransform(
[
'returnArgs /*comments (*/( 1, 2,',
'...[3, 4] //comments )',
')'
].join('\n'),
[
'returnArgs.apply(undefined, /*comments (*/Array.prototype.concat.call( [1, 2],',
'____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([3, 4]) //comments )',
'))'
].join('\n'));
});
});


describe('within method call expression', function () {

var object = {
returnArgsAndThis: function() {
return Array.prototype.slice.call(arguments).concat(this);
}
};


it('should keep the \'this\' context in case of method call ', function () {
expect(eval(transform('object.returnArgsAndThis(1, 2, ...[3, 4])', { includeSpreadRuntime: true }))).toEqual([1, 2, 3, 4, object]);
});

it('should keep the \'this\' context in case of computed method call ', function () {
expect(eval(transform('object[\'return\'+\'ArgsAndThis\'](1, 2, ...[3, 4])', { includeSpreadRuntime: true }))).toEqual([1, 2, 3, 4, object]);
});


it('should ouput the following code source', function () {
var transformedCode = transform('object.returnArgsAndThis(1, 2,...[3, 4])');
transformedCode = transformedCode.replace(/_this\d*/g, '_this');
expect(transformedCode).toBe([
'(function() { ',
'var _this = object; ',
'return _this.returnArgsAndThis.apply(_this, Array.prototype.concat.call(',
'[1, 2],____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([3, 4])',
'))',
'})()'
].join(''));
});


});


describe('within new expression', function () {

function MyClass(a, b) {
this.a = a;
this.b = b;
}

function FakeClass(a) {
return a;
}

it('should pass spread array as arguments of the construtor, and produce an object instance of called function', function () {
var result = eval(transform('new MyClass(...[1, 2])', { includeSpreadRuntime: true }));
expect(result).toEqual({
a: 1,
b: 2
});
expect(result instanceof MyClass).toBe(true);
});

it('should return the function return value if the function has one', function () {
expect(eval(transform('new FakeClass(...[1, 2])', { includeSpreadRuntime: true }))).toBe(1);
expect(eval(transform('new FakeClass(...[null])', { includeSpreadRuntime: true }))).toBe(null);
});


it('should ouput the following code source', function () {
var transformedCode = transform('new MyClass(...[1, 2])');
transformedCode = transformedCode.replace(/_result\d*/g, '_result');
transformedCode = transformedCode.replace(/_class\d*/g, '_class');
expect(transformedCode).toBe([
'____JSTRANSFORM_SPREAD_RUNTIME____.executeNewExpression(MyClass, ',
'Array.prototype.concat.call(____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([1, 2]))',
')'
].join(''));
});

it('should keep new lines and comments', function () {
var transformedCode = transform('/*hello world (*/ new /*hello*/\nMyClass(\n /*comments*/ ...[1//comment\n, 2])');
transformedCode = transformedCode.replace(/_result\d*/g, '_result');
transformedCode = transformedCode.replace(/_class\d*/g, '_class');
expect(transformedCode).toBe([
'/*hello world (*/ /*hello*/',
'____JSTRANSFORM_SPREAD_RUNTIME____.executeNewExpression(MyClass, Array.prototype.concat.call(',
' /*comments*/ ____JSTRANSFORM_SPREAD_RUNTIME____.assertSpreadElement([1//comment',
', 2])))'
].join('\n'));
});
});
});


29 changes: 29 additions & 0 deletions visitors/es6-spread-operator-runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(function (global) {

function assertSpreadElement(array) {
if (Array.isArray(array)) {
return array;
}
throw new TypeError(array + ' is not an array');
}

function executeNewExpression(func, args) {
var result = Object.create(func.prototype);
var funcResult = func.apply(result, args);
return typeof funcResult === 'undefined' ? result : funcResult;
}

global.____JSTRANSFORM_SPREAD_RUNTIME____ = {
assertSpreadElement: assertSpreadElement,
executeNewExpression: executeNewExpression
};
})((function () {
if (typeof window !== 'undefined') {
return window;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
}
return this;
})());
Loading