Skip to content

Update upstream #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
71 changes: 60 additions & 11 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,24 +358,73 @@ module.exports = function(grunt) {
});

//alias tasks
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['eslint', 'package', 'test:unit', 'test:promises-aplus', 'tests:docs', 'test:protractor']);
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', [
'eslint',
'package',
'test:unit',
'test:promises-aplus',
'tests:docs',
'test:protractor'
]);
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
grunt.registerTask('test:jquery', 'Run the jQuery (latest) unit tests with Karma', ['tests:jquery']);
grunt.registerTask('test:jquery-2.2', 'Run the jQuery 2.2 unit tests with Karma', ['tests:jquery-2.2']);
grunt.registerTask('test:jquery-2.1', 'Run the jQuery 2.1 unit tests with Karma', ['tests:jquery-2.1']);
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['build', 'tests:modules']);
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', [
'build',
'tests:modules'
]);
grunt.registerTask('test:docs', 'Run the doc-page tests with Karma', ['package', 'tests:docs']);
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', ['test:jqlite', 'test:jquery', 'test:jquery-2.2', 'test:jquery-2.1', 'test:modules']);
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'protractor:normal']);
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', [
'test:jqlite',
'test:jquery',
'test:jquery-2.2',
'test:jquery-2.1',
'test:modules'
]);
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', [
'webdriver',
'connect:testserver',
'protractor:normal'
]);
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', [
'connect:testserver',
'protractor:travis'
]);
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', [
'webdriver',
'connect:testserver',
'protractor:jenkins'
]);
grunt.registerTask('test:e2e', 'Alias for test:protractor', ['test:protractor']);
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter', 'shell:promises-aplus-tests']);

grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
grunt.registerTask('test:promises-aplus',[
'build:promises-aplus-adapter',
'shell:promises-aplus-tests'
]);
grunt.registerTask('minify', [
'bower',
'clean',
'build',
'minall'
]);
grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'write', 'docs', 'copy', 'compress']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'eslint']);
grunt.registerTask('package', [
'bower',
'validate-angular-files',
'clean',
'buildall',
'minall',
'collect-errors',
'write',
'docs',
'copy',
'compress'
]);
grunt.registerTask('ci-checks', [
'ddescribe-iit',
'merge-conflict',
'eslint'
]);
grunt.registerTask('default', ['package']);
};

Expand Down
12 changes: 10 additions & 2 deletions karma-shared.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@ module.exports = function(config, specificOptions) {
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 2,
browserNoActivityTimeout: 30000,


reporters: ['spec'],
specReporter: {
maxLogLines: 5, // limit number of lines logged per test
suppressErrorSummary: true, // do not print error summary
suppressFailed: false, // do not print information about failed tests
suppressPassed: true, // do not print information about passed tests
suppressSkipped: false, // do not print information about skipped tests
showSpecTiming: false, // print the time elapsed for each spec
failFast: false // test would finish with error when a first fail occurs.
},
// SauceLabs config for local development.
sauceLabs: {
testName: specificOptions.testName || 'AngularJS',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"karma-ng-scenario": "^1.0.0",
"karma-sauce-launcher": "^1.1.0",
"karma-script-launcher": "^1.0.0",
"karma-spec-reporter": "^0.0.31",
"load-grunt-tasks": "^3.5.0",
"lodash": "~2.4.1",
"log4js": "^0.6.27",
Expand Down
19 changes: 15 additions & 4 deletions scripts/travis/before_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,26 @@ set -e

yarn global add [email protected]

mkdir -p $LOGS_DIR
mkdir -p "$LOGS_DIR"

if [ $JOB != "ci-checks" ]; then
if [ "$JOB" != "ci-checks" ]; then
echo "start_browser_provider"
./scripts/travis/start_browser_provider.sh
fi

if [ $JOB != "ci-checks" ]; then
# ci-checks and unit tests do not run against the packaged code
if [ "$JOB" != "ci-checks" ] && [ "$JOB" != "unit" ]; then
grunt package
fi

# unit runs the docs tests too which need a built version of the code
if [ "$JOB" = "unit" ]; then
grunt build
fi

# check this after the package, because at this point the browser_provider
# has probably arrived
if [ "$JOB" != "ci-checks" ]; then
echo "wait_for_browser_provider"
./scripts/travis/wait_for_browser_provider.sh
fi
fi
4 changes: 2 additions & 2 deletions scripts/travis/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ elif [ "$JOB" == "unit" ]; then
fi

grunt test:promises-aplus
grunt test:unit --browsers="$BROWSERS" --reporters=dots
grunt tests:docs --browsers="$BROWSERS" --reporters=dots
grunt test:unit --browsers="$BROWSERS" --reporters=spec
grunt tests:docs --browsers="$BROWSERS" --reporters=spec
elif [ "$JOB" == "docs-e2e" ]; then
grunt test:travis-protractor --specs="docs/app/e2e/**/*.scenario.js"
elif [ "$JOB" == "e2e" ]; then
Expand Down
23 changes: 16 additions & 7 deletions src/ng/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,9 @@ function isStateless($filter, filterName) {
return !fn.$stateful;
}

var PURITY_ABSOLUTE = 1;
var PURITY_RELATIVE = 2;

// Detect nodes which could depend on non-shallow state of objects
function isPure(node, parentIsPure) {
switch (node.type) {
Expand All @@ -634,18 +637,18 @@ function isPure(node, parentIsPure) {

// Unary always convert to primative
case AST.UnaryExpression:
return true;
return PURITY_ABSOLUTE;

// The binary + operator can invoke a stateful toString().
case AST.BinaryExpression:
return node.operator !== '+';
return node.operator !== '+' ? PURITY_ABSOLUTE : false;

// Functions / filters probably read state from within objects
case AST.CallExpression:
return false;
}

return (undefined === parentIsPure) || parentIsPure;
return (undefined === parentIsPure) ? PURITY_RELATIVE : parentIsPure;
}

function findConstantAndWatchExpressions(ast, $filter, parentIsPure) {
Expand Down Expand Up @@ -873,7 +876,7 @@ ASTCompiler.prototype = {
forEach(inputs, function(input) {
result.push('var ' + input.name + '=' + self.generateFunction(input.name, 's'));
if (input.isPure) {
result.push(input.name, '.isPure=true;');
result.push(input.name, '.isPure=' + JSON.stringify(input.isPure) + ';');
}
});
if (inputs.length) {
Expand Down Expand Up @@ -1960,10 +1963,16 @@ function $ParseProvider() {
fn.$$watchDelegate = watchDelegate;
fn.inputs = parsedExpression.inputs;
} else if (!interceptorFn.$stateful) {
// If there is an interceptor, but no watchDelegate then treat the interceptor like
// we treat filters - it is assumed to be a pure function unless flagged with $stateful
// Treat interceptor like filters - assume non-stateful by default and use the inputsWatchDelegate
fn.$$watchDelegate = inputsWatchDelegate;
fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
fn.inputs = (parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]).map(function(e) {
// Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a
// potentially non-pure interceptor function.
if (e.isPure === PURITY_RELATIVE) {
return function depurifier(s) { return e(s); };
}
return e;
});
}

return fn;
Expand Down
16 changes: 16 additions & 0 deletions test/ng/directive/ngClassSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,22 @@ describe('ngClass', function() {
})
);

// https://github.com/angular/angular.js/issues/15905
it('should support a mixed literal-array/object variable', inject(function($rootScope, $compile) {
element = $compile('<div ng-class="[classVar]"></div>')($rootScope);

$rootScope.classVar = {orange: true};
$rootScope.$digest();
expect(element).toHaveClass('orange');

$rootScope.classVar.orange = false;
$rootScope.$digest();

expect(element).not.toHaveClass('orange');
})
);


it('should do value stabilization as expected when one-time binding',
inject(function($rootScope, $compile) {
element = $compile('<div ng-class="::className"></div>')($rootScope);
Expand Down
45 changes: 45 additions & 0 deletions test/ng/parseSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3277,6 +3277,25 @@ describe('parser', function() {
expect(called).toBe(true);
}));

it('should always be invoked if inputs are non-primitive', inject(function($parse) {
var called = false;
function interceptor(v) {
called = true;
return v.sub;
}

scope.$watch($parse('[o]', interceptor));
scope.o = {sub: 1};

called = false;
scope.$digest();
expect(called).toBe(true);

called = false;
scope.$digest();
expect(called).toBe(true);
}));

it('should not be invoked unless the input.valueOf() changes even if the instance changes', inject(function($parse) {
var called = false;
function interceptor(v) {
Expand Down Expand Up @@ -3321,6 +3340,32 @@ describe('parser', function() {
scope.$digest();
expect(called).toBe(true);
}));

it('should not affect when a one-time binding becomes stable', inject(function($parse) {
scope.$watch($parse('::x'));
scope.$watch($parse('::x', identity));
scope.$watch($parse('::x', function() { return 1; })); //interceptor that returns non-undefined

scope.$digest();
expect(scope.$$watchersCount).toBe(3);

scope.x = 1;
scope.$digest();
expect(scope.$$watchersCount).toBe(0);
}));

it('should not affect when a one-time literal binding becomes stable', inject(function($parse) {
scope.$watch($parse('::[x]'));
scope.$watch($parse('::[x]', identity));
scope.$watch($parse('::[x]', function() { return 1; })); //interceptor that returns non-literal

scope.$digest();
expect(scope.$$watchersCount).toBe(3);

scope.x = 1;
scope.$digest();
expect(scope.$$watchersCount).toBe(0);
}));
});

describe('literals', function() {
Expand Down
8 changes: 7 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@ [email protected]:
version "1.0.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"

colors@^1.1.0, colors@~1.1.2:
colors@^1.1.0, colors@^1.1.2, colors@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"

Expand Down Expand Up @@ -3649,6 +3649,12 @@ karma-script-launcher@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz#cd017c4de5ef09e5a9da793276176108dd4b542d"

karma-spec-reporter@^0.0.31:
version "0.0.31"
resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3"
dependencies:
colors "^1.1.2"

karma@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/karma/-/karma-1.7.0.tgz#6f7a1a406446fa2e187ec95398698f4cee476269"
Expand Down