Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b879223cf3 | |||
| bba6004147 | |||
| d386b7ae4b | |||
| ebc5a477db | |||
| 21c935a303 | |||
| 7e5ef766da | |||
| 1cb96303e9 | |||
| d2058d92bd | |||
| 053f4e26ae | |||
| 45ca45a29a | |||
| e2bf5726ab | |||
| bf706f2f52 | |||
| d2fe381ea8 | |||
| 63c83ffa43 | |||
| 7fa13c3da2 | |||
| 4b91042559 | |||
| a9ecde1e33 | |||
| ada25a9266 | |||
| 0f956b2893 | |||
| 17eb3d717f | |||
| c9ccc801b9 | |||
| 420490aa1b | |||
| 2a65c3deb7 | |||
| ef0c333776 | |||
| bce1d8ecad | |||
| 5a1bc6eb32 | |||
| 1f7a0b2b72 | |||
| a665550933 | |||
| d434f3db53 | |||
| 7e08975b67 | |||
| 82c481bb23 | |||
| b1f46bb1b2 | |||
| 3a6bf0d5bc |
+17
-21
@@ -1,6 +1,7 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '0.10'
|
||||
- '4.2'
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -14,28 +15,26 @@ branches:
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- JOB=ci-checks
|
||||
- JOB=unit BROWSER_PROVIDER=saucelabs
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
|
||||
- JOB=unit BROWSER_PROVIDER=browserstack
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack
|
||||
global:
|
||||
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
- BROWSER_STACK_USERNAME=VojtaJina
|
||||
- BROWSER_STACK_ACCESS_KEY=QCQJ1ZpWXpBkSwEdD8ev
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: "JOB=unit BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=docs-e2e BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack"
|
||||
# node 4 likes the G++ v4.8 compiler
|
||||
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
|
||||
install:
|
||||
# Check the size of caches
|
||||
@@ -45,21 +44,18 @@ install:
|
||||
- npm config set spin false
|
||||
# Log HTTP requests
|
||||
- npm config set loglevel http
|
||||
- npm install -g npm@2.5
|
||||
# Instal npm dependecies and ensure that npm cache is not stale
|
||||
- scripts/npm/install-dependencies.sh
|
||||
#- npm install -g npm@2.5
|
||||
# Install npm dependencies and ensure that npm cache is not stale
|
||||
- npm install
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
- ./scripts/travis/start_browser_provider.sh
|
||||
- npm install -g grunt-cli
|
||||
- grunt package
|
||||
- ./scripts/travis/wait_for_browser_provider.sh
|
||||
- ./scripts/travis/before_build.sh
|
||||
|
||||
script:
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
after_script:
|
||||
- ./scripts/travis/tear_down_browser_provider.sh
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
notifications:
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
<a name="1.3.20"></a>
|
||||
# 1.3.20 shallow-translucence (2015-09-29)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$parse:** do not convert to string computed properties multiple times
|
||||
([d434f3db](https://github.com/angular/angular.js/commit/d434f3db53d6209eb140b904e83bbde401686c16))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
|
||||
<a name="1.3.19"></a>
|
||||
# 1.3.19 glutinous-shriek (2015-09-15)
|
||||
|
||||
|
||||
+14
-12
@@ -155,7 +155,7 @@ module.exports = function(grunt) {
|
||||
jscs: {
|
||||
src: ['src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
config: ".jscsrc"
|
||||
config: '.jscsrc'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -220,9 +220,9 @@ module.exports = function(grunt) {
|
||||
dest: 'build/angular-aria.js',
|
||||
src: util.wrap(files['angularModules']['ngAria'], 'module')
|
||||
},
|
||||
"promises-aplus-adapter": {
|
||||
'promises-aplus-adapter': {
|
||||
dest:'tmp/promises-aplus-adapter++.js',
|
||||
src:['src/ng/q.js','lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
src:['src/ng/q.js', 'lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
}
|
||||
},
|
||||
|
||||
@@ -241,7 +241,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
|
||||
"ddescribe-iit": {
|
||||
'ddescribe-iit': {
|
||||
files: [
|
||||
'src/**/*.js',
|
||||
'test/**/*.js',
|
||||
@@ -262,7 +262,7 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
"merge-conflict": {
|
||||
'merge-conflict': {
|
||||
files: [
|
||||
'src/**/*',
|
||||
'test/**/*',
|
||||
@@ -292,11 +292,11 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
shell: {
|
||||
"npm-install": {
|
||||
command: path.normalize('scripts/npm/install-dependencies.sh')
|
||||
'npm-install': {
|
||||
command: 'node scripts/npm/check-node-modules.js'
|
||||
},
|
||||
|
||||
"promises-aplus-tests": {
|
||||
'promises-aplus-tests': {
|
||||
options: {
|
||||
stdout: false,
|
||||
stderr: true,
|
||||
@@ -327,8 +327,10 @@ module.exports = function(grunt) {
|
||||
grunt.task.run('shell:npm-install');
|
||||
}
|
||||
|
||||
|
||||
|
||||
//alias tasks
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', '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 unit tests with Karma', ['tests:jquery']);
|
||||
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['build', 'tests:modules']);
|
||||
@@ -338,11 +340,11 @@ module.exports = function(grunt) {
|
||||
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('test:promises-aplus',['build:promises-aplus-adapter', 'shell:promises-aplus-tests']);
|
||||
|
||||
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
|
||||
grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
|
||||
grunt.registerTask('default', ['package']);
|
||||
};
|
||||
|
||||
Vendored
+2
-1
@@ -32,6 +32,7 @@ var angularFiles = {
|
||||
'src/ng/q.js',
|
||||
'src/ng/raf.js',
|
||||
'src/ng/rootScope.js',
|
||||
'src/ng/rootElement.js',
|
||||
'src/ng/sanitizeUri.js',
|
||||
'src/ng/sce.js',
|
||||
'src/ng/sniffer.js',
|
||||
@@ -78,7 +79,7 @@ var angularFiles = {
|
||||
],
|
||||
|
||||
'angularLoader': [
|
||||
'stringify.js',
|
||||
'src/stringify.js',
|
||||
'src/minErr.js',
|
||||
'src/loader.js'
|
||||
],
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:baddir
|
||||
@fullName Invalid Directive Name
|
||||
@description
|
||||
|
||||
This error occurs when the name of a directive is not valid.
|
||||
|
||||
Directives must start with a lowercase character.
|
||||
@@ -0,0 +1,7 @@
|
||||
@ngdoc error
|
||||
@name ng:cpta
|
||||
@fullName Copying TypedArray
|
||||
@description
|
||||
|
||||
Copying TypedArray's with a destination is not supported because TypedArray
|
||||
objects can not be mutated, they are fixed length.
|
||||
@@ -0,0 +1,28 @@
|
||||
@ngdoc error
|
||||
@name ngModel:nopromise
|
||||
@fullName No promise
|
||||
@description
|
||||
|
||||
The return value of an async validator, must always be a promise. If you want to return a
|
||||
non-promise value, you can convert it to a promise using {@link ng.$q#resolve `$q.resolve()`} or
|
||||
{@link ng.$q#reject `$q.reject()`}.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
.directive('asyncValidator', function($q) {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elem, attrs, ngModel) {
|
||||
ngModel.$asyncValidators.myAsyncValidation = function(modelValue, viewValue) {
|
||||
if (/* I don't need to hit the backend API */) {
|
||||
return $q.resolve(); // to mark as valid or
|
||||
// return $q.reject(); // to mark as invalid
|
||||
} else {
|
||||
// ...send a request to the backend and return a promise
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
})
|
||||
```
|
||||
@@ -173,7 +173,7 @@ function request(method, url, options, response) {
|
||||
res.on('error', function (e) { console.log(e); });
|
||||
break;
|
||||
case 401:
|
||||
console.log('Eror: Login credentials expired! Please login.');
|
||||
console.log('Error: Login credentials expired! Please login.');
|
||||
break;
|
||||
default:
|
||||
data = [];
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Browserstack tunnel"
|
||||
echo "TODO: implement me"
|
||||
exit 1
|
||||
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var glob = require("glob");
|
||||
var _ = require('lodash');
|
||||
var files = require('../../angularFiles').files;
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('validate-angular-files', function() {
|
||||
var combinedFiles = _.clone(files.angularModules);
|
||||
combinedFiles.ng = files.angularSrc;
|
||||
combinedFiles.angularLoader = files.angularLoader;
|
||||
|
||||
var errorsDetected = false;
|
||||
var directories = [];
|
||||
var detectedFiles = {};
|
||||
|
||||
for (var section in combinedFiles) {
|
||||
var sectionFiles = combinedFiles[section];
|
||||
|
||||
if (section != 'angularLoader') {
|
||||
directories.push('src/' + section);
|
||||
}
|
||||
|
||||
grunt.log.debug('Validating ' + sectionFiles.length + ' files from the "' + section + '" module.');
|
||||
|
||||
sectionFiles.forEach(function(file) {
|
||||
detectedFiles[file] = true;
|
||||
|
||||
if (!fs.existsSync(file)) {
|
||||
grunt.log.error(file + ' does not exist in the local file structure.');
|
||||
errorsDetected = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
directories.forEach(function(directory) {
|
||||
glob.sync(directory + '/**/*').forEach(function(filePath) {
|
||||
if (!fs.lstatSync(filePath).isDirectory()) {
|
||||
var fileName = path.basename(filePath);
|
||||
var isHiddenFile = fileName[0] == '.';
|
||||
if (!isHiddenFile && !detectedFiles[filePath]) {
|
||||
grunt.log.error(filePath + ' exists in the local file structure but isn\'t used by any module.');
|
||||
errorsDetected = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (errorsDetected) {
|
||||
throw new Error('Not all files were properly detected in the local file structure.');
|
||||
} else {
|
||||
grunt.log.ok('All files were detected successfully!');
|
||||
}
|
||||
});
|
||||
};
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Sauce Connect tunnel"
|
||||
|
||||
killall sc
|
||||
|
||||
while [[ -n `ps -ef | grep "sauce-connect-" | grep -v "grep"` ]]; do
|
||||
printf "."
|
||||
sleep .5
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Sauce Connect tunnel has been shut down"
|
||||
+240
-74
@@ -207,7 +207,7 @@
|
||||
"dependencies": {
|
||||
"traceur": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "git+https://github.com/vojtajina/traceur-compiler#d90b1e34c799bf61cd1aafdc33db0a554fa9e617",
|
||||
"resolved": "git+https://github.com/vojtajina/traceur-compiler.git#d90b1e34c799bf61cd1aafdc33db0a554fa9e617",
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.7.1",
|
||||
@@ -2580,14 +2580,6 @@
|
||||
},
|
||||
"async-each": {
|
||||
"version": "0.1.6"
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "0.3.6",
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.8.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2740,6 +2732,49 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "6.0.1",
|
||||
"dependencies": {
|
||||
"inflight": {
|
||||
"version": "1.0.4",
|
||||
"dependencies": {
|
||||
"wrappy": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1"
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "1.1.2",
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.3.3",
|
||||
"dependencies": {
|
||||
"wrappy": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"grunt": {
|
||||
"version": "0.4.5",
|
||||
"dependencies": {
|
||||
@@ -5470,14 +5505,6 @@
|
||||
},
|
||||
"async-each": {
|
||||
"version": "0.1.6"
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "0.3.5",
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.5.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6505,37 +6532,45 @@
|
||||
}
|
||||
},
|
||||
"protractor": {
|
||||
"version": "2.0.0",
|
||||
"version": "2.5.1",
|
||||
"dependencies": {
|
||||
"request": {
|
||||
"version": "2.36.0",
|
||||
"version": "2.57.0",
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "0.6.6"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0"
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.2.11"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.5.2"
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.3"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "0.12.1",
|
||||
"bl": {
|
||||
"version": "0.9.4",
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.3.2"
|
||||
"readable-stream": {
|
||||
"version": "1.0.33",
|
||||
"dependencies": {
|
||||
"core-util-is": {
|
||||
"version": "1.0.2"
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1"
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.10.0"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1"
|
||||
},
|
||||
"form-data": {
|
||||
"version": "0.1.4",
|
||||
"version": "0.2.0",
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.9.2"
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "0.0.7",
|
||||
"dependencies": {
|
||||
@@ -6543,17 +6578,34 @@
|
||||
"version": "0.0.5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.0.14",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.12.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.7"
|
||||
},
|
||||
"qs": {
|
||||
"version": "3.1.0"
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.0"
|
||||
"version": "0.4.2"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.2.1"
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "0.10.1",
|
||||
"version": "0.11.0",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "0.1.5"
|
||||
@@ -6567,38 +6619,120 @@
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.3.0"
|
||||
"version": "0.8.0"
|
||||
},
|
||||
"hawk": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.3.1",
|
||||
"dependencies": {
|
||||
"hoek": {
|
||||
"version": "0.9.1"
|
||||
"version": "2.16.3"
|
||||
},
|
||||
"boom": {
|
||||
"version": "0.4.2"
|
||||
"version": "2.10.1"
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "0.2.2"
|
||||
"version": "2.0.5"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "0.2.4"
|
||||
"version": "1.0.9"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.5.0"
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5"
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.5",
|
||||
"dependencies": {
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2"
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "1.8.0",
|
||||
"dependencies": {
|
||||
"bluebird": {
|
||||
"version": "2.10.2"
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.1",
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.1.0"
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.3"
|
||||
},
|
||||
"has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.9.0",
|
||||
"dependencies": {
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-my-json-valid": {
|
||||
"version": "2.12.3",
|
||||
"dependencies": {
|
||||
"generate-function": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"generate-object-property": {
|
||||
"version": "1.2.0",
|
||||
"dependencies": {
|
||||
"is-property": {
|
||||
"version": "1.0.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsonpointer": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"selenium-webdriver": {
|
||||
"version": "2.45.1",
|
||||
"version": "2.47.0",
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "2.3.2",
|
||||
"version": "2.4.4",
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "4.5.3",
|
||||
"version": "5.0.15",
|
||||
"dependencies": {
|
||||
"inflight": {
|
||||
"version": "1.0.4",
|
||||
@@ -6612,13 +6746,13 @@
|
||||
"version": "2.0.1"
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "2.0.4",
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.2",
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "0.2.0"
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1"
|
||||
@@ -6628,12 +6762,15 @@
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.3",
|
||||
"dependencies": {
|
||||
"wrappy": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6643,33 +6780,33 @@
|
||||
"version": "0.0.24"
|
||||
},
|
||||
"ws": {
|
||||
"version": "0.7.1",
|
||||
"version": "0.8.1",
|
||||
"dependencies": {
|
||||
"options": {
|
||||
"version": "0.0.6"
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.1"
|
||||
"version": "1.0.2"
|
||||
},
|
||||
"bufferutil": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.2.1",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.6.2"
|
||||
"version": "2.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.2.1",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.6.2"
|
||||
"version": "2.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6682,10 +6819,10 @@
|
||||
"version": "0.6.1"
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "2.6.2",
|
||||
"version": "4.2.0",
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "3.5.0"
|
||||
"version": "3.10.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6700,18 +6837,47 @@
|
||||
"version": "1.1.0"
|
||||
},
|
||||
"jasminewd2": {
|
||||
"version": "0.0.3"
|
||||
"version": "0.0.6"
|
||||
},
|
||||
"jasmine": {
|
||||
"version": "2.1.1",
|
||||
"version": "2.3.2",
|
||||
"dependencies": {
|
||||
"exit": {
|
||||
"version": "0.1.2"
|
||||
},
|
||||
"jasmine-core": {
|
||||
"version": "2.1.3"
|
||||
"version": "2.3.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"saucelabs": {
|
||||
"version": "0.1.1"
|
||||
"version": "1.0.1",
|
||||
"dependencies": {
|
||||
"https-proxy-agent": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "2.0.1",
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.0.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "3.2.11",
|
||||
@@ -6723,10 +6889,10 @@
|
||||
"version": "0.3.0",
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0"
|
||||
"version": "2.7.3"
|
||||
},
|
||||
"sigmund": {
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6739,7 +6905,7 @@
|
||||
"version": "0.6.1",
|
||||
"dependencies": {
|
||||
"wordwrap": {
|
||||
"version": "0.0.2"
|
||||
"version": "0.0.3"
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10"
|
||||
@@ -6756,14 +6922,14 @@
|
||||
"version": "0.1.32",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"version": "0.1.0"
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-entities": {
|
||||
"version": "1.1.2"
|
||||
"version": "1.1.3"
|
||||
},
|
||||
"accessibility-developer-tools": {
|
||||
"version": "2.6.0"
|
||||
|
||||
Generated
+544
-290
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,10 @@
|
||||
"npm": "~2.5"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"scripts": {
|
||||
"preinstall": "node scripts/npm/check-node-modules.js --purge",
|
||||
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-benchpress": "0.x.x",
|
||||
"benchmark": "1.x.x",
|
||||
@@ -21,6 +25,7 @@
|
||||
"dgeni": "^0.4.0",
|
||||
"dgeni-packages": "^0.10.0",
|
||||
"event-stream": "~3.1.0",
|
||||
"glob": "^6.0.1",
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-bump": "~0.0.13",
|
||||
"grunt-contrib-clean": "~0.6.0",
|
||||
|
||||
@@ -29,6 +29,8 @@ function init {
|
||||
angular-touch
|
||||
angular-messages
|
||||
)
|
||||
# get the npm dist-tag from a custom property (distTag) in package.json
|
||||
DIST_TAG=$(readJsonProp "package.json" "distTag")
|
||||
}
|
||||
|
||||
|
||||
@@ -110,8 +112,6 @@ function publish {
|
||||
|
||||
# don't publish every build to npm
|
||||
if [ "${NEW_VERSION/+sha}" = "$NEW_VERSION" ] ; then
|
||||
# get the npm dist-tag from a custom property (distTag) in package.json
|
||||
DIST_TAG=$(readJsonProp "package.json" "distTag")
|
||||
echo "-- Publishing to npm as $DIST_TAG"
|
||||
npm publish --tag=$DIST_TAG
|
||||
fi
|
||||
|
||||
@@ -7,6 +7,8 @@ echo "#################################"
|
||||
# Enable tracing and exit on first failure
|
||||
set -xe
|
||||
|
||||
scripts/jenkins/set-node-version.sh
|
||||
|
||||
# This is the default set of browsers to use on the CI server unless overridden via env variable
|
||||
if [[ -z "$BROWSERS" ]]
|
||||
then
|
||||
@@ -19,6 +21,7 @@ rm -f angular.js.size
|
||||
|
||||
|
||||
# BUILD #
|
||||
npm install -g grunt-cli
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
|
||||
@@ -4,9 +4,7 @@ echo "#################################"
|
||||
echo "#### Update master ##############"
|
||||
echo "#################################"
|
||||
|
||||
ARG_DEFS=(
|
||||
"[--no-test=(true|false)]"
|
||||
)
|
||||
ARG_DEFS=()
|
||||
|
||||
function init {
|
||||
if [[ ! $VERBOSE ]]; then
|
||||
@@ -17,14 +15,7 @@ function init {
|
||||
|
||||
function build {
|
||||
cd ../..
|
||||
|
||||
if [[ $NO_TEST == "true" ]]; then
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
else
|
||||
./jenkins_build.sh
|
||||
fi
|
||||
|
||||
scripts/jenkins/build.sh
|
||||
cd $SCRIPT_DIR
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ function init {
|
||||
}
|
||||
|
||||
function build {
|
||||
./set-node-version.sh
|
||||
cd ../..
|
||||
|
||||
npm install -g grunt-cli
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install nvm for this shell
|
||||
source ~/.nvm/nvm.sh
|
||||
|
||||
# Use node.js at 4.2.x
|
||||
nvm install 4.2
|
||||
@@ -0,0 +1,74 @@
|
||||
// Implementation based on:
|
||||
// https://github.com/angular/angular/blob/3b9c08676a4c921bbfa847802e08566fb601ba7a/tools/npm/check-node-modules.js
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
var purgeIfStale = process.argv.indexOf('--purge') !== -1;
|
||||
|
||||
process.chdir(PROJECT_ROOT);
|
||||
checkNodeModules(purgeIfStale);
|
||||
}
|
||||
|
||||
function checkNodeModules(purgeIfStale) {
|
||||
var nodeModulesOk = compareMarkerFiles(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE);
|
||||
|
||||
if (nodeModulesOk) {
|
||||
console.log(':-) npm dependencies are looking good!');
|
||||
} else if (purgeIfStale) {
|
||||
console.log(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.log(' Purging \'' + NODE_MODULES_DIR + '\'...');
|
||||
deleteDirSync(NODE_MODULES_DIR);
|
||||
} else {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.warn(separator);
|
||||
console.warn(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.warn('You can rebuild the dependencies by running `npm install`.');
|
||||
console.warn(separator);
|
||||
}
|
||||
|
||||
return nodeModulesOk;
|
||||
}
|
||||
|
||||
function compareMarkerFiles(markerFilePath, cachedMarkerFilePath) {
|
||||
if (!fs.existsSync(cachedMarkerFilePath)) return false;
|
||||
|
||||
var opts = {encoding: 'utf-8'};
|
||||
var markerContent = fs.readFileSync(markerFilePath, opts);
|
||||
var cachedMarkerContent = fs.readFileSync(cachedMarkerFilePath, opts);
|
||||
|
||||
return markerContent === cachedMarkerContent;
|
||||
}
|
||||
|
||||
// Custom implementation of `rm -rf` that works consistently across OSes
|
||||
function deleteDirSync(path) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.readdirSync(path).forEach(deleteDirOrFileSync);
|
||||
fs.rmdirSync(path);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function deleteDirOrFileSync(subpath) {
|
||||
var curPath = path + '/' + subpath;
|
||||
|
||||
if (fs.lstatSync(curPath).isDirectory()) {
|
||||
deleteDirSync(curPath);
|
||||
} else {
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
process.chdir(PROJECT_ROOT);
|
||||
copyFile(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE, onCopied);
|
||||
}
|
||||
|
||||
// Implementation based on:
|
||||
// https://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js#answer-21995878
|
||||
function copyFile(srcPath, dstPath, callback) {
|
||||
var callbackCalled = false;
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
done(new Error('Missing source file: ' + srcPath));
|
||||
return;
|
||||
}
|
||||
|
||||
var rs = fs.createReadStream(srcPath);
|
||||
rs.on('error', done);
|
||||
|
||||
var ws = fs.createWriteStream(dstPath);
|
||||
ws.on('error', done);
|
||||
ws.on('finish', done);
|
||||
|
||||
rs.pipe(ws);
|
||||
|
||||
// Helpers
|
||||
function done(err) {
|
||||
if (callback && !callbackCalled) {
|
||||
callbackCalled = true;
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onCopied(err) {
|
||||
if (err) {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.error(separator);
|
||||
console.error(
|
||||
'Failed to copy `' + NPM_SHRINKWRAP_FILE + '` to `' + NPM_SHRINKWRAP_CACHED_FILE + '`:');
|
||||
console.error(err);
|
||||
console.error(separator);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SHRINKWRAP_FILE=npm-shrinkwrap.json
|
||||
SHRINKWRAP_CACHED_FILE=node_modules/npm-shrinkwrap.cached.json
|
||||
|
||||
if diff -q $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE; then
|
||||
echo 'No shrinkwrap changes detected. npm install will be skipped...';
|
||||
else
|
||||
echo 'Blowing away node_modules and reinstalling npm dependencies...'
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
cp $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE
|
||||
echo 'npm install successful!'
|
||||
fi
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p $LOGS_DIR
|
||||
|
||||
if [ $JOB != "ci-checks" ]; then
|
||||
echo "start_browser_provider"
|
||||
./scripts/travis/start_browser_provider.sh
|
||||
fi
|
||||
|
||||
npm install -g grunt-cli
|
||||
|
||||
if [ $JOB != "ci-checks" ]; then
|
||||
grunt package
|
||||
echo "wait_for_browser_provider"
|
||||
./scripts/travis/wait_for_browser_provider.sh
|
||||
fi
|
||||
@@ -5,7 +5,9 @@ set -e
|
||||
export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev`
|
||||
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
if [ $JOB = "unit" ]; then
|
||||
if [ $JOB = "ci-checks" ]; then
|
||||
grunt ci-checks
|
||||
elif [ $JOB = "unit" ]; then
|
||||
if [ "$BROWSER_PROVIDER" == "browserstack" ]; then
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS"
|
||||
else
|
||||
@@ -14,7 +16,6 @@ if [ $JOB = "unit" ]; then
|
||||
|
||||
grunt test:promises-aplus
|
||||
grunt test:unit --browsers $BROWSERS --reporters dots
|
||||
grunt ci-checks
|
||||
grunt tests:docs --browsers $BROWSERS --reporters dots
|
||||
elif [ $JOB = "docs-e2e" ]; then
|
||||
grunt test:travis-protractor --specs "docs/app/e2e/**/*.scenario.js"
|
||||
@@ -31,5 +32,5 @@ elif [ $JOB = "e2e" ]; then
|
||||
export TARGET_SPECS="test/e2e/tests/**/*.js,$TARGET_SPECS"
|
||||
grunt test:travis-protractor --specs "$TARGET_SPECS"
|
||||
else
|
||||
echo "Unknown job type. Please set JOB=unit or JOB=e2e-*."
|
||||
echo "Unknown job type. Please set JOB=ci-checks, JOB=unit or JOB=e2e-*."
|
||||
fi
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Has to be run from project root directory.
|
||||
|
||||
./lib/${BROWSER_PROVIDER}/teardown_tunnel.sh
|
||||
+111
-59
@@ -36,6 +36,7 @@
|
||||
isUndefined: true,
|
||||
isDefined: true,
|
||||
isObject: true,
|
||||
isBlankObject: true,
|
||||
isString: true,
|
||||
isNumber: true,
|
||||
isDate: true,
|
||||
@@ -172,6 +173,7 @@ var
|
||||
splice = [].splice,
|
||||
push = [].push,
|
||||
toString = Object.prototype.toString,
|
||||
getPrototypeOf = Object.getPrototypeOf,
|
||||
ngMinErr = minErr('ng'),
|
||||
|
||||
/** @name angular */
|
||||
@@ -461,6 +463,16 @@ function isObject(value) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a value is an object with a null prototype
|
||||
*
|
||||
* @returns {boolean} True if `value` is an `Object` with a null prototype
|
||||
*/
|
||||
function isBlankObject(value) {
|
||||
return value !== null && typeof value === 'object' && !getPrototypeOf(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.isString
|
||||
@@ -597,6 +609,12 @@ function isPromiseLike(obj) {
|
||||
}
|
||||
|
||||
|
||||
var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
|
||||
function isTypedArray(value) {
|
||||
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
|
||||
}
|
||||
|
||||
|
||||
var trim = function(value) {
|
||||
return isString(value) ? value.trim() : value;
|
||||
};
|
||||
@@ -713,77 +731,111 @@ function arrayRemove(array, value) {
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
function copy(source, destination, stackSource, stackDest) {
|
||||
if (isWindow(source) || isScope(source)) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
function copy(source, destination) {
|
||||
var stackSource = [];
|
||||
var stackDest = [];
|
||||
|
||||
if (destination) {
|
||||
if (isTypedArray(destination)) {
|
||||
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
if (source === destination) {
|
||||
throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
|
||||
}
|
||||
|
||||
// Empty the destination object
|
||||
if (isArray(destination)) {
|
||||
destination.length = 0;
|
||||
} else {
|
||||
forEach(destination, function(value, key) {
|
||||
if (key !== '$$hashKey') {
|
||||
delete destination[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
return copyRecurse(source, destination);
|
||||
}
|
||||
|
||||
if (!destination) {
|
||||
destination = source;
|
||||
if (source) {
|
||||
if (isArray(source)) {
|
||||
destination = copy(source, [], stackSource, stackDest);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else if (isObject(source)) {
|
||||
var emptyObject = Object.create(Object.getPrototypeOf(source));
|
||||
destination = copy(source, emptyObject, stackSource, stackDest);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (source === destination) throw ngMinErr('cpi',
|
||||
"Can't copy! Source and destination are identical.");
|
||||
return copyElement(source);
|
||||
|
||||
stackSource = stackSource || [];
|
||||
stackDest = stackDest || [];
|
||||
|
||||
if (isObject(source)) {
|
||||
var index = stackSource.indexOf(source);
|
||||
if (index !== -1) return stackDest[index];
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
}
|
||||
|
||||
var result;
|
||||
function copyRecurse(source, destination) {
|
||||
var h = destination.$$hashKey;
|
||||
var result, key;
|
||||
if (isArray(source)) {
|
||||
destination.length = 0;
|
||||
for (var i = 0; i < source.length; i++) {
|
||||
result = copy(source[i], null, stackSource, stackDest);
|
||||
if (isObject(source[i])) {
|
||||
stackSource.push(source[i]);
|
||||
stackDest.push(result);
|
||||
for (var i = 0, ii = source.length; i < ii; i++) {
|
||||
destination.push(copyElement(source[i]));
|
||||
}
|
||||
} else if (isBlankObject(source)) {
|
||||
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
||||
for (key in source) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
} else if (source && typeof source.hasOwnProperty === 'function') {
|
||||
// Slow path, which must rely on hasOwnProperty
|
||||
for (key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
destination.push(result);
|
||||
}
|
||||
} else {
|
||||
var h = destination.$$hashKey;
|
||||
if (isArray(destination)) {
|
||||
destination.length = 0;
|
||||
} else {
|
||||
forEach(destination, function(value, key) {
|
||||
delete destination[key];
|
||||
});
|
||||
}
|
||||
for (var key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
result = copy(source[key], null, stackSource, stackDest);
|
||||
if (isObject(source[key])) {
|
||||
stackSource.push(source[key]);
|
||||
stackDest.push(result);
|
||||
}
|
||||
destination[key] = result;
|
||||
// Slowest path --- hasOwnProperty can't be called as a method
|
||||
for (key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
}
|
||||
setHashKey(destination,h);
|
||||
}
|
||||
setHashKey(destination, h);
|
||||
return destination;
|
||||
}
|
||||
|
||||
function copyElement(source) {
|
||||
// Simple values
|
||||
if (!isObject(source)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// Already copied values
|
||||
var index = stackSource.indexOf(source);
|
||||
if (index !== -1) {
|
||||
return stackDest[index];
|
||||
}
|
||||
|
||||
if (isWindow(source) || isScope(source)) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}
|
||||
|
||||
var needsRecurse = false;
|
||||
var destination;
|
||||
|
||||
if (isArray(source)) {
|
||||
destination = [];
|
||||
needsRecurse = true;
|
||||
} else if (isTypedArray(source)) {
|
||||
destination = new source.constructor(source);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else if (isFunction(source.cloneNode)) {
|
||||
destination = source.cloneNode(true);
|
||||
} else {
|
||||
destination = Object.create(getPrototypeOf(source));
|
||||
needsRecurse = true;
|
||||
}
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
|
||||
return needsRecurse
|
||||
? copyRecurse(source, destination)
|
||||
: destination;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -757,14 +757,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
function assertValidDirectiveName(name) {
|
||||
var letter = name.charAt(0);
|
||||
if (!letter || letter !== lowercase(letter)) {
|
||||
throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $compileProvider#directive
|
||||
@@ -783,7 +775,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
this.directive = function registerDirective(name, directiveFactory) {
|
||||
assertNotHasOwnProperty(name, 'directive');
|
||||
if (isString(name)) {
|
||||
assertValidDirectiveName(name);
|
||||
assertArg(directiveFactory, 'directiveFactory');
|
||||
if (!hasDirectives.hasOwnProperty(name)) {
|
||||
hasDirectives[name] = [];
|
||||
|
||||
@@ -318,13 +318,9 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
*
|
||||
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
|
||||
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
|
||||
* `<form>` but can be nested. This allows you to have nested forms, which is very useful when
|
||||
* using Angular validation directives in forms that are dynamically generated using the
|
||||
* {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
|
||||
* attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
|
||||
* `ngForm` directive and nest these in an outer `form` element.
|
||||
*
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
|
||||
* `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
|
||||
* of controls needs to be determined.
|
||||
*
|
||||
* # CSS classes
|
||||
* - `ng-valid` is set if the form is valid.
|
||||
|
||||
@@ -1535,13 +1535,16 @@ var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: ['?ngModel'],
|
||||
link: {
|
||||
pre: function(scope, element, attr, ctrls) {
|
||||
if (ctrls[0]) {
|
||||
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
|
||||
$browser, $filter, $parse);
|
||||
compile: function(tElement, tAttr) {
|
||||
if (lowercase(tAttr.type) === 'hidden') tAttr.$set('autocomplete', 'off');
|
||||
return {
|
||||
pre: function(scope, element, attr, ctrls) {
|
||||
if (ctrls[0]) {
|
||||
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
|
||||
$browser, $filter, $parse);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
@@ -596,7 +596,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
forEach(ctrl.$asyncValidators, function(validator, name) {
|
||||
var promise = validator(modelValue, viewValue);
|
||||
if (!isPromiseLike(promise)) {
|
||||
throw ngModelMinErr("$asyncValidators",
|
||||
throw ngModelMinErr('nopromise',
|
||||
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
|
||||
}
|
||||
setValidity(name, undefined);
|
||||
|
||||
+20
-10
@@ -38,20 +38,30 @@ var $parseMinErr = minErr('$parse');
|
||||
|
||||
|
||||
function ensureSafeMemberName(name, fullExpression) {
|
||||
if (name === "__defineGetter__" || name === "__defineSetter__"
|
||||
|| name === "__lookupGetter__" || name === "__lookupSetter__"
|
||||
|| name === "__proto__") {
|
||||
throw $parseMinErr('isecfld',
|
||||
'Attempting to access a disallowed field in Angular expressions! '
|
||||
+ 'Expression: {0}', fullExpression);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function getStringValue(name, fullExpression) {
|
||||
// From the JavaScript docs:
|
||||
// Property names must be strings. This means that non-string objects cannot be used
|
||||
// as keys in an object. Any non-string object, including a number, is typecasted
|
||||
// into a string via the toString method.
|
||||
//
|
||||
// So, to ensure that we are checking the same `name` that JavaScript would use,
|
||||
// we cast it to a string, if possible
|
||||
name = (isObject(name) && name.toString) ? name.toString() : name;
|
||||
|
||||
if (name === "__defineGetter__" || name === "__defineSetter__"
|
||||
|| name === "__lookupGetter__" || name === "__lookupSetter__"
|
||||
|| name === "__proto__") {
|
||||
throw $parseMinErr('isecfld',
|
||||
'Attempting to access a disallowed field in Angular expressions! '
|
||||
// we cast it to a string, if possible.
|
||||
// Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
|
||||
// this is, this will handle objects that misbehave.
|
||||
name = name + '';
|
||||
if (!isString(name)) {
|
||||
throw $parseMinErr('iseccst',
|
||||
'Cannot convert object to primitive value! '
|
||||
+ 'Expression: {0}', fullExpression);
|
||||
}
|
||||
return name;
|
||||
@@ -698,7 +708,7 @@ Parser.prototype = {
|
||||
|
||||
return extend(function $parseObjectIndex(self, locals) {
|
||||
var o = obj(self, locals),
|
||||
i = indexFn(self, locals),
|
||||
i = getStringValue(indexFn(self, locals), expression),
|
||||
v;
|
||||
|
||||
ensureSafeMemberName(i, expression);
|
||||
@@ -707,7 +717,7 @@ Parser.prototype = {
|
||||
return v;
|
||||
}, {
|
||||
assign: function(self, value, locals) {
|
||||
var key = ensureSafeMemberName(indexFn(self, locals), expression);
|
||||
var key = ensureSafeMemberName(getStringValue(indexFn(self, locals), expression), expression);
|
||||
// prevent overwriting of Function.constructor which would break ensureSafeObject check
|
||||
var o = ensureSafeObject(obj(self, locals), expression);
|
||||
if (!o) obj.assign(self, o = {}, locals);
|
||||
|
||||
@@ -1956,7 +1956,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
function onAnimationProgress(event) {
|
||||
event.stopPropagation();
|
||||
var ev = event.originalEvent || event;
|
||||
var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
|
||||
var timeStamp = ev.$manualTimeStamp || Date.now();
|
||||
|
||||
/* Firefox (or possibly just Gecko) likes to not round values up
|
||||
* when a ms measurement is used for the animation */
|
||||
@@ -1964,7 +1964,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
|
||||
/* $manualTimeStamp is a mocked timeStamp value which is set
|
||||
* within browserTrigger(). This is only here so that tests can
|
||||
* mock animations properly. Real events fallback to event.timeStamp,
|
||||
* mock animations properly. Real events fallback to Date.now(),
|
||||
* or, if they don't, then a timeStamp is automatically created for them.
|
||||
* We're checking to see if the timeStamp surpasses the expected delay,
|
||||
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
||||
|
||||
+283
-2
@@ -78,6 +78,186 @@ describe('angular', function() {
|
||||
expect(copy(objWithRegExp.re) === objWithRegExp.re).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should copy a Uint8Array with no destination", function() {
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
var src = new Uint8Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint8Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Uint8ClampedArray with no destination", function() {
|
||||
if (typeof Uint8ClampedArray !== 'undefined') {
|
||||
var src = new Uint8ClampedArray(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint8ClampedArray).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Uint16Array with no destination", function() {
|
||||
if (typeof Uint16Array !== 'undefined') {
|
||||
var src = new Uint16Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint16Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Uint32Array with no destination", function() {
|
||||
if (typeof Uint32Array !== 'undefined') {
|
||||
var src = new Uint32Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint32Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Int8Array with no destination", function() {
|
||||
if (typeof Int8Array !== 'undefined') {
|
||||
var src = new Int8Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Int8Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Int16Array with no destination", function() {
|
||||
if (typeof Int16Array !== 'undefined') {
|
||||
var src = new Int16Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Int16Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Int32Array with no destination", function() {
|
||||
if (typeof Int32Array !== 'undefined') {
|
||||
var src = new Int32Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Int32Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Float32Array with no destination", function() {
|
||||
if (typeof Float32Array !== 'undefined') {
|
||||
var src = new Float32Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Float32Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Float64Array with no destination", function() {
|
||||
if (typeof Float64Array !== 'undefined') {
|
||||
var src = new Float64Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Float64Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint8Array is the destination", function() {
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
var src = new Uint8Array();
|
||||
var dst = new Uint8Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint8ClampedArray is the destination", function() {
|
||||
if (typeof Uint8ClampedArray !== 'undefined') {
|
||||
var src = new Uint8ClampedArray();
|
||||
var dst = new Uint8ClampedArray(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint16Array is the destination", function() {
|
||||
if (typeof Uint16Array !== 'undefined') {
|
||||
var src = new Uint16Array();
|
||||
var dst = new Uint16Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint32Array is the destination", function() {
|
||||
if (typeof Uint32Array !== 'undefined') {
|
||||
var src = new Uint32Array();
|
||||
var dst = new Uint32Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Int8Array is the destination", function() {
|
||||
if (typeof Int8Array !== 'undefined') {
|
||||
var src = new Int8Array();
|
||||
var dst = new Int8Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Int16Array is the destination", function() {
|
||||
if (typeof Int16Array !== 'undefined') {
|
||||
var src = new Int16Array();
|
||||
var dst = new Int16Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Int32Array is the destination", function() {
|
||||
if (typeof Int32Array !== 'undefined') {
|
||||
var src = new Int32Array();
|
||||
var dst = new Int32Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Float32Array is the destination", function() {
|
||||
if (typeof Float32Array !== 'undefined') {
|
||||
var src = new Float32Array();
|
||||
var dst = new Float32Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Float64Array is the destination", function() {
|
||||
if (typeof Float64Array !== 'undefined') {
|
||||
var src = new Float64Array();
|
||||
var dst = new Float64Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should deeply copy an array into an existing array", function() {
|
||||
var src = [1, {name:"value"}];
|
||||
var dst = [{key:"v"}];
|
||||
@@ -133,11 +313,19 @@ describe('angular', function() {
|
||||
it('should throw an exception if a Scope is being copied', inject(function($rootScope) {
|
||||
expect(function() { copy($rootScope.$new()); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy({child: $rootScope.$new()}, {}); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy([$rootScope.$new()]); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}));
|
||||
|
||||
it('should throw an exception if a Window is being copied', function() {
|
||||
expect(function() { copy(window); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy({child: window}); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy([window], []); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
});
|
||||
|
||||
it('should throw an exception when source and destination are equivalent', function() {
|
||||
@@ -154,9 +342,14 @@ describe('angular', function() {
|
||||
hashKey(src);
|
||||
dst = copy(src);
|
||||
expect(hashKey(dst)).not.toEqual(hashKey(src));
|
||||
|
||||
src = {foo: {}};
|
||||
hashKey(src.foo);
|
||||
dst = copy(src);
|
||||
expect(hashKey(src.foo)).not.toEqual(hashKey(dst.foo));
|
||||
});
|
||||
|
||||
it('should retain the previous $$hashKey', function() {
|
||||
it('should retain the previous $$hashKey when copying object with hashKey', function() {
|
||||
var src,dst,h;
|
||||
src = {};
|
||||
dst = {};
|
||||
@@ -171,7 +364,21 @@ describe('angular', function() {
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
});
|
||||
|
||||
it('should handle circular references when circularRefs is turned on', function() {
|
||||
it('should retain the previous $$hashKey when copying non-object', function() {
|
||||
var dst = {};
|
||||
var h = hashKey(dst);
|
||||
|
||||
copy(null, dst);
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
|
||||
copy(42, dst);
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
|
||||
copy(new Date(), dst);
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
});
|
||||
|
||||
it('should handle circular references', function() {
|
||||
var a = {b: {a: null}, self: null, selfs: [null, null, [null]]};
|
||||
a.b.a = a;
|
||||
a.self = a;
|
||||
@@ -182,13 +389,87 @@ describe('angular', function() {
|
||||
|
||||
expect(aCopy).not.toBe(a);
|
||||
expect(aCopy).toBe(aCopy.self);
|
||||
expect(aCopy).toBe(aCopy.selfs[2][0]);
|
||||
expect(aCopy.selfs[2]).not.toBe(a.selfs[2]);
|
||||
|
||||
var copyTo = [];
|
||||
aCopy = copy(a, copyTo);
|
||||
expect(aCopy).toBe(copyTo);
|
||||
expect(aCopy).not.toBe(a);
|
||||
expect(aCopy).toBe(aCopy.self);
|
||||
});
|
||||
|
||||
it('should deeply copy XML nodes', function() {
|
||||
var anElement = document.createElement('foo');
|
||||
anElement.appendChild(document.createElement('bar'));
|
||||
var theCopy = anElement.cloneNode(true);
|
||||
expect(copy(anElement).outerHTML).toEqual(theCopy.outerHTML);
|
||||
expect(copy(anElement)).not.toBe(anElement);
|
||||
});
|
||||
|
||||
it('should not try to call a non-function called `cloneNode`', function() {
|
||||
expect(copy.bind(null, { cloneNode: 100 })).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle objects with multiple references', function() {
|
||||
var b = {};
|
||||
var a = [b, -1, b];
|
||||
|
||||
var aCopy = copy(a);
|
||||
expect(aCopy[0]).not.toBe(a[0]);
|
||||
expect(aCopy[0]).toBe(aCopy[2]);
|
||||
|
||||
var copyTo = [];
|
||||
aCopy = copy(a, copyTo);
|
||||
expect(aCopy).toBe(copyTo);
|
||||
expect(aCopy[0]).not.toBe(a[0]);
|
||||
expect(aCopy[0]).toBe(aCopy[2]);
|
||||
});
|
||||
|
||||
it('should handle date/regex objects with multiple references', function() {
|
||||
var re = /foo/;
|
||||
var d = new Date();
|
||||
var o = {re: re, re2: re, d: d, d2: d};
|
||||
|
||||
var oCopy = copy(o);
|
||||
expect(oCopy.re).toBe(oCopy.re2);
|
||||
expect(oCopy.d).toBe(oCopy.d2);
|
||||
|
||||
oCopy = copy(o, {});
|
||||
expect(oCopy.re).toBe(oCopy.re2);
|
||||
expect(oCopy.d).toBe(oCopy.d2);
|
||||
});
|
||||
|
||||
it('should clear destination arrays correctly when source is non-array', function() {
|
||||
expect(copy(null, [1,2,3])).toEqual([]);
|
||||
expect(copy(undefined, [1,2,3])).toEqual([]);
|
||||
expect(copy({0: 1, 1: 2}, [1,2,3])).toEqual([1,2]);
|
||||
expect(copy(new Date(), [1,2,3])).toEqual([]);
|
||||
expect(copy(/a/, [1,2,3])).toEqual([]);
|
||||
expect(copy(true, [1,2,3])).toEqual([]);
|
||||
});
|
||||
|
||||
it('should clear destination objects correctly when source is non-array', function() {
|
||||
expect(copy(null, {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(undefined, {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(new Date(), {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(/a/, {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(true, {0:1,1:2,2:3})).toEqual({});
|
||||
});
|
||||
|
||||
it('should copy objects with no prototype parent', function() {
|
||||
var obj = extend(Object.create(null), {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
});
|
||||
var dest = copy(obj);
|
||||
|
||||
expect(Object.getPrototypeOf(dest)).toBe(null);
|
||||
expect(dest.a).toBe(1);
|
||||
expect(dest.b).toBe(2);
|
||||
expect(dest.c).toBe(3);
|
||||
expect(Object.keys(dest)).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app>
|
||||
<body>
|
||||
<form>
|
||||
<input type="hidden" value="{{value}}" />
|
||||
<button ng-click="value = '{{ 7 * 6 }}'">Click me</button>
|
||||
</form>
|
||||
<script src="angular.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
describe('hidden thingy', function() {
|
||||
it('should pass', function() {
|
||||
|
||||
loadFixture('input-hidden');
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('');
|
||||
|
||||
element(by.css('button')).click();
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('{{ 7 * 6 }}');
|
||||
|
||||
loadFixture('sample');
|
||||
browser.driver.executeScript('history.back()');
|
||||
var expectedValue = browser.params.browser === 'safari' ? '{{ 7 * 6 }}' : '';
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual(expectedValue);
|
||||
});
|
||||
});
|
||||
@@ -147,7 +147,6 @@ describe('$compile', function() {
|
||||
|
||||
|
||||
describe('configuration', function() {
|
||||
|
||||
it('should register a directive', function() {
|
||||
module(function() {
|
||||
directive('div', function(log) {
|
||||
@@ -202,15 +201,6 @@ describe('$compile', function() {
|
||||
});
|
||||
inject(function($compile) {});
|
||||
});
|
||||
|
||||
it('should throw an exception if a directive name starts with a non-lowercase letter', function() {
|
||||
module(function() {
|
||||
expect(function() {
|
||||
directive('BadDirectiveName', function() { });
|
||||
}).toThrowMinErr('$compile','baddir', "Directive name 'BadDirectiveName' is invalid. The first character must be a lowercase letter");
|
||||
});
|
||||
inject(function($compile) {});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -904,7 +904,7 @@ describe('ngModel', function() {
|
||||
|
||||
expect(function() {
|
||||
scope.$apply('value = "123"');
|
||||
}).toThrowMinErr("ngModel", "$asyncValidators",
|
||||
}).toThrowMinErr("ngModel", "nopromise",
|
||||
"Expected asynchronous validator to return a promise but got 'true' instead.");
|
||||
}));
|
||||
|
||||
|
||||
@@ -1215,6 +1215,15 @@ describe('parser', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should prevent the exploit', function() {
|
||||
expect(function() {
|
||||
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
|
||||
});
|
||||
if (!msie || msie > 10) {
|
||||
expect((1)['__proto__'].foo).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it('should prevent the exploit', function() {
|
||||
expect(function() {
|
||||
scope.$eval('' +
|
||||
|
||||
Reference in New Issue
Block a user